fuse unit tests and fixes
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good

This commit is contained in:
Scott E. Graves 2024-11-10 16:53:00 -06:00
parent d7d9199f8e
commit 74546807f4
2 changed files with 104 additions and 71 deletions

View File

@ -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<i_open_file> 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<std::uint32_t>(file_info->flags);
auto osx_flags = static_cast<std::uint32_t>(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<int>(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<std::uint64_t>(stbuf->f_bsize));
stbuf->f_blocks = utils::divide_with_ceiling(
total_bytes, static_cast<std::uint64_t>(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);

View File

@ -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));