1 // Copyright 2014 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "include/file_util.h"
6
7 #include <fcntl.h>
8 #include <limits>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12
13 #include "include/eintr_wrapper.h"
14
15 namespace gestures {
16
OpenFile(const char * filename,const char * mode)17 FILE* OpenFile(const char* filename, const char* mode) {
18 FILE* result = nullptr;
19 do {
20 result = fopen(filename, mode);
21 } while (!result && errno == EINTR);
22 return result;
23 }
24
CloseFile(FILE * file)25 bool CloseFile(FILE* file) {
26 if (file == nullptr)
27 return true;
28 return fclose(file) == 0;
29 }
30
ReadFileToString(const char * path,std::string * contents,size_t max_size)31 bool ReadFileToString(const char* path,
32 std::string* contents,
33 size_t max_size) {
34 if (contents)
35 contents->clear();
36 FILE* file = OpenFile(path, "rb");
37 if (!file) {
38 return false;
39 }
40
41 char buf[1 << 16];
42 size_t len;
43 size_t size = 0;
44 bool read_status = true;
45
46 // Many files supplied in |path| have incorrect size (proc files etc).
47 // Hence, the file is read sequentially as opposed to a one-shot read.
48 while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
49 if (contents)
50 contents->append(buf, std::min(len, max_size - size));
51
52 if ((max_size - size) < len) {
53 read_status = false;
54 break;
55 }
56
57 size += len;
58 }
59 CloseFile(file);
60
61 return read_status;
62 }
63
ReadFileToString(const char * path,std::string * contents)64 bool ReadFileToString(const char* path, std::string* contents) {
65 return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
66 }
67
WriteFileDescriptor(const int fd,const char * data,int size)68 int WriteFileDescriptor(const int fd, const char* data, int size) {
69 // Allow for partial writes.
70 ssize_t bytes_written_total = 0;
71 for (ssize_t bytes_written_partial = 0; bytes_written_total < size;
72 bytes_written_total += bytes_written_partial) {
73 bytes_written_partial =
74 HANDLE_EINTR(write(fd, data + bytes_written_total,
75 size - bytes_written_total));
76 if (bytes_written_partial < 0)
77 return -1;
78 }
79
80 return bytes_written_total;
81 }
82
WriteFile(const char * filename,const char * data,int size)83 int WriteFile(const char *filename, const char* data, int size) {
84 int fd = HANDLE_EINTR(creat(filename, 0666));
85 if (fd < 0)
86 return -1;
87
88 int bytes_written = WriteFileDescriptor(fd, data, size);
89 if (int ret = IGNORE_EINTR(close(fd)) < 0)
90 return ret;
91 return bytes_written;
92 }
93
94 } // namespace gestures
95