/* 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
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.
*
return NULL;
}
- if (pclose (pp) == -1) {
- perror ("pclose");
+ if (pclose (pp) != 0) {
+ 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;
}
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.
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.
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;
/* Releases the lock on checksum. */
if (close (fd) == -1) {
perrorf (g, "close");
+ /* Allocated in hard_link_to_cached_appliance above, must be
+ * freed along this error path.
+ */
+ free (*kernel);
+ free (*initrd);
+ free (*appliance);
return -1;
}
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.
/* Releases the lock on checksum. */
if (close (fd) == -1) {
perrorf (g, "close");
+ /* Allocated in hard_link_to_cached_appliance above, must be
+ * freed along this error path.
+ */
+ free (*kernel);
+ free (*initrd);
+ free (*appliance);
return -1;
}
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;
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");
}
if (pid > 0) { /* Parent. */
- if (g->verbose)
- guestfs___print_timestamped_argv (g, argv);
-
int status;
if (waitpid (pid, &status, 0) == -1) {
perrorf (g, "waitpid");
_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'.
*