diff options
author | Richard Jones <rjones@redhat.com> | 2009-04-06 12:55:26 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-04-06 12:55:26 +0100 |
commit | 8e570870f577ff0c3db074f88924633b559af5d4 (patch) | |
tree | 711af1263615c8cd977eceb0e4286425b53bd725 /daemon | |
parent | 1cf85b1e60e85c4940869c6291d75ac44a5bd190 (diff) | |
download | libguestfs-8e570870f577ff0c3db074f88924633b559af5d4.tar.gz libguestfs-8e570870f577ff0c3db074f88924633b559af5d4.tar.xz libguestfs-8e570870f577ff0c3db074f88924633b559af5d4.zip |
Implement list-devices and list-partitions.
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/actions.h | 8 | ||||
-rw-r--r-- | daemon/daemon.h | 2 | ||||
-rw-r--r-- | daemon/devsparts.c | 133 | ||||
-rw-r--r-- | daemon/guestfsd.c | 24 | ||||
-rw-r--r-- | daemon/ls.c | 10 | ||||
-rw-r--r-- | daemon/stubs.c | 144 |
7 files changed, 257 insertions, 65 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 76e75c6a..5faa6523 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -21,6 +21,7 @@ noinst_PROGRAMS = guestfsd guestfsd_SOURCES = \ actions.h \ daemon.h \ + devsparts.c \ file.c \ guestfsd.c \ ls.c \ diff --git a/daemon/actions.h b/daemon/actions.h index c4b9b157..58b8a24c 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -19,9 +19,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -extern char *do_cat (const char *path); -extern char *do_ll (const char *directory); -extern char **do_ls (const char *directory); extern int do_mount (const char *device, const char *mountpoint); extern int do_sync (); extern int do_touch (const char *path); +extern char *do_cat (const char *path); +extern char *do_ll (const char *directory); +extern char **do_ls (const char *directory); +extern char **do_list_devices (); +extern char **do_list_partitions (); diff --git a/daemon/daemon.h b/daemon/daemon.h index 3740595c..60e1982b 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -29,7 +29,9 @@ extern void xread (int sock, void *buf, size_t len); extern int add_string (char ***argv, int *size, int *alloc, const char *str); extern int count_strings (char **argv); +extern void sort_strings (char **argv, int len); extern void free_strings (char **argv); +extern void free_stringslen (char **argv, int len); extern int command (char **stdoutput, char **stderror, const char *name, ...); diff --git a/daemon/devsparts.c b/daemon/devsparts.c new file mode 100644 index 00000000..b0d79569 --- /dev/null +++ b/daemon/devsparts.c @@ -0,0 +1,133 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/stat.h> + +#include "daemon.h" +#include "actions.h" + +char ** +do_list_devices (void) +{ + char **r = NULL; + int size = 0, alloc = 0; + DIR *dir; + struct dirent *d; + char buf[256]; + + dir = opendir ("/sys/block"); + if (!dir) { + reply_with_perror ("opendir: /sys/block"); + return NULL; + } + + while ((d = readdir (dir)) != NULL) { + if (strncmp (d->d_name, "sd", 2) == 0) { + snprintf (buf, sizeof buf, "/dev/%s", d->d_name); + if (add_string (&r, &size, &alloc, buf) == -1) { + closedir (dir); + return NULL; + } + } + } + + if (add_string (&r, &size, &alloc, NULL) == -1) { + closedir (dir); + return NULL; + } + + if (closedir (dir) == -1) { + reply_with_perror ("closedir: /sys/block"); + free_strings (r); + return NULL; + } + + sort_strings (r, size-1); + return r; +} + +char ** +do_list_partitions (void) +{ + char **r = NULL; + int size = 0, alloc = 0; + DIR *dir, *dir2; + struct dirent *d; + char buf[256], devname[256]; + + dir = opendir ("/sys/block"); + if (!dir) { + reply_with_perror ("opendir: /sys/block"); + return NULL; + } + + while ((d = readdir (dir)) != NULL) { + if (strncmp (d->d_name, "sd", 2) == 0) { + strncpy (devname, d->d_name, sizeof devname); + devname[sizeof devname - 1] = '\0'; + + snprintf (buf, sizeof buf, "/sys/block/%s", devname); + + dir2 = opendir (buf); + if (!dir2) { + reply_with_perror ("opendir: %s", buf); + free_stringslen (r, size); + return NULL; + } + while ((d = readdir (dir2)) != NULL) { + if (strncmp (d->d_name, devname, strlen (devname)) == 0) { + snprintf (buf, sizeof buf, "/dev/%s", d->d_name); + + if (add_string (&r, &size, &alloc, buf) == -1) { + closedir (dir2); + closedir (dir); + return NULL; + } + } + } + + if (closedir (dir2) == -1) { + reply_with_perror ("closedir: /sys/block/%s", devname); + free_stringslen (r, size); + return NULL; + } + } + } + + if (add_string (&r, &size, &alloc, NULL) == -1) { + closedir (dir); + return NULL; + } + + if (closedir (dir) == -1) { + reply_with_perror ("closedir: /sys/block"); + free_strings (r); + return NULL; + } + + sort_strings (r, size-1); + return r; +} diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 6730c1d2..a243c0be 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -272,6 +272,20 @@ count_strings (char **argv) return argc; } +static int +compare (const void *vp1, const void *vp2) +{ + char * const *p1 = (char * const *) vp1; + char * const *p2 = (char * const *) vp2; + return strcmp (*p1, *p2); +} + +void +sort_strings (char **argv, int len) +{ + qsort (argv, len, sizeof (char *), compare); +} + void free_strings (char **argv) { @@ -282,6 +296,16 @@ free_strings (char **argv) free (argv); } +void +free_stringslen (char **argv, int len) +{ + int i; + + for (i = 0; i < len; ++i) + free (argv[i]); + free (argv); +} + /* This is a more sane version of 'system(3)' for running external * commands. It uses fork/execvp, so we don't need to worry about * quoting of parameters, and it allows us to capture any error diff --git a/daemon/ls.c b/daemon/ls.c index 05e2cc70..261bc964 100644 --- a/daemon/ls.c +++ b/daemon/ls.c @@ -29,14 +29,6 @@ #include "daemon.h" #include "actions.h" -static int -compare (const void *vp1, const void *vp2) -{ - char * const *p1 = (char * const *) vp1; - char * const *p2 = (char * const *) vp2; - return strcmp (*p1, *p2); -} - char ** do_ls (const char *path) { @@ -78,7 +70,7 @@ do_ls (const char *path) return NULL; } - qsort (r, size-1, sizeof (char *), compare); + sort_strings (r, size-1); return r; } diff --git a/daemon/stubs.c b/daemon/stubs.c index 4eccfb5b..faece82d 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -25,6 +25,64 @@ #include "../src/guestfs_protocol.h" #include "actions.h" +static void mount_stub (XDR *xdr_in) +{ + int r; + struct guestfs_mount_args args; + const char *device; + const char *mountpoint; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_mount_args (xdr_in, &args)) { + reply_with_error ("mount: daemon failed to decode procedure arguments"); + return; + } + device = args.device; + mountpoint = args.mountpoint; + + r = do_mount (device, mountpoint); + if (r == -1) + /* do_mount has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void sync_stub (XDR *xdr_in) +{ + int r; + + r = do_sync (); + if (r == -1) + /* do_sync has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + +static void touch_stub (XDR *xdr_in) +{ + int r; + struct guestfs_touch_args args; + const char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_touch_args (xdr_in, &args)) { + reply_with_error ("touch: daemon failed to decode procedure arguments"); + return; + } + path = args.path; + + r = do_touch (path); + if (r == -1) + /* do_touch has already called reply_with_error, so just return */ + return; + + reply (NULL, NULL); +} + static void cat_stub (XDR *xdr_in) { char *r; @@ -101,67 +159,50 @@ static void ls_stub (XDR *xdr_in) free_strings (r); } -static void mount_stub (XDR *xdr_in) -{ - int r; - struct guestfs_mount_args args; - const char *device; - const char *mountpoint; - - memset (&args, 0, sizeof args); - - if (!xdr_guestfs_mount_args (xdr_in, &args)) { - reply_with_error ("mount: daemon failed to decode procedure arguments"); - return; - } - device = args.device; - mountpoint = args.mountpoint; - - r = do_mount (device, mountpoint); - if (r == -1) - /* do_mount has already called reply_with_error, so just return */ - return; - - reply (NULL, NULL); -} - -static void sync_stub (XDR *xdr_in) +static void list_devices_stub (XDR *xdr_in) { - int r; + char **r; - r = do_sync (); - if (r == -1) - /* do_sync has already called reply_with_error, so just return */ + r = do_list_devices (); + if (r == NULL) + /* do_list_devices has already called reply_with_error, so just return */ return; - reply (NULL, NULL); + struct guestfs_list_devices_ret ret; + ret.devices.devices_len = count_strings (r); + ret.devices.devices_val = r; + reply ((xdrproc_t) &xdr_guestfs_list_devices_ret, (char *) &ret); + free_strings (r); } -static void touch_stub (XDR *xdr_in) +static void list_partitions_stub (XDR *xdr_in) { - int r; - struct guestfs_touch_args args; - const char *path; - - memset (&args, 0, sizeof args); - - if (!xdr_guestfs_touch_args (xdr_in, &args)) { - reply_with_error ("touch: daemon failed to decode procedure arguments"); - return; - } - path = args.path; + char **r; - r = do_touch (path); - if (r == -1) - /* do_touch has already called reply_with_error, so just return */ + r = do_list_partitions (); + if (r == NULL) + /* do_list_partitions has already called reply_with_error, so just return */ return; - reply (NULL, NULL); + struct guestfs_list_partitions_ret ret; + ret.partitions.partitions_len = count_strings (r); + ret.partitions.partitions_val = r; + reply ((xdrproc_t) &xdr_guestfs_list_partitions_ret, (char *) &ret); + free_strings (r); } void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { + case GUESTFS_PROC_MOUNT: + mount_stub (xdr_in); + break; + case GUESTFS_PROC_SYNC: + sync_stub (xdr_in); + break; + case GUESTFS_PROC_TOUCH: + touch_stub (xdr_in); + break; case GUESTFS_PROC_CAT: cat_stub (xdr_in); break; @@ -171,14 +212,11 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_LS: ls_stub (xdr_in); break; - case GUESTFS_PROC_MOUNT: - mount_stub (xdr_in); + case GUESTFS_PROC_LIST_DEVICES: + list_devices_stub (xdr_in); break; - case GUESTFS_PROC_SYNC: - sync_stub (xdr_in); - break; - case GUESTFS_PROC_TOUCH: - touch_stub (xdr_in); + case GUESTFS_PROC_LIST_PARTITIONS: + list_partitions_stub (xdr_in); break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); |