| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/lib/util/posix_file_system.h" |
| |
| #include <dirent.h> |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| |
| #include <map> |
| #include <memory> |
| #include <sstream> |
| |
| #include "google/protobuf/io/zero_copy_stream.h" |
| #include "google/protobuf/io/zero_copy_stream_impl.h" |
| #include "src/lib/util/file_system.h" |
| |
| namespace cobalt::util { |
| |
| using lib::statusor::StatusOr; |
| |
| bool PosixFileSystem::MakeDirectory(const std::string &directory) { |
| return mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0; |
| } |
| |
| class CloseDir { |
| public: |
| void operator()(DIR *dir) { closedir(dir); } |
| }; |
| |
| StatusOr<std::vector<std::string>> PosixFileSystem::ListFiles(const std::string &directory) { |
| std::vector<std::string> files; |
| std::unique_ptr<DIR, CloseDir> dir(opendir(directory.c_str()), CloseDir()); |
| struct dirent *ent; |
| if (dir != nullptr) { |
| while ((ent = readdir(dir.get())) != nullptr) { |
| if (ent->d_name[0] == '.' && (ent->d_name[1] == '.' || ent->d_name[1] == '\0')) { |
| continue; |
| } |
| files.emplace_back(ent->d_name); |
| } |
| } else { |
| std::stringstream ss; |
| ss << "Unable to open directory [" << directory << "]: " << errno; |
| return Status(StatusCode::INTERNAL, ss.str()); |
| } |
| |
| return files; |
| } |
| |
| bool PosixFileSystem::Delete(const std::string &file) { return std::remove(file.c_str()) == 0; } |
| |
| StatusOr<size_t> PosixFileSystem::FileSize(const std::string &file) { |
| struct stat st; |
| if (stat(file.c_str(), &st) != 0) { |
| std::stringstream ss; |
| ss << "Unable to stat file [" << file << "]: " << std::strerror(errno) << "[" << errno << "]"; |
| return Status(StatusCode::INTERNAL, ss.str()); |
| } |
| return static_cast<size_t>(st.st_size); |
| } |
| |
| bool PosixFileSystem::FileExists(const std::string &file) { |
| struct stat buffer; |
| return (stat(file.c_str(), &buffer) == 0); |
| } |
| |
| bool PosixFileSystem::Rename(const std::string &from, const std::string &to) { |
| return std::rename(from.c_str(), to.c_str()) == 0; |
| } |
| |
| lib::statusor::StatusOr<FileSystem::ProtoInputStreamPtr> PosixFileSystem::NewProtoInputStream( |
| const std::string &file, int block_size) { |
| auto fs = open(file.c_str(), O_RDWR); |
| if (fs == -1) { |
| std::stringstream ss; |
| ss << "Unable to open file [" << file << "] in read mode."; |
| return Status(ErrnoToStatusCode(errno).value_or(StatusCode::DATA_LOSS), ss.str(), |
| std::strerror(errno)); |
| } |
| auto stream = std::make_unique<google::protobuf::io::FileInputStream>(fs, block_size); |
| stream->SetCloseOnDelete(true); |
| return {std::move(stream)}; |
| } |
| |
| lib::statusor::StatusOr<FileSystem::ProtoOutputStreamPtr> PosixFileSystem::NewProtoOutputStream( |
| const std::string &file, bool append, int block_size) { |
| auto flags = O_WRONLY | O_CREAT; |
| if (append) { |
| flags |= O_APPEND; |
| } |
| auto fs = open(file.c_str(), flags, S_IRUSR | S_IWUSR); |
| if (fs == -1) { |
| std::stringstream ss; |
| ss << "Unable to open file [" << file << "] in write mode."; |
| return Status(ErrnoToStatusCode(errno).value_or(StatusCode::DATA_LOSS), ss.str(), |
| std::strerror(errno)); |
| } |
| auto stream = std::make_unique<google::protobuf::io::FileOutputStream>(fs, block_size); |
| stream->SetCloseOnDelete(true); |
| return {std::move(stream)}; |
| } |
| |
| } // namespace cobalt::util |