From 90c61f66909affa269dfb396f0e5cc67f4e4de44 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Sun, 21 Feb 2016 20:14:05 -0500 Subject: Implement mkdir/rmdir --- src/operations.cc | 41 +++++++++++++++++++++++++++++++++++++++-- src/posix_extras.cc | 20 ++++++++++++++++++++ src/posix_extras.h | 12 ++++++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/operations.cc b/src/operations.cc index b62fdf0..382974e 100644 --- a/src/operations.cc +++ b/src/operations.cc @@ -123,8 +123,7 @@ int Mknod(const char* const c_path, const mode_t mode, try { const std::string path(c_path); if (path == "/") { - // They're asking to create the mount point. Huh? - return -EEXIST; + return -EISDIR; } else { root_->MkNod(EncodePath(path).c_str(), mode, dev); return 0; @@ -208,6 +207,24 @@ int Unlink(const char* c_path) noexcept { } } +int Mkdir(const char* const c_path, const mode_t mode) noexcept { + try { + const std::string path(c_path); + if (path == "/") { + // They're asking to create the mount point. Huh? + return -EEXIST; + } else { + root_->MkDir(EncodePath(path).c_str(), mode); + return 0; + } + } catch (const std::system_error& e) { + return -e.code().value(); + } catch (...) { + LOG(ERROR) << "mknod: caught unexpected value"; + return -ENOTRECOVERABLE; + } +} + int Opendir(const char* const path, fuse_file_info* const file_info) noexcept { return OpenResource(path, O_DIRECTORY, &file_info->fh); } @@ -248,6 +265,24 @@ int Releasedir(const char*, fuse_file_info* const file_info) noexcept { return ReleaseResource(file_info->fh); } +int Rmdir(const char* c_path) noexcept { + try { + const std::string path(c_path); + if (path == "/") { + // Removing the root is probably a bad idea. + return -EPERM; + } else { + root_->RmDirAt(EncodePath(path).c_str()); + return 0; + } + } catch (const std::system_error& e) { + return -e.code().value(); + } catch (...) { + LOG(ERROR) << "unlink: caught unexpected value"; + return -ENOTRECOVERABLE; + } +} + } // namespace fuse_operations FuseOperations(File* const root) { @@ -274,9 +309,11 @@ fuse_operations FuseOperations(File* const root) { result.release = &Release; result.unlink = &Unlink; + result.mkdir = &Mkdir; result.opendir = &Opendir; result.readdir = &Readdir; result.releasedir = &Releasedir; + result.rmdir = &Rmdir; return result; } diff --git a/src/posix_extras.cc b/src/posix_extras.cc index 7b82f0a..5fc60f6 100644 --- a/src/posix_extras.cc +++ b/src/posix_extras.cc @@ -78,6 +78,16 @@ struct stat File::LinkStatAt(const char* const path) const { return result; } +void File::MkDir(const char* const path, const mode_t mode) const { + if (path[0] == '/') { + throw std::invalid_argument("absolute path"); + } + + if (mkdirat(fd_, path, mode | S_IFDIR) == -1) { + throw SystemError(); + } +} + void File::MkNod(const char* const path, const mode_t mode, const dev_t dev) const { if (path[0] == '/') { @@ -119,6 +129,16 @@ std::vector File::Read(off_t offset, size_t bytes) const { return result; } +void File::RmDirAt(const char* const path) const { + if (path[0] == '/') { + throw std::invalid_argument("absolute path"); + } + + if (unlinkat(fd_, path, AT_REMOVEDIR) == -1) { + throw SystemError(); + } +} + void File::UnlinkAt(const char* const path) const { if (path[0] == '/') { throw std::invalid_argument("absolute path"); diff --git a/src/posix_extras.h b/src/posix_extras.h index f92bff7..41117f2 100644 --- a/src/posix_extras.h +++ b/src/posix_extras.h @@ -69,8 +69,12 @@ class File { // indeed be relative (i.e., it must not start with '/'). struct stat LinkStatAt(const char* path) const; - // Creates a file or directory at the path relative to the file descriptor. - // The path must indeed be relative (i.e., it must not start with '/'). + // Creates a directory at the path relative to the file descriptor. The path + // must indeed be relative (i.e., it must not start with '/'). + void MkDir(const char* path, mode_t mode) const; + + // Creates a file at the path relative to the file descriptor. The path must + // indeed be relative (i.e., it must not start with '/'). void MkNod(const char* path, mode_t mode, dev_t dev) const; // Calls openat(2) on the path relative to the file descriptor. The path must @@ -85,6 +89,10 @@ class File { // fewer bytes are returned. std::vector Read(off_t, size_t) const; + // Removes the directory at the path relative to the file descriptor. The + // path must indeed be relative (i.e., it must not start with '/'). + void RmDirAt(const char* path) const; + // Removes the file at the path relative to the file descriptor. The path // must indeed be relative (i.e., it must not start with '/'). void UnlinkAt(const char* path) const; -- cgit v1.2.3