diff options
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/actions.h | 2 | ||||
-rw-r--r-- | daemon/initrd.c | 88 | ||||
-rw-r--r-- | daemon/mount.c | 45 | ||||
-rw-r--r-- | daemon/stubs.c | 60 |
5 files changed, 196 insertions, 0 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 2884e936..88c382cf 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -43,6 +43,7 @@ guestfsd_SOURCES = \ guestfsd.c \ headtail.c \ hexdump.c \ + initrd.c \ ls.c \ lvm.c \ mount.c \ diff --git a/daemon/actions.h b/daemon/actions.h index 7d87b677..1d412dcc 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -148,3 +148,5 @@ extern char **do_tail_n (int nrlines, char *path); extern char *do_df (void); extern char *do_df_h (void); extern int64_t do_du (char *path); +extern char **do_initrd_list (char *path); +extern int do_mount_loop (char *file, char *mountpoint); diff --git a/daemon/initrd.c b/daemon/initrd.c new file mode 100644 index 00000000..513ed8da --- /dev/null +++ b/daemon/initrd.c @@ -0,0 +1,88 @@ +/* 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 "../src/guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" + +char ** +do_initrd_list (char *path) +{ + FILE *fp; + int len; + char *cmd; + char filename[PATH_MAX]; + char **filenames = NULL; + int size = 0, alloc = 0; + + NEED_ROOT (NULL); + ABS_PATH (path, NULL); + + /* "zcat /sysroot/<path> | cpio --quiet -it", but path must be quoted. */ + len = 64 + 2 * strlen (path); + cmd = malloc (len); + if (!cmd) { + reply_with_perror ("malloc"); + return NULL; + } + + strcpy (cmd, "zcat /sysroot"); + shell_quote (cmd+13, len-13, path); + strcat (cmd, " | cpio --quiet -it"); + + fprintf (stderr, "%s\n", cmd); + + fp = popen (cmd, "r"); + if (fp == NULL) { + reply_with_perror ("popen: %s", cmd); + free (cmd); + return NULL; + } + free (cmd); + + while (fgets (filename, sizeof filename, fp) != NULL) { + len = strlen (filename); + if (len > 0 && filename[len-1] == '\n') + filename[len-1] = '\0'; + + if (add_string (&filenames, &size, &alloc, filename) == -1) { + pclose (fp); + return NULL; + } + } + + if (add_string (&filenames, &size, &alloc, NULL) == -1) { + pclose (fp); + return NULL; + } + + if (pclose (fp) == -1) { + reply_with_perror ("pclose"); + free_strings (filenames); + return NULL; + } + + return filenames; +} diff --git a/daemon/mount.c b/daemon/mount.c index 4955fcf3..b0cb496e 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -71,6 +71,7 @@ do_mount_vfs (char *options, char *vfstype, else r = command (NULL, &error, "mount", "-o", options, device, mp, NULL); + free (mp); if (r == -1) { reply_with_error ("mount: %s on %s: %s", device, mountpoint, error); free (error); @@ -277,3 +278,47 @@ do_umount_all (void) return 0; } + +/* Mount using the loopback device. You can't use the generic + * do_mount call for this because the first parameter isn't a + * device. + */ +int +do_mount_loop (char *file, char *mountpoint) +{ + int len, r; + char *buf, *mp; + char *error; + + NEED_ROOT (-1); + ABS_PATH (file, -1); + + /* We have to prefix /sysroot on both the filename and the mountpoint. */ + len = strlen (mountpoint) + 9; + mp = malloc (len); + if (!mp) { + reply_with_perror ("malloc"); + return -1; + } + snprintf (mp, len, "/sysroot%s", mountpoint); + + len = strlen (file) + 9; + buf = malloc (len); + if (!file) { + reply_with_perror ("malloc"); + free (mp); + return -1; + } + snprintf (buf, len, "/sysroot%s", file); + + r = command (NULL, &error, "mount", "-o", "loop", buf, mp, NULL); + free (mp); + free (buf); + if (r == -1) { + reply_with_error ("mount: %s on %s: %s", file, mountpoint, error); + free (error); + return -1; + } + + return 0; +} diff --git a/daemon/stubs.c b/daemon/stubs.c index 67e6ef5b..6d7cb0e7 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -3205,6 +3205,60 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_du_args, (char *) &args); } +static void initrd_list_stub (XDR *xdr_in) +{ + char **r; + struct guestfs_initrd_list_args args; + char *path; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_initrd_list_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "initrd_list"); + return; + } + path = args.path; + + r = do_initrd_list (path); + if (r == NULL) + /* do_initrd_list has already called reply_with_error */ + goto done; + + struct guestfs_initrd_list_ret ret; + ret.filenames.filenames_len = count_strings (r); + ret.filenames.filenames_val = r; + reply ((xdrproc_t) &xdr_guestfs_initrd_list_ret, (char *) &ret); + free_strings (r); +done: + xdr_free ((xdrproc_t) xdr_guestfs_initrd_list_args, (char *) &args); +} + +static void mount_loop_stub (XDR *xdr_in) +{ + int r; + struct guestfs_mount_loop_args args; + char *file; + char *mountpoint; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_mount_loop_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "mount_loop"); + return; + } + file = args.file; + mountpoint = args.mountpoint; + + r = do_mount_loop (file, mountpoint); + if (r == -1) + /* do_mount_loop has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_mount_loop_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -3589,6 +3643,12 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_DU: du_stub (xdr_in); break; + case GUESTFS_PROC_INITRD_LIST: + initrd_list_stub (xdr_in); + break; + case GUESTFS_PROC_MOUNT_LOOP: + mount_loop_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory", proc_nr); } |