blob: edafbcd60f8f742bea661706a2802a851226cc4b [file] [log] [blame]
// 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;
using util::Status;
using util::StatusCode;
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