1dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes/*
2dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * Copyright (C) 2015 The Android Open Source Project
3dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes *
4dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * you may not use this file except in compliance with the License.
6dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * You may obtain a copy of the License at
7dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes *
8dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes *
10dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * Unless required by applicable law or agreed to in writing, software
11dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * See the License for the specific language governing permissions and
14dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes * limitations under the License.
15dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes */
16dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes
17c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert#include "base/file.h"
18dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes
19dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes#include <errno.h>
20dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes#include <fcntl.h>
21dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes#include <sys/stat.h>
22dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes#include <sys/types.h>
23dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes
24c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert#include <string>
25c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert
2676d9cad62c19eef99b61f95d3a7c256804c6ad80Dan Albert#include "base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
27c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert#define LOG_TAG "base.file"
28c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert#include "cutils/log.h"
2994d1360f7eacd52771fb7030b26aeb722a584bd5Dan Albert#include "utils/Compat.h"
30af4885a4a83ed28c3194131e80bd3b40bc03a2ccElliott Hughes
31c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertnamespace android {
32c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertnamespace base {
33c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert
34c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertbool ReadFdToString(int fd, std::string* content) {
35f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  content->clear();
36f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes
37f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  char buf[BUFSIZ];
38f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  ssize_t n;
39f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
40f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes    content->append(buf, n);
41f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  }
42f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  return (n == 0) ? true : false;
43f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes}
44f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes
45c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertbool ReadFileToString(const std::string& path, std::string* content) {
46dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  content->clear();
47dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes
48c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert  int fd =
49c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert      TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
50dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  if (fd == -1) {
51dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    return false;
52dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  }
53f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  bool result = ReadFdToString(fd, content);
5412c67f4dfe1daf975e4c3f04211008b470206526Nick Kralevich  close(fd);
55f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  return result;
56dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes}
57dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes
58c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertbool WriteStringToFd(const std::string& content, int fd) {
59dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  const char* p = content.data();
60dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  size_t left = content.size();
61dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  while (left > 0) {
62dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left));
63dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    if (n == -1) {
64dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes      return false;
65dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    }
66dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    p += n;
67dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes    left -= n;
68dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  }
69dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes  return true;
70dec12b2b71ec73483f9a2267ee5717d7eb0cdf6dElliott Hughes}
71202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes
72202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughesstatic bool CleanUpAfterFailedWrite(const std::string& path) {
73202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  // Something went wrong. Let's not leave a corrupt file lying around.
74202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  int saved_errno = errno;
75202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  unlink(path.c_str());
76202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  errno = saved_errno;
77202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  return false;
78202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes}
79202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes
8031fa09c1c611633c8c9bdc2f1466d8de47ca95e6Elliott Hughes#if !defined(_WIN32)
81c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertbool WriteStringToFile(const std::string& content, const std::string& path,
82c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert                       mode_t mode, uid_t owner, gid_t group) {
83c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert  int fd = TEMP_FAILURE_RETRY(
84c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert      open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
85c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert           mode));
86202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  if (fd == -1) {
879d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    ALOGE("android::WriteStringToFile open failed: %s", strerror(errno));
88202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes    return false;
89202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  }
90f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes
91c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert  // We do an explicit fchmod here because we assume that the caller really
92c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert  // meant what they said and doesn't want the umask-influenced mode.
939d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  if (fchmod(fd, mode) == -1) {
949d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno));
959d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    return CleanUpAfterFailedWrite(path);
969d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  }
979d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  if (fchown(fd, owner, group) == -1) {
989d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    ALOGE("android::WriteStringToFile fchown failed: %s", strerror(errno));
999d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    return CleanUpAfterFailedWrite(path);
1009d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  }
1019d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  if (!WriteStringToFd(content, fd)) {
1029d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    ALOGE("android::WriteStringToFile write failed: %s", strerror(errno));
1039d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes    return CleanUpAfterFailedWrite(path);
1049d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  }
10512c67f4dfe1daf975e4c3f04211008b470206526Nick Kralevich  close(fd);
1069d1f515ed1066d095b923c538e8ac19c73e045f4Elliott Hughes  return true;
107202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes}
10831fa09c1c611633c8c9bdc2f1466d8de47ca95e6Elliott Hughes#endif
109202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes
110c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albertbool WriteStringToFile(const std::string& content, const std::string& path) {
111c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert  int fd = TEMP_FAILURE_RETRY(
112c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert      open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
113c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert           DEFFILEMODE));
114202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  if (fd == -1) {
115202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes    return false;
116202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes  }
117f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes
118f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  bool result = WriteStringToFd(content, fd);
11912c67f4dfe1daf975e4c3f04211008b470206526Nick Kralevich  close(fd);
120f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes  return result || CleanUpAfterFailedWrite(path);
121202f024dee8a450b92b17b2a4b90d412879321bdElliott Hughes}
122c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert
12356085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughesbool ReadFully(int fd, void* data, size_t byte_count) {
12456085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  uint8_t* p = reinterpret_cast<uint8_t*>(data);
12556085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  size_t remaining = byte_count;
12656085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  while (remaining > 0) {
12756085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining));
12856085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    if (n <= 0) return false;
12956085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    p += n;
13056085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    remaining -= n;
13156085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  }
13256085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  return true;
13356085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes}
13456085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes
13556085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughesbool WriteFully(int fd, const void* data, size_t byte_count) {
13656085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
13756085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  size_t remaining = byte_count;
13856085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  while (remaining > 0) {
13956085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining));
14056085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    if (n == -1) return false;
14156085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    p += n;
14256085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes    remaining -= n;
14356085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  }
14456085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes  return true;
14556085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes}
14656085edbf8c74a3a123f08e44be6e8f294deb465Elliott Hughes
147c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert}  // namespace base
148c007bc3856a4cf86b8f610eb045f26a9dedc2894Dan Albert}  // namespace android
149