From af5ec9381ea3b4e54aa7ef3a50d474d827f7ef19 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 18 Oct 2012 22:08:52 +0100 Subject: fuse: Use command mini-library to run the fusermount command. --- src/fuse.c | 89 ++++++++++++++++++++------------------------------------------ 1 file changed, 28 insertions(+), 61 deletions(-) (limited to 'src/fuse.c') diff --git a/src/fuse.c b/src/fuse.c index 7342e5c2..76d008a1 100644 --- a/src/fuse.c +++ b/src/fuse.c @@ -1044,17 +1044,19 @@ guestfs___free_fuse (guestfs_h *g) free_dir_caches (g); } -static int do_fusermount (guestfs_h *g, const char *localmountpoint, int error_fd); - int guestfs__umount_local (guestfs_h *g, const struct guestfs_umount_local_argv *optargs) { + int ret = -1; size_t i, tries; char *localmountpoint; char *fusermount_log = NULL; - int error_fd = -1; - int ret = -1; + struct command *cmd = NULL; + int r; + FILE *fp; + char error_message[4096]; + size_t n; /* How many times should we try the fusermount command? */ if (optargs->bitmask & GUESTFS_UMOUNT_LOCAL_RETRY_BITMASK) @@ -1081,22 +1083,22 @@ guestfs__umount_local (guestfs_h *g, * all 'tries' have failed do we print the contents of this file. A * temporary failure when retry == true will not cause any error. */ - fusermount_log = safe_asprintf (g, "%s/fusermount.log", g->tmpdir); - error_fd = open (fusermount_log, - O_RDWR|O_CREAT|O_TRUNC|O_NOCTTY /* not O_CLOEXEC */, - 0600); - if (error_fd == -1) { - perrorf (g, _("open: %s"), fusermount_log); - goto out; - } + fusermount_log = safe_asprintf (g, "%s/fusermount%d", g->tmpdir, ++g->unique); for (i = 0; i < tries; ++i) { - int r; - - r = do_fusermount (g, localmountpoint, error_fd); + cmd = guestfs___new_command (g); + guestfs___cmd_add_string_unquoted (cmd, "fusermount -u "); + guestfs___cmd_add_string_quoted (cmd, localmountpoint); + guestfs___cmd_add_string_unquoted (cmd, " > "); + guestfs___cmd_add_string_quoted (cmd, fusermount_log); + guestfs___cmd_add_string_unquoted (cmd, " 2>&1"); + guestfs___cmd_clear_capture_errors (cmd); + r = guestfs___cmd_run (cmd); + guestfs___cmd_close (cmd); + cmd = NULL; if (r == -1) goto out; - if (r) { + if (WIFEXITED (r) && WEXITSTATUS (r) == EXIT_SUCCESS) { /* External fusermount succeeded. Note that the original thread * is responsible for setting g->localmountpoint to NULL. */ @@ -1108,26 +1110,25 @@ guestfs__umount_local (guestfs_h *g, } if (ret == -1) { /* fusermount failed */ - char error_message[4096]; - ssize_t n; - /* Get the error message from the log file. */ - if (lseek (error_fd, 0, SEEK_SET) >= 0 && - (n = read (error_fd, error_message, sizeof error_message - 1)) > 0) { + fp = fopen (fusermount_log, "r"); + if (fp != NULL) { + n = fread (error_message, 1, sizeof error_message, fp); while (n > 0 && error_message[n-1] == '\n') n--; error_message[n] = '\0'; + fclose (fp); + error (g, _("fusermount failed: %s: %s"), localmountpoint, error_message); } else { - snprintf (error_message, sizeof error_message, - "(fusermount error could not be preserved)"); + perrorf (g, + _("fusermount failed: %s: " + "original error could not be preserved"), localmountpoint); } - - error (g, _("fusermount failed: %s: %s"), localmountpoint, error_message); - goto out; } out: - if (error_fd >= 0) close (error_fd); + if (cmd) + guestfs___cmd_close (cmd); if (fusermount_log) { unlink (fusermount_log); free (fusermount_log); @@ -1136,40 +1137,6 @@ guestfs__umount_local (guestfs_h *g, return ret; } -static int -do_fusermount (guestfs_h *g, const char *localmountpoint, int error_fd) -{ - pid_t pid; - int status; - - pid = fork (); - if (pid == -1) { - perrorf (g, "fork"); - return -1; - } - - if (pid == 0) { /* child */ - /* Ensure stdout and stderr point to the error_fd. */ - dup2 (error_fd, STDOUT_FILENO); - dup2 (error_fd, STDERR_FILENO); - close (error_fd); - execlp ("fusermount", "fusermount", "-u", localmountpoint, NULL); - perror ("exec: fusermount"); - _exit (EXIT_FAILURE); - } - - /* Parent. */ - if (waitpid (pid, &status, 0) == -1) { - perrorf (g, "waitpid"); - return -1; - } - - if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) - return 0; /* it failed to unmount the mountpoint */ - - return 1; /* unmount was successful */ -} - /* Functions handling the directory cache. * * Note on attribute caching: FUSE can cache filesystem attributes for -- cgit