Add listxattr for Linux, remove xattr support for Windows

This commit is contained in:
Marcus Holland-Moritz 2023-07-01 11:30:02 +02:00
parent 6f210daf93
commit e6dc6731e7

View File

@ -788,7 +788,6 @@ int op_statfs(char const* path, native_statvfs* st) {
return -op_statfs_common(log_, userdata, st); return -op_statfs_common(log_, userdata, st);
} }
#endif #endif
#if DWARFS_FUSE_LOWLEVEL #if DWARFS_FUSE_LOWLEVEL
@ -804,33 +803,41 @@ void op_getxattr(fuse_req_t req, fuse_ino_t ino, char const* name,
int err = ENODATA; int err = ENODATA;
try { try {
std::ostringstream oss;
size_t extra_size = 0;
if (ino == FUSE_ROOT_ID) { if (ino == FUSE_ROOT_ID) {
if (name == pid_xattr) { if (name == pid_xattr) {
auto pidstr = std::to_string(::getpid()); // use to_string() to prevent locale-specific formatting
if (size > 0) { oss << std::to_string(::getpid());
fuse_reply_buf(req, pidstr.data(), pidstr.size());
} else {
fuse_reply_xattr(req, pidstr.size());
}
return;
} else if (name == perfmon_xattr) { } else if (name == perfmon_xattr) {
#if DWARFS_PERFMON_ENABLED #if DWARFS_PERFMON_ENABLED
std::ostringstream oss;
if (userdata->perfmon) { if (userdata->perfmon) {
userdata->perfmon->summarize(oss); userdata->perfmon->summarize(oss);
extra_size = 4096;
} else { } else {
oss << "performance monitor is disabled"; oss << "performance monitor is disabled\n";
} }
auto summary = oss.str();
#else #else
auto summary = std::string("no performance monitor support"); oss << "no performance monitor support\n";
#endif #endif
if (size > 0) {
fuse_reply_buf(req, summary.data(), summary.size());
} else {
fuse_reply_xattr(req, summary.size());
} }
}
auto value = oss.view();
LOG_TRACE << __func__ << ": value.size=" << value.size()
<< ", extra_size=" << extra_size;
if (!value.empty()) {
if (size == 0) {
fuse_reply_xattr(req, value.size() + extra_size);
return; return;
} else if (size >= value.size()) {
fuse_reply_buf(req, value.data(), value.size());
return;
} else {
err = ERANGE;
} }
} }
} catch (dwarfs::system_error const& e) { } catch (dwarfs::system_error const& e) {
@ -852,32 +859,51 @@ int op_getxattr(char const* path, char const* name, char* value, size_t size) {
LOG_DEBUG << __func__ << "(" << path << ", " << name << ", " << size << ")"; LOG_DEBUG << __func__ << "(" << path << ", " << name << ", " << size << ")";
int err = -ENODATA; return -ENOTSUP;
}
#endif
#if DWARFS_FUSE_LOWLEVEL
template <typename LoggerPolicy>
void op_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) {
dUSERDATA;
PERFMON_EXT_SCOPED_SECTION(*userdata, op_listxattr)
LOG_PROXY(LoggerPolicy, userdata->lgr);
LOG_DEBUG << __func__ << "(" << ino << ", " << size << ")";
int err = ERANGE;
try { try {
std::string_view pv(path); std::ostringstream oss;
if ((pv == "" || pv == "/") && name == pid_xattr) { if (ino == FUSE_ROOT_ID) {
auto pidstr = std::to_string(::_getpid()); oss << pid_xattr << '\0';
if (size == 0) { oss << perfmon_xattr << '\0';
return pidstr.size();
} else if (size < pidstr.size()) {
return -ERANGE;
} }
::strncpy_s(value, size, pidstr.data(), pidstr.size());
return pidstr.size(); auto xattrs = oss.view();
LOG_TRACE << __func__ << ": xattrs.size=" << xattrs.size();
if (size == 0) {
fuse_reply_xattr(req, xattrs.size());
return;
} else if (size >= xattrs.size()) {
fuse_reply_buf(req, xattrs.data(), xattrs.size());
return;
} }
} catch (dwarfs::system_error const& e) { } catch (dwarfs::system_error const& e) {
LOG_ERROR << e.what(); LOG_ERROR << e.what();
err = -e.get_errno(); err = e.get_errno();
} catch (std::exception const& e) { } catch (std::exception const& e) {
LOG_ERROR << e.what(); LOG_ERROR << e.what();
err = -EIO; err = EIO;
} }
return err; fuse_reply_err(req, err);
} }
#else
template <typename LoggerPolicy> template <typename LoggerPolicy>
int op_listxattr(char const* path, char* list, size_t size) { int op_listxattr(char const* path, char* list, size_t size) {
dUSERDATA; dUSERDATA;
@ -886,20 +912,11 @@ int op_listxattr(char const* path, char* list, size_t size) {
LOG_DEBUG << __func__ << "(" << path << ", " << size << ")"; LOG_DEBUG << __func__ << "(" << path << ", " << size << ")";
const std::string all_xattr = return -ENOTSUP;
std::string(pid_xattr) + '\0' + std::string(perfmon_xattr) + '\0';
if (size > 0) {
if (size < all_xattr.size()) {
return -ERANGE;
}
::memcpy(list, all_xattr.data(), all_xattr.size());
}
return all_xattr.size();
} }
#endif
#if !DWARFS_FUSE_LOWLEVEL
// XXX: Not implementing this currently crashes WinFsp when a file is renamed // XXX: Not implementing this currently crashes WinFsp when a file is renamed
template <typename LoggerPolicy> template <typename LoggerPolicy>
int op_rename(char const* from, char const* to, unsigned int flags) { int op_rename(char const* from, char const* to, unsigned int flags) {
@ -999,7 +1016,7 @@ void init_fuse_ops(struct fuse_lowlevel_ops& ops) {
ops.readdir = &op_readdir<LoggerPolicy>; ops.readdir = &op_readdir<LoggerPolicy>;
ops.statfs = &op_statfs<LoggerPolicy>; ops.statfs = &op_statfs<LoggerPolicy>;
ops.getxattr = &op_getxattr<LoggerPolicy>; ops.getxattr = &op_getxattr<LoggerPolicy>;
// ops.listxattr = &op_listxattr<LoggerPolicy>; ops.listxattr = &op_listxattr<LoggerPolicy>;
} }
#else #else
template <typename LoggerPolicy> template <typename LoggerPolicy>