From: Darrick J. Wong Date: Wed, 21 May 2025 22:36:28 +0000 (-0700) Subject: fuse2fs: support XATTR_CREATE/REPLACE in setxattr X-Git-Tag: v1.47.3-rc1~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c7fec6121e6b24732db30ac408d9c8ab4805245;p=thirdparty%2Fe2fsprogs.git fuse2fs: support XATTR_CREATE/REPLACE in setxattr Fix the setxattr implementation to support the create and replace flags instead of performing an upsert regardless of inputs. Cc: linux-ext4@vger.kernel.org # v1.43 Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs") Signed-off-by: Darrick J. Wong Link: https://lore.kernel.org/r/174786677657.1383760.12232239908991346763.stgit@frogsfrogsfrogs Signed-off-by: Theodore Ts'o --- diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index 41489281..e33a0a88 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -18,6 +18,9 @@ # include # include #endif +#ifdef HAVE_SYS_XATTR_H +#include +#endif #include #include #include @@ -2517,7 +2520,7 @@ out: static int op_setxattr(const char *path EXT2FS_ATTR((unused)), const char *key, const char *value, - size_t len, int flags EXT2FS_ATTR((unused))) + size_t len, int flags) { struct fuse_context *ctxt = fuse_get_context(); struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; @@ -2527,6 +2530,9 @@ static int op_setxattr(const char *path EXT2FS_ATTR((unused)), errcode_t err; int ret = 0; + if (flags & ~(XATTR_CREATE | XATTR_REPLACE)) + return -EOPNOTSUPP; + FUSE2FS_CHECK_CONTEXT(ff); fs = ff->fs; pthread_mutex_lock(&ff->bfl); @@ -2561,6 +2567,31 @@ static int op_setxattr(const char *path EXT2FS_ATTR((unused)), goto out2; } + if (flags & (XATTR_CREATE | XATTR_REPLACE)) { + void *buf; + size_t buflen; + + err = ext2fs_xattr_get(h, key, &buf, &buflen); + switch (err) { + case EXT2_ET_EA_KEY_NOT_FOUND: + if (flags & XATTR_REPLACE) { + ret = -ENODATA; + goto out2; + } + break; + case 0: + ext2fs_free_mem(&buf); + if (flags & XATTR_CREATE) { + ret = -EEXIST; + goto out2; + } + break; + default: + ret = translate_error(fs, ino, err); + goto out2; + } + } + err = ext2fs_xattr_set(h, key, value, len); if (err) { ret = translate_error(fs, ino, err);