btrfs_subvolume_show shows the detailed information of a subvolume or snapshot.
Signed-off-by: Hu Tao <[email protected]> --- daemon/btrfs.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 9 +++ src/MAX_PROC_NR | 2 +- 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/daemon/btrfs.c b/daemon/btrfs.c index e179b57..36ba588 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -29,6 +29,7 @@ #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); @@ -813,3 +814,169 @@ do_btrfs_fsck (const char *device, int64_t superblock, int repair) return 0; } + +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, *pend, *colon; + 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; + } + + /* 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 = out; + + p = strchr (p, '\n'); + if (p) { + *p = '\0'; + p++; + } + else { + reply_with_error ("truncated output"); + return NULL; + } + + /* If the path is the btrfs root, `btrfs subvolume show' reports: + * <path> is btrfs root + */ + if (strstr(out, "is btrfs root") != NULL) { + reply_with_error ("%s is btrfs root", subvolume); + return NULL; + } + + /* The first line is the path of the subvolume. */ + if (add_string (&ret, strdup("path")) == -1) { + return NULL; + } + if (add_string (&ret, out) == -1) { + return NULL; + } + + /* Read the lines and split into "key: value". */ + while (*p) { + /* leading spaces and tabs */ + while (*p && c_isspace (*p)) p++; + + pend = strchrnul (p, '\n'); + if (*pend == '\n') { + *pend = '\0'; + pend++; + } + + if (!*p) continue; + + colon = strchr (p, ':'); + if (colon) { + *colon = '\0'; + + /* snapshot is special, see the output above */ + if (strncmp(p, "Snapshot", sizeof("Snapshot") - 1) == 0) { + char *ss = NULL; + + if (add_string (&ret, p) == -1) { + return NULL; + } + + /* each line is the path of a snapshot. */ + p = pend; + while (*p && strchr(p, ':') == NULL) { + while (*p && c_isspace (*p)) p++; + pend = strchrnul (p, '\n'); + if (*pend == '\n') { + *pend = '\0'; + pend++; + } + if (ss) { + ss = realloc(ss, strlen(ss) + strlen(p)); + strcat(ss, ","); + strcat(ss, p); + } else { + ss = strdup(p); + } + + p = pend; + } + + if (ss) { + if (add_string (&ret, ss) == -1) { + free(ss); + return NULL; + } + } + else { + if (add_string (&ret, strdup("")) == -1) { + return NULL; + } + } + + continue; + } + + do { colon++; } while (*colon && c_isspace (*colon)); + + if (add_string (&ret, p) == -1) { + return NULL; + } + if (add_string (&ret, colon) == -1) { + return NULL; + } + } + else { + if (add_string (&ret, p) == -1) { + return NULL; + } + if (add_string (&ret, "") == -1) { + return NULL; + } + } + + p = pend; + } + + if (end_stringsbuf (&ret) == -1) + return NULL; + + return ret.argv; + +} diff --git a/generator/actions.ml b/generator/actions.ml index cf96039..24d3ecc 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12014,6 +12014,15 @@ This is the internal call which implements C<guestfs_lstatnslist>." }; 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 425; + optional = Some "btrfs"; camel_name = "BTRFSSubvolumeShow"; + shortdesc = "show detailed information of the subvolume"; + longdesc = "\ +show 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 9524ef4..5e4a522 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -424 +425 -- 1.9.3 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
