Add xfs_info to show the geometry of the xfs filesystem. Signed-off-by: Wanlong Gao <gaowanlong at cn.fujitsu.com> --- Hi Rich, I got an odd error, can you help me with this error or give me a debug method? Thanks, Wanlong Gao daemon/Makefile.am | 1 + daemon/xfs.c | 278 +++++++++++++++++++++++++++++++ generator/generator_actions.ml | 8 + generator/generator_structs.ml | 30 ++++ gobject/Makefile.inc | 2 + java/Makefile.inc | 1 + java/com/redhat/et/libguestfs/.gitignore | 1 + po/POTFILES | 3 + src/MAX_PROC_NR | 2 +- 9 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 daemon/xfs.c diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 9e2a633..afe8874 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -165,6 +165,7 @@ guestfsd_SOURCES = \ utimens.c \ wc.c \ xattr.c \ + xfs.c \ zero.c \ zerofree.c guestfsd_LDADD = \ diff --git a/daemon/xfs.c b/daemon/xfs.c new file mode 100644 index 0000000..b328d09 --- /dev/null +++ b/daemon/xfs.c @@ -0,0 +1,278 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2012 Fujitsu Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "c-ctype.h" +#include "actions.h" + +int +optgroup_xfs_available (void) +{ + return prog_exists ("mkfs.xfs"); +} + +static char * +split_strdup (char *string) +{ + char *end = string; + while (*end != ' ' && *end != ',') end++; + size_t len = end - string; + char *ret = malloc (len + 1); + if (!ret) { + reply_with_perror ("malloc"); + return NULL; + } + strncpy (ret, string, len); + ret[len] = '\0'; + fprintf(stderr, "%s\n", ret); + return ret; +} + +static int +parse_uint32 (uint32_t *ret, const char *str) +{ + uint32_t r; + + if (sscanf (str, "%" SCNu32, &r) != 1) { + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); + return -1; + } + + *ret = r; + return 0; +} + +static int +parse_uint64 (uint64_t *ret, const char *str) +{ + uint64_t r; + + if (sscanf (str, "%" SCNu64, &r) != 1) { + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); + return -1; + } + + *ret = r; + return 0; +} + +static guestfs_int_xfsinfo * +parse_xfs_info (char **lines) +{ + guestfs_int_xfsinfo *ret; + char *buf, *p; + size_t i; + + ret = calloc (1, sizeof *ret); + if (ret == NULL) { + reply_with_error ("calloc"); + return NULL; + } + + for (i = 0; lines[i] != NULL; ++i) { + if (p = strstr (lines[i], "meta-data=")) { + ret->mntpoint = split_strdup (p + 10); + if (ret->mntpoint == NULL) goto error; + } else if (p = strstr (lines[i], "isize=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->inodesize, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "agcount=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->agcount, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "agsize=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->agsize, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "sectsz=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (i == 1) + if (parse_uint32 (&ret->sectsize, buf) == -1) + goto error; + else if (i == 6) + if (parse_uint32 (&ret->logsectsize, buf) == -1) + goto error; + else goto error; + } else if (p = strstr (lines[i], "attr=")) { + buf = split_strdup (p + 5); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->attr, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "bsize=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (i == 2) + if (parse_uint32 (&ret->blocksize, buf) == -1) + goto error; + else if (i == 4) + if (parse_uint32 (&ret->dirblocksize, buf) == -1) + goto error; + else if (i == 5) + if (parse_uint32 (&ret->logblocksize, buf) == -1) + goto error; + else goto error; + } else if (p = strstr (lines[i], "blocks=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (i == 2) + if (parse_uint64 (&ret->datablocks, buf) == -1) + goto error; + else if (i == 5) + if (parse_uint32 (&ret->logblocks, buf) == -1) + goto error; + else if (i == 7) + if (parse_uint64 (&ret->rtblocks, buf) == -1) + goto error; + else goto error; + } else if (p = strstr (lines[i], "imaxpct=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->imaxpct, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "sunit=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (i == 3) + if (parse_uint32 (&ret->sunit, buf) == -1) + goto error; + else if (i == 6) + if (parse_uint32 (&ret->logsunit, buf) == -1) + goto error; + else goto error; + } else if (p = strstr (lines[i], "swidth=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->swidth, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "naming =version ")) { + buf = split_strdup (p + 18); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->dirversion, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "ascii-ci=")) { + buf = split_strdup (p + 9); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->cimode, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "log =")) { + ret->logname = split_strdup (p + 10); + if (ret->logname == NULL) goto error; + } else if (p = strstr (lines[i], "version=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->logversion, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "lazy-count=")) { + buf = split_strdup (p + 11); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->lazycount, buf) == -1) + goto error; + } else if (p = strstr (lines[i], "realtime =")) { + ret->rtname = split_strdup (p + 10); + if (ret->rtname == NULL) goto error; + } else if (p = strstr (lines[i], "rtextents=")) { + buf = split_strdup (p + 10); + if (buf == NULL) goto error; + if (parse_uint64 (&ret->rtextents, buf) == -1) + goto error; + } + + free (buf); + } + + if (ret->mntpoint == NULL) { + ret->mntpoint = strdup (""); + if (ret->mntpoint == NULL) goto error; + } + if (ret->logname == NULL) { + ret->logname = strdup (""); + if (ret->logname == NULL) goto error; + } + if (ret->rtname == NULL) { + ret->rtname = strdup (""); + if (ret->rtname == NULL) goto error; + } + + return ret; + +error: + free (buf); + free (ret->mntpoint); + free (ret->logname); + free (ret->rtname); + free (ret); + return NULL; +} + +guestfs_int_xfsinfo * +do_xfs_info (const char *path) +{ + int r; + char *buf; + char *out = NULL, *err = NULL; + char **lines = NULL; + guestfs_int_xfsinfo *ret = NULL; + + if (do_is_dir (path)) { + buf = sysroot_path (path); + if (!buf) { + reply_with_perror ("malloc"); + return NULL; + } + } else { + buf = strdup(path); + if (!buf) { + reply_with_perror ("strdup"); + return NULL; + } + } + + r = command (&out, &err, "xfs_info", buf, NULL); + free (buf); + if (r == -1) { + reply_with_error ("%s", err); + goto error; + } + + lines = split_lines (out); + if (lines == NULL) + goto error; + + ret = parse_xfs_info (lines); + +error: + free (err); + free (out); + if (lines) + free_strings (lines); + return ret; +} diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index c83bf70..dd9ea03 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -8995,6 +8995,14 @@ be returned if you called C<guestfs_list_devices>. To find out the maximum number of devices that could be added, call C<guestfs_max_disks>." }; + { defaults with + name = "xfs_info"; + style = RStruct ("info", "xfsinfo"), [Pathname "path"], []; + proc_nr = Some 337; + shortdesc = "get geometry of XFS filesystem"; + longdesc = "\ +This functions can print out the geometry of a mounted XFS filesystem." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/generator/generator_structs.ml b/generator/generator_structs.ml index 024bb3c..3dded35 100644 --- a/generator/generator_structs.ml +++ b/generator/generator_structs.ml @@ -213,6 +213,35 @@ let structs = [ "iso_volume_effective_t", FInt64; ]; + (* XFS info descriptor. *) + "xfsinfo", [ + "mntpoint", FString; + "inodesize", FUInt32; + "agcount", FUInt32; + "agsize", FUInt32; + "sectsize", FUInt32; + "attr", FUInt32; + "blocksize", FUInt32; + "datablocks", FUInt64; + "imaxpct", FUInt32; + "sunit", FUInt32; + "swidth", FUInt32; + "dirversion", FUInt32; + "dirblocksize", FUInt32; + "cimode", FInt32; + "logname", FString; + "logblocksize", FUInt32; + "logblocks", FUInt32; + "logversion", FUInt32; + "logsectsize", FUInt32; + "logsunit", FUInt32; + "lazycount", FUInt32; + "rtname", FString; + "rtextsize", FUInt32; + "rtblocks", FUInt64; + "rtextents", FUInt64; + ]; + (* /proc/mdstat information. See linux.git/drivers/md/md.c *) "mdstat", [ "mdstat_device", FString; @@ -243,6 +272,7 @@ let camel_structs = [ "partition", "Partition"; "application", "Application"; "isoinfo", "ISOInfo"; + "xfsinfo", "XFSInfo"; "mdstat", "MDStat"; "btrfssubvolume", "BTRFSSubvolume"; ] diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index e84236d..d70e106 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -36,6 +36,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/struct-partition.h \ include/guestfs-gobject/struct-application.h \ include/guestfs-gobject/struct-isoinfo.h \ + include/guestfs-gobject/struct-xfsinfo.h \ include/guestfs-gobject/struct-mdstat.h \ include/guestfs-gobject/struct-btrfssubvolume.h \ include/guestfs-gobject/optargs-internal_test.h \ @@ -80,6 +81,7 @@ guestfs_gobject_sources= \ src/struct-partition.c \ src/struct-application.c \ src/struct-isoinfo.c \ + src/struct-xfsinfo.c \ src/struct-mdstat.c \ src/struct-btrfssubvolume.c \ src/optargs-internal_test.c \ diff --git a/java/Makefile.inc b/java/Makefile.inc index efad2a0..da8de49 100644 --- a/java/Makefile.inc +++ b/java/Makefile.inc @@ -35,4 +35,5 @@ java_built_sources = \ com/redhat/et/libguestfs/VG.java \ com/redhat/et/libguestfs/Version.java \ com/redhat/et/libguestfs/XAttr.java \ + com/redhat/et/libguestfs/XFSInfo.java \ com/redhat/et/libguestfs/GuestFS.java diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore index 9556d81..1034665 100644 --- a/java/com/redhat/et/libguestfs/.gitignore +++ b/java/com/redhat/et/libguestfs/.gitignore @@ -13,3 +13,4 @@ StatVFS.java VG.java Version.java XAttr.java +XFSInfo.java diff --git a/po/POTFILES b/po/POTFILES index 6c819d3..017f5bd 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -84,6 +84,7 @@ daemon/upload.c daemon/utimens.c daemon/wc.c daemon/xattr.c +daemon/xfs.c daemon/zero.c daemon/zerofree.c df/df.c @@ -155,6 +156,7 @@ gobject/src/optargs-ntfsclone_out.c gobject/src/optargs-ntfsfix.c gobject/src/optargs-ntfsresize_opts.c gobject/src/optargs-set_e2attrs.c +gobject/src/optargs-test0.c gobject/src/optargs-tune2fs.c gobject/src/optargs-umount_local.c gobject/src/session.c @@ -173,6 +175,7 @@ gobject/src/struct-stat.c gobject/src/struct-statvfs.c gobject/src/struct-version.c gobject/src/struct-xattr.c +gobject/src/struct-xfsinfo.c gobject/src/tristate.c inspector/virt-inspector.c java/com_redhat_et_libguestfs_GuestFS.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index e64f24d..f59a90f 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -336 +337 -- 1.7.11.1.165.g299666c
Richard W.M. Jones
2012-Jul-16 09:15 UTC
[Libguestfs] [PATCH V4] NEW API: add new api xfs_info
On Mon, Jul 16, 2012 at 05:05:39PM +0800, Wanlong Gao wrote:> Add xfs_info to show the geometry of the xfs filesystem. > > Signed-off-by: Wanlong Gao <gaowanlong at cn.fujitsu.com> > > Hi Rich, > I got an odd error, can you help me with this error > or give me a debug method?I think in general the patch is looking good. Is does however really need a test, and it should be possible to add one using something like this (untested): tests = [ InitEmpty, IfAvailable "xfs", TestOutputStruct ( [["part_disk"; "/dev/sda"; "mbr"]; ["mkfs"; "xfs"; "/dev/sda1"; ""; "NOARG"; ""; ""]; ["mount_options"; ""; "/dev/sda1"; "/"]; ["xfs_info"; "/"]], [CompareWithInt ("blocksize", 4096); (* other comparisons here if you want *) ]); ] (NB This requires the mkfs-opts -> mkfs patch that I posted on the mailing list on Saturday, but which is not upstream) What is the odd error that you are seeing? For debugging, just print stuff out, as you are doing, and then run the program using LIBGUESTFS_DEBUG=1. Rich.> Thanks, > Wanlong Gao > > > daemon/Makefile.am | 1 + > daemon/xfs.c | 278 +++++++++++++++++++++++++++++++ > generator/generator_actions.ml | 8 + > generator/generator_structs.ml | 30 ++++ > gobject/Makefile.inc | 2 + > java/Makefile.inc | 1 + > java/com/redhat/et/libguestfs/.gitignore | 1 + > po/POTFILES | 3 + > src/MAX_PROC_NR | 2 +- > 9 files changed, 325 insertions(+), 1 deletion(-) > create mode 100644 daemon/xfs.c > > diff --git a/daemon/Makefile.am b/daemon/Makefile.am > index 9e2a633..afe8874 100644 > --- a/daemon/Makefile.am > +++ b/daemon/Makefile.am > @@ -165,6 +165,7 @@ guestfsd_SOURCES = \ > utimens.c \ > wc.c \ > xattr.c \ > + xfs.c \ > zero.c \ > zerofree.c > guestfsd_LDADD = \ > diff --git a/daemon/xfs.c b/daemon/xfs.c > new file mode 100644 > index 0000000..b328d09 > --- /dev/null > +++ b/daemon/xfs.c > @@ -0,0 +1,278 @@ > +/* libguestfs - the guestfsd daemon > + * Copyright (C) 2012 Fujitsu Limited. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#include <config.h> > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <inttypes.h> > +#include <string.h> > +#include <unistd.h> > + > +#include "guestfs_protocol.h" > +#include "daemon.h" > +#include "c-ctype.h" > +#include "actions.h" > + > +int > +optgroup_xfs_available (void) > +{ > + return prog_exists ("mkfs.xfs"); > +} > + > +static char * > +split_strdup (char *string) > +{ > + char *end = string; > + while (*end != ' ' && *end != ',') end++; > + size_t len = end - string; > + char *ret = malloc (len + 1); > + if (!ret) { > + reply_with_perror ("malloc"); > + return NULL; > + } > + strncpy (ret, string, len); > + ret[len] = '\0'; > + fprintf(stderr, "%s\n", ret); > + return ret; > +} > + > +static int > +parse_uint32 (uint32_t *ret, const char *str) > +{ > + uint32_t r; > + > + if (sscanf (str, "%" SCNu32, &r) != 1) { > + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); > + return -1; > + } > + > + *ret = r; > + return 0; > +} > + > +static int > +parse_uint64 (uint64_t *ret, const char *str) > +{ > + uint64_t r; > + > + if (sscanf (str, "%" SCNu64, &r) != 1) { > + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); > + return -1; > + } > + > + *ret = r; > + return 0; > +} > + > +static guestfs_int_xfsinfo * > +parse_xfs_info (char **lines) > +{ > + guestfs_int_xfsinfo *ret; > + char *buf, *p; > + size_t i; > + > + ret = calloc (1, sizeof *ret); > + if (ret == NULL) { > + reply_with_error ("calloc"); > + return NULL; > + } > + > + for (i = 0; lines[i] != NULL; ++i) { > + if (p = strstr (lines[i], "meta-data=")) { > + ret->mntpoint = split_strdup (p + 10); > + if (ret->mntpoint == NULL) goto error; > + } else if (p = strstr (lines[i], "isize=")) { > + buf = split_strdup (p + 6); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->inodesize, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "agcount=")) { > + buf = split_strdup (p + 8); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->agcount, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "agsize=")) { > + buf = split_strdup (p + 7); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->agsize, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "sectsz=")) { > + buf = split_strdup (p + 7); > + if (buf == NULL) goto error; > + if (i == 1) > + if (parse_uint32 (&ret->sectsize, buf) == -1) > + goto error; > + else if (i == 6) > + if (parse_uint32 (&ret->logsectsize, buf) == -1) > + goto error; > + else goto error; > + } else if (p = strstr (lines[i], "attr=")) { > + buf = split_strdup (p + 5); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->attr, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "bsize=")) { > + buf = split_strdup (p + 6); > + if (buf == NULL) goto error; > + if (i == 2) > + if (parse_uint32 (&ret->blocksize, buf) == -1) > + goto error; > + else if (i == 4) > + if (parse_uint32 (&ret->dirblocksize, buf) == -1) > + goto error; > + else if (i == 5) > + if (parse_uint32 (&ret->logblocksize, buf) == -1) > + goto error; > + else goto error; > + } else if (p = strstr (lines[i], "blocks=")) { > + buf = split_strdup (p + 7); > + if (buf == NULL) goto error; > + if (i == 2) > + if (parse_uint64 (&ret->datablocks, buf) == -1) > + goto error; > + else if (i == 5) > + if (parse_uint32 (&ret->logblocks, buf) == -1) > + goto error; > + else if (i == 7) > + if (parse_uint64 (&ret->rtblocks, buf) == -1) > + goto error; > + else goto error; > + } else if (p = strstr (lines[i], "imaxpct=")) { > + buf = split_strdup (p + 8); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->imaxpct, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "sunit=")) { > + buf = split_strdup (p + 6); > + if (buf == NULL) goto error; > + if (i == 3) > + if (parse_uint32 (&ret->sunit, buf) == -1) > + goto error; > + else if (i == 6) > + if (parse_uint32 (&ret->logsunit, buf) == -1) > + goto error; > + else goto error; > + } else if (p = strstr (lines[i], "swidth=")) { > + buf = split_strdup (p + 7); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->swidth, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "naming =version ")) { > + buf = split_strdup (p + 18); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->dirversion, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "ascii-ci=")) { > + buf = split_strdup (p + 9); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->cimode, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "log =")) { > + ret->logname = split_strdup (p + 10); > + if (ret->logname == NULL) goto error; > + } else if (p = strstr (lines[i], "version=")) { > + buf = split_strdup (p + 8); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->logversion, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "lazy-count=")) { > + buf = split_strdup (p + 11); > + if (buf == NULL) goto error; > + if (parse_uint32 (&ret->lazycount, buf) == -1) > + goto error; > + } else if (p = strstr (lines[i], "realtime =")) { > + ret->rtname = split_strdup (p + 10); > + if (ret->rtname == NULL) goto error; > + } else if (p = strstr (lines[i], "rtextents=")) { > + buf = split_strdup (p + 10); > + if (buf == NULL) goto error; > + if (parse_uint64 (&ret->rtextents, buf) == -1) > + goto error; > + } > + > + free (buf); > + } > + > + if (ret->mntpoint == NULL) { > + ret->mntpoint = strdup (""); > + if (ret->mntpoint == NULL) goto error; > + } > + if (ret->logname == NULL) { > + ret->logname = strdup (""); > + if (ret->logname == NULL) goto error; > + } > + if (ret->rtname == NULL) { > + ret->rtname = strdup (""); > + if (ret->rtname == NULL) goto error; > + } > + > + return ret; > + > +error: > + free (buf); > + free (ret->mntpoint); > + free (ret->logname); > + free (ret->rtname); > + free (ret); > + return NULL; > +} > + > +guestfs_int_xfsinfo * > +do_xfs_info (const char *path) > +{ > + int r; > + char *buf; > + char *out = NULL, *err = NULL; > + char **lines = NULL; > + guestfs_int_xfsinfo *ret = NULL; > + > + if (do_is_dir (path)) { > + buf = sysroot_path (path); > + if (!buf) { > + reply_with_perror ("malloc"); > + return NULL; > + } > + } else { > + buf = strdup(path); > + if (!buf) { > + reply_with_perror ("strdup"); > + return NULL; > + } > + } > + > + r = command (&out, &err, "xfs_info", buf, NULL); > + free (buf); > + if (r == -1) { > + reply_with_error ("%s", err); > + goto error; > + } > + > + lines = split_lines (out); > + if (lines == NULL) > + goto error; > + > + ret = parse_xfs_info (lines); > + > +error: > + free (err); > + free (out); > + if (lines) > + free_strings (lines); > + return ret; > +} > diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml > index c83bf70..dd9ea03 100644 > --- a/generator/generator_actions.ml > +++ b/generator/generator_actions.ml > @@ -8995,6 +8995,14 @@ be returned if you called C<guestfs_list_devices>. > To find out the maximum number of devices that could be added, > call C<guestfs_max_disks>." }; > > + { defaults with > + name = "xfs_info"; > + style = RStruct ("info", "xfsinfo"), [Pathname "path"], []; > + proc_nr = Some 337; > + shortdesc = "get geometry of XFS filesystem"; > + longdesc = "\ > +This functions can print out the geometry of a mounted XFS filesystem." }; > + > ] > > (* Non-API meta-commands available only in guestfish. > diff --git a/generator/generator_structs.ml b/generator/generator_structs.ml > index 024bb3c..3dded35 100644 > --- a/generator/generator_structs.ml > +++ b/generator/generator_structs.ml > @@ -213,6 +213,35 @@ let structs = [ > "iso_volume_effective_t", FInt64; > ]; > > + (* XFS info descriptor. *) > + "xfsinfo", [ > + "mntpoint", FString; > + "inodesize", FUInt32; > + "agcount", FUInt32; > + "agsize", FUInt32; > + "sectsize", FUInt32; > + "attr", FUInt32; > + "blocksize", FUInt32; > + "datablocks", FUInt64; > + "imaxpct", FUInt32; > + "sunit", FUInt32; > + "swidth", FUInt32; > + "dirversion", FUInt32; > + "dirblocksize", FUInt32; > + "cimode", FInt32; > + "logname", FString; > + "logblocksize", FUInt32; > + "logblocks", FUInt32; > + "logversion", FUInt32; > + "logsectsize", FUInt32; > + "logsunit", FUInt32; > + "lazycount", FUInt32; > + "rtname", FString; > + "rtextsize", FUInt32; > + "rtblocks", FUInt64; > + "rtextents", FUInt64; > + ]; > + > (* /proc/mdstat information. See linux.git/drivers/md/md.c *) > "mdstat", [ > "mdstat_device", FString; > @@ -243,6 +272,7 @@ let camel_structs = [ > "partition", "Partition"; > "application", "Application"; > "isoinfo", "ISOInfo"; > + "xfsinfo", "XFSInfo"; > "mdstat", "MDStat"; > "btrfssubvolume", "BTRFSSubvolume"; > ] > diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc > index e84236d..d70e106 100644 > --- a/gobject/Makefile.inc > +++ b/gobject/Makefile.inc > @@ -36,6 +36,7 @@ guestfs_gobject_headers= \ > include/guestfs-gobject/struct-partition.h \ > include/guestfs-gobject/struct-application.h \ > include/guestfs-gobject/struct-isoinfo.h \ > + include/guestfs-gobject/struct-xfsinfo.h \ > include/guestfs-gobject/struct-mdstat.h \ > include/guestfs-gobject/struct-btrfssubvolume.h \ > include/guestfs-gobject/optargs-internal_test.h \ > @@ -80,6 +81,7 @@ guestfs_gobject_sources= \ > src/struct-partition.c \ > src/struct-application.c \ > src/struct-isoinfo.c \ > + src/struct-xfsinfo.c \ > src/struct-mdstat.c \ > src/struct-btrfssubvolume.c \ > src/optargs-internal_test.c \ > diff --git a/java/Makefile.inc b/java/Makefile.inc > index efad2a0..da8de49 100644 > --- a/java/Makefile.inc > +++ b/java/Makefile.inc > @@ -35,4 +35,5 @@ java_built_sources = \ > com/redhat/et/libguestfs/VG.java \ > com/redhat/et/libguestfs/Version.java \ > com/redhat/et/libguestfs/XAttr.java \ > + com/redhat/et/libguestfs/XFSInfo.java \ > com/redhat/et/libguestfs/GuestFS.java > diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore > index 9556d81..1034665 100644 > --- a/java/com/redhat/et/libguestfs/.gitignore > +++ b/java/com/redhat/et/libguestfs/.gitignore > @@ -13,3 +13,4 @@ StatVFS.java > VG.java > Version.java > XAttr.java > +XFSInfo.java > diff --git a/po/POTFILES b/po/POTFILES > index 6c819d3..017f5bd 100644 > --- a/po/POTFILES > +++ b/po/POTFILES > @@ -84,6 +84,7 @@ daemon/upload.c > daemon/utimens.c > daemon/wc.c > daemon/xattr.c > +daemon/xfs.c > daemon/zero.c > daemon/zerofree.c > df/df.c > @@ -155,6 +156,7 @@ gobject/src/optargs-ntfsclone_out.c > gobject/src/optargs-ntfsfix.c > gobject/src/optargs-ntfsresize_opts.c > gobject/src/optargs-set_e2attrs.c > +gobject/src/optargs-test0.c > gobject/src/optargs-tune2fs.c > gobject/src/optargs-umount_local.c > gobject/src/session.c > @@ -173,6 +175,7 @@ gobject/src/struct-stat.c > gobject/src/struct-statvfs.c > gobject/src/struct-version.c > gobject/src/struct-xattr.c > +gobject/src/struct-xfsinfo.c > gobject/src/tristate.c > inspector/virt-inspector.c > java/com_redhat_et_libguestfs_GuestFS.c > diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR > index e64f24d..f59a90f 100644 > --- a/src/MAX_PROC_NR > +++ b/src/MAX_PROC_NR > @@ -1 +1 @@ > -336 > +337 > -- > 1.7.11.1.165.g299666c-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top
Add xfs_info to show the geometry of the xfs filesystem. Signed-off-by: Wanlong Gao <gaowanlong at cn.fujitsu.com> --- daemon/Makefile.am | 1 + daemon/xfs.c | 314 +++++++++++++++++++++++++++++++ generator/generator_actions.ml | 17 ++ generator/generator_structs.ml | 30 +++ gobject/Makefile.inc | 2 + java/Makefile.inc | 1 + java/com/redhat/et/libguestfs/.gitignore | 1 + po/POTFILES | 6 + src/MAX_PROC_NR | 2 +- 9 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 daemon/xfs.c diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 9e2a633..afe8874 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -165,6 +165,7 @@ guestfsd_SOURCES = \ utimens.c \ wc.c \ xattr.c \ + xfs.c \ zero.c \ zerofree.c guestfsd_LDADD = \ diff --git a/daemon/xfs.c b/daemon/xfs.c new file mode 100644 index 0000000..bbc089f --- /dev/null +++ b/daemon/xfs.c @@ -0,0 +1,314 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2012 Fujitsu Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <unistd.h> + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "c-ctype.h" +#include "actions.h" + +int +optgroup_xfs_available (void) +{ + return prog_exists ("mkfs.xfs"); +} + +static char * +split_strdup (char *string) +{ + char *end = string; + while (*end != ' ' && *end != ',' && *end != '\0') end++; + size_t len = end - string; + char *ret = malloc (len + 1); + if (!ret) { + reply_with_perror ("malloc"); + return NULL; + } + strncpy (ret, string, len); + ret[len] = '\0'; + fprintf(stderr, "\nBuf :%s\n", ret); + return ret; +} + +static int +parse_uint32 (uint32_t *ret, const char *str) +{ + uint32_t r; + + if (sscanf (str, "%" SCNu32, &r) != 1) { + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); + return -1; + } + + *ret = r; + return 0; +} + +static int +parse_uint64 (uint64_t *ret, const char *str) +{ + uint64_t r; + + if (sscanf (str, "%" SCNu64, &r) != 1) { + reply_with_error ("cannot parse numeric field from isoinfo: %s", str); + return -1; + } + + *ret = r; + return 0; +} + +static guestfs_int_xfsinfo * +parse_xfs_info (char **lines) +{ + guestfs_int_xfsinfo *ret; + char *buf, *p; + size_t i; + + ret = calloc (1, sizeof *ret); + if (ret == NULL) { + reply_with_error ("calloc"); + return NULL; + } + + for (i = 0; lines[i] != NULL; ++i) { + if (p = strstr (lines[i], "meta-data=")) { + ret->mntpoint = split_strdup (p + 10); + if (ret->mntpoint == NULL) goto error; + } + if (p = strstr (lines[i], "isize=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->inodesize, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "agcount=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->agcount, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "agsize=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->agsize, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "sectsz=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (i == 1) { + if (parse_uint32 (&ret->sectsize, buf) == -1) + goto error; + free (buf); + } else if (i == 6) { + if (parse_uint32 (&ret->logsectsize, buf) == -1) + goto error; + free (buf); + } else goto error; + } + if (p = strstr (lines[i], "attr=")) { + buf = split_strdup (p + 5); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->attr, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "bsize=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (i == 2) { + if (parse_uint32 (&ret->blocksize, buf) == -1) + goto error; + free (buf); + } else if (i == 4) { + if (parse_uint32 (&ret->dirblocksize, buf) == -1) + goto error; + free (buf); + } else if (i == 5) { + if (parse_uint32 (&ret->logblocksize, buf) == -1) + goto error; + free (buf); + } else goto error; + } + if (p = strstr (lines[i], "blocks=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (i == 2) { + if (parse_uint64 (&ret->datablocks, buf) == -1) + goto error; + free (buf); + } else if (i == 5) { + if (parse_uint32 (&ret->logblocks, buf) == -1) + goto error; + free (buf); + } else if (i == 7) { + if (parse_uint64 (&ret->rtblocks, buf) == -1) + goto error; + free (buf); + } else goto error; + } + if (p = strstr (lines[i], "imaxpct=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->imaxpct, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "sunit=")) { + buf = split_strdup (p + 6); + if (buf == NULL) goto error; + if (i == 3) { + if (parse_uint32 (&ret->sunit, buf) == -1) + goto error; + free (buf); + } else if (i == 6) { + if (parse_uint32 (&ret->logsunit, buf) == -1) + goto error; + free (buf); + } else goto error; + } + if (p = strstr (lines[i], "swidth=")) { + buf = split_strdup (p + 7); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->swidth, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "naming =version ")) { + buf = split_strdup (p + 18); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->dirversion, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "ascii-ci=")) { + buf = split_strdup (p + 9); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->cimode, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "log =")) { + ret->logname = split_strdup (p + 10); + if (ret->logname == NULL) goto error; + } + if (p = strstr (lines[i], "version=")) { + buf = split_strdup (p + 8); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->logversion, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "lazy-count=")) { + buf = split_strdup (p + 11); + if (buf == NULL) goto error; + if (parse_uint32 (&ret->lazycount, buf) == -1) + goto error; + free (buf); + } + if (p = strstr (lines[i], "realtime =")) { + ret->rtname = split_strdup (p + 10); + if (ret->rtname == NULL) goto error; + } + if (p = strstr (lines[i], "rtextents=")) { + buf = split_strdup (p + 10); + if (buf == NULL) goto error; + if (parse_uint64 (&ret->rtextents, buf) == -1) + goto error; + free (buf); + } + } + + if (ret->mntpoint == NULL) { + ret->mntpoint = strdup (""); + if (ret->mntpoint == NULL) goto error; + } + if (ret->logname == NULL) { + ret->logname = strdup (""); + if (ret->logname == NULL) goto error; + } + if (ret->rtname == NULL) { + ret->rtname = strdup (""); + if (ret->rtname == NULL) goto error; + } + + return ret; + +error: + free (buf); + free (ret->mntpoint); + free (ret->logname); + free (ret->rtname); + free (ret); + return NULL; +} + +guestfs_int_xfsinfo * +do_xfs_info (const char *path) +{ + int r; + char *buf; + char *out = NULL, *err = NULL; + char **lines = NULL; + guestfs_int_xfsinfo *ret = NULL; + + if (do_is_dir (path)) { + buf = sysroot_path (path); + if (!buf) { + reply_with_perror ("malloc"); + return NULL; + } + } else { + buf = strdup(path); + if (!buf) { + reply_with_perror ("strdup"); + return NULL; + } + } + + r = command (&out, &err, "xfs_info", buf, NULL); + free (buf); + if (r == -1) { + reply_with_error ("%s", err); + goto error; + } + + lines = split_lines (out); + if (lines == NULL) + goto error; + + ret = parse_xfs_info (lines); + +error: + free (err); + free (out); + if (lines) + free_strings (lines); + return ret; +} diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 9322126..a566834 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -8945,6 +8945,23 @@ be returned if you called C<guestfs_list_devices>. To find out the maximum number of devices that could be added, call C<guestfs_max_disks>." }; + { defaults with + name = "xfs_info"; + style = RStruct ("info", "xfsinfo"), [Pathname "path"], []; + proc_nr = Some 337; + tests = [ + InitEmpty, IfAvailable "xfs", TestOutputStruct ( + [["part_disk"; "/dev/sda"; "mbr"]; + ["mkfs"; "xfs"; "/dev/sda1"; ""; "NOARG"; ""; ""]; + ["mount_options"; ""; "/dev/sda1"; "/"]; + ["xfs_info"; "/"]], + [CompareWithInt ("blocksize", 4096); + ]) + ]; + shortdesc = "get geometry of XFS filesystem"; + longdesc = "\ +This functions can print out the geometry of a mounted XFS filesystem." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/generator/generator_structs.ml b/generator/generator_structs.ml index 024bb3c..3dded35 100644 --- a/generator/generator_structs.ml +++ b/generator/generator_structs.ml @@ -213,6 +213,35 @@ let structs = [ "iso_volume_effective_t", FInt64; ]; + (* XFS info descriptor. *) + "xfsinfo", [ + "mntpoint", FString; + "inodesize", FUInt32; + "agcount", FUInt32; + "agsize", FUInt32; + "sectsize", FUInt32; + "attr", FUInt32; + "blocksize", FUInt32; + "datablocks", FUInt64; + "imaxpct", FUInt32; + "sunit", FUInt32; + "swidth", FUInt32; + "dirversion", FUInt32; + "dirblocksize", FUInt32; + "cimode", FInt32; + "logname", FString; + "logblocksize", FUInt32; + "logblocks", FUInt32; + "logversion", FUInt32; + "logsectsize", FUInt32; + "logsunit", FUInt32; + "lazycount", FUInt32; + "rtname", FString; + "rtextsize", FUInt32; + "rtblocks", FUInt64; + "rtextents", FUInt64; + ]; + (* /proc/mdstat information. See linux.git/drivers/md/md.c *) "mdstat", [ "mdstat_device", FString; @@ -243,6 +272,7 @@ let camel_structs = [ "partition", "Partition"; "application", "Application"; "isoinfo", "ISOInfo"; + "xfsinfo", "XFSInfo"; "mdstat", "MDStat"; "btrfssubvolume", "BTRFSSubvolume"; ] diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index 4de56a9..2ca9e19 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -36,6 +36,7 @@ guestfs_gobject_headers= \ include/guestfs-gobject/struct-partition.h \ include/guestfs-gobject/struct-application.h \ include/guestfs-gobject/struct-isoinfo.h \ + include/guestfs-gobject/struct-xfsinfo.h \ include/guestfs-gobject/struct-mdstat.h \ include/guestfs-gobject/struct-btrfssubvolume.h \ include/guestfs-gobject/optargs-internal_test.h \ @@ -80,6 +81,7 @@ guestfs_gobject_sources= \ src/struct-partition.c \ src/struct-application.c \ src/struct-isoinfo.c \ + src/struct-xfsinfo.c \ src/struct-mdstat.c \ src/struct-btrfssubvolume.c \ src/optargs-internal_test.c \ diff --git a/java/Makefile.inc b/java/Makefile.inc index efad2a0..da8de49 100644 --- a/java/Makefile.inc +++ b/java/Makefile.inc @@ -35,4 +35,5 @@ java_built_sources = \ com/redhat/et/libguestfs/VG.java \ com/redhat/et/libguestfs/Version.java \ com/redhat/et/libguestfs/XAttr.java \ + com/redhat/et/libguestfs/XFSInfo.java \ com/redhat/et/libguestfs/GuestFS.java diff --git a/java/com/redhat/et/libguestfs/.gitignore b/java/com/redhat/et/libguestfs/.gitignore index 9556d81..1034665 100644 --- a/java/com/redhat/et/libguestfs/.gitignore +++ b/java/com/redhat/et/libguestfs/.gitignore @@ -13,3 +13,4 @@ StatVFS.java VG.java Version.java XAttr.java +XFSInfo.java diff --git a/po/POTFILES b/po/POTFILES index 7f67911..92189ef 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -84,6 +84,7 @@ daemon/upload.c daemon/utimens.c daemon/wc.c daemon/xattr.c +daemon/xfs.c daemon/zero.c daemon/zerofree.c df/df.c @@ -134,6 +135,7 @@ format/format.c fuse/guestmount.c gobject/src/optargs-add_domain.c gobject/src/optargs-add_drive.c +gobject/src/optargs-add_drive_opts.c gobject/src/optargs-btrfs_filesystem_resize.c gobject/src/optargs-btrfs_fsck.c gobject/src/optargs-compress_device_out.c @@ -149,12 +151,15 @@ gobject/src/optargs-internal_test.c gobject/src/optargs-md_create.c gobject/src/optargs-mkfs.c gobject/src/optargs-mkfs_btrfs.c +gobject/src/optargs-mkfs_opts.c gobject/src/optargs-mount_9p.c gobject/src/optargs-mount_local.c gobject/src/optargs-ntfsclone_out.c gobject/src/optargs-ntfsfix.c gobject/src/optargs-ntfsresize.c +gobject/src/optargs-ntfsresize_opts.c gobject/src/optargs-set_e2attrs.c +gobject/src/optargs-test0.c gobject/src/optargs-tune2fs.c gobject/src/optargs-umount_local.c gobject/src/session.c @@ -173,6 +178,7 @@ gobject/src/struct-stat.c gobject/src/struct-statvfs.c gobject/src/struct-version.c gobject/src/struct-xattr.c +gobject/src/struct-xfsinfo.c gobject/src/tristate.c inspector/virt-inspector.c java/com_redhat_et_libguestfs_GuestFS.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index e64f24d..f59a90f 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -336 +337 -- 1.7.11.2.249.g31c7954
Apparently Analagous Threads
- [PATCH v2 0/7] Add symbol versioning (now working).
- [PATCH v3 0/5] Add symbol versioning.
- [PATCH V2 1/4] mount: add a macro to resolve path or device
- [PATCH 1/5] mount: add a macro to resolve path or device
- [PATCH V4 1/3] umount: add force umount and lazy umount