diff --git a/appliance/init b/appliance/init index eb1b4876c..cca62e710 100755 --- a/appliance/init +++ b/appliance/init @@ -88,11 +88,26 @@ for f in /sys/block/{h,s,ub,v}d*/queue/scheduler; do echo noop > $f; done # Update the system clock. hwclock -u -s +# Parse the kernel command line. +if grep -sq guestfs_verbose=1 /proc/cmdline; then + guestfs_verbose=1 +fi +if grep -sq guestfs_network=1 /proc/cmdline; then + guestfs_network=1 +fi +if grep -sq guestfs_rescue=1 /proc/cmdline; then + guestfs_rescue=1 +fi +if grep -sq guestfs_noreboot=1 /proc/cmdline; then + guestfs_noreboot=1 +fi +eval `grep -Eo 'guestfs_channel=[^[:space:]]+' /proc/cmdline` + # Set up the network. ip addr add 127.0.0.1/8 brd + dev lo scope host ip link set dev lo up -if grep -sq guestfs_network=1 /proc/cmdline; then +if test "$guestfs_network" = 1; then if dhclient --version >/dev/null 2>&1; then dhclient else @@ -113,7 +128,7 @@ lvm vgchange -aay --sysinit ldmtool create all # These are useful when debugging. -if grep -sq guestfs_verbose=1 /proc/cmdline; then +if test "$guestfs_verbose" = 1; then uname -a ls -lR /dev cat /proc/mounts @@ -132,7 +147,7 @@ if grep -sq guestfs_verbose=1 /proc/cmdline; then echo -n "uptime: "; cat /proc/uptime fi -if ! grep -sq guestfs_rescue=1 /proc/cmdline; then +if ! test "$guestfs_rescue" = 1; then # Run the daemon. # Run the daemon under valgrind if ./configure --enable-valgrind-daemon @@ -145,7 +160,19 @@ if ! grep -sq guestfs_rescue=1 /proc/cmdline; then fi # Run guestfsd, under valgrind if asked. - $vg guestfsd + cmd="$vg guestfsd" + if test "x$guestfs_channel" != "x"; then + cmd="$cmd --channel $guestfs_channel" + fi + if test "$guestfs_verbose" = 1; then + cmd="$cmd --verbose" + fi + if test "$guestfs_network" = 1; then + cmd="$cmd --network" + fi + echo $cmd + $cmd + if [ $? -eq 119 ]; then echo "DAEMON VALGRIND FAILED" # Sleep so valgrind messages are seen by the host. Note this @@ -181,7 +208,7 @@ fi sync -if ! grep -sq guestfs_noreboot=1 /proc/cmdline; then +if ! test "$guestfs_noreboot" = 1; then # qemu has the -no-reboot flag, so issuing a reboot here actually # causes qemu to exit gracefully. reboot -f diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 4995a2b9c..584c685a2 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -58,8 +58,6 @@ GUESTFSD_EXT_CMD(str_udevadm, udevadm); -static char *read_cmdline (void); - #ifndef MAX # define MAX(a,b) ((a)>(b)?(a):(b)) #endif @@ -139,16 +137,18 @@ usage (void) int main (int argc, char *argv[]) { - static const char *options = "lrtv?"; + static const char *options = "c:lnrtv?"; static const struct option long_options[] = { { "help", 0, 0, '?' }, + { "channel", 1, 0, 'c' }, { "listen", 0, 0, 'l' }, + { "network", 0, 0, 'n' }, { "test", 0, 0, 't' }, { "verbose", 0, 0, 'v' }, { 0, 0, 0, 0 } }; int c; - char *cmdline; + const char *channel = NULL; int listen_mode = 0; ignore_value (chdir ("/")); @@ -188,10 +188,18 @@ main (int argc, char *argv[]) if (c == -1) break; switch (c) { + case 'c': + channel = optarg; + break; + case 'l': listen_mode = 1; break; + case 'n': + enable_network = 1; + break; + /* The -r flag is used when running standalone. It changes * several aspects of the daemon. */ @@ -225,23 +233,6 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - cmdline = read_cmdline (); - - /* Set the verbose flag. */ - verbose = verbose || - (cmdline && strstr (cmdline, "guestfs_verbose=1") != NULL); - if (verbose) - printf ("verbose daemon enabled\n"); - - if (verbose) { - if (cmdline) - printf ("linux command line: %s\n", cmdline); - else - printf ("could not read linux command line\n"); - } - - enable_network = cmdline && strstr (cmdline, "guestfs_network=1") != NULL; - #ifndef WIN32 /* Make sure SIGPIPE doesn't kill us. */ struct sigaction sa; @@ -283,17 +274,8 @@ main (int argc, char *argv[]) copy_lvm (); /* Connect to virtio-serial channel. */ - char *channel, *p; - if (cmdline && (p = strstr (cmdline, "guestfs_channel=")) != NULL) { - p += 16; - channel = strndup (p, strcspn (p, " \n")); - } - else - channel = strdup (VIRTIO_SERIAL_CHANNEL); - if (!channel) { - perror ("strdup"); - exit (EXIT_FAILURE); - } + if (!channel) + channel = VIRTIO_SERIAL_CHANNEL; if (verbose) printf ("trying to open virtio-serial channel '%s'\n", channel); @@ -347,10 +329,6 @@ main (int argc, char *argv[]) if (STRPREFIX (channel, "/dev/ttyS")) makeraw (channel, sock); - /* cmdline, channel not used after this point */ - free (cmdline); - free (channel); - /* Wait for udev devices to be created. If you start libguestfs, * especially with disks that contain complex (eg. mdadm) data * already, then it is possible for the 'mdadm' and LVM commands @@ -384,55 +362,6 @@ main (int argc, char *argv[]) exit (EXIT_SUCCESS); } -/* Read /proc/cmdline. */ -static char * -read_cmdline (void) -{ - int fd = open ("/proc/cmdline", O_RDONLY|O_CLOEXEC); - if (fd == -1) { - perror ("/proc/cmdline"); - return NULL; - } - - size_t len = 0; - ssize_t n; - char buf[256]; - char *r = NULL; - - for (;;) { - n = read (fd, buf, sizeof buf); - if (n == -1) { - perror ("read"); - free (r); - close (fd); - return NULL; - } - if (n == 0) - break; - char *newr = realloc (r, len + n + 1); /* + 1 is for terminating NUL */ - if (newr == NULL) { - perror ("realloc"); - free (r); - close (fd); - return NULL; - } - r = newr; - memcpy (&r[len], buf, n); - len += n; - } - - if (r) - r[len] = '\0'; - - if (close (fd) == -1) { - perror ("close"); - free (r); - return NULL; - } - - return r; -} - /* Try to make the socket raw, but don't fail if it's not possible. */ static void makeraw (const char *channel, int fd) diff --git a/daemon/guestfsd.pod b/daemon/guestfsd.pod index 22c800362..f1672ae0b 100644 --- a/daemon/guestfsd.pod +++ b/daemon/guestfsd.pod @@ -50,6 +50,14 @@ removed. Display brief help. +=item B<-c> CHANNEL + +=item B<--channel> CHANNEL + +Pass the name of the virtio-serial channel, serial port, etc. over +which guestfsd will communicate with the library. If this parameter +is not given, then an internal default port is used. + =item B<-l> =item B<--listen> @@ -59,6 +67,12 @@ already exists, create the channel as a Unix domain socket, listen on it, and accept a single connection. This is mainly used for testing the daemon. +=item B<-n> + +=item B<--network> + +Enable network features in the daemon. + =item B<-r> Set the root filesystem to be F (instead of the default which is