// Copyright 2014 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include // PATH_MAX #include #include #include #include "src/main/cpp/util/errors.h" #include "src/main/cpp/util/exit_code.h" #include "src/main/cpp/util/file.h" #include "src/main/cpp/util/strings.h" namespace blaze_util { using std::string; using std::vector; bool ReadFrom(file_handle_type handle, string *content, int max_size) { static const size_t kReadSize = 4096; // read 4K chunks content->clear(); char buf[kReadSize]; // OPT: This loop generates one spurious read on regular files. int error; while (int r = ReadFromHandle( handle, buf, max_size > 0 ? std::min(static_cast(max_size), kReadSize) : kReadSize, &error)) { if (r < 0) { if (error == ReadFileResult::INTERRUPTED || error == ReadFileResult::AGAIN) { continue; } return false; } content->append(buf, r); if (max_size > 0) { if (max_size > r) { max_size -= r; } else { break; } } } return true; } bool ReadFrom(file_handle_type handle, void *data, size_t size) { static const size_t kReadSize = 4096; // read 4K chunks size_t offset = 0; int error; while (int r = ReadFromHandle(handle, reinterpret_cast(data) + offset, std::min(kReadSize, size), &error)) { if (r < 0) { if (error == ReadFileResult::INTERRUPTED || error == ReadFileResult::AGAIN) { continue; } return false; } offset += r; if (size > static_cast(r)) { size -= r; } else { break; } } return true; } bool WriteFile(const std::string &content, const std::string &filename, unsigned int perm) { return WriteFile(content.c_str(), content.size(), filename, perm); } string Dirname(const string &path) { return SplitPath(path).first; } string Basename(const string &path) { return SplitPath(path).second; } string JoinPath(const string &path1, const string &path2) { if (path1.empty()) { // "" + "/bar" return path2; } if (path1[path1.size() - 1] == '/') { if (path2.find('/') == 0) { // foo/ + /bar return path1 + path2.substr(1); } else { // foo/ + bar return path1 + path2; } } else { if (path2.find('/') == 0) { // foo + /bar return path1 + path2; } else { // foo + bar return path1 + "/" + path2; } } } class DirectoryTreeWalker : public DirectoryEntryConsumer { public: DirectoryTreeWalker(vector *files, _ForEachDirectoryEntry walk_entries) : _files(files), _walk_entries(walk_entries) {} void Consume(const string &path, bool is_directory) override { if (is_directory) { Walk(path); } else { _files->push_back(path); } } void Walk(const string &path) { _walk_entries(path, this); } private: vector *_files; _ForEachDirectoryEntry _walk_entries; }; void GetAllFilesUnder(const string &path, vector *result) { _GetAllFilesUnder(path, result, &ForEachDirectoryEntry); } void _GetAllFilesUnder(const string &path, vector *result, _ForEachDirectoryEntry walk_entries) { DirectoryTreeWalker(result, walk_entries).Walk(path); } } // namespace blaze_util