[Pkg-libvirt-commits] [libguestfs] 162/233: make-fs: Use an anonymous pipe instead of a named pipe.
Hilko Bengen
bengen at moszumanska.debian.org
Wed Feb 19 21:11:55 UTC 2014
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to branch experimental
in repository libguestfs.
commit 5bf8c81d7d5bf438b13f3866750362d002847129
Author: Richard W.M. Jones <rjones at redhat.com>
Date: Wed Jan 29 08:08:33 2014 +0000
make-fs: Use an anonymous pipe instead of a named pipe.
The previous translation from Perl slavishly followed the Perl code a
bit too much and used a named pipe to communicate between the
uncompressing subprocess and libguestfs tar-in. From C we can use an
anonymous pipe instead.
This updates commit d3512deb6728dffbb3a958c7168b81dbde56d748.
---
make-fs/make-fs.c | 121 +++++++++++++++++++++++++-----------------------------
1 file changed, 55 insertions(+), 66 deletions(-)
diff --git a/make-fs/make-fs.c b/make-fs/make-fs.c
index 4f9a8c5..ec1ff1a 100644
--- a/make-fs/make-fs.c
+++ b/make-fs/make-fs.c
@@ -292,61 +292,44 @@ exec_command_count_output (char **argv, uint64_t *bytes_rtn)
_exit (EXIT_FAILURE);
}
-/* Execute a command in the background (don't wait) and send the output
- * to a file.
+/* Execute a command in the background (don't wait) and send the
+ * output to a pipe. It returns the PID of the subprocess and the
+ * file descriptor of the pipe.
*/
static int
-bg_command (char **argv, const char *file)
+bg_command (char **argv, int *fd_rtn, pid_t *pid_rtn)
{
- pid_t pid;
- int fd;
+ int fd[2];
- pid = fork ();
- if (pid == -1) {
+ if (pipe (fd) == -1) {
+ perror ("pipe");
+ return -1;
+ }
+ *pid_rtn = fork ();
+ if (*pid_rtn == -1) {
perror ("fork");
return -1;
}
- if (pid > 0)
+ if (*pid_rtn > 0) {
+ close (fd[1]);
+
+ /* Return read-side of the pipe. */
+ *fd_rtn = fd[0];
+
/* Return immediately in the parent without waiting. */
return 0;
+ }
/* Child process. */
- fd = open (file, O_WRONLY|O_NOCTTY);
- if (fd == -1) {
- perror (file);
- _exit (EXIT_FAILURE);
- }
- dup2 (fd, 1);
- close (fd);
+ close (fd[0]);
+ dup2 (fd[1], 1);
+ close (fd[1]);
execvp (argv[0], argv);
perror ("execvp");
_exit (EXIT_FAILURE);
}
-static char *
-create_pipe (void)
-{
- char *tmppipe;
-
- if (asprintf (&tmppipe, "/tmp/makefsXXXXXX") == -1) {
- perror ("asprintf");
- return NULL;
- }
- if (mkstemp (tmppipe) == -1) {
- perror (tmppipe);
- return NULL;
- }
-
- /* Convert the temporary file into a pipe. */
- unlink (tmppipe);
- if (mkfifo (tmppipe, 0600) == -1) {
- perror ("mkfifo");
- return NULL;
- }
- return tmppipe;
-}
-
/* Estimate the size of the input. This returns the estimated size
* (in bytes) of the input. It also sets ifmt to the format of the
* input, either the string "directory" if the input is a directory,
@@ -506,19 +489,19 @@ estimate_input (const char *input, uint64_t *estimate_rtn, char **ifmt_rtn)
* just sets ifile = input. However normally the input will be either
* a directory or a compressed tarball. In that case we set up an
* external command to do the tar/uncompression to a temporary pipe,
- * and set ifile to the name of the pipe.
+ * and set ifile to the name of the pipe. If there is a subprocess,
+ * the PID is returned so that callers can wait on it.
*/
static int
prepare_input (const char *input, const char *ifmt,
- char **ifile_rtn, int *ifile_delete_on_exit)
+ char **ifile_rtn, int *fd_rtn, pid_t *pid_rtn)
{
- char *tmppipe;
const char *argv[7];
+ *pid_rtn = 0;
+ *fd_rtn = -1;
+
if (STREQ (ifmt, "directory")) {
- tmppipe = create_pipe ();
- if (tmppipe == NULL)
- return -1;
argv[0] = "tar";
argv[1] = "-C";
argv[2] = input;
@@ -527,20 +510,16 @@ prepare_input (const char *input, const char *ifmt,
argv[5] = ".";
argv[6] = NULL;
- if (bg_command ((char **) argv, tmppipe) == -1) {
- unlink (tmppipe);
- free (tmppipe);
+ if (bg_command ((char **) argv, fd_rtn, pid_rtn) == -1)
return -1;
- }
- *ifile_rtn = tmppipe;
- *ifile_delete_on_exit = 1;
+ if (asprintf (ifile_rtn, "/dev/fd/%d", *fd_rtn) == -1) {
+ perror ("asprintf");
+ return -1;
+ }
}
else {
if (strstr (ifmt, "compress")) {
- tmppipe = create_pipe ();
- if (tmppipe == NULL)
- return -1;
if (strstr (ifmt, "compress'd")) {
argv[0] = "uncompress";
argv[1] = "-c";
@@ -569,14 +548,13 @@ prepare_input (const char *input, const char *ifmt,
/* Shouldn't happen - see estimate_input above. */
abort ();
- if (bg_command ((char **) argv, tmppipe) == -1) {
- unlink (tmppipe);
- free (tmppipe);
+ if (bg_command ((char **) argv, fd_rtn, pid_rtn) == -1)
return -1;
- }
- *ifile_rtn = tmppipe;
- *ifile_delete_on_exit = 1;
+ if (asprintf (ifile_rtn, "/dev/fd/%d", *fd_rtn) == -1) {
+ perror ("asprintf");
+ return -1;
+ }
}
else {
/* Plain tar file, read directly from the file. */
@@ -585,7 +563,6 @@ prepare_input (const char *input, const char *ifmt,
perror ("strdup");
return -1;
}
- *ifile_delete_on_exit = 0;
}
}
@@ -632,7 +609,8 @@ do_make_fs (const char *input, const char *output_str)
struct guestfs_disk_create_argv optargs;
CLEANUP_FREE char *ifmt = NULL;
CLEANUP_FREE char *ifile = NULL;
- int ifile_delete_on_exit, r;
+ pid_t pid;
+ int status, fd;
/* Use of CLEANUP_UNLINK_FREE *output ensures the output file is
* deleted unless we successfully reach the end of this function.
@@ -810,17 +788,28 @@ do_make_fs (const char *input, const char *output_str)
}
/* Prepare the input to be copied in. */
- if (prepare_input (input, ifmt, &ifile, &ifile_delete_on_exit) == -1)
+ if (prepare_input (input, ifmt, &ifile, &fd, &pid) == -1)
return -1;
if (verbose)
fprintf (stderr, "uploading from %s to / ...\n", ifile);
- r = guestfs_tar_in (g, ifile, "/");
- if (ifile_delete_on_exit)
- unlink (ifile);
- if (r == -1)
+ if (guestfs_tar_in (g, ifile, "/") == -1)
return -1;
+ /* Clean up subprocess. */
+ if (pid > 0) {
+ if (waitpid (pid, &status, 0) == -1) {
+ perror ("waitpid");
+ return -1;
+ }
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) {
+ fprintf (stderr, _("%s: subprocess failed\n"), program_name);
+ return -1;
+ }
+ }
+ if (fd >= 0)
+ close (fd);
+
if (verbose) {
CLEANUP_FREE_STATVFS struct guestfs_statvfs *stats =
guestfs_statvfs (g, "/");
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git
More information about the Pkg-libvirt-commits
mailing list