blob: 577df780c41c6831d413b904ece7081e1b97ed00 [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
17#include "utils/file.h"
18
19#include <errno.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23
Elliott Hughesaf4885a2015-02-03 13:02:57 -080024#include <utils/Compat.h> // For TEMP_FAILURE_RETRY on Darwin.
25
Elliott Hughesf682b472015-02-06 12:19:48 -080026bool android::ReadFdToString(int fd, std::string* content) {
27 content->clear();
28
29 char buf[BUFSIZ];
30 ssize_t n;
31 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
32 content->append(buf, n);
33 }
34 return (n == 0) ? true : false;
35}
36
Elliott Hughesdec12b22015-02-02 17:31:27 -080037bool android::ReadFileToString(const std::string& path, std::string* content) {
38 content->clear();
39
40 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
41 if (fd == -1) {
42 return false;
43 }
Elliott Hughesf682b472015-02-06 12:19:48 -080044 bool result = ReadFdToString(fd, content);
45 TEMP_FAILURE_RETRY(close(fd));
46 return result;
Elliott Hughesdec12b22015-02-02 17:31:27 -080047}
48
Elliott Hughesf682b472015-02-06 12:19:48 -080049bool android::WriteStringToFd(const std::string& content, int fd) {
Elliott Hughesdec12b22015-02-02 17:31:27 -080050 const char* p = content.data();
51 size_t left = content.size();
52 while (left > 0) {
53 ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left));
54 if (n == -1) {
Elliott Hughesdec12b22015-02-02 17:31:27 -080055 return false;
56 }
57 p += n;
58 left -= n;
59 }
Elliott Hughesdec12b22015-02-02 17:31:27 -080060 return true;
61}
Elliott Hughes202f0242015-02-04 13:19:13 -080062
63static bool CleanUpAfterFailedWrite(const std::string& path) {
64 // Something went wrong. Let's not leave a corrupt file lying around.
65 int saved_errno = errno;
66 unlink(path.c_str());
67 errno = saved_errno;
68 return false;
69}
70
Elliott Hughes31fa09c2015-02-04 19:38:28 -080071#if !defined(_WIN32)
Elliott Hughes202f0242015-02-04 13:19:13 -080072bool android::WriteStringToFile(const std::string& content, const std::string& path,
73 mode_t mode, uid_t owner, gid_t group) {
74 int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
75 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
76 mode));
77 if (fd == -1) {
78 return false;
79 }
Elliott Hughesf682b472015-02-06 12:19:48 -080080
Elliott Hughes202f0242015-02-04 13:19:13 -080081 // We do an explicit fchmod here because we assume that the caller really meant what they
82 // said and doesn't want the umask-influenced mode.
Elliott Hughesf682b472015-02-06 12:19:48 -080083 bool result = (fchmod(fd, mode) != -1 && fchown(fd, owner, group) == -1 && WriteStringToFd(content, fd));
84 TEMP_FAILURE_RETRY(close(fd));
85 return result || CleanUpAfterFailedWrite(path);
Elliott Hughes202f0242015-02-04 13:19:13 -080086}
Elliott Hughes31fa09c2015-02-04 19:38:28 -080087#endif
Elliott Hughes202f0242015-02-04 13:19:13 -080088
89bool android::WriteStringToFile(const std::string& content, const std::string& path) {
90 int fd = TEMP_FAILURE_RETRY(open(path.c_str(),
91 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
92 DEFFILEMODE));
93 if (fd == -1) {
94 return false;
95 }
Elliott Hughesf682b472015-02-06 12:19:48 -080096
97 bool result = WriteStringToFd(content, fd);
98 TEMP_FAILURE_RETRY(close(fd));
99 return result || CleanUpAfterFailedWrite(path);
Elliott Hughes202f0242015-02-04 13:19:13 -0800100}