Richard W.M. Jones
2012-May-02 13:02 UTC
[Libguestfs] [PATCH] fish: Add --pipe-error flag to allow detection of errors in pipe commands (RHBZ#803533).
From: "Richard W.M. Jones" <rjones at redhat.com> For a test case, see: https://bugzilla.redhat.com/show_bug.cgi?id=803533 In guestfish, we use the gnulib closeout module which sets up an atexit handler to detect if there were any errors on stdout when the program exits. This is so we can fail correctly in out of disk space cases like: guestfish [...] > output However the atexit handler just checks that there was any error on stdout (using ferror). If a pipe command such as: ><fs> command_with_lots_of_output | head ran at any time during the session, the error flag would be set (because the underlying writes failed with EPIPE errors). So the commit first adds a test for ferror (stdout) after each command that we issue. This brings error handling closer to the point of failure, and so is generally a good thing. Secondly we reset the error flag after detecting and dealing with the error, so that avoids the redundant 'guestfish: write error' message produced by gnulib closeout. Thirdly we add a --pipe-error flag which causes guestfish commands to fail on pipe commands line the one above. The default is off for backwards compatibility reasons. --- fish/fish.c | 15 +++++++++++++++ fish/guestfish.pod | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/fish/fish.c b/fish/fish.c index d0688f1..63fb30f 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -74,6 +74,7 @@ static void add_history_line (const char *); static int override_progress_bars = -1; static struct progress_bar *bar = NULL; +static int pipe_error = 0; /* Currently open libguestfs handle. */ guestfs_h *g = NULL; @@ -126,6 +127,7 @@ usage (int status) " -m|--mount dev[:mnt[:opts]] Mount dev on mnt (if omitted, /)\n" " -n|--no-sync Don't autosync\n" " -N|--new type Create prepared disk (test1.img, ...)\n" + " --pipe-error Pipe commands can detect write errors\n" " --progress-bars Enable progress bars even when not interactive\n" " --no-progress-bars Disable progress bars\n" " --remote[=pid] Send commands to remote %s\n" @@ -158,6 +160,7 @@ main (int argc, char *argv[]) /* Set global program name that is not polluted with libtool artifacts. */ set_program_name (argv[0]); + /* Initialize gnulib closeout module. */ atexit (close_stdout); setlocale (LC_ALL, ""); @@ -190,6 +193,7 @@ main (int argc, char *argv[]) { "new", 1, 0, 'N' }, { "no-dest-paths", 0, 0, 'D' }, { "no-sync", 0, 0, 'n' }, + { "pipe-error", 0, 0, 0 }, { "progress-bars", 0, 0, 0 }, { "no-progress-bars", 0, 0, 0 }, { "remote", 2, 0, 0 }, @@ -280,6 +284,8 @@ main (int argc, char *argv[]) remote_control_csh = 1; } else if (STREQ (long_options[option_index].name, "live")) { live = 1; + } else if (STREQ (long_options[option_index].name, "pipe-error")) { + pipe_error = 1; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); @@ -1129,6 +1135,15 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd, perror ("failed to flush standard output"); return -1; } + if (ferror (stdout)) { + if (!pipecmd || pipe_error) { + fprintf (stderr, "%s: write error%s\n", program_name, + pipecmd ? " on pipe" : ""); + r = -1; + } + /* We've dealt with this error, so clear the flag. */ + clearerr (stdout); + } if (pipecmd) { close (1); diff --git a/fish/guestfish.pod b/fish/guestfish.pod index a45af00..29aa2d6 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -350,6 +350,18 @@ alternative to the I<-a> option: whereas I<-a> adds an existing disk, I<-N> creates a preformatted disk with a filesystem and adds it. See L</PREPARED DISK IMAGES> below. +=item B<--pipe-error> + +If writes fail to pipe commands (see L</PIPES> below), then the +command returns an error. + +The default (also for historical reasons) is to ignore such errors so +that: + + ><fs> command_with_lots_of_output | head + +doesn't give an error. + =item B<--progress-bars> Enable progress bars, even when guestfish is used non-interactively. -- 1.7.10
Possibly Parallel Threads
- [PATCH] fish: reset the console on ^Z RHBZ#1213844
- [PATCH] fish: add option --blocksize for disks
- [PATCH libguestfs] guestfish: detect a few more failed syscalls
- use STREQ(a,b), not strcmp(a,b) == 0
- [PATCH v3 1/1] tools: add '--blocksize' option for C-based tools