From 74546807f41838f4d5442ff87377052259a2b002 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sun, 10 Nov 2024 16:53:00 -0600 Subject: [PATCH] fuse unit tests and fixes --- .../src/drives/fuse/fuse_drive.cpp | 138 +++++++++--------- .../src/fuse_drive_create_and_open_test.cpp | 37 ++++- 2 files changed, 104 insertions(+), 71 deletions(-) diff --git a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp index 878988f0..c24419ba 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp @@ -81,8 +81,8 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid, struct fuse_file_info * /*file_info*/) -> api_error { #else -auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid) - -> api_error { +auto fuse_drive::chown_impl(std::string api_path, uid_t uid, + gid_t gid) -> api_error { #endif return check_and_perform( api_path, X_OK, [&](api_meta_map &meta) -> api_error { @@ -116,18 +116,15 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode, struct fuse_file_info *file_info) -> api_error { file_info->fh = 0U; - const auto is_directory_op = - ((file_info->flags & O_DIRECTORY) == O_DIRECTORY); - const auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT); - const auto is_truncate_op = (((file_info->flags & O_TRUNC) != 0) && - (((file_info->flags & O_WRONLY) != 0) || - ((file_info->flags & O_RDWR) != 0))); + auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT); + auto is_directory_op = ((file_info->flags & O_DIRECTORY) == O_DIRECTORY); + auto is_truncate_op = ((file_info->flags & O_TRUNC) == O_TRUNC); if (((file_info->flags & O_WRONLY) != 0) || ((file_info->flags & O_RDWR) != 0)) { - const auto res = provider_.is_file_writeable(api_path) - ? api_error::success - : api_error::permission_denied; + auto res = provider_.is_file_writeable(api_path) + ? api_error::success + : api_error::permission_denied; if (res != api_error::success) { return res; } @@ -167,21 +164,26 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode, if (res != api_error::success) { return res; } + if (not(is_directory_op ? dir_exists : file_exists)) { return (is_directory_op ? api_error::directory_not_found : api_error::item_not_found); } + + if (is_truncate_op && not file_exists) { + return api_error::item_not_found; + } } std::uint64_t handle{}; { std::shared_ptr open_file; if (is_create_op) { - const auto now = utils::time::get_time_now(); + auto now = utils::time::get_time_now(); #if defined(__APPLE__) - const auto osx_flags = static_cast(file_info->flags); + auto osx_flags = static_cast(file_info->flags); #else // !defined(__APPLE__) - const auto osx_flags = 0U; + auto osx_flags = 0U; #endif // defined(__APPLE__) auto meta = create_meta_attributes( @@ -388,8 +390,8 @@ api_error fuse_drive::ftruncate_impl(std::string /*api_path*/, off_t size, return api_error::invalid_handle; } - const auto res = check_writeable(f->get_open_data(file_info->fh), - api_error::invalid_handle); + auto res = check_writeable(f->get_open_data(file_info->fh), + api_error::invalid_handle); if (res != api_error::success) { return res; } @@ -440,7 +442,7 @@ auto fuse_drive::get_item_meta(const std::string &api_path, const std::string &name, std::string &value) const -> api_error { api_meta_map meta{}; - const auto ret = get_item_meta(api_path, meta); + auto ret = get_item_meta(api_path, meta); if (ret == api_error::success) { value = meta[name]; } @@ -453,10 +455,10 @@ auto fuse_drive::getattr_impl(std::string api_path, struct stat *st, struct fuse_file_info * /*file_info*/) -> api_error { #else -auto fuse_drive::getattr_impl(std::string api_path, struct stat *st) - -> api_error { +auto fuse_drive::getattr_impl(std::string api_path, + struct stat *st) -> api_error { #endif - const auto parent = utils::path::get_parent_api_path(api_path); + auto parent = utils::path::get_parent_api_path(api_path); auto res = check_parent_access(api_path, X_OK); if (res != api_error::success) { @@ -536,8 +538,8 @@ auto fuse_drive::getxtimes_impl(std::string api_path, struct timespec *bkuptime, #endif // __APPLE__ #if FUSE_USE_VERSION >= 30 -auto fuse_drive::init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg) - -> void * { +auto fuse_drive::init_impl(struct fuse_conn_info *conn, + struct fuse_config *cfg) -> void * { #else void *fuse_drive::init_impl(struct fuse_conn_info *conn) { #endif @@ -617,7 +619,7 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error { return res; } - const auto now = utils::time::get_time_now(); + auto now = utils::time::get_time_now(); auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now, true, get_effective_gid(), "", mode, now, 0U, 0U, 0U, "", get_effective_uid(), now); @@ -656,8 +658,7 @@ auto fuse_drive::open_impl(std::string api_path, auto fuse_drive::opendir_impl(std::string api_path, struct fuse_file_info *file_info) -> api_error { - const auto mask = - (O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK; + auto mask = (O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK; auto res = check_access(api_path, mask); if (res != api_error::success) { return res; @@ -762,9 +763,8 @@ auto fuse_drive::release_impl(std::string /*api_path*/, return api_error::success; } -auto fuse_drive::releasedir_impl(std::string /*api_path*/, - struct fuse_file_info *file_info) - -> api_error { +auto fuse_drive::releasedir_impl( + std::string /*api_path*/, struct fuse_file_info *file_info) -> api_error { auto iter = directory_cache_->get_directory(file_info->fh); if (iter == nullptr) { return api_error::invalid_handle; @@ -776,15 +776,15 @@ auto fuse_drive::releasedir_impl(std::string /*api_path*/, auto fuse_drive::rename_directory(const std::string &from_api_path, const std::string &to_api_path) -> int { - const auto res = fm_->rename_directory(from_api_path, to_api_path); + auto res = fm_->rename_directory(from_api_path, to_api_path); errno = std::abs(utils::from_api_error(res)); return (res == api_error::success) ? 0 : -1; } auto fuse_drive::rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite) - -> int { - const auto res = fm_->rename_file(from_api_path, to_api_path, overwrite); + const std::string &to_api_path, + bool overwrite) -> int { + auto res = fm_->rename_file(from_api_path, to_api_path, overwrite); errno = std::abs(utils::from_api_error(res)); return (res == api_error::success) ? 0 : -1; } @@ -793,8 +793,8 @@ auto fuse_drive::rename_file(const std::string &from_api_path, auto fuse_drive::rename_impl(std::string from_api_path, std::string to_api_path, unsigned int /*flags*/) -> api_error { #else -auto fuse_drive::rename_impl(std::string from_api_path, std::string to_api_path) - -> api_error { +auto fuse_drive::rename_impl(std::string from_api_path, + std::string to_api_path) -> api_error { #endif auto res = check_parent_access(to_api_path, W_OK | X_OK); if (res != api_error::success) { @@ -874,7 +874,7 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name, ((res = provider_.get_item_meta(api_path, meta)) == api_error::success)) { res = api_error::xattr_not_found; if (meta.find(attribute_name) != meta.end()) { - const auto data = macaron::Base64::Decode(meta[attribute_name]); + auto data = macaron::Base64::Decode(meta[attribute_name]); if ((position == nullptr) || (*position < data.size())) { res = api_error::success; attribute_size = static_cast(data.size()); @@ -901,16 +901,16 @@ auto fuse_drive::getxattr_impl(std::string api_path, const char *name, } #else // __APPLE__ auto fuse_drive::getxattr_impl(std::string api_path, const char *name, - char *value, size_t size, int &attribute_size) - -> api_error { + char *value, size_t size, + int &attribute_size) -> api_error { return getxattr_common(api_path, name, value, size, attribute_size, nullptr); } #endif // __APPLE__ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, - int &required_size, bool &return_size) - -> api_error { - const auto check_size = (size == 0); + int &required_size, + bool &return_size) -> api_error { + auto check_size = (size == 0); auto res = check_parent_access(api_path, X_OK); if (res != api_error::success) { @@ -925,7 +925,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, #if defined(__APPLE__) if (attribute_name != G_KAUTH_FILESEC_XATTR) { #endif - const auto attribute_name_size = strlen(attribute_name.c_str()) + 1U; + auto attribute_name_size = strlen(attribute_name.c_str()) + 1U; if (size >= attribute_name_size) { std::memcpy(&buffer[required_size], attribute_name.data(), attribute_name_size); @@ -948,8 +948,8 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, return res; } -auto fuse_drive::removexattr_impl(std::string api_path, const char *name) - -> api_error { +auto fuse_drive::removexattr_impl(std::string api_path, + const char *name) -> api_error { std::string attribute_name; #if defined(__APPLE__) auto res = parse_xattr_parameters(name, 0, attribute_name, api_path); @@ -977,8 +977,8 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name, uint32_t position) -> api_error { #else // __APPLE__ auto fuse_drive::setxattr_impl(std::string api_path, const char *name, - const char *value, size_t size, int flags) - -> api_error { + const char *value, size_t size, + int flags) -> api_error { #endif std::string attribute_name; #if defined(__APPLE__) @@ -992,7 +992,7 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name, return res; } - const auto attribute_namespace = + auto attribute_namespace = utils::string::contains(attribute_name, ".") ? utils::string::split(attribute_name, '.', false)[0U] : ""; @@ -1053,8 +1053,8 @@ void fuse_drive::set_item_meta(const std::string &api_path, } #if defined(__APPLE__) -auto fuse_drive::setattr_x_impl(std::string api_path, struct setattr_x *attr) - -> api_error { +auto fuse_drive::setattr_x_impl(std::string api_path, + struct setattr_x *attr) -> api_error { bool exists{}; auto res = provider_.is_file(api_path, exists); if (res != api_error::success) { @@ -1108,7 +1108,7 @@ auto fuse_drive::setattr_x_impl(std::string api_path, struct setattr_x *attr) ts[0].tv_sec = attr->acctime.tv_sec; ts[0].tv_nsec = attr->acctime.tv_nsec; } else { - struct timeval tv{}; + struct timeval tv {}; gettimeofday(&tv, NULL); ts[0].tv_sec = tv.tv_sec; ts[0].tv_nsec = tv.tv_usec * 1000; @@ -1153,13 +1153,12 @@ auto fuse_drive::setattr_x_impl(std::string api_path, struct setattr_x *attr) return api_error::success; } -auto fuse_drive::setbkuptime_impl(std::string api_path, - const struct timespec *bkuptime) - -> api_error { +auto fuse_drive::setbkuptime_impl( + std::string api_path, const struct timespec *bkuptime) -> api_error { return check_and_perform( api_path, X_OK, [&](api_meta_map &meta) -> api_error { - const auto nanos = bkuptime->tv_nsec + - (bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND); + auto nanos = bkuptime->tv_nsec + + (bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND); return provider_.set_item_meta(api_path, META_BACKUP, std::to_string(nanos)); }); @@ -1169,8 +1168,8 @@ auto fuse_drive::setchgtime_impl(std::string api_path, const struct timespec *chgtime) -> api_error { return check_and_perform( api_path, X_OK, [&](api_meta_map &meta) -> api_error { - const auto nanos = chgtime->tv_nsec + - (chgtime->tv_nsec * utils::time::NANOS_PER_SECOND); + auto nanos = chgtime->tv_nsec + + (chgtime->tv_nsec * utils::time::NANOS_PER_SECOND); return provider_.set_item_meta(api_path, META_CHANGED, std::to_string(nanos)); }); @@ -1180,7 +1179,7 @@ auto fuse_drive::setcrtime_impl(std::string api_path, const struct timespec *crtime) -> api_error { return check_and_perform( api_path, X_OK, [&](api_meta_map &meta) -> api_error { - const auto nanos = + auto nanos = crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND); return provider_.set_item_meta(api_path, META_CREATION, std::to_string(nanos)); @@ -1191,15 +1190,15 @@ auto fuse_drive::setvolname_impl(const char * /*volname*/) -> api_error { return api_error::success; } -auto fuse_drive::statfs_x_impl(std::string /*api_path*/, struct statfs *stbuf) - -> api_error { +auto fuse_drive::statfs_x_impl(std::string /*api_path*/, + struct statfs *stbuf) -> api_error { if (statfs(&config_.get_cache_directory()[0], stbuf) != 0) { return api_error::os_error; } - const auto total_bytes = provider_.get_total_drive_space(); - const auto total_used = provider_.get_used_drive_space(); - const auto used_blocks = utils::divide_with_ceiling( + auto total_bytes = provider_.get_total_drive_space(); + auto total_used = provider_.get_used_drive_space(); + auto used_blocks = utils::divide_with_ceiling( total_used, static_cast(stbuf->f_bsize)); stbuf->f_blocks = utils::divide_with_ceiling( total_bytes, static_cast(stbuf->f_bsize)); @@ -1217,16 +1216,15 @@ auto fuse_drive::statfs_x_impl(std::string /*api_path*/, struct statfs *stbuf) return api_error::success; } #else // __APPLE__ -auto fuse_drive::statfs_impl(std::string /*api_path*/, struct statvfs *stbuf) - -> api_error { +auto fuse_drive::statfs_impl(std::string /*api_path*/, + struct statvfs *stbuf) -> api_error { if (statvfs(config_.get_cache_directory().data(), stbuf) != 0) { return api_error::os_error; } - const auto total_bytes = provider_.get_total_drive_space(); - const auto total_used = provider_.get_used_drive_space(); - const auto used_blocks = - utils::divide_with_ceiling(total_used, stbuf->f_frsize); + auto total_bytes = provider_.get_total_drive_space(); + auto total_used = provider_.get_used_drive_space(); + auto used_blocks = utils::divide_with_ceiling(total_used, stbuf->f_frsize); stbuf->f_files = 4294967295; stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize); stbuf->f_bavail = stbuf->f_bfree = @@ -1299,8 +1297,8 @@ auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2], struct fuse_file_info * /*file_info*/) -> api_error { #else -auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2]) - -> api_error { +auto fuse_drive::utimens_impl(std::string api_path, + const struct timespec tv[2]) -> api_error { #endif api_meta_map meta; auto res = provider_.get_item_meta(api_path, meta); diff --git a/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp b/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp index a90a442c..3788c699 100644 --- a/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp @@ -71,7 +71,42 @@ TYPED_TEST(fuse_test, create_can_create_file) { this->unlink_file_and_test(file_path); } -TYPED_TEST(fuse_test, create_can_create_and_truncate_file) { +TYPED_TEST(fuse_test, create_can_create_with_truncate_file) { + std::string file_name{"create_test"}; + auto file_path = this->create_file_path(file_name); + + auto handle = open(file_path.c_str(), O_CREAT | O_TRUNC, ACCESSPERMS); + EXPECT_LE(1, handle); + close(handle); + + auto size = utils::file::file{file_path}.size(); + EXPECT_TRUE(size.has_value()); + EXPECT_EQ(0U, *size); + + this->unlink_file_and_test(file_path); +} + +TYPED_TEST(fuse_test, create_can_create_or_open_and_truncate_existing_file) { + std::string file_name{"create_test"}; + auto file_path = this->create_file_and_test(file_name); + EXPECT_EQ(0, truncate(file_path.c_str(), 24U)); + + auto size = utils::file::file{file_path}.size(); + EXPECT_TRUE(size.has_value()); + EXPECT_EQ(24U, *size); + + auto handle = open(file_path.c_str(), O_CREAT | O_TRUNC, ACCESSPERMS); + EXPECT_LE(1, handle); + close(handle); + + size = utils::file::file{file_path}.size(); + EXPECT_TRUE(size.has_value()); + EXPECT_EQ(0U, *size); + + this->unlink_file_and_test(file_path); +} + +TYPED_TEST(fuse_test, create_can_open_and_truncate_existing_file) { std::string file_name{"create_test"}; auto file_path = this->create_file_and_test(file_name); EXPECT_EQ(0, truncate(file_path.c_str(), 24U));