Return a list of Linux MD devices detected in the guest. --- appliance/packagelist.in | 2 + daemon/Makefile.am | 4 +- daemon/daemon.h | 1 + daemon/guestfsd.c | 23 ++++++--- daemon/md.c | 95 ++++++++++++++++++++++++++++++++++++ generator/generator_actions.ml | 10 ++++ regressions/test-list-mddevices.sh | 43 ++++++++++++++++ src/MAX_PROC_NR | 2 +- 8 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 daemon/md.c create mode 100755 regressions/test-list-mddevices.sh
diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 9b723d0..9da24e7 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -39,6 +39,7 @@ ntfs-3g reiserfs-utils libselinux + pcre systemd /* for /sbin/reboot */ udev util-linux-ng @@ -59,6 +60,7 @@ hfsplus iproute libaugeas0 + libpcre3 linux-image nilfs-tools ntfs-3g diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 7757067..921392a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -129,6 +129,7 @@ guestfsd_SOURCES = \ luks.c \ lvm.c \ lvm-filter.c \ + md.c \ mkfs.c \ mknod.c \ modprobe.c \ @@ -173,7 +174,8 @@ guestfsd_LDADD = \ $(LIBSOCKET) \ $(LIB_CLOCK_GETTIME) \ $(LIBINTL) \ - $(SERVENT_LIB) + $(SERVENT_LIB) \ + $(PCRE_LIBS) guestfsd_CPPFLAGS = -I$(top_srcdir)/gnulib/lib guestfsd_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) diff --git a/daemon/daemon.h b/daemon/daemon.h index 6ed68fd..3ca4693 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -47,6 +47,7 @@ extern int xwrite (int sock, const void *buf, size_t len) extern int xread (int sock, void *buf, size_t len) __attribute__((__warn_unused_result__)); +extern int add_string_nodup (char ***argv, int *size, int *alloc, char *str); extern int add_string (char ***argv, int *size, int *alloc, const char *str); extern size_t count_strings (char *const *argv); extern void sort_strings (char **argv, int len); diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index eacbc1d..930ee27 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -415,10 +415,9 @@ xread (int sock, void *v_buf, size_t len) } int -add_string (char ***argv, int *size, int *alloc, const char *str) +add_string_nodup (char ***argv, int *size, int *alloc, char *str) { char **new_argv; - char *new_str; if (*size >= *alloc) { *alloc += 64; @@ -426,11 +425,23 @@ add_string (char ***argv, int *size, int *alloc, const char *str) if (new_argv == NULL) { reply_with_perror ("realloc"); free_strings (*argv); + *argv = NULL; return -1; } *argv = new_argv; } + (*argv)[*size] = str; + + (*size)++; + return 0; +} + +int +add_string (char ***argv, int *size, int *alloc, const char *str) +{ + char *new_str; + if (str) { new_str = strdup (str); if (new_str == NULL) { @@ -438,13 +449,11 @@ add_string (char ***argv, int *size, int *alloc, const char *str) free_strings (*argv); return -1; } - } else + } else { new_str = NULL; + } - (*argv)[*size] = new_str; - - (*size)++; - return 0; + return add_string_nodup (argv, size, alloc, new_str); } size_t diff --git a/daemon/md.c b/daemon/md.c new file mode 100644 index 0000000..6b8430a --- /dev/null +++ b/daemon/md.c @@ -0,0 +1,95 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2011 Red Hat Inc. + * + * 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 <pcre.h> +#include <stdio.h> +#include <string.h> + +#include "daemon.h" +#include "actions.h" + +char ** +do_list_mddevices (void) +{ + /* Compile and keep a regular expression for matching md lines */ + static pcre *mdre = NULL; + if (NULL == mdre) { + const char *err; + int erroffset; + mdre = pcre_compile("^md(\\d+)\\s*:", 0, &err, &erroffset, NULL); + if (NULL == mdre) { + reply_with_error("(%s:%i) pcre_compile failure at offset %i: %s", + __FILE__, __LINE__, erroffset, err); + return NULL; + } + } + + char **r = NULL; + int size = 0, alloc = 0; + + FILE *mdstat = fopen("/proc/mdstat", "r"); + if (!mdstat) { + reply_with_perror("open /proc/mdstat"); + return NULL; + } + + /* Test each line of /proc/mdstat against the regular expression */ + char *line = NULL; + size_t bufsize = 0; + ssize_t len = 0; + while ((len = getline(&line, &bufsize, mdstat)) != -1) { + int ovec[6]; + + int matches = pcre_exec(mdre, NULL, line, len, 0, 0, + ovec, sizeof(ovec) / sizeof(ovec[0])); + /* No match, next line */ + if (matches < 0) continue; + + /* ovec wasn't big enough. This should be impossible. */ + if (matches == 0) { + reply_with_error("(%s:%i) pcre_exec output vector too small", + __FILE__, __LINE__); + if (r != NULL) { + free_strings(r); + r = NULL; + } + goto error; + } + + /* We got a match. Add it to the returned list */ + char *dev = malloc(strlen("/dev/md") + ovec[1] + 1); + if (NULL == dev) { + reply_with_perror("malloc"); + goto error; + } + char *n = mempcpy(dev, "/dev/md", strlen("/dev/md")); + n = mempcpy(n, line + ovec[2], ovec[3] - ovec[2]); + *n = '\0'; + + if (add_string_nodup(&r, &size, &alloc, dev) == -1) goto error; + } + + return r; + +error: + fclose(mdstat); + if (r != NULL) free_strings(r); + return NULL; +} diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index d3fa3e0..1cf5288 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -6332,6 +6332,16 @@ is for copying blocks within existing files. See C<guestfs_cp>, C<guestfs_cp_a> and C<guestfs_mv> for general file copying and moving functions."); + ("list_mddevices", (RStringList "mddevices", [], []), 298, [], + [], + "list Linux md devices", + "\ +List all Linux md devices. + +The non-textual names as known to the appliance are returned, eg. +C</dev/md127>. Note that this will normally be different to the name used by the +guest."); + ] let all_functions = non_daemon_functions @ daemon_functions diff --git a/regressions/test-list-mddevices.sh b/regressions/test-list-mddevices.sh new file mode 100755 index 0000000..2415322 --- /dev/null +++ b/regressions/test-list-mddevices.sh @@ -0,0 +1,43 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2011 Red Hat Inc. +# +# 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. + +# Test guestfish list-mddevices command + +set -e + +../fish/guestfish <<EOF >/dev/null 2>&1 +sparse md-test1.img 100M +sparse md-test2.img 100M +run +debug sh "/usr/bin/yes | mdadm -C /dev/md/test --level=1 --raid-devices=2 /dev/vda /dev/vdb" +EOF + +output=$( +../fish/guestfish -a md-test1.img -a md-test2.img <<EOF +run +list-mddevices +EOF +) + +if [ "$output" != "/dev/md127" ]; then + echo "$0: error: output of list-mddevices did not match expected output" + echo "$output" + exit 1 +fi + +rm -f md-test1.img md-test2.img diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 95de1ee..a1f7f63 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -297 +298
_______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs