aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-21 20:14:05 -0500
committerGravatar Benjamin Barenblat <bbaren@mit.edu>2016-02-21 20:38:12 -0500
commit90c61f66909affa269dfb396f0e5cc67f4e4de44 (patch)
treecce220e2b634edac84352ec6a104dc03cb8a0a35
parent273ed4f9042fbdb8fc4f8335638b09058bb5def0 (diff)
Implement mkdir/rmdir
-rw-r--r--src/operations.cc41
-rw-r--r--src/posix_extras.cc20
-rw-r--r--src/posix_extras.h12
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<Directory>(path, O_DIRECTORY, &file_info->fh);
}
@@ -248,6 +265,24 @@ int Releasedir(const char*, fuse_file_info* const file_info) noexcept {
return ReleaseResource<Directory>(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<std::uint8_t> 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<std::uint8_t> 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;