mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
guestfish -i and virt-inspector work on filenames containing spaces (RHBZ#507810).
This commit fixes a long-standing bug which prevented guestfish -i and virt-inspector from working on disk images which had a space in the filename (or other unsafe characters). It works by ensuring that the strings passed between guestfish -i and virt-inspector are quoted correctly in both directions. Note that this commit adds a dependency from virt-inspector to the perl module String::ShellQuote. We have previously used this module in virt-make-fs.
This commit is contained in:
115
fish/fish.c
115
fish/fish.c
@@ -1,5 +1,5 @@
|
||||
/* guestfish - the filesystem interactive shell
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
* Copyright (C) 2009-2010 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
|
||||
@@ -66,6 +66,7 @@ static void cmdline (char *argv[], int optind, int argc);
|
||||
static void initialize_readline (void);
|
||||
static void cleanup_readline (void);
|
||||
static void add_history_line (const char *);
|
||||
static int print_shell_quote (FILE *stream, const char *str);
|
||||
|
||||
/* Currently open libguestfs handle. */
|
||||
guestfs_h *g;
|
||||
@@ -362,9 +363,6 @@ main (int argc, char *argv[])
|
||||
|
||||
/* Inspector mode invalidates most of the other arguments. */
|
||||
if (inspector) {
|
||||
char cmd[1024];
|
||||
int r;
|
||||
|
||||
if (drvs || mps || remote_control_listen || remote_control ||
|
||||
guestfs_get_selinux (g)) {
|
||||
fprintf (stderr, _("%s: cannot use -i option with -a, -m, -N, "
|
||||
@@ -379,44 +377,89 @@ main (int argc, char *argv[])
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strcpy (cmd, "a=`virt-inspector");
|
||||
char *cmd;
|
||||
size_t cmdlen;
|
||||
FILE *fp = open_memstream (&cmd, &cmdlen);
|
||||
if (fp == NULL) {
|
||||
perror ("open_memstream");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf (fp, "virt-inspector");
|
||||
while (optind < argc) {
|
||||
if (strlen (cmd) + strlen (argv[optind]) + strlen (real_argv0) + 60
|
||||
>= sizeof cmd) {
|
||||
fprintf (stderr,
|
||||
_("%s: virt-inspector command too long for fixed-size buffer\n"),
|
||||
program_name);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
strcat (cmd, " '");
|
||||
strcat (cmd, argv[optind]);
|
||||
strcat (cmd, "'");
|
||||
fputc (' ', fp);
|
||||
print_shell_quote (fp, argv[optind]);
|
||||
optind++;
|
||||
}
|
||||
|
||||
if (read_only)
|
||||
strcat (cmd, " --ro-fish");
|
||||
fprintf (fp, " --ro-fish");
|
||||
else
|
||||
strcat (cmd, " --fish");
|
||||
fprintf (fp, " --fish");
|
||||
|
||||
sprintf (&cmd[strlen(cmd)], "` && %s $a", real_argv0);
|
||||
|
||||
if (guestfs_get_verbose (g))
|
||||
strcat (cmd, " -v");
|
||||
if (!guestfs_get_autosync (g))
|
||||
strcat (cmd, " -n");
|
||||
if (guestfs_get_trace (g))
|
||||
strcat (cmd, " -x");
|
||||
if (fclose (fp) == -1) {
|
||||
perror ("fclose");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr,
|
||||
"%s -i: running virt-inspector command:\n%s\n", program_name, cmd);
|
||||
"%s -i: running: %s\n", program_name, cmd);
|
||||
|
||||
r = system (cmd);
|
||||
if (r == -1) {
|
||||
perror ("system");
|
||||
FILE *pp = popen (cmd, "r");
|
||||
if (pp == NULL) {
|
||||
perror (cmd);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *cmd2;
|
||||
fp = open_memstream (&cmd2, &cmdlen);
|
||||
if (fp == NULL) {
|
||||
perror ("open_memstream");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf (fp, "%s", real_argv0);
|
||||
|
||||
if (guestfs_get_verbose (g))
|
||||
fprintf (fp, " -v");
|
||||
if (!guestfs_get_autosync (g))
|
||||
fprintf (fp, " -n");
|
||||
if (guestfs_get_trace (g))
|
||||
fprintf (fp, " -x");
|
||||
|
||||
char *insp = NULL;
|
||||
size_t insplen;
|
||||
if (getline (&insp, &insplen, pp) == -1) {
|
||||
perror (cmd);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
fprintf (fp, " %s", insp);
|
||||
|
||||
if (pclose (pp) == -1) {
|
||||
perror (cmd);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fclose (fp) == -1) {
|
||||
perror ("fclose");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr,
|
||||
"%s -i: running: %s\n", program_name, cmd2);
|
||||
|
||||
int r = system (cmd2);
|
||||
if (r == -1) {
|
||||
perror (cmd2);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
free (cmd);
|
||||
free (cmd2);
|
||||
free (insp);
|
||||
|
||||
exit (WEXITSTATUS (r));
|
||||
}
|
||||
|
||||
@@ -1616,3 +1659,17 @@ file_out (const char *arg)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
print_shell_quote (FILE *stream, const char *str)
|
||||
{
|
||||
#define SAFE(c) (c_isalnum((c)) || \
|
||||
(c) == '/' || (c) == '-' || (c) == '_' || (c) == '.')
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i]; ++i) {
|
||||
if (!SAFE(str[i]))
|
||||
putc ('\\', stream);
|
||||
putc (str[i], stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use Pod::Usage;
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
use XML::Writer;
|
||||
use String::ShellQuote qw(shell_quote);
|
||||
use Locale::TextDomain 'libguestfs';
|
||||
|
||||
# Optional:
|
||||
@@ -298,13 +299,17 @@ if ($output eq "fish" || $output eq "ro-fish") {
|
||||
print "--ro ";
|
||||
}
|
||||
|
||||
print "-a $_ " foreach @images;
|
||||
foreach (@images) {
|
||||
printf "-a %s ", shell_quote ($_);
|
||||
}
|
||||
|
||||
my $mounts = $oses->{$root_dev}->{mounts};
|
||||
# Have to mount / first. Luckily '/' is early in the ASCII
|
||||
# character set, so this should be OK.
|
||||
foreach (sort keys %$mounts) {
|
||||
print "-m $mounts->{$_}:$_ " if $_ ne "swap" && $_ ne "none";
|
||||
if ($_ ne "swap" && $_ ne "none") {
|
||||
printf "-m %s ", shell_quote ("$mounts->{$_}:$_");
|
||||
}
|
||||
}
|
||||
print "\n"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user