From 3119aa687d4d594b50ee9df5ff6e8d709eb7ca85 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 19 Apr 2010 14:41:01 +0100 Subject: fish: Allow -< upload -< cat /foo some data some more data --- fish/fish.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fish/fish.h | 3 ++ fish/guestfish.pod | 33 +++++++++++++ 3 files changed, 177 insertions(+) (limited to 'fish') diff --git a/fish/fish.c b/fish/fish.c index 61a84050..db3149e1 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -1419,3 +1419,144 @@ resolve_win_path (const char *path) return ret; } + +/* Resolve the special FileIn paths ("-" or "-< or "END\n" in input. */ + size_t blen = strlen (buffer); + if (STREQLEN (buffer, endmarker, markerlen) && + (blen == markerlen || + (blen == markerlen+1 && buffer[markerlen] == '\n'))) + goto found_end; + + if (xwrite (fd, buffer, blen) == -1) { + if (!write_error) perror ("write"); + write_error = 1; + /* continue reading up to the end marker */ + } + } + + /* Reached EOF of stdin without finding the end marker, which + * is likely to be an error. + */ + fprintf (stderr, "%s: end of input reached without finding '%s'\n", + program_name, endmarker); + goto error2; + + found_end: + if (write_error) { + close (fd); + goto error2; + } + + if (close (fd) == -1) { + perror ("close"); + goto error2; + } + + return file_in_tmpfile; + + error2: + unlink (file_in_tmpfile); + + error1: + free (file_in_tmpfile); + file_in_tmpfile = NULL; + return NULL; +} + +void +free_file_in (char *s) +{ + if (file_in_tmpfile) { + if (unlink (file_in_tmpfile) == -1) + perror (file_in_tmpfile); + file_in_tmpfile = NULL; + } + + /* Free the device or file name which was strdup'd in file_in(). + * Note it's not immediately clear, but for -<< heredocs, + * s == file_in_tmpfile, so this frees up that buffer. + */ + free (s); +} + +/* Resolve the special FileOut paths ("-" or filename). + * The caller (cmds.c) will call free (str) after the command has run. + */ +char * +file_out (const char *arg) +{ + char *ret; + + if (STREQ (arg, "-")) + ret = strdup ("/dev/stdout"); + else + ret = strdup (arg); + + if (!ret) { + perror ("strdup"); + return NULL; + } + return ret; +} diff --git a/fish/fish.h b/fish/fish.h index 5856b8ef..05135fba 100644 --- a/fish/fish.h +++ b/fish/fish.h @@ -65,6 +65,9 @@ extern int is_true (const char *str); extern char **parse_string_list (const char *str); extern int xwrite (int fd, const void *buf, size_t len); extern char *resolve_win_path (const char *path); +extern char *file_in (const char *arg); +extern void free_file_in (char *s); +extern char *file_out (const char *arg); extern void extended_help_message (void); /* in cmds.c (auto-generated) */ diff --git a/fish/guestfish.pod b/fish/guestfish.pod index e61d4e5b..836c4f7f 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -486,6 +486,39 @@ user ID of the process, and C<$PID> is the process ID of the server. Guestfish client and server versions must match exactly. +=head1 UPLOADING AND DOWNLOADING FILES + +For commands such as C, C, C, C and +others which upload from or download to a local file, you can use the +special filename C<-> to mean "from stdin" or "to stdout". For example: + + upload - /foo + +reads stdin and creates from that a file C in the disk image, +and: + + tar-out /etc - | tar tf - + +writes the tarball to stdout and then pipes that into the external +"tar" command (see L). + +When using C<-> to read from stdin, the input is read up to the end of +stdin. You can also use a special "heredoc"-like syntax to read up to +some arbitrary end marker: + + upload -<. The end +marker must appear on a line of its own, without any preceeding or +following characters (not even spaces). + +Note that the C<-EE> syntax only applies to parameters used to +upload local files (so-called "FileIn" parameters in the generator). + =head1 GUESTFISH COMMANDS The commands in this section are guestfish convenience commands, in -- cgit