diff options
author | Benjamin Barenblat <bbaren@mit.edu> | 2016-02-21 21:38:54 -0500 |
---|---|---|
committer | Benjamin Barenblat <bbaren@mit.edu> | 2016-02-21 21:38:54 -0500 |
commit | 878573f07cadf10fc1c32efd180409ddf854f855 (patch) | |
tree | b5b420e4e4ec823bc9fe63206e1bb8a777d51709 | |
parent | fa0cb2cf4e0b52e57f50b2b8cc25228d481abc31 (diff) |
operations: Abstract away common exception-handling
-rw-r--r-- | src/operations.cc | 316 |
1 files changed, 119 insertions, 197 deletions
diff --git a/src/operations.cc b/src/operations.cc index 4433809..e4e76b3 100644 --- a/src/operations.cc +++ b/src/operations.cc @@ -46,7 +46,7 @@ namespace { // Pointer to the directory underlying the mount point. File* root_; -mode_t DirectoryTypeToFileType(const unsigned char type) noexcept { +mode_t DirectoryTypeToFileType(const unsigned char type) { return static_cast<mode_t>(DTTOIF(type)); } @@ -61,39 +61,25 @@ void* Initialize(fuse_conn_info*) noexcept { return nullptr; } void Destroy(void*) noexcept {} -int Getattr(const char* const c_path, struct stat* output) noexcept { - try { - const std::string path(c_path); - if (path == "/") { - *output = root_->Stat(); - } else { - *output = root_->LinkStatAt(EncodePath(path).c_str()); - } - return 0; - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "getattr: caught unexpected value"; - return -ENOTRECOVERABLE; +int Getattr(const char* const c_path, struct stat* output) { + const std::string path(c_path); + if (path == "/") { + *output = root_->Stat(); + } else { + *output = root_->LinkStatAt(EncodePath(path).c_str()); } + return 0; } int Fgetattr(const char*, struct stat* const output, - struct fuse_file_info* const file_info) noexcept { - try { - *output = reinterpret_cast<File*>(file_info->fh)->Stat(); - return 0; - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "getattr: caught unexpected value"; - return -ENOTRECOVERABLE; - } + struct fuse_file_info* const file_info) { + *output = reinterpret_cast<File*>(file_info->fh)->Stat(); + return 0; } template <typename T> int OpenResource(const char* const c_path, const int flags, - uint64_t* const handle) noexcept { + uint64_t* const handle) { try { const std::string path(c_path); std::unique_ptr<T> t(new T( @@ -104,11 +90,6 @@ int OpenResource(const char* const c_path, const int flags, return 0; } catch (const std::bad_alloc&) { return -ENOMEM; - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "caught unexpected value"; - return -ENOTRECOVERABLE; } } @@ -118,206 +99,145 @@ int ReleaseResource(const uint64_t handle) noexcept { return 0; } -int Mknod(const char* const c_path, const mode_t mode, - const dev_t dev) noexcept { - try { - const std::string path(c_path); - if (path == "/") { - return -EISDIR; - } else { - root_->MkNod(EncodePath(path).c_str(), mode, dev); - return 0; - } - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "mknod: caught unexpected value"; - return -ENOTRECOVERABLE; +int Mknod(const char* const c_path, const mode_t mode, const dev_t dev) { + const std::string path(c_path); + if (path == "/") { + return -EISDIR; + } else { + root_->MkNod(EncodePath(path).c_str(), mode, dev); + return 0; } } -int Chmod(const char* const c_path, const mode_t mode) noexcept { - try { - const std::string path(c_path); - root_->ChModAt(path == "/" ? "." : EncodePath(path).c_str(), mode); - return 0; - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "getattr: caught unexpected value"; - return -ENOTRECOVERABLE; - } +int Chmod(const char* const c_path, const mode_t mode) { + const std::string path(c_path); + root_->ChModAt(path == "/" ? "." : EncodePath(path).c_str(), mode); + return 0; } -int Rename(const char* const c_old_path, - const char* const c_new_path) noexcept { - try { - const std::string old_path(c_old_path); - const std::string new_path(c_new_path); - if (old_path == "/" || new_path == "/") { - return -EINVAL; - } else { - root_->RenameAt(EncodePath(old_path).c_str(), - EncodePath(new_path).c_str()); - return 0; - } - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "mknod: caught unexpected value"; - return -ENOTRECOVERABLE; +int Rename(const char* const c_old_path, const char* const c_new_path) { + const std::string old_path(c_old_path); + const std::string new_path(c_new_path); + if (old_path == "/" || new_path == "/") { + return -EINVAL; + } else { + root_->RenameAt(EncodePath(old_path).c_str(), EncodePath(new_path).c_str()); + return 0; } } -int Open(const char* const path, fuse_file_info* const file_info) noexcept { +int Open(const char* const path, fuse_file_info* const file_info) { return OpenResource<File>(path, file_info->flags, &file_info->fh); } int Read(const char*, char* const buffer, const size_t bytes, - const off_t offset, fuse_file_info* const file_info) noexcept { - LOG(INFO) << "read with offset " << offset; - try { - auto* const file = reinterpret_cast<File*>(file_info->fh); - const std::vector<std::uint8_t> read = file->Read(offset, bytes); - std::memcpy(buffer, read.data(), read.size()); - return static_cast<int>(read.size()); - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "read: caught unexpected value"; - return -ENOTRECOVERABLE; - } + const off_t offset, fuse_file_info* const file_info) { + auto* const file = reinterpret_cast<File*>(file_info->fh); + const std::vector<std::uint8_t> read = file->Read(offset, bytes); + std::memcpy(buffer, read.data(), read.size()); + return static_cast<int>(read.size()); } int Write(const char*, const char* const buffer, const size_t bytes, - const off_t offset, fuse_file_info* const file_info) noexcept { - try { - auto* const file = reinterpret_cast<File*>(file_info->fh); - const std::vector<std::uint8_t> to_write(buffer, buffer + bytes); - file->Write(offset, to_write); - return static_cast<int>(bytes); - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "read: caught unexpected value"; - return -ENOTRECOVERABLE; - } + const off_t offset, fuse_file_info* const file_info) { + auto* const file = reinterpret_cast<File*>(file_info->fh); + const std::vector<std::uint8_t> to_write(buffer, buffer + bytes); + file->Write(offset, to_write); + return static_cast<int>(bytes); } -int Utimens(const char* const c_path, const timespec times[2]) noexcept { - try { - const std::string path(c_path); - root_->UTimeNs(path == "/" ? "." : EncodePath(path).c_str(), times[0], - times[1]); - return 0; - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "utimens: caught unexpected value"; - return -ENOTRECOVERABLE; - } +int Utimens(const char* const c_path, const timespec times[2]) { + const std::string path(c_path); + root_->UTimeNs(path == "/" ? "." : EncodePath(path).c_str(), times[0], + times[1]); + return 0; } -int Release(const char*, fuse_file_info* const file_info) noexcept { +int Release(const char*, fuse_file_info* const file_info) { return ReleaseResource<File>(file_info->fh); } -int Unlink(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_->UnlinkAt(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; +int Unlink(const char* c_path) { + const std::string path(c_path); + if (path == "/") { + // Removing the root is probably a bad idea. + return -EPERM; + } else { + root_->UnlinkAt(EncodePath(path).c_str()); + return 0; } } -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 Mkdir(const char* const c_path, const mode_t mode) { + 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; } } -int Opendir(const char* const path, fuse_file_info* const file_info) noexcept { +int Opendir(const char* const path, fuse_file_info* const file_info) { return OpenResource<Directory>(path, O_DIRECTORY, &file_info->fh); } int Readdir(const char*, void* const buffer, fuse_fill_dir_t filler, - const off_t offset, fuse_file_info* const file_info) noexcept { - try { - auto* const directory = reinterpret_cast<Directory*>(file_info->fh); + const off_t offset, fuse_file_info* const file_info) { + auto* const directory = reinterpret_cast<Directory*>(file_info->fh); - static_assert(std::is_same<off_t, long>(), - "off_t is not convertible with long"); - if (offset != directory->offset()) { - directory->Seek(offset); - } + static_assert(std::is_same<off_t, long>(), + "off_t is not convertible with long"); + if (offset != directory->offset()) { + directory->Seek(offset); + } - for (std::experimental::optional<dirent> entry = directory->ReadOne(); - entry; entry = directory->ReadOne()) { - struct stat stats; - std::memset(&stats, 0, sizeof(stats)); - stats.st_ino = entry->d_ino; - stats.st_mode = DirectoryTypeToFileType(entry->d_type); - const off_t next_offset = directory->offset(); - if (filler(buffer, entry->d_name, &stats, next_offset)) { - break; - } + for (std::experimental::optional<dirent> entry = directory->ReadOne(); entry; + entry = directory->ReadOne()) { + struct stat stats; + std::memset(&stats, 0, sizeof(stats)); + stats.st_ino = entry->d_ino; + stats.st_mode = DirectoryTypeToFileType(entry->d_type); + const off_t next_offset = directory->offset(); + if (filler(buffer, entry->d_name, &stats, next_offset)) { + break; } - } catch (const std::system_error& e) { - return -e.code().value(); - } catch (...) { - LOG(ERROR) << "readdir: caught unexpected value"; - return -ENOTRECOVERABLE; } - return 0; } -int Releasedir(const char*, fuse_file_info* const file_info) noexcept { +int Releasedir(const char*, fuse_file_info* const file_info) { return ReleaseResource<Directory>(file_info->fh); } -int Rmdir(const char* c_path) noexcept { +int Rmdir(const char* c_path) { + 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; + } +} + +template <typename Function, Function f, typename... Args> +int CatchAndReturnExceptions(Args... args) 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; - } + return f(args...); } catch (const std::system_error& e) { return -e.code().value(); } catch (...) { - LOG(ERROR) << "unlink: caught unexpected value"; + LOG(ERROR) << "caught unexpected value"; return -ENOTRECOVERABLE; } } } // namespace +#define CATCH_AND_RETURN_EXCEPTIONS(f) CatchAndReturnExceptions<decltype(f), f> + fuse_operations FuseOperations(File* const root) { root_ = root; @@ -328,29 +248,31 @@ fuse_operations FuseOperations(File* const root) { result.flag_nopath = true; result.flag_utime_omit_ok = true; - result.init = &Initialize; - result.destroy = &Destroy; + result.init = Initialize; + result.destroy = Destroy; - result.getattr = &Getattr; - result.fgetattr = &Fgetattr; + result.getattr = CATCH_AND_RETURN_EXCEPTIONS(Getattr); + result.fgetattr = CATCH_AND_RETURN_EXCEPTIONS(Fgetattr); - result.mknod = &Mknod; - result.chmod = &Chmod; - result.rename = &Rename; - result.open = &Open; - result.read = &Read; - result.write = &Write; - result.utimens = &Utimens; - result.release = &Release; - result.unlink = &Unlink; + result.mknod = CATCH_AND_RETURN_EXCEPTIONS(Mknod); + result.chmod = CATCH_AND_RETURN_EXCEPTIONS(Chmod); + result.rename = CATCH_AND_RETURN_EXCEPTIONS(Rename); + result.open = CATCH_AND_RETURN_EXCEPTIONS(Open); + result.read = CATCH_AND_RETURN_EXCEPTIONS(Read); + result.write = CATCH_AND_RETURN_EXCEPTIONS(Write); + result.utimens = CATCH_AND_RETURN_EXCEPTIONS(Utimens); + result.release = CATCH_AND_RETURN_EXCEPTIONS(Release); + result.unlink = CATCH_AND_RETURN_EXCEPTIONS(Unlink); - result.mkdir = &Mkdir; - result.opendir = &Opendir; - result.readdir = &Readdir; - result.releasedir = &Releasedir; - result.rmdir = &Rmdir; + result.mkdir = CATCH_AND_RETURN_EXCEPTIONS(Mkdir); + result.opendir = CATCH_AND_RETURN_EXCEPTIONS(Opendir); + result.readdir = CATCH_AND_RETURN_EXCEPTIONS(Readdir); + result.releasedir = CATCH_AND_RETURN_EXCEPTIONS(Releasedir); + result.rmdir = CATCH_AND_RETURN_EXCEPTIONS(Rmdir); return result; } +#undef CATCH_AND_RETURN_EXCEPTIONS + } // namespace scoville |