summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-04-06 12:55:26 +0100
committerRichard Jones <rjones@redhat.com>2009-04-06 12:55:26 +0100
commit8e570870f577ff0c3db074f88924633b559af5d4 (patch)
tree711af1263615c8cd977eceb0e4286425b53bd725 /daemon
parent1cf85b1e60e85c4940869c6291d75ac44a5bd190 (diff)
downloadlibguestfs-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.am1
-rw-r--r--daemon/actions.h8
-rw-r--r--daemon/daemon.h2
-rw-r--r--daemon/devsparts.c133
-rw-r--r--daemon/guestfsd.c24
-rw-r--r--daemon/ls.c10
-rw-r--r--daemon/stubs.c144
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);