xref: /aosp_15_r20/external/libchrome-gestures/src/file_util.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
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