summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-10-18 15:07:18 +0100
committerRichard W.M. Jones <rjones@redhat.com>2012-10-18 22:11:52 +0100
commit8d4f3f85f2bdf38a2868ea785cf66efa65af25f3 (patch)
tree18b6ffcc9426c8aa751588e41857eb14f26feaff /src
parentfa209341f834d1ab00e0d9fa767c8221506285e4 (diff)
downloadlibguestfs-8d4f3f85f2bdf38a2868ea785cf66efa65af25f3.tar.gz
libguestfs-8d4f3f85f2bdf38a2868ea785cf66efa65af25f3.tar.xz
libguestfs-8d4f3f85f2bdf38a2868ea785cf66efa65af25f3.zip
appliance: Use command mini-library to run febootstrap-supermin-helper (RHBZ#713678)
Diffstat (limited to 'src')
-rw-r--r--src/appliance.c227
1 files changed, 70 insertions, 157 deletions
diff --git a/src/appliance.c b/src/appliance.c
index 9db42cb4..2241e181 100644
--- a/src/appliance.c
+++ b/src/appliance.c
@@ -54,8 +54,7 @@ static char *calculate_supermin_checksum (guestfs_h *g, const char *supermin_pat
static int check_for_cached_appliance (guestfs_h *g, const char *supermin_path, const char *checksum, uid_t uid, char **kernel, char **initrd, char **appliance);
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[]);
+static int run_supermin_helper (guestfs_h *g, const char *supermin_path, const char *cachedir);
/* RHBZ#790721: It makes no sense to have multiple threads racing to
* build the appliance from within a single process, and the code
@@ -245,6 +244,18 @@ contains_supermin_appliance (guestfs_h *g, const char *path, void *data)
return dir_contains_files (path, "supermin.d", NULL);
}
+#define MAX_CHECKSUM_LEN 256
+
+static void
+read_checksum (guestfs_h *g, void *checksumv, const char *line, size_t len)
+{
+ char *checksum = checksumv;
+
+ if (len > MAX_CHECKSUM_LEN)
+ return;
+ strcpy (checksum, line);
+}
+
/* supermin_path is a path which is known to contain a supermin
* appliance. Using febootstrap-supermin-helper -f checksum calculate
* the checksum so we can see if it is cached.
@@ -252,59 +263,44 @@ contains_supermin_appliance (guestfs_h *g, const char *path, void *data)
static char *
calculate_supermin_checksum (guestfs_h *g, const char *supermin_path)
{
- size_t len = 2 * strlen (supermin_path) + 256;
- char cmd[len];
+ size_t len;
+ struct command *cmd;
int pass_u_g_args = getuid () != geteuid () || getgid () != getegid ();
+ int r;
+ char checksum[MAX_CHECKSUM_LEN + 1] = { 0 };
- if (!pass_u_g_args)
- snprintf (cmd, len,
- "febootstrap-supermin-helper%s "
- "-f checksum "
- "'%s/supermin.d' "
- host_cpu,
- g->verbose ? " --verbose" : "",
- supermin_path);
- else
- snprintf (cmd, len,
- "febootstrap-supermin-helper%s "
- "-u %i "
- "-g %i "
- "-f checksum "
- "'%s/supermin.d' "
- host_cpu,
- g->verbose ? " --verbose" : "",
- geteuid (), getegid (),
- supermin_path);
-
+ cmd = guestfs___new_command (g);
+ guestfs___cmd_add_arg (cmd, "febootstrap-supermin-helper");
if (g->verbose)
- guestfs___print_timestamped_message (g, "%s", cmd);
-
+ guestfs___cmd_add_arg (cmd, "--verbose");
+ if (pass_u_g_args) {
+ guestfs___cmd_add_arg (cmd, "-u");
+ guestfs___cmd_add_arg_format (cmd, "%d", geteuid ());
+ guestfs___cmd_add_arg (cmd, "-g");
+ guestfs___cmd_add_arg_format (cmd, "%d", getegid ());
+ }
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "checksum");
+ guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
+ guestfs___cmd_add_arg (cmd, host_cpu);
+ guestfs___cmd_set_stdout_callback (cmd, read_checksum, checksum, 0);
+
+ r = guestfs___cmd_run (cmd);
/* Errors here are non-fatal, so we don't need to call error(). */
- FILE *pp = popen (cmd, "r");
- if (pp == NULL)
- return NULL;
-
- char checksum[256];
- if (fgets (checksum, sizeof checksum, pp) == NULL) {
- pclose (pp);
+ if (r == -1) {
+ guestfs___cmd_close (cmd);
return NULL;
}
+ guestfs___cmd_close (cmd);
- if (pclose (pp) != 0) {
- warning (g, "pclose: %m");
- return NULL;
- }
+ debug (g, "checksum of existing appliance: %s", checksum);
len = strlen (checksum);
-
if (len < 16) { /* sanity check */
warning (g, "febootstrap-supermin-helper -f checksum returned a short string");
return NULL;
}
- if (len > 0 && checksum[len-1] == '\n')
- checksum[--len] = '\0';
-
return safe_strndup (g, checksum, len);
}
@@ -498,7 +494,7 @@ build_supermin_appliance (guestfs_h *g,
if (g->verbose)
guestfs___print_timestamped_message (g, "run febootstrap-supermin-helper");
- int r = run_supermin_helper (g, supermin_path, tmpcd, len);
+ int r = run_supermin_helper (g, supermin_path, tmpcd);
if (r == -1) {
guestfs___remove_tmpdir (g, tmpcd);
return -1;
@@ -672,127 +668,44 @@ hard_link_to_cached_appliance (guestfs_h *g,
*/
static int
run_supermin_helper (guestfs_h *g, const char *supermin_path,
- const char *cachedir, size_t cdlen)
+ const char *cachedir)
{
- size_t pathlen = strlen (supermin_path);
-
- const char *argv[30];
- size_t i = 0;
-
- char uid[32];
- snprintf (uid, sizeof uid, "%i", geteuid ());
- char gid[32];
- snprintf (gid, sizeof gid, "%i", getegid ());
- char supermin_d[pathlen + 32];
- snprintf (supermin_d, pathlen + 32, "%s/supermin.d", supermin_path);
- char kernel[cdlen + 32];
- snprintf (kernel, cdlen + 32, "%s/kernel", cachedir);
- char initrd[cdlen + 32];
- snprintf (initrd, cdlen + 32, "%s/initrd", cachedir);
- char root[cdlen + 32];
- snprintf (root, cdlen + 32, "%s/root", cachedir);
-
- int pass_u_g_args = getuid () != geteuid () || getgid () != getegid ();
-
- argv[i++] = "febootstrap-supermin-helper";
+ struct command *cmd;
+ int r;
+ uid_t uid = getuid ();
+ uid_t euid = geteuid ();
+ gid_t gid = getgid ();
+ gid_t egid = getegid ();
+ int pass_u_g_args = uid != euid || gid != egid;
+
+ cmd = guestfs___new_command (g);
+ guestfs___cmd_add_arg (cmd, "febootstrap-supermin-helper");
if (g->verbose)
- argv[i++] = "--verbose";
+ guestfs___cmd_add_arg (cmd, "--verbose");
if (pass_u_g_args) {
- argv[i++] = "-u";
- argv[i++] = uid;
- argv[i++] = "-g";
- argv[i++] = gid;
- }
- argv[i++] = "--copy-kernel";
- argv[i++] = "-f";
- argv[i++] = "ext2";
- argv[i++] = supermin_d;
- argv[i++] = host_cpu;
- argv[i++] = kernel;
- argv[i++] = initrd;
- 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");
+ guestfs___cmd_add_arg (cmd, "-u");
+ guestfs___cmd_add_arg_format (cmd, "%d", euid);
+ guestfs___cmd_add_arg (cmd, "-g");
+ guestfs___cmd_add_arg_format (cmd, "%d", egid);
+ }
+ guestfs___cmd_add_arg (cmd, "--copy-kernel");
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "ext2");
+ guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
+ guestfs___cmd_add_arg (cmd, host_cpu);
+ guestfs___cmd_add_arg_format (cmd, "%s/kernel", cachedir);
+ guestfs___cmd_add_arg_format (cmd, "%s/initrd", cachedir);
+ guestfs___cmd_add_arg_format (cmd, "%s/root", cachedir);
+
+ r = guestfs___cmd_run (cmd);
+ if (r == -1)
+ return -1;
+ if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
+ error (g, _("external command failed, see earlier error messages"));
return -1;
}
- if (pid > 0) { /* Parent. */
- int status;
- if (waitpid (pid, &status, 0) == -1) {
- perrorf (g, "waitpid");
- return -1;
- }
- if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) {
- error (g, _("external command failed, see earlier error messages"));
- return -1;
- }
- return 0;
- }
-
- /* Child. */
-
- /* Set a sensible umask in the subprocess, so kernel and initrd
- * output files are world-readable (RHBZ#610880).
- */
- umask (0022);
-
- execvp ("febootstrap-supermin-helper", (char * const *) argv);
- perror ("execvp");
- _exit (EXIT_FAILURE);
-}
-
-static void
-print_febootstrap_command_line (guestfs_h *g, const char *argv[])
-{
- size_t 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);
+ return 0;
}
/* Search elements of g->path, returning the first path element which