| // 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_ |