|
|
|
@ -137,13 +137,16 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_create_op) {
|
|
|
|
|
if ((res = check_access(api_path, W_OK)) == api_error::item_not_found) {
|
|
|
|
|
res = check_access(api_path, W_OK);
|
|
|
|
|
if (res == api_error::item_not_found) {
|
|
|
|
|
res = check_parent_access(api_path, W_OK);
|
|
|
|
|
}
|
|
|
|
|
} else if ((res = check_access(api_path, R_OK)) ==
|
|
|
|
|
api_error::item_not_found) {
|
|
|
|
|
} else {
|
|
|
|
|
res = check_access(api_path, R_OK);
|
|
|
|
|
if (res == api_error::item_not_found) {
|
|
|
|
|
res = check_parent_access(api_path, R_OK);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
@ -202,19 +205,24 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|
|
|
|
if ((res != api_error::item_exists) && (res != api_error::success)) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
} else if (((res = fm_->open(api_path, is_directory_op, file_info->flags,
|
|
|
|
|
handle, open_file)) != api_error::success)) {
|
|
|
|
|
} else {
|
|
|
|
|
res = fm_->open(api_path, is_directory_op, file_info->flags, handle,
|
|
|
|
|
open_file);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file_info->fh = handle;
|
|
|
|
|
if (is_truncate_op) {
|
|
|
|
|
#if FUSE_USE_VERSION >= 30
|
|
|
|
|
if ((res = truncate_impl(api_path, 0, file_info)) != api_error::success) {
|
|
|
|
|
#else
|
|
|
|
|
if ((res = ftruncate_impl(api_path, 0, file_info)) != api_error::success) {
|
|
|
|
|
#endif
|
|
|
|
|
res = truncate_impl(api_path, 0, file_info);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
#else // FUSE_USE_VERSION < 30
|
|
|
|
|
res = ftruncate_impl(api_path, 0, file_info);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
#endif // FUSE_USE_VERSION >= 30
|
|
|
|
|
fm_->close(handle);
|
|
|
|
|
file_info->fh = 0U;
|
|
|
|
|
errno = std::abs(utils::from_api_error(res));
|
|
|
|
@ -283,9 +291,9 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_open_flags(
|
|
|
|
|
open_file->get_open_data(file_info->fh), O_WRONLY | O_APPEND,
|
|
|
|
|
api_error::invalid_handle)) != api_error::success) {
|
|
|
|
|
res = check_open_flags(open_file->get_open_data(file_info->fh),
|
|
|
|
|
O_WRONLY | O_APPEND, api_error::invalid_handle);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -329,7 +337,7 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
|
|
|
|
static_cast<std::uint64_t>(offset + length), allocator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
|
|
|
|
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *unix_st,
|
|
|
|
|
struct fuse_file_info *file_info) -> api_error {
|
|
|
|
|
std::shared_ptr<i_open_file> open_file;
|
|
|
|
|
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
|
|
|
@ -348,7 +356,7 @@ auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta,
|
|
|
|
|
directory, provider_, st);
|
|
|
|
|
directory, provider_, unix_st);
|
|
|
|
|
|
|
|
|
|
return api_error::success;
|
|
|
|
|
}
|
|
|
|
@ -456,12 +464,12 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if FUSE_USE_VERSION >= 30
|
|
|
|
|
auto fuse_drive::getattr_impl(std::string api_path, struct stat *st,
|
|
|
|
|
auto fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
|
|
|
|
|
struct fuse_file_info * /*file_info*/)
|
|
|
|
|
-> api_error {
|
|
|
|
|
#else
|
|
|
|
|
auto fuse_drive::getattr_impl(std::string api_path,
|
|
|
|
|
struct stat *st) -> api_error {
|
|
|
|
|
struct stat *unix_st) -> api_error {
|
|
|
|
|
#endif
|
|
|
|
|
auto parent = utils::path::get_parent_api_path(api_path);
|
|
|
|
|
|
|
|
|
@ -473,16 +481,17 @@ auto fuse_drive::getattr_impl(std::string api_path,
|
|
|
|
|
auto found = false;
|
|
|
|
|
directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
|
|
|
|
|
directory_item dir_item{};
|
|
|
|
|
if ((found = (iter.get_directory_item(api_path, dir_item) ==
|
|
|
|
|
api_error::success))) {
|
|
|
|
|
found = (iter.get_directory_item(api_path, dir_item) == api_error::success);
|
|
|
|
|
if (found) {
|
|
|
|
|
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
|
|
|
|
|
dir_item.directory, provider_, st);
|
|
|
|
|
dir_item.directory, provider_, unix_st);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (not found) {
|
|
|
|
|
api_meta_map meta{};
|
|
|
|
|
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) {
|
|
|
|
|
res = provider_.get_item_meta(api_path, meta);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -493,7 +502,7 @@ auto fuse_drive::getattr_impl(std::string api_path,
|
|
|
|
|
}
|
|
|
|
|
fuse_drive_base::populate_stat(api_path,
|
|
|
|
|
utils::string::to_uint64(meta[META_SIZE]),
|
|
|
|
|
meta, directory, provider_, st);
|
|
|
|
|
meta, directory, provider_, unix_st);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return api_error::success;
|
|
|
|
@ -669,7 +678,8 @@ auto fuse_drive::opendir_impl(std::string api_path,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_parent_access(api_path, mask)) != api_error::success) {
|
|
|
|
|
res = check_parent_access(api_path, mask);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -683,8 +693,8 @@ auto fuse_drive::opendir_impl(std::string api_path,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
directory_item_list list{};
|
|
|
|
|
if ((res = provider_.get_directory_items(api_path, list)) !=
|
|
|
|
|
api_error::success) {
|
|
|
|
|
res = provider_.get_directory_items(api_path, list);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -712,7 +722,8 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
|
|
|
|
data_buffer data;
|
|
|
|
|
res =
|
|
|
|
|
open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data);
|
|
|
|
|
if ((bytes_read = data.size()) != 0U) {
|
|
|
|
|
bytes_read = data.size();
|
|
|
|
|
if (bytes_read != 0U) {
|
|
|
|
|
std::memcpy(buffer, data.data(), data.size());
|
|
|
|
|
data.clear();
|
|
|
|
|
update_accessed_time(api_path);
|
|
|
|
@ -742,13 +753,14 @@ auto fuse_drive::readdir_impl(std::string api_path, void *buf,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (res == api_error::success) {
|
|
|
|
|
res = (iter->fill_buffer(
|
|
|
|
|
res =
|
|
|
|
|
(iter->fill_buffer(
|
|
|
|
|
static_cast<remote::file_offset>(offset++), fuse_fill_dir, buf,
|
|
|
|
|
[this](const std::string &cur_api_path,
|
|
|
|
|
std::uint64_t cur_file_size, const api_meta_map &meta,
|
|
|
|
|
bool directory, struct stat *st) {
|
|
|
|
|
fuse_drive_base::populate_stat(cur_api_path, cur_file_size,
|
|
|
|
|
meta, directory, provider_, st);
|
|
|
|
|
bool directory, struct stat *unix_st) {
|
|
|
|
|
fuse_drive_base::populate_stat(cur_api_path, cur_file_size, meta,
|
|
|
|
|
directory, provider_, unix_st);
|
|
|
|
|
}) == 0)
|
|
|
|
|
? api_error::success
|
|
|
|
|
: api_error::os_error;
|
|
|
|
@ -806,8 +818,8 @@ auto fuse_drive::rename_impl(std::string from_api_path,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_parent_access(from_api_path, W_OK | X_OK)) !=
|
|
|
|
|
api_error::success) {
|
|
|
|
|
res = check_parent_access(from_api_path, W_OK | X_OK);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -834,7 +846,8 @@ auto fuse_drive::rmdir_impl(std::string api_path) -> api_error {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = provider_.remove_directory(api_path)) != api_error::success) {
|
|
|
|
|
res = provider_.remove_directory(api_path);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -859,42 +872,48 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
|
|
|
|
res = check_parent_access(api_path, X_OK);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
api_meta_map meta;
|
|
|
|
|
auto found = false;
|
|
|
|
|
auto found{false};
|
|
|
|
|
directory_cache_->execute_action(
|
|
|
|
|
utils::path::get_parent_api_path(api_path),
|
|
|
|
|
[&](directory_iterator &iterator) {
|
|
|
|
|
directory_item dir_item{};
|
|
|
|
|
if ((found = (iterator.get_directory_item(api_path, dir_item) ==
|
|
|
|
|
api_error::success))) {
|
|
|
|
|
found = (iterator.get_directory_item(api_path, dir_item) ==
|
|
|
|
|
api_error::success);
|
|
|
|
|
if (found) {
|
|
|
|
|
meta = dir_item.meta;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (found ||
|
|
|
|
|
((res = provider_.get_item_meta(api_path, meta)) == api_error::success)) {
|
|
|
|
|
res = api_error::xattr_not_found;
|
|
|
|
|
if (meta.find(attribute_name) != meta.end()) {
|
|
|
|
|
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());
|
|
|
|
|
if (size != 0U) {
|
|
|
|
|
res = api_error::xattr_buffer_small;
|
|
|
|
|
if (size >= data.size()) {
|
|
|
|
|
memcpy(value, data.data(), data.size());
|
|
|
|
|
return api_error::success;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
res = found ? api_error::success : provider_.get_item_meta(api_path, meta);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
if (meta.find(attribute_name) == meta.end()) {
|
|
|
|
|
return api_error::xattr_not_found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto data = macaron::Base64::Decode(meta.at(attribute_name));
|
|
|
|
|
if ((position == nullptr) || (*position < data.size())) {
|
|
|
|
|
attribute_size = static_cast<int>(data.size());
|
|
|
|
|
if (size == 0U) {
|
|
|
|
|
return api_error::success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (size < data.size()) {
|
|
|
|
|
return api_error::xattr_buffer_small;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::memcpy(value, data.data(), data.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return api_error::success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
@ -923,7 +942,8 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
api_meta_map meta;
|
|
|
|
|
if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) {
|
|
|
|
|
res = provider_.get_item_meta(api_path, meta);
|
|
|
|
|
if (res == api_error::success) {
|
|
|
|
|
for (auto &&meta_item : meta) {
|
|
|
|
|
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
|
|
|
|
|
auto attribute_name = meta_item.first;
|
|
|
|
@ -1016,15 +1036,18 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
api_meta_map meta;
|
|
|
|
|
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) {
|
|
|
|
|
res = provider_.get_item_meta(api_path, meta);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
|
|
|
|
res = check_parent_access(api_path, X_OK);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_owner(meta)) != api_error::success) {
|
|
|
|
|
res = check_owner(meta);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1254,12 +1277,12 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
|
|
|
|
res = check_parent_access(api_path, X_OK);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_access(api_path, W_OK)) != api_error::success) {
|
|
|
|
|
res = check_access(api_path, W_OK);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1267,8 +1290,8 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
|
|
|
|
{
|
|
|
|
|
open_file_data ofd{O_RDWR};
|
|
|
|
|
std::shared_ptr<i_open_file> open_file;
|
|
|
|
|
if ((res = fm_->open(api_path, false, ofd, handle, open_file)) !=
|
|
|
|
|
api_error::success) {
|
|
|
|
|
res = fm_->open(api_path, false, ofd, handle, open_file);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1311,7 +1334,8 @@ auto fuse_drive::utimens_impl(std::string api_path,
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((res = check_owner(meta)) != api_error::success) {
|
|
|
|
|
res = check_owner(meta);
|
|
|
|
|
if (res != api_error::success) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|