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 177