|
14 | 14 |
|
15 | 15 | #include "common/util/file_util.h"
|
16 | 16 |
|
| 17 | +#include <fcntl.h> |
| 18 | + |
17 | 19 | #include <algorithm>
|
18 | 20 | #include <cerrno>
|
| 21 | +#include <cstdint> |
| 22 | +#include <cstdio> |
19 | 23 | #include <cstdlib>
|
20 | 24 | #include <cstring>
|
21 | 25 | #include <filesystem>
|
22 |
| -#include <fstream> |
23 |
| -#include <iostream> |
24 | 26 | #include <memory>
|
25 | 27 | #include <string>
|
26 | 28 | #include <system_error>
|
|
34 | 36 | #include "common/util/logging.h"
|
35 | 37 |
|
36 | 38 | #ifndef _WIN32
|
37 |
| -#include <fcntl.h> |
38 | 39 | #include <sys/mman.h>
|
39 | 40 | #include <sys/stat.h>
|
40 | 41 | #include <unistd.h>
|
| 42 | +#else |
| 43 | +#include <io.h> |
41 | 44 | #endif
|
42 | 45 |
|
43 | 46 | namespace fs = std::filesystem;
|
@@ -154,34 +157,35 @@ absl::Status FileExists(const std::string &filename) {
|
154 | 157 |
|
155 | 158 | absl::StatusOr<std::string> GetContentAsString(absl::string_view filename) {
|
156 | 159 | std::string content;
|
157 |
| - std::ifstream fs; |
158 |
| - std::istream *stream = nullptr; |
| 160 | + FILE *stream = nullptr; |
159 | 161 | const bool use_stdin = IsStdin(filename);
|
160 | 162 | if (use_stdin) {
|
161 |
| - stream = &std::cin; |
| 163 | +#ifdef _WIN32 |
| 164 | + _setmode(_fileno(stdin), _O_BINARY); // Work around DOS/Win silliness. |
| 165 | +#endif |
| 166 | + stream = stdin; |
162 | 167 | } else {
|
163 | 168 | const std::string filename_str = std::string{filename};
|
164 | 169 | if (absl::Status status = FileExists(filename_str); !status.ok()) {
|
165 | 170 | return status; // Bail
|
166 | 171 | }
|
167 |
| - fs.open(filename_str.c_str()); |
| 172 | + stream = fopen(filename_str.c_str(), "rb"); |
168 | 173 | std::error_code err;
|
169 | 174 | const size_t prealloc = fs::file_size(filename_str, err);
|
170 | 175 | if (err.value() == 0) content.reserve(prealloc);
|
171 |
| - stream = &fs; |
172 | 176 | }
|
173 |
| - if (!stream->good()) { |
| 177 | + if (!stream) { |
174 | 178 | return CreateErrorStatusFromErrno(filename, "can't read");
|
175 | 179 | }
|
176 | 180 | char buffer[4096];
|
177 |
| - while (stream->good() && !stream->eof()) { |
178 |
| - stream->read(buffer, sizeof(buffer)); |
179 |
| - content.append(buffer, stream->gcount()); |
180 |
| - } |
181 |
| - |
182 |
| - // Allow stdin to be reopened for more input. |
183 |
| - if (use_stdin && std::cin.eof()) std::cin.clear(); |
184 |
| - return std::move(content); |
| 181 | + int bytes_read; |
| 182 | + do { |
| 183 | + bytes_read = fread(buffer, 1, sizeof(buffer), stream); |
| 184 | + content.append(buffer, bytes_read); |
| 185 | + } while (bytes_read > 0); |
| 186 | + fclose(stream); |
| 187 | + |
| 188 | + return content; |
185 | 189 | }
|
186 | 190 |
|
187 | 191 | static absl::StatusOr<std::unique_ptr<MemBlock>> AttemptMemMapFile(
|
@@ -244,11 +248,19 @@ absl::StatusOr<std::unique_ptr<MemBlock>> GetContentAsMemBlock(
|
244 | 248 | absl::Status SetContents(absl::string_view filename,
|
245 | 249 | absl::string_view content) {
|
246 | 250 | VLOG(1) << __FUNCTION__ << ": Writing file: " << filename;
|
247 |
| - std::ofstream f(std::string(filename).c_str()); |
248 |
| - if (!f.good()) return CreateErrorStatusFromErrno(filename, "can't write."); |
249 |
| - f << content; |
250 |
| - f.close(); |
251 |
| - if (!f.good()) return CreateErrorStatusFromErrno(filename, "closing."); |
| 251 | + FILE *out = fopen(std::string(filename).c_str(), "wb"); |
| 252 | + if (!out) return CreateErrorStatusFromErrno(filename, "can't write."); |
| 253 | + const int64_t expected_write = content.size(); |
| 254 | + int64_t total_written = 0; |
| 255 | + while (!content.empty()) { |
| 256 | + int64_t w = fwrite(content.data(), 1, content.size(), out); |
| 257 | + total_written += w; |
| 258 | + content.remove_prefix(w); |
| 259 | + } |
| 260 | + const bool written_completely = (total_written == expected_write); |
| 261 | + if (fclose(out) != 0 || !written_completely) { |
| 262 | + return CreateErrorStatusFromErrno(filename, "closing."); |
| 263 | + } |
252 | 264 | return absl::OkStatus();
|
253 | 265 | }
|
254 | 266 |
|
|
0 commit comments