OSDN Git Service

init.rc: remove bg_non_interactive cgroup [ DO NOT MERGE ]
[android-x86/system-core.git] / base / file.cpp
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "android-base/file.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include <string>
25
26 #include "android-base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
27 #include "android-base/utf8.h"
28 #define LOG_TAG "base.file"
29 #include "cutils/log.h"
30 #include "utils/Compat.h"
31
32 namespace android {
33 namespace base {
34
35 // Versions of standard library APIs that support UTF-8 strings.
36 using namespace android::base::utf8;
37
38 bool ReadFdToString(int fd, std::string* content) {
39   content->clear();
40
41   char buf[BUFSIZ];
42   ssize_t n;
43   while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
44     content->append(buf, n);
45   }
46   return (n == 0) ? true : false;
47 }
48
49 bool ReadFileToString(const std::string& path, std::string* content) {
50   content->clear();
51
52   int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
53   if (fd == -1) {
54     return false;
55   }
56   bool result = ReadFdToString(fd, content);
57   close(fd);
58   return result;
59 }
60
61 bool WriteStringToFd(const std::string& content, int fd) {
62   const char* p = content.data();
63   size_t left = content.size();
64   while (left > 0) {
65     ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left));
66     if (n == -1) {
67       return false;
68     }
69     p += n;
70     left -= n;
71   }
72   return true;
73 }
74
75 static bool CleanUpAfterFailedWrite(const std::string& path) {
76   // Something went wrong. Let's not leave a corrupt file lying around.
77   int saved_errno = errno;
78   unlink(path.c_str());
79   errno = saved_errno;
80   return false;
81 }
82
83 #if !defined(_WIN32)
84 bool WriteStringToFile(const std::string& content, const std::string& path,
85                        mode_t mode, uid_t owner, gid_t group) {
86   int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
87   int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
88   if (fd == -1) {
89     ALOGE("android::WriteStringToFile open failed: %s", strerror(errno));
90     return false;
91   }
92
93   // We do an explicit fchmod here because we assume that the caller really
94   // meant what they said and doesn't want the umask-influenced mode.
95   if (fchmod(fd, mode) == -1) {
96     ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno));
97     return CleanUpAfterFailedWrite(path);
98   }
99   if (fchown(fd, owner, group) == -1) {
100     ALOGE("android::WriteStringToFile fchown failed: %s", strerror(errno));
101     return CleanUpAfterFailedWrite(path);
102   }
103   if (!WriteStringToFd(content, fd)) {
104     ALOGE("android::WriteStringToFile write failed: %s", strerror(errno));
105     return CleanUpAfterFailedWrite(path);
106   }
107   close(fd);
108   return true;
109 }
110 #endif
111
112 bool WriteStringToFile(const std::string& content, const std::string& path) {
113   int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
114   int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE));
115   if (fd == -1) {
116     return false;
117   }
118
119   bool result = WriteStringToFd(content, fd);
120   close(fd);
121   return result || CleanUpAfterFailedWrite(path);
122 }
123
124 bool ReadFully(int fd, void* data, size_t byte_count) {
125   uint8_t* p = reinterpret_cast<uint8_t*>(data);
126   size_t remaining = byte_count;
127   while (remaining > 0) {
128     ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining));
129     if (n <= 0) return false;
130     p += n;
131     remaining -= n;
132   }
133   return true;
134 }
135
136 bool WriteFully(int fd, const void* data, size_t byte_count) {
137   const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
138   size_t remaining = byte_count;
139   while (remaining > 0) {
140     ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining));
141     if (n == -1) return false;
142     p += n;
143     remaining -= n;
144   }
145   return true;
146 }
147
148 bool RemoveFileIfExists(const std::string& path, std::string* err) {
149   struct stat st;
150 #if defined(_WIN32)
151   //TODO: Windows version can't handle symbol link correctly.
152   int result = stat(path.c_str(), &st);
153   bool file_type_removable = (result == 0 && S_ISREG(st.st_mode));
154 #else
155   int result = lstat(path.c_str(), &st);
156   bool file_type_removable = (result == 0 && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)));
157 #endif
158   if (result == 0) {
159     if (!file_type_removable) {
160       if (err != nullptr) {
161         *err = "is not a regular or symbol link file";
162       }
163       return false;
164     }
165     if (unlink(path.c_str()) == -1) {
166       if (err != nullptr) {
167         *err = strerror(errno);
168       }
169       return false;
170     }
171   }
172   return true;
173 }
174
175 }  // namespace base
176 }  // namespace android