diff options
author | Elliott Hughes <enh@google.com> | 2015-02-04 22:43:01 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-02-04 22:43:02 +0000 |
commit | 27d28d3baff860d1fd936a5fcf2d920577c52575 (patch) | |
tree | 476e2ec43e56c4eb5fd604b7450fd17a3c1bfd53 | |
parent | aec43a12a76160e924fc0af9b131bd385cf7a60c (diff) | |
parent | 202f024dee8a450b92b17b2a4b90d412879321bd (diff) | |
download | system_core-27d28d3baff860d1fd936a5fcf2d920577c52575.zip system_core-27d28d3baff860d1fd936a5fcf2d920577c52575.tar.gz system_core-27d28d3baff860d1fd936a5fcf2d920577c52575.tar.bz2 |
Merge "Add a WriteStringToFile overload that cares about permissions."
-rw-r--r-- | include/utils/file.h | 3 | ||||
-rw-r--r-- | libutils/file.cpp | 43 |
2 files changed, 38 insertions, 8 deletions
diff --git a/include/utils/file.h b/include/utils/file.h index 108cabc..d6b7057 100644 --- a/include/utils/file.h +++ b/include/utils/file.h @@ -18,11 +18,14 @@ #define UTILS_FILE_H #include <string> +#include <sys/stat.h> namespace android { bool ReadFileToString(const std::string& path, std::string* content); bool WriteStringToFile(const std::string& content, const std::string& path); +bool WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group); } // namespace android diff --git a/libutils/file.cpp b/libutils/file.cpp index aa35ff2..bfd1f55 100644 --- a/libutils/file.cpp +++ b/libutils/file.cpp @@ -46,14 +46,7 @@ bool android::ReadFileToString(const std::string& path, std::string* content) { } } -bool android::WriteStringToFile(const std::string& content, const std::string& path) { - int fd = TEMP_FAILURE_RETRY(open(path.c_str(), - O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, - DEFFILEMODE)); - if (fd == -1) { - return false; - } - +static bool WriteStringToFd(const std::string& content, int fd) { const char* p = content.data(); size_t left = content.size(); while (left > 0) { @@ -68,3 +61,37 @@ bool android::WriteStringToFile(const std::string& content, const std::string& p TEMP_FAILURE_RETRY(close(fd)); return true; } + +static bool CleanUpAfterFailedWrite(const std::string& path) { + // Something went wrong. Let's not leave a corrupt file lying around. + int saved_errno = errno; + unlink(path.c_str()); + errno = saved_errno; + return false; +} + +bool android::WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group) { + int fd = TEMP_FAILURE_RETRY(open(path.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + mode)); + if (fd == -1) { + return false; + } + // We do an explicit fchmod here because we assume that the caller really meant what they + // said and doesn't want the umask-influenced mode. + if (fchmod(fd, mode) != -1 && fchown(fd, owner, group) == -1 && WriteStringToFd(content, fd)) { + return true; + } + return CleanUpAfterFailedWrite(path); +} + +bool android::WriteStringToFile(const std::string& content, const std::string& path) { + int fd = TEMP_FAILURE_RETRY(open(path.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + DEFFILEMODE)); + if (fd == -1) { + return false; + } + return WriteStringToFd(content, fd) || CleanUpAfterFailedWrite(path); +} |