X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fappliance.c;h=1df8c3616c97d1b85e4cdb613087bd0d40d13b09;hp=1740dfcf2e7d65a79c65110d3049d7328be98279;hb=635af5be04265f845186b40e9a9fe7b102ad6909;hpb=4beb2844091310012b5e28971707397d1d51d833 diff --git a/src/appliance.c b/src/appliance.c index 1740dfc..1df8c36 100644 --- a/src/appliance.c +++ b/src/appliance.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2010 Red Hat Inc. + * Copyright (C) 2010-2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -55,6 +55,7 @@ static int check_for_cached_appliance (guestfs_h *g, const char *supermin_path, static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, const char *checksum, uid_t uid, char **kernel, char **initrd, char **appliance); static int hard_link_to_cached_appliance (guestfs_h *g, const char *cachedir, char **kernel, char **initrd, char **appliance); static int run_supermin_helper (guestfs_h *g, const char *supermin_path, const char *cachedir, size_t cdlen); +static void print_febootstrap_command_line (guestfs_h *g, const char *argv[]); /* Locate or build the appliance. * @@ -241,14 +242,14 @@ calculate_supermin_checksum (guestfs_h *g, const char *supermin_path) } if (pclose (pp) == -1) { - perror ("pclose"); + warning (g, "pclose: %m"); return NULL; } len = strlen (checksum); if (len < 16) { /* sanity check */ - fprintf (stderr, "libguestfs: internal error: febootstrap-supermin-helper -f checksum returned a short string\n"); + warning (g, "febootstrap-supermin-helper -f checksum returned a short string"); return NULL; } @@ -308,7 +309,7 @@ check_for_cached_appliance (guestfs_h *g, uid_t uid, char **kernel, char **initrd, char **appliance) { - const char *tmpdir = guestfs_tmpdir (); + const char *tmpdir = guestfs___persistent_tmpdir (); /* len must be longer than the length of any pathname we can * generate in this function. @@ -320,7 +321,6 @@ check_for_cached_appliance (guestfs_h *g, snprintf (filename, len, "%s/checksum", cachedir); (void) mkdir (cachedir, 0755); - (void) utime (cachedir, NULL); /* See if the cache directory exists and passes some simple checks * to make sure it has not been tampered with. @@ -329,28 +329,34 @@ check_for_cached_appliance (guestfs_h *g, if (lstat (cachedir, &statbuf) == -1) return 0; if (statbuf.st_uid != uid) { - error (g, _("security: cached appliance %s is not owned by UID %d\n"), + error (g, _("security: cached appliance %s is not owned by UID %d"), filename, uid); return -1; } if (!S_ISDIR (statbuf.st_mode)) { - error (g, _("security: cached appliance %s is not a directory (mode %o)\n"), + error (g, _("security: cached appliance %s is not a directory (mode %o)"), filename, statbuf.st_mode); return -1; } if ((statbuf.st_mode & 0022) != 0) { - error (g, _("security: cached appliance %s is writable by group or other (mode %o)\n"), + error (g, _("security: cached appliance %s is writable by group or other (mode %o)"), cachedir, statbuf.st_mode); return -1; } + (void) utime (cachedir, NULL); + garbage_collect_appliances (cachedir); /* Try to open and acquire a lock on the checksum file. */ int fd = open (filename, O_RDONLY); if (fd == -1) return 0; +#ifdef HAVE_FUTIMENS (void) futimens (fd, NULL); +#else + (void) futimes (fd, NULL); +#endif struct flock fl; fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; @@ -418,7 +424,7 @@ build_supermin_appliance (guestfs_h *g, if (g->verbose) guestfs___print_timestamped_message (g, "begin building supermin appliance"); - const char *tmpdir = guestfs_tmpdir (); + const char *tmpdir = guestfs___persistent_tmpdir (); /* len must be longer than the length of any pathname we can * generate in this function. @@ -563,18 +569,23 @@ hard_link_to_cached_appliance (guestfs_h *g, perrorf (g, "link: %s %s", filename, *kernel); goto error; } + (void) lutimes (filename, NULL); /* lutimes because it's a symlink */ + snprintf (filename, len, "%s/initrd", cachedir); (void) unlink (*initrd); if (link (filename, *initrd) == -1) { perrorf (g, "link: %s %s", filename, *initrd); goto error; } + (void) utime (filename, NULL); + snprintf (filename, len, "%s/root", cachedir); (void) unlink (*appliance); if (link (filename, *appliance) == -1) { perrorf (g, "link: %s %s", filename, *appliance); goto error; } + (void) utime (filename, NULL); return 0; @@ -630,6 +641,9 @@ run_supermin_helper (guestfs_h *g, const char *supermin_path, argv[i++] = root; argv[i++] = NULL; + if (g->verbose) + print_febootstrap_command_line (g, argv); + pid_t pid = fork (); if (pid == -1) { perrorf (g, "fork"); @@ -637,9 +651,6 @@ run_supermin_helper (guestfs_h *g, const char *supermin_path, } if (pid > 0) { /* Parent. */ - if (g->verbose) - guestfs___print_timestamped_argv (g, argv); - int status; if (waitpid (pid, &status, 0) == -1) { perrorf (g, "waitpid"); @@ -664,6 +675,54 @@ run_supermin_helper (guestfs_h *g, const char *supermin_path, _exit (EXIT_FAILURE); } +static void +print_febootstrap_command_line (guestfs_h *g, const char *argv[]) +{ + int i; + int needs_quote; + char *buf; + size_t len; + + /* Calculate length of the buffer needed. This is an overestimate. */ + len = 0; + for (i = 0; argv[i] != NULL; ++i) + len += strlen (argv[i]) + 32; + + buf = malloc (len); + if (buf == NULL) { + warning (g, "malloc: %m"); + return; + } + + len = 0; + for (i = 0; argv[i] != NULL; ++i) { + if (i > 0) { + strcpy (&buf[len], " "); + len++; + } + + /* Does it need shell quoting? This only deals with simple cases. */ + needs_quote = strcspn (argv[i], " ") != strlen (argv[i]); + + if (needs_quote) { + strcpy (&buf[len], "'"); + len++; + } + + strcpy (&buf[len], argv[i]); + len += strlen (argv[i]); + + if (needs_quote) { + strcpy (&buf[len], "'"); + len++; + } + } + + guestfs___print_timestamped_message (g, "%s", buf); + + free (buf); +} + /* Search elements of g->path, returning the first path element which * matches the predicate function 'pred'. *