summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-02-04 22:43:01 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-02-04 22:43:02 +0000
commit27d28d3baff860d1fd936a5fcf2d920577c52575 (patch)
tree476e2ec43e56c4eb5fd604b7450fd17a3c1bfd53
parentaec43a12a76160e924fc0af9b131bd385cf7a60c (diff)
parent202f024dee8a450b92b17b2a4b90d412879321bd (diff)
downloadsystem_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.h3
-rw-r--r--libutils/file.cpp43
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);
+}