14a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley/*
24a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * Copyright (C) 2015, The Android Open Source Project
34a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley *
44a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * Licensed under the Apache License, Version 2.0 (the "License");
54a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * you may not use this file except in compliance with the License.
64a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * You may obtain a copy of the License at
74a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley *
84a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley *     http://www.apache.org/licenses/LICENSE-2.0
94a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley *
104a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * Unless required by applicable law or agreed to in writing, software
114a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * distributed under the License is distributed on an "AS IS" BASIS,
124a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * See the License for the specific language governing permissions and
144a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley * limitations under the License.
154a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley */
164a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
174a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley#include "io_delegate.h"
184a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
19054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include <cstring>
204a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley#include <fstream>
21054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include <vector>
22054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
23054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#ifdef _WIN32
24054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include <direct.h>
25054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#else
26054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include <sys/stat.h>
279d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley#include <unistd.h>
28054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#endif
29054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
300a62067f35e957493bc37c4b42dfdcfc16353831Elliott Hughes#include <android-base/strings.h>
316453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
32054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include "logging.h"
33054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include "os.h"
344a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
354a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wileyusing std::string;
364a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wileyusing std::unique_ptr;
37054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wileyusing std::vector;
384a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
396453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlinusing android::base::Split;
406453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
414a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wileynamespace android {
424a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wileynamespace aidl {
434a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
448decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wileybool IoDelegate::GetAbsolutePath(const string& path, string* absolute_path) {
458decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley#ifdef _WIN32
468decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
478decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  char buf[4096];
488decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  DWORD path_len = GetFullPathName(path.c_str(), sizeof(buf), buf, nullptr);
498decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (path_len <= 0 || path_len >= sizeof(buf)) {
508decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    LOG(ERROR) << "Failed to GetFullPathName(" << path << ")";
518decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    return false;
528decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  }
538decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  *absolute_path = buf;
548decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
558decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  return true;
568decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
578decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley#else
588decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
598decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (path.empty()) {
608decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    LOG(ERROR) << "Giving up on finding an absolute path to represent the "
618decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley                  "empty string.";
628decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    return false;
638decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  }
648decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (path[0] == OS_PATH_SEPARATOR) {
658decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    *absolute_path = path;
668decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    return true;
678decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  }
688decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
698decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  char buf[4096];
708decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (getcwd(buf, sizeof(buf)) == nullptr) {
718decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    LOG(ERROR) << "Path of current working directory does not fit in "
728decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley               << sizeof(buf) << " bytes";
738decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    return false;
748decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  }
758decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
768decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  *absolute_path = buf;
778decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  *absolute_path += OS_PATH_SEPARATOR;
788decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  *absolute_path += path;
798decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  return true;
808decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley#endif
818decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley}
828decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
834a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wileyunique_ptr<string> IoDelegate::GetFileContents(
844a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley    const string& filename,
854a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley    const string& content_suffix) const {
864a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  unique_ptr<string> contents;
874a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  std::ifstream in(filename, std::ios::in | std::ios::binary);
884a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  if (!in) {
894a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley    return contents;
904a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  }
914a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  contents.reset(new string);
924a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  in.seekg(0, std::ios::end);
934a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  ssize_t file_size = in.tellg();
944a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  contents->resize(file_size + content_suffix.length());
954a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  in.seekg(0, std::ios::beg);
964a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  // Read the file contents into the beginning of the string
974a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  in.read(&(*contents)[0], file_size);
984a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  // Drop the suffix in at the end.
994a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  contents->replace(file_size, content_suffix.length(), content_suffix);
1004a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  in.close();
1014a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
1024a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley  return contents;
1034a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley}
1044a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley
105ef1409302aa97b1807e55c63588ac0a428f41a06Christopher Wileyunique_ptr<LineReader> IoDelegate::GetLineReader(
106ef1409302aa97b1807e55c63588ac0a428f41a06Christopher Wiley    const string& file_path) const {
107ef1409302aa97b1807e55c63588ac0a428f41a06Christopher Wiley  return LineReader::ReadFromFile(file_path);
108ef1409302aa97b1807e55c63588ac0a428f41a06Christopher Wiley}
109ef1409302aa97b1807e55c63588ac0a428f41a06Christopher Wiley
11072877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wileybool IoDelegate::FileIsReadable(const string& path) const {
11172877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley#ifdef _WIN32
11272877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley  // check that the file exists and is not write-only
11372877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley  return (0 == _access(path.c_str(), 0)) &&  // mode 0=exist
11472877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley         (0 == _access(path.c_str(), 4));    // mode 4=readable
11572877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley#else
11672877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley  return (0 == access(path.c_str(), R_OK));
11772877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley#endif
11872877acd3b57462fcd452bff4a9d7ff936936a8eChristopher Wiley}
119054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
120054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wileybool IoDelegate::CreatedNestedDirs(
121054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    const string& caller_base_dir,
122054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    const vector<string>& nested_subdirs) const {
123054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  string base_dir = caller_base_dir;
124054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (base_dir.empty()) {
125054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    base_dir = ".";
126054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
127054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  for (const string& subdir : nested_subdirs) {
128054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    if (base_dir[base_dir.size() - 1] != OS_PATH_SEPARATOR) {
129054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      base_dir += OS_PATH_SEPARATOR;
130054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    }
131054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    base_dir += subdir;
132054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    bool success;
133054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#ifdef _WIN32
134054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    success = _mkdir(base_dir.c_str()) == 0;
135054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#else
136054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    success = mkdir(base_dir.c_str(),
137054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                    S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0;
138054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#endif
1393badcdead366eb89cadd28e84f06e37067e62c99Christopher Wiley    // On darwin when you try to mkdir("/", ...) we get EISDIR.
1403badcdead366eb89cadd28e84f06e37067e62c99Christopher Wiley    if (!success && (errno != EEXIST && errno != EISDIR)) {
141d669de90be1ba7e601fcd83092a0e9ca5effa178Dan Albert      LOG(ERROR) << "Error while creating " << base_dir << ": "
142d669de90be1ba7e601fcd83092a0e9ca5effa178Dan Albert                 << strerror(errno);
143d669de90be1ba7e601fcd83092a0e9ca5effa178Dan Albert      return false;
144054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    }
145054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
146054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  return true;
147054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley}
148054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
1496453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlinbool IoDelegate::CreatePathForFile(const string& path) const {
1506453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin  if (path.empty()) {
1516453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin    return true;
1526453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin  }
1536453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
1548decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  string absolute_path;
1558decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (!GetAbsolutePath(path, &absolute_path)) {
1568decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley    return false;
1578decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  }
1588decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
1598decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  auto directories = Split(absolute_path, string{1u, OS_PATH_SEPARATOR});
1608decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley
1618decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  // The "base" directory is just the root of the file system.  On Windows,
1628decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  // this will look like "C:\" but on Unix style file systems we get an empty
1638decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  // string after splitting "/foo" with "/"
1648decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  string base = directories[0];
1658decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  if (base.empty()) {
1666453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin    base = "/";
1676453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin  }
1688decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  directories.erase(directories.begin());
1696453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
1708decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  // Remove the actual file in question, we're just creating the directory path.
1718decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  directories.pop_back();
1726453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
1738decf95ffeffcc8aa14aa743ae398bc38d54b0acChristopher Wiley  return CreatedNestedDirs(base, directories);
1746453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin}
1756453351b3ee9ce9b91650a8175464a6e339130c7Casey Dahlin
176054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wileyunique_ptr<CodeWriter> IoDelegate::GetCodeWriter(
177054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    const string& file_path) const {
178054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  return GetFileWriter(file_path);
179054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley}
180054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
1819d6e0b29add607669e440085f1fc60cd434dc987Christopher Wileyvoid IoDelegate::RemovePath(const std::string& file_path) const {
1829d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley#ifdef _WIN32
1839d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  _unlink(file_path.c_str());
1849d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley#else
1859d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  unlink(file_path.c_str());
1869d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley#endif
1879d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley}
1889d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley
1894a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley}  // namespace android
1904a2884b0e9414ed9dfee4e141e8bd462c07b442bChristopher Wiley}  // namespace aidl
191