All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Subject: [PATCH 07/11] btrfs-progs: sub list: Change the default behavior of "subvolume list" and allow non-privileged user to call it
Date: Fri, 11 May 2018 16:29:45 +0900	[thread overview]
Message-ID: <20180511072949.15269-8-misono.tomohiro@jp.fujitsu.com> (raw)
In-Reply-To: <20180511072949.15269-1-misono.tomohiro@jp.fujitsu.com>

Change the default behavior of "subvolume list" and allow non-privileged
user to call it as well.

>From this commit, by default it only lists subvolumes under the specified
path (incl. the path itself except top-level subvolume). Also, if kernel
supports new ioctls (BTRFS_IOC_GET_SUBVOL_INFO/BTRFS_IOC_GET_ROOTREF/
BTRFS_IOC_INO_LOOKUP_USER),
  - the specified path can be non-subvolume directory.
  - non-privileged user can also call it.

Note that root user can list all the subvolume in the fs with -a option
(the same behavior as before).

Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
---
 Documentation/btrfs-subvolume.asciidoc |  2 +
 cmds-subvolume.c                       | 90 +++++++++++++++++++++++++++++-----
 2 files changed, 81 insertions(+), 11 deletions(-)

diff --git a/Documentation/btrfs-subvolume.asciidoc b/Documentation/btrfs-subvolume.asciidoc
index a8c4af4b..e03d4a6e 100644
--- a/Documentation/btrfs-subvolume.asciidoc
+++ b/Documentation/btrfs-subvolume.asciidoc
@@ -92,6 +92,7 @@ The output format is similar to *subvolume list* command.
 
 *list* [options] [-G [\+|-]<value>] [-C [+|-]<value>] [--sort=rootid,gen,ogen,path] <path>::
 List the subvolumes present in the filesystem <path>.
+By default, this lists the subvolume under the specified path.
 +
 For every subvolume the following information is shown by default. +
 ID <ID> top level <ID> path <path> +
@@ -109,6 +110,7 @@ print parent ID.
 -a::::
 print all the subvolumes in the filesystem and distinguish between
 absolute and relative path with respect to the given <path>.
