blob: 0d280acb3e07cd02246f9afb59c3da1ae98de602 [file] [log] [blame] [edit]
// Copyright 2016 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.
#ifndef SRC_STORAGE_MINFS_HOST_H_
#define SRC_STORAGE_MINFS_HOST_H_
#ifdef __Fuchsia__
#error Host-only Header
#endif
#include <dirent.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <fbl/macros.h>
#include "src/storage/minfs/bcache.h"
#define PATH_PREFIX "::"
#define PREFIX_SIZE 2
// Return "true" if the path refers to a file on the
// host machine. Otherwise, refers to a file within the
// target disk image.
static inline bool host_path(const char* path) {
if (strncmp(path, PATH_PREFIX, PREFIX_SIZE)) {
return true;
}
return false;
}
int emu_mkfs(const char* path);
int emu_mount(const char* path);
int emu_mount_bcache(std::unique_ptr<minfs::Bcache> bc);
bool emu_is_mounted();
int emu_get_used_resources(const char* path, uint64_t* out_data_size, uint64_t* out_inodes,
uint64_t* out_used_size);
int emu_open(const char* path, int flags, mode_t mode);
int emu_close(int fd);
ssize_t emu_write(int fd, const void* buf, size_t count);
ssize_t emu_pwrite(int fd, const void* buf, size_t count, off_t off);
ssize_t emu_read(int fd, void* buf, size_t count);
ssize_t emu_pread(int fd, void* buf, size_t count, off_t off);
int emu_ftruncate(int fd, off_t len);
off_t emu_lseek(int fd, off_t offset, int whence);
int emu_fstat(int fd, struct stat* s);
int emu_stat(const char* fn, struct stat* s);
int emu_mkdir(const char* path, mode_t mode);
DIR* emu_opendir(const char* name);
struct dirent* emu_readdir(DIR* dirp);
void emu_rewinddir(DIR* dirp);
int emu_closedir(DIR* dirp);
// FileWrapper is a wrapper around an open file descriptor,
// which abstracts away the "hostness" or "targetness"
// of the underlying target. Additionally, it provides
// RAII semantics to the underlying file descriptor.
class FileWrapper {
public:
constexpr FileWrapper() : hostfile_(false), fd_(0) {}
// Not copyable or movable
FileWrapper(const FileWrapper&) = delete;
FileWrapper& operator=(const FileWrapper&) = delete;
FileWrapper(FileWrapper&&) = delete;
FileWrapper& operator=(FileWrapper&&) = delete;
~FileWrapper() { Close(); }
static int Open(const char* path, int flags, mode_t mode, FileWrapper* out) {
int r;
if (host_path(path)) {
out->hostfile_ = true;
r = open(path, flags, mode);
} else {
out->hostfile_ = false;
r = emu_open(path, flags, mode);
}
if (r > 0) {
out->fd_ = r;
}
return r;
}
int Close() {
if (fd_ == 0) {
return -1;
}
int r = hostfile_ ? close(fd_) : emu_close(fd_);
fd_ = 0;
return r;
}
ssize_t Read(void* buf, size_t count) {
return hostfile_ ? read(fd_, buf, count) : emu_read(fd_, buf, count);
}
ssize_t Write(void* buf, size_t count) {
return hostfile_ ? write(fd_, buf, count) : emu_write(fd_, buf, count);
}
private:
bool hostfile_;
int fd_{};
};
// DirWrapper is a wrapper around an open directory,
// which abstracts away the "hostness" or "targetness"
// of the underlying target. Additionally, it provides
// RAII semantics to the underlying directory.
class DirWrapper {
public:
constexpr DirWrapper() : hostdir_(false), dir_(NULL) {}
// Not copyable or movable
DirWrapper(const DirWrapper&) = delete;
DirWrapper& operator=(const DirWrapper&) = delete;
DirWrapper(DirWrapper&&) = delete;
DirWrapper& operator=(DirWrapper&&) = delete;
~DirWrapper() { Close(); }
static int Make(const char* path, mode_t mode) {
return host_path(path) ? mkdir(path, mode) : emu_mkdir(path, mode);
}
static int Open(const char* path, DirWrapper* out) {
if (host_path(path)) {
out->hostdir_ = true;
out->dir_ = opendir(path);
} else {
out->hostdir_ = false;
out->dir_ = emu_opendir(path);
}
return out->dir_ == NULL ? -1 : 0;
}
int Close() { return hostdir_ ? closedir(dir_) : emu_closedir(dir_); }
struct dirent* ReadDir() {
return hostdir_ ? readdir(dir_) : emu_readdir(dir_);
}
private:
bool hostdir_;
DIR* dir_;
};
#endif // SRC_STORAGE_MINFS_HOST_H_