btrfs_subvolume_show shows the detailed information of a subvolume or snapshot.
Signed-off-by: Hu Tao <[email protected]> --- daemon/btrfs.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 25 +++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 220 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index bcd7a50..18722c8 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -24,11 +24,13 @@ #include <pcre.h> #include <string.h> #include <unistd.h> +#include <assert.h> #include "daemon.h" #include "actions.h" #include "optgroups.h" #include "xstrtol.h" +#include "c-ctype.h" GUESTFSD_EXT_CMD(str_btrfs, btrfs); GUESTFSD_EXT_CMD(str_btrfstune, btrfstune); @@ -821,3 +823,195 @@ do_btrfs_fsck (const char *device, int64_t superblock, int repair) return 0; } + +/* analyze_line: analyze one line contains key:value pair. + * returns the next position following \n. + */ +static char * +analyze_line (char *line, char **key, char **value) +{ + char *p = line; + char *next = NULL; + char delimiter = ':'; + char *del_pos = NULL; + + if (!line || *line == '\0') { + *key = NULL; + *value = NULL; + return NULL; + } + + next = strchr (p, '\n'); + if (next) { + *next = '\0'; + ++next; + } + + /* leading spaces and tabs */ + while (*p && c_isspace (*p)) + ++p; + + assert (key); + if (*p == delimiter) + *key = NULL; + else + *key = p; + + del_pos = strchr (p, delimiter); + if (del_pos) { + *del_pos = '\0'; + + /* leading spaces and tabs */ + do { + ++del_pos; + } while (*del_pos && c_isspace (*del_pos)); + assert (value); + *value = del_pos; + } else + *value = NULL; + + return next; +} + +char ** +do_btrfs_subvolume_show (const char *subvolume) +{ + const size_t MAX_ARGS = 64; + const char *argv[MAX_ARGS]; + size_t i = 0; + CLEANUP_FREE char *subvolume_buf = NULL; + CLEANUP_FREE char *err = NULL; + CLEANUP_FREE char *out = NULL; + char *p, *key = NULL, *value = NULL; + DECLARE_STRINGSBUF (ret); + int r; + + subvolume_buf = sysroot_path (subvolume); + if (subvolume_buf == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + ADD_ARG (argv, i, str_btrfs); + ADD_ARG (argv, i, "subvolume"); + ADD_ARG (argv, i, "show"); + ADD_ARG (argv, i, subvolume_buf); + ADD_ARG (argv, i, NULL); + + r = commandv (&out, &err, argv); + if (r == -1) { + reply_with_error ("%s: %s", subvolume, err); + return NULL; + } + + /* If the path is the btrfs root, `btrfs subvolume show' reports: + * <path> is btrfs root + */ + if (out && strstr (out, "is btrfs root") != NULL) { + reply_with_error ("%s is btrfs root", subvolume); + return NULL; + } + + /* If the path is a normal directory, `btrfs subvolume show' reports: + * ERROR: <path> is not a subvolume + */ + if (err && strstr (err, "is not a subvolume")) { + reply_with_error ("%s is not a subvolume", subvolume); + return NULL; + } + + /* Output is: + * + * / + * Name: root + * uuid: c875169e-cf4e-a04d-9959-b667dec36234 + * Parent uuid: - + * Creation time: 2014-11-13 10:13:08 + * Object ID: 256 + * Generation (Gen): 6579 + * Gen at creation: 5 + * Parent: 5 + * Top Level: 5 + * Flags: - + * Snapshot(s): + * snapshots/test1 + * snapshots/test2 + * snapshots/test3 + * + */ + p = analyze_line(out, &key, &value); + if (!p) { + reply_with_error ("truncated output: %s", out); + return NULL; + } + + /* The first line is the path of the subvolume. */ + if (key && !value) { + if (add_string (&ret, "path") == -1) + return NULL; + if (add_string (&ret, key) == -1) + return NULL; + } else { + if (add_string (&ret, key) == -1) + return NULL; + if (add_string (&ret, value) == -1) + return NULL; + } + + /* Read the lines and split into "key: value". */ + p = analyze_line(p, &key, &value); + while (key) { + /* snapshot is special, see the output above */ + if (STREQLEN (key, "Snapshot(s)", sizeof ("Snapshot(s)") - 1)) { + char *ss = NULL; + int ss_len = 0; + + if (add_string (&ret, key) == -1) + return NULL; + + p = analyze_line(p, &key, &value); + + while (key && !value) { + ss = realloc (ss, ss_len + strlen (key) + 1); + if (!ss) + return NULL; + + if (ss_len != 0) + ss[ss_len++] = ','; + + memcpy (ss + ss_len, key, strlen (key)); + ss_len += strlen (key); + ss[ss_len] = '\0'; + + p = analyze_line(p, &key, &value); + } + + if (ss) { + if (add_string_nodup (&ret, ss) == -1) { + free (ss); + return NULL; + } + } else { + if (add_string (&ret, "") == -1) + return NULL; + } + } else { + if (add_string (&ret, key ? key : "") == -1) + return NULL; + if (value && !STREQ(value, "-")) { + if (add_string (&ret, value) == -1) + return NULL; + } else { + if (add_string (&ret, "") == -1) + return NULL; + } + + p = analyze_line(p, &key, &value); + } + } + + if (end_stringsbuf (&ret) == -1) + return NULL; + + return ret.argv; +} diff --git a/generator/actions.ml b/generator/actions.ml index df1be22..cfd7472 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12047,6 +12047,31 @@ This uses the L<blockdev(8)> command." }; longdesc = "\ Get the default subvolume or snapshot of a filesystem mounted at C<mountpoint>." }; + { defaults with + name = "btrfs_subvolume_show"; + style = RHashtable "btrfssubvolumeinfo", [Pathname "subvolume"], []; + proc_nr = Some 426; + optional = Some "btrfs"; camel_name = "BTRFSSubvolumeShow"; + tests = [ + InitPartition, Always, TestLastFail ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_subvolume_show"; "/"]]), []; + InitPartition, Always, TestRun ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["btrfs_subvolume_create"; "/sub1"; "NOARG"]; + ["btrfs_subvolume_show"; "/sub1"]]), []; + InitPartition, Always, TestLastFail ( + [["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""]; + ["mount"; "/dev/sda1"; "/"]; + ["mkdir"; "/dir1"]; + ["btrfs_subvolume_show"; "/dir1"]]), []; + ]; + shortdesc = "return detailed information of the subvolume"; + longdesc = "\ +Return detailed information of the subvolume." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 5e4a522..9f51d08 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -425 +426 -- 1.9.3 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