+This requires root privileges.
 -c::::
 print the ogeneration of the subvolume, aliases: ogen or origin generation.
 -g::::
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index 06686943..c3952172 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -1126,6 +1126,7 @@ out:
 }
 
 static struct subvol_list *btrfs_list_subvols(int fd,
+					      int is_list_all,
 					      struct btrfs_list_filter_set_v2 *filter_set)
 {
 	struct subvol_list *subvols;
@@ -1133,6 +1134,7 @@ static struct subvol_list *btrfs_list_subvols(int fd,
 	struct btrfs_util_subvolume_iterator *iter;
 	enum btrfs_util_error err;
 	int ret = -1;
+	int tree_id = 0;
 
 	subvols = malloc(sizeof(*subvols));
 	if (!subvols) {
@@ -1141,8 +1143,11 @@ static struct subvol_list *btrfs_list_subvols(int fd,
 	}
 	subvols->num = 0;
 
+	if (is_list_all)
+		tree_id = BTRFS_FS_TREE_OBJECTID;
+
 	err = btrfs_util_create_subvolume_iterator_fd(fd,
-						      BTRFS_FS_TREE_OBJECTID, 0,
+						      tree_id, 0,
 						      &iter);
 	if (err) {
 		iter = NULL;
@@ -1189,6 +1194,60 @@ static struct subvol_list *btrfs_list_subvols(int fd,
 		subvols->num++;
 	}
 
+	/*
+	 * Subvolume iterator does not include the information of the
+	 * specified path/fd. So, add it here.
+	 */
+	if (!is_list_all) {
+		uint64_t id;
+		struct listed_subvol subvol;
+
+		err = btrfs_util_is_subvolume_fd(fd);
+		if (err != BTRFS_UTIL_OK) {
+			if (err == BTRFS_UTIL_ERROR_NOT_SUBVOLUME)
+				ret = 0;
+			goto out;
+		}
+		err = btrfs_util_subvolume_id_fd(fd, &id);
+		if (err)
+			goto out;
+		if (id == BTRFS_FS_TREE_OBJECTID) {
+			/* Skip top level subvolume */
+			ret = 0;
+			goto out;
+		}
+
+		err = btrfs_util_subvolume_info_fd(fd, 0, &subvol.info);
+		if (err)
+			goto out;
+
+		subvol.path = strdup(".");
+		if (!filters_match(&subvol, filter_set)) {
+			free(subvol.path);
+		} else {
+			if (subvols->num >= capacity) {
+				struct subvol_list *new_subvols;
+				size_t new_capacity =
+					max_t(size_t, 1, capacity * 2);
+
+				new_subvols = realloc(subvols,
+					sizeof(*new_subvols) +
+					new_capacity *
+					sizeof(new_subvols->subvols[0]));
+				if (!new_subvols) {
+					error("out of memory");
+					goto out;
+				}
+
+				subvols = new_subvols;
+				capacity = new_capacity;
+			}
+
+			subvols->subvols[subvols->num] = subvol;
+			subvols->num++;
+		}
+	}
+
 	ret = 0;
 out:
 	if (iter)
@@ -1202,20 +1261,14 @@ static int btrfs_list_subvols_print_v2(int fd,
 				    struct btrfs_list_filter_set_v2 *filter_set,
 				    struct btrfs_list_comparer_set_v2 *comp_set,
 				    enum btrfs_list_layout layout,
-				    int full_path, const char *raw_prefix)
+				    int is_list_all, const char *raw_prefix)
 {
 	struct subvol_list *subvols;
 
-	/*
-	 * full_path hasn't done anything since 4f5ebb3ef553 ("Btrfs-progs: fix
-	 * to make list specified directory's subvolumes work"). See
-	 * https://www.spinics.net/lists/linux-btrfs/msg69820.html
-	 */
-
 	if (filter_set->only_deleted)
 		subvols = btrfs_list_deleted_subvols(fd, filter_set);
 	else
-		subvols = btrfs_list_subvols(fd, filter_set);
+		subvols = btrfs_list_subvols(fd, is_list_all, filter_set);
 	if (!subvols)
 		return -1;
 
@@ -1311,6 +1364,14 @@ static int btrfs_list_parse_filter_string_v2(char *opt_arg,
 	return 0;
 }
 
+static bool is_root(void)
+{
+	uid_t uid;
+
+	uid = geteuid();
+	return (uid == 0);
+}
+
 /*
  * Naming of options:
  * - uppercase for filters and sort options
@@ -1319,12 +1380,13 @@ static int btrfs_list_parse_filter_string_v2(char *opt_arg,
 static const char * const cmd_subvol_list_usage[] = {
 	"btrfs subvolume list [options] <path>",
 	"List subvolumes and snapshots in the filesystem.",
+	"By default, this only lists the subvolume under the specified path.",
 	"",
 	"Path filtering:",
 	"-o           print only subvolumes below specified path",
 	"-a           print all the subvolumes in the filesystem and",
 	"             distinguish absolute and relative path with respect",
-	"             to the given <path>",
+	"             to the given <path> (require root privileges)",
 	"",
 	"Field selection:",
 	"-p           print parent ID",
@@ -1485,6 +1547,12 @@ static int cmd_subvol_list(int argc, char **argv)
 	if (ret)
 		goto out;
 
+	if (is_list_all && !is_root()) {
+		ret = -1;
+		error("Only root can use -a option");
+		goto out;
+	}
+
 	if (is_list_all)
 		btrfs_list_setup_filter_v2(&filter_set,
 					BTRFS_LIST_FILTER_FULL_PATH,
@@ -1501,7 +1569,7 @@ static int cmd_subvol_list(int argc, char **argv)
 	btrfs_list_setup_print_column_v2(BTRFS_LIST_PATH);
 
 	ret = btrfs_list_subvols_print_v2(fd, filter_set, comparer_set,
-			layout, !is_list_all && !is_only_in_path, NULL);
+			layout, is_list_all, NULL);
 
 out:
 	close_file_or_dir(fd, dirstream);
-- 
2.14.3



  parent reply	other threads:[~2018-05-11  7:27 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-11  7:29 [PATCH 00/11] btrfs-progs: Rework of "subvolume list/show" and relax the root privileges of them Tomohiro Misono
2018-05-11  7:29 ` [PATCH 01/11] btrfs-progs: ioctl/libbtrfsutil: Add 3 definitions of new unprivileged ioctl Tomohiro Misono
2018-05-11  7:29 ` [PATCH 02/11] btrfs-progs: libbtrfsutil: Factor out btrfs_util_subvolume_info_fd() Tomohiro Misono
2018-05-11  7:29 ` [PATCH 03/11] btrfs-porgs: libbtrfsutil: Relax the privileges of util_subvolume_info() Tomohiro Misono
2018-05-11  7:29 ` [PATCH 04/11] btrfs-progs: libbtrfsuitl: Factor out btrfs_util_subvolume_iterator_next() Tomohiro Misono
2018-05-11  7:29 ` [PATCH 05/11] btrfs-progs: libbtrfsutil: Update the behavior of subvolume iterator and relax the privileges Tomohiro Misono
2018-05-11  7:29 ` [PATCH 06/11] btrfs-progs: sub list: Use libbtrfsuitl for subvolume list Tomohiro Misono
2018-05-11  7:29 ` Tomohiro Misono [this message]
2018-05-11  7:29 ` [PATCH 08/11] btrfs-progs: utils: Fallback to open without O_NOATIME flag in find_mount_root(): Tomohiro Misono
2018-05-11  7:29 ` [PATCH 09/11] btrfs-progs: sub show: Allow non-privileged user to call "subvolume show" Tomohiro Misono
2018-05-11  7:29 ` [PATCH 10/11] btrfs-progs: test: Add helper function to check if test user exists Tomohiro Misono
2018-05-11  7:29 ` [PATCH 11/11] btrfs-porgs: test: Add cli-test/009 to check subvolume list for both root and normal user Tomohiro Misono

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180511072949.15269-8-misono.tomohiro@jp.fujitsu.com \
    --to=misono.tomohiro@jp.fujitsu.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.