From: Darrick J. Wong <djwong@xxxxxxxxxx> Fix the setxattr implementation to support the create and replace flags instead of performing an upsert regardless of inputs. Cc: <linux-ext4@xxxxxxxxxxxxxxx> # v1.43 Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs") Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- misc/fuse2fs.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index 40bb223d50c4fe..33f72cf08f7b3a 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -2507,7 +2507,7 @@ static int op_listxattr(const char *path, char *names, size_t len) 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; @@ -2517,6 +2517,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); @@ -2551,6 +2554,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);