diff mbox series

[v2,1/2] btrfs-progs: cmd/subvolume: fix return value when the target exists

Message ID f92666963689150f0fd732b2418c317da916781c.1704875723.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: fix the return value of "btrfs subvolume create" | expand

Commit Message

Qu Wenruo Jan. 10, 2024, 8:36 a.m. UTC
[BUG]
When try to create a subvolume where the target path already exists, the
"btrfs" comannd doesn't return error code correctly.

  # mkfs.btrfs -f $dev
  # mount $dev $mnt
  # touch $mnt/subv1
  # btrfs subvolume create $mnt/subv1
  ERROR: target path already exists: $mnt/subv1
  # echo $?
  0

[CAUSE]
The check on whether target exists is done by path_is_dir(), if it
return 0 or 1, it means there is something in that path already.

But unfortunately commit 5aa959fb3440 ("btrfs-progs: subvolume create:
accept multiple arguments") only changed the out tag, which would
directly return @ret, not updating the return value correct.

[FIX]
Make sure all error out branch has their @ret manually updated.

Fixes: 5aa959fb3440 ("btrfs-progs: subvolume create: accept multiple arguments")
Issue: #730
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 cmds/subvolume.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/cmds/subvolume.c b/cmds/subvolume.c
index 57be9eac5e56..b01d5c80f63d 100644
--- a/cmds/subvolume.c
+++ b/cmds/subvolume.c
@@ -160,12 +160,14 @@  static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
 	}
 	if (ret >= 0) {
 		error("target path already exists: %s", dst);
+		ret = -EEXIST;
 		goto out;
 	}
 
 	dupname = strdup(dst);
 	if (!dupname) {
 		error_msg(ERROR_MSG_MEMORY, "duplicating %s", dst);
+		ret = -ENOMEM;
 		goto out;
 	}
 	newname = basename(dupname);
@@ -173,18 +175,21 @@  static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
 	dupdir = strdup(dst);
 	if (!dupdir) {
 		error_msg(ERROR_MSG_MEMORY, "duplicating %s", dst);
+		ret = -ENOMEM;
 		goto out;
 	}
 	dstdir = dirname(dupdir);
 
 	if (!test_issubvolname(newname)) {
 		error("invalid subvolume name: %s", newname);
+		ret = -EINVAL;
 		goto out;
 	}
 
 	len = strlen(newname);
 	if (len > BTRFS_VOL_NAME_MAX) {
 		error("subvolume name too long: %s", newname);
+		ret = -EINVAL;
 		goto out;
 	}
 
@@ -208,6 +213,8 @@  static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
 					goto out;
 				}
 			} else if (ret <= 0) {
+				if (ret == 0)
+					ret = -EEXIST;
 				errno = ret ;
 				error("failed to check directory %s before creation: %m", p);
 				goto out;
@@ -218,8 +225,10 @@  static int create_one_subvolume(const char *dst, struct btrfs_qgroup_inherit *in
 	}
 
 	fddst = btrfs_open_dir(dstdir, &dirstream, 1);
-	if (fddst < 0)
+	if (fddst < 0) {
+		ret = fddst;
 		goto out;
+	}
 
 	pr_verbose(LOG_DEFAULT, "Create subvolume '%s/%s'\n", dstdir, newname);
 	if (inherit) {