mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: Reimplement xfs_info using xfs_info2
Remove all the complicated old C parsing code and reimplement xfs_info using xfs_info2. Note that this function will be deprecated.
This commit is contained in:
committed by
rwmjones
parent
dfd2700616
commit
e1deb358ce
310
daemon/xfs.c
310
daemon/xfs.c
@@ -38,316 +38,6 @@ optgroup_xfs_available (void)
|
||||
return prog_exists ("mkfs.xfs");
|
||||
}
|
||||
|
||||
/* Return everything up to the first comma, equals or space in the input
|
||||
* string, strdup'ing the return value.
|
||||
*/
|
||||
static char *
|
||||
split_strdup (char *string)
|
||||
{
|
||||
size_t len;
|
||||
char *ret;
|
||||
|
||||
len = strcspn (string, " ,=");
|
||||
ret = strndup (string, len);
|
||||
if (!ret) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
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 xfs_info: %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 xfs_info: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Typical crazy output from the xfs_info command:
|
||||
*
|
||||
* meta-data=/dev/sda1 isize=256 agcount=4, agsize=6392 blks
|
||||
* = sectsz=512 attr=2
|
||||
*[ = crc=0 ]
|
||||
* data = bsize=4096 blocks=25568, imaxpct=25
|
||||
* = sunit=0 swidth=0 blks
|
||||
* naming =version 2 bsize=4096 ascii-ci=0
|
||||
* log =internal bsize=4096 blocks=1200, version=2
|
||||
* = sectsz=512 sunit=0 blks, lazy-count=1
|
||||
* realtime =none extsz=4096 blocks=0, rtextents=0
|
||||
*
|
||||
* [...] line only appears in Fedora >= 21
|
||||
*
|
||||
* We may need to revisit this parsing code if the output changes
|
||||
* in future.
|
||||
*/
|
||||
static guestfs_int_xfsinfo *
|
||||
parse_xfs_info (char **lines)
|
||||
{
|
||||
guestfs_int_xfsinfo *ret;
|
||||
CLEANUP_FREE char *section = NULL; /* first column, eg "meta-data", "data" */
|
||||
char *p;
|
||||
size_t i;
|
||||
|
||||
ret = malloc (sizeof *ret);
|
||||
if (ret == NULL) {
|
||||
reply_with_error ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize fields to NULL or -1 so the caller can tell which fields
|
||||
* were updated in the code below.
|
||||
*/
|
||||
ret->xfs_mntpoint = NULL;
|
||||
ret->xfs_inodesize = -1;
|
||||
ret->xfs_agcount = -1;
|
||||
ret->xfs_agsize = -1;
|
||||
ret->xfs_sectsize = -1;
|
||||
ret->xfs_attr = -1;
|
||||
ret->xfs_blocksize = -1;
|
||||
ret->xfs_datablocks = -1;
|
||||
ret->xfs_imaxpct = -1;
|
||||
ret->xfs_sunit = -1;
|
||||
ret->xfs_swidth = -1;
|
||||
ret->xfs_dirversion = -1;
|
||||
ret->xfs_dirblocksize = -1;
|
||||
ret->xfs_cimode = -1;
|
||||
ret->xfs_logname = NULL;
|
||||
ret->xfs_logblocksize = -1;
|
||||
ret->xfs_logblocks = -1;
|
||||
ret->xfs_logversion = -1;
|
||||
ret->xfs_logsectsize = -1;
|
||||
ret->xfs_logsunit = -1;
|
||||
ret->xfs_lazycount = -1;
|
||||
ret->xfs_rtname = NULL;
|
||||
ret->xfs_rtextsize = -1;
|
||||
ret->xfs_rtblocks = -1;
|
||||
ret->xfs_rtextents = -1;
|
||||
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
if (verbose)
|
||||
fprintf (stderr, "xfs_info: lines[%zu] = \'%s\'\n", i, lines[i]);
|
||||
|
||||
if (c_isalpha (lines[i][0])) {
|
||||
free (section);
|
||||
section = split_strdup (lines[i]);
|
||||
if (!section) goto error;
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "xfs_info: new section %s\n", section);
|
||||
}
|
||||
|
||||
if ((p = strstr (lines[i], "meta-data="))) {
|
||||
ret->xfs_mntpoint = split_strdup (p + 10);
|
||||
if (ret->xfs_mntpoint == NULL) goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "isize="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 6);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_inodesize, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "agcount="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 8);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_agcount, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "agsize="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 7);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_agsize, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "sectsz="))) {
|
||||
if (section) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 7);
|
||||
if (buf == NULL) goto error;
|
||||
if (STREQ (section, "meta-data")) {
|
||||
if (parse_uint32 (&ret->xfs_sectsize, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "log")) {
|
||||
if (parse_uint32 (&ret->xfs_logsectsize, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p = strstr (lines[i], "attr="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 5);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_attr, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "bsize="))) {
|
||||
if (section) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 6);
|
||||
if (buf == NULL) goto error;
|
||||
if (STREQ (section, "data")) {
|
||||
if (parse_uint32 (&ret->xfs_blocksize, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "naming")) {
|
||||
if (parse_uint32 (&ret->xfs_dirblocksize, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "log")) {
|
||||
if (parse_uint32 (&ret->xfs_logblocksize, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p = strstr (lines[i], "blocks="))) {
|
||||
if (section) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 7);
|
||||
if (buf == NULL) goto error;
|
||||
if (STREQ (section, "data")) {
|
||||
if (parse_uint64 (&ret->xfs_datablocks, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "log")) {
|
||||
if (parse_uint32 (&ret->xfs_logblocks, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "realtime")) {
|
||||
if (parse_uint64 (&ret->xfs_rtblocks, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p = strstr (lines[i], "imaxpct="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 8);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_imaxpct, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "sunit="))) {
|
||||
if (section) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 6);
|
||||
if (buf == NULL) goto error;
|
||||
if (STREQ (section, "data")) {
|
||||
if (parse_uint32 (&ret->xfs_sunit, buf) == -1)
|
||||
goto error;
|
||||
} else if (STREQ (section, "log")) {
|
||||
if (parse_uint32 (&ret->xfs_logsunit, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p = strstr (lines[i], "swidth="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 7);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_swidth, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "naming =version "))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 18);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_dirversion, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "ascii-ci="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 9);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_cimode, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "log ="))) {
|
||||
ret->xfs_logname = split_strdup (p + 10);
|
||||
if (ret->xfs_logname == NULL) goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "version="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 8);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_logversion, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "lazy-count="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 11);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint32 (&ret->xfs_lazycount, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "realtime ="))) {
|
||||
ret->xfs_rtname = split_strdup (p + 10);
|
||||
if (ret->xfs_rtname == NULL) goto error;
|
||||
}
|
||||
if ((p = strstr (lines[i], "rtextents="))) {
|
||||
CLEANUP_FREE char *buf = split_strdup (p + 10);
|
||||
if (buf == NULL) goto error;
|
||||
if (parse_uint64 (&ret->xfs_rtextents, buf) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret->xfs_mntpoint == NULL) {
|
||||
ret->xfs_mntpoint = strdup ("");
|
||||
if (ret->xfs_mntpoint == NULL) goto error;
|
||||
}
|
||||
if (ret->xfs_logname == NULL) {
|
||||
ret->xfs_logname = strdup ("");
|
||||
if (ret->xfs_logname == NULL) goto error;
|
||||
}
|
||||
if (ret->xfs_rtname == NULL) {
|
||||
ret->xfs_rtname = strdup ("");
|
||||
if (ret->xfs_rtname == NULL) goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free (ret->xfs_mntpoint);
|
||||
free (ret->xfs_logname);
|
||||
free (ret->xfs_rtname);
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guestfs_int_xfsinfo *
|
||||
do_xfs_info (const char *pathordevice)
|
||||
{
|
||||
int r;
|
||||
CLEANUP_FREE char *buf = NULL;
|
||||
CLEANUP_FREE char *out = NULL, *err = NULL;
|
||||
CLEANUP_FREE_STRING_LIST char **lines = NULL;
|
||||
int is_dev;
|
||||
|
||||
is_dev = is_device_parameter (pathordevice);
|
||||
buf = is_dev ? strdup (pathordevice)
|
||||
: sysroot_path (pathordevice);
|
||||
if (buf == NULL) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = command (&out, &err, "xfs_info", buf, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lines = split_lines (out);
|
||||
if (lines == NULL)
|
||||
return NULL;
|
||||
|
||||
return parse_xfs_info (lines);
|
||||
}
|
||||
|
||||
int
|
||||
do_xfs_growfs (const char *path,
|
||||
int datasec, int logsec, int rtsec,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*)
|
||||
|
||||
open Printf
|
||||
open Scanf
|
||||
|
||||
open Std_utils
|
||||
|
||||
@@ -126,3 +127,47 @@ let xfs_info2 dev =
|
||||
) groups;
|
||||
|
||||
List.rev !values
|
||||
|
||||
(* Deprecated xfs_info. *)
|
||||
let xfs_info dev =
|
||||
let h = xfs_info2 dev in
|
||||
|
||||
let find field parsefn =
|
||||
try List.assoc field h |> parsefn
|
||||
with
|
||||
| Not_found ->
|
||||
failwithf "xfs_info: unexpected missing field: %s" field
|
||||
| exn ->
|
||||
failwithf "xfs_info: failure finding field: %s: %s"
|
||||
field (Printexc.to_string exn)
|
||||
in
|
||||
|
||||
let parse_blks s = sscanf s "%ld blks" Fun.id in
|
||||
let parse_version s = sscanf s "version %ld" Fun.id in
|
||||
|
||||
{ Structs.xfs_mntpoint = find "meta-data" Fun.id;
|
||||
xfs_inodesize = find "meta-data.isize" Int32.of_string;
|
||||
xfs_agcount = find "meta-data.agcount" Int32.of_string;
|
||||
xfs_agsize = find "meta-data.agsize" parse_blks;
|
||||
xfs_sectsize = find "meta-data.sectsz" Int32.of_string;
|
||||
xfs_attr = find "meta-data.attr" Int32.of_string;
|
||||
xfs_blocksize = find "data.bsize" Int32.of_string;
|
||||
xfs_datablocks = find "data.blocks" Int64.of_string;
|
||||
xfs_imaxpct = find "data.imaxpct" Int32.of_string;
|
||||
xfs_sunit = find "data.sunit" Int32.of_string;
|
||||
xfs_swidth = find "data.swidth" parse_blks;
|
||||
xfs_dirversion = find "naming" parse_version;
|
||||
xfs_dirblocksize = find "naming.bsize" Int32.of_string;
|
||||
xfs_cimode = find "naming.ascii-ci" Int32.of_string;
|
||||
xfs_logname = find "log" Fun.id;
|
||||
xfs_logblocksize = find "log.bsize" Int32.of_string;
|
||||
xfs_logblocks = find "log.blocks" Int32.of_string;
|
||||
xfs_logversion = find "log.version" Int32.of_string;
|
||||
xfs_logsectsize = find "log.sectsz" Int32.of_string;
|
||||
xfs_logsunit = find "log.sunit" parse_blks;
|
||||
xfs_lazycount = find "log.lazy-count" Int32.of_string;
|
||||
xfs_rtname = find "realtime" Fun.id;
|
||||
xfs_rtextsize = find "realtime.extsz" Int32.of_string;
|
||||
xfs_rtblocks = find "realtime.blocks" Int64.of_string;
|
||||
xfs_rtextents = find "realtime.rtextents" Int64.of_string;
|
||||
}
|
||||
|
||||
@@ -7262,6 +7262,7 @@ call C<guestfs_max_disks>.|} };
|
||||
{ defaults with
|
||||
name = "xfs_info"; added = (1, 19, 21);
|
||||
style = RStruct ("info", "xfsinfo"), [String (Dev_or_Path, "pathordevice")], [];
|
||||
impl = OCaml "Xfs.xfs_info";
|
||||
optional = Some "xfs";
|
||||
tests = [
|
||||
InitEmpty, Always, TestResult (
|
||||
|
||||
Reference in New Issue
Block a user