blob: 4e7ac82d1bea70c3f4a3b970d5177bce805eca14 [file] [log] [blame]
Elliott Hughesdec12b22015-02-02 17:31:27 -08001/*
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
Elliott Hughes4f713192015-12-04 22:00:26 -080017#include "android-base/file.h"
Elliott Hughesdec12b22015-02-02 17:31:27 -080018
19#include <errno.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23
Dan Albertc007bc32015-03-16 10:08:46 -070024#include <string>
Elliott Hughesaf4885a2015-02-03 13:02:57 -080025
Elliott Hughes4f713192015-12-04 22:00:26 -080026#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
Elliott Hughese5dd71a2016-07-28 15:15:28 -070027#include "android-base/logging.h"
Elliott Hughes4f713192015-12-04 22:00:26 -080028#include "android-base/utf8.h"
Dan Albert94d13602015-03-26 23:33:28 -070029#include "utils/Compat.h"
Dan Albertc007bc32015-03-16 10:08:46 -070030
31namespace android {
32namespace base {
33
Elliott Hughesc1fd4922015-11-11 18:02:29 +000034// Versions of standard library APIs that support UTF-8 strings.
35using namespace android::base::utf8;
36
Dan Albertc007bc32015-03-16 10:08:46 -070037bool ReadFdToString(int fd, std::string* content) {
Elliott Hughesf682b472015-02-06 12:19:48 -080038 content->clear();
39
40 char buf[BUFSIZ];
41 ssize_t n;
42 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
43 content->append(buf, n);
44 }
45 return (n == 0) ? true : false;
46}
47
Dan Albertc007bc32015-03-16 10:08:46 -070048bool ReadFileToString(const std::string& path, std::string* content) {
Elliott Hughesdec12b22015-02-02 17:31:27 -080049 content->clear();
50
Elliott Hughes470d79a2015-09-01 13:35:44 -070051 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
Elliott Hughesdec12b22015-02-02 17:31:27 -080052 if (fd == -1) {
53 return false;
54 }
Elliott Hughesf682b472015-02-06 12:19:48 -080055 bool result = ReadFdToString(fd, content);
Nick Kralevich95db36e2015-05-20 08:59:21 -070056 close(fd);
Elliott Hughesf682b472015-02-06 12:19:48 -080057 return result;
Elliott Hughesdec12b22015-02-02 17:31:27 -080058}
59
Dan Albertc007bc32015-03-16 10:08:46 -070060bool WriteStringToFd(const std::string& content, int fd) {
Elliott Hughesdec12b22015-02-02 17:31:27 -080061 const char* p = content.data();
62 size_t left = content.size();
63 while (left > 0) {
64 ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left));
65 if (n == -1) {
Elliott Hughesdec12b22015-02-02 17:31:27 -080066 return false;
67 }
68 p += n;
69 left -= n;
70 }
Elliott Hughesdec12b22015-02-02 17:31:27 -080071 return true;
72}
Elliott Hughes202f0242015-02-04 13:19:13 -080073
74static bool CleanUpAfterFailedWrite(const std::string& path) {
75 // Something went wrong. Let's not leave a corrupt file lying around.
76 int saved_errno = errno;
77 unlink(path.c_str());
78 errno = saved_errno;
79 return false;
80}
81
Elliott Hughes31fa09c2015-02-04 19:38:28 -080082#if !defined(_WIN32)
Dan Albertc007bc32015-03-16 10:08:46 -070083bool WriteStringToFile(const std::string& content, const std::string& path,
84 mode_t mode, uid_t owner, gid_t group) {
Elliott Hughes470d79a2015-09-01 13:35:44 -070085 int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
86 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
Elliott Hughes202f0242015-02-04 13:19:13 -080087 if (fd == -1) {
Elliott Hughese5dd71a2016-07-28 15:15:28 -070088 PLOG(ERROR) << "android::WriteStringToFile open failed";
Elliott Hughes202f0242015-02-04 13:19:13 -080089 return false;
90 }
Elliott Hughesf682b472015-02-06 12:19:48 -080091
Dan Albertc007bc32015-03-16 10:08:46 -070092 // We do an explicit fchmod here because we assume that the caller really
93 // meant what they said and doesn't want the umask-influenced mode.
Elliott Hughes9d1f5152015-02-17 10:16:04 -080094 if (fchmod(fd, mode) == -1) {
Elliott Hughese5dd71a2016-07-28 15:15:28 -070095 PLOG(ERROR) << "android::WriteStringToFile fchmod failed";
Elliott Hughes9d1f5152015-02-17 10:16:04 -080096 return CleanUpAfterFailedWrite(path);
97 }
98 if (fchown(fd, owner, group) == -1) {
Elliott Hughese5dd71a2016-07-28 15:15:28 -070099 PLOG(ERROR) << "android::WriteStringToFile fchown failed";
Elliott Hughes9d1f5152015-02-17 10:16:04 -0800100 return CleanUpAfterFailedWrite(path);
101 }
102 if (!WriteStringToFd(content, fd)) {
Elliott Hughese5dd71a2016-07-28 15:15:28 -0700103 PLOG(ERROR) << "android::WriteStringToFile write failed";
Elliott Hughes9d1f5152015-02-17 10:16:04 -0800104 return CleanUpAfterFailedWrite(path);
105 }
Nick Kralevich95db36e2015-05-20 08:59:21 -0700106 close(fd);
Elliott Hughes9d1f5152015-02-17 10:16:04 -0800107 return true;
Elliott Hughes202f0242015-02-04 13:19:13 -0800108}
Elliott Hughes31fa09c2015-02-04 19:38:28 -0800109#endif
Elliott Hughes202f0242015-02-04 13:19:13 -0800110
Dan Albertc007bc32015-03-16 10:08:46 -0700111bool WriteStringToFile(const std::string& content, const std::string& path) {
Elliott Hughes470d79a2015-09-01 13:35:44 -0700112 int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
113 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE));
Elliott Hughes202f0242015-02-04 13:19:13 -0800114 if (fd == -1) {
115 return false;
116 }
Elliott Hughesf682b472015-02-06 12:19:48 -0800117
118 bool result = WriteStringToFd(content, fd);
Nick Kralevich95db36e2015-05-20 08:59:21 -0700119 close(fd);
Elliott Hughesf682b472015-02-06 12:19:48 -0800120 return result || CleanUpAfterFailedWrite(path);
Elliott Hughes202f0242015-02-04 13:19:13 -0800121}
Dan Albertc007bc32015-03-16 10:08:46 -0700122
Elliott Hughes56085ed2015-04-24 21:57:16 -0700123bool ReadFully(int fd, void* data, size_t byte_count) {
124 uint8_t* p = reinterpret_cast<uint8_t*>(data);
125 size_t remaining = byte_count;
126 while (remaining > 0) {
127 ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining));
128 if (n <= 0) return false;
129 p += n;
130 remaining -= n;
131 }
132 return true;
133}
134
135bool WriteFully(int fd, const void* data, size_t byte_count) {
136 const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
137 size_t remaining = byte_count;
138 while (remaining > 0) {
139 ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining));
140 if (n == -1) return false;
141 p += n;
142 remaining -= n;
143 }
144 return true;
145}
146
Yabin Cuib6e314a2016-01-29 17:25:54 -0800147bool RemoveFileIfExists(const std::string& path, std::string* err) {
148 struct stat st;
149#if defined(_WIN32)
150 //TODO: Windows version can't handle symbol link correctly.
151 int result = stat(path.c_str(), &st);
152 bool file_type_removable = (result == 0 && S_ISREG(st.st_mode));
153#else
154 int result = lstat(path.c_str(), &st);
155 bool file_type_removable = (result == 0 && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)));
156#endif
157 if (result == 0) {
158 if (!file_type_removable) {
159 if (err != nullptr) {
160 *err = "is not a regular or symbol link file";
161 }
162 return false;
163 }
164 if (unlink(path.c_str()) == -1) {
165 if (err != nullptr) {
166 *err = strerror(errno);
167 }
168 return false;
169 }
170 }
171 return true;
172}
173
Dan Albertc007bc32015-03-16 10:08:46 -0700174} // namespace base
175} // namespace android