diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | daemon/file.c | 48 | ||||
-rw-r--r-- | generator/generator_actions.ml | 67 | ||||
-rw-r--r-- | src/file.c | 66 |
4 files changed, 111 insertions, 71 deletions
@@ -567,7 +567,6 @@ the p.o.v of the API and ABI. - guestfs_lstatlist - guestfs_lxattrlist - - guestfs_read_lines - guestfs_readlinklist - guestfs_write - guestfs_write_append diff --git a/daemon/file.c b/daemon/file.c index 42c13c9c..0b197412 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -85,54 +85,6 @@ do_touch (const char *path) return 0; } -char ** -do_read_lines (const char *path) -{ - DECLARE_STRINGSBUF (r); - FILE *fp; - char *line = NULL; - size_t len = 0; - ssize_t n; - - CHROOT_IN; - fp = fopen (path, "r"); - CHROOT_OUT; - - if (!fp) { - reply_with_perror ("fopen: %s", path); - return NULL; - } - - while ((n = getline (&line, &len, fp)) != -1) { - /* Remove either LF or CRLF. */ - if (n >= 2 && line[n-2] == '\r' && line[n-1] == '\n') - line[n-2] = '\0'; - else if (n >= 1 && line[n-1] == '\n') - line[n-1] = '\0'; - - if (add_string (&r, line) == -1) { - free (line); - fclose (fp); - return NULL; - } - } - - free (line); - - if (end_stringsbuf (&r) == -1) { - fclose (fp); - return NULL; - } - - if (fclose (fp) == EOF) { - reply_with_perror ("fclose: %s", path); - free_stringslen (r.argv, r.size); - return NULL; - } - - return r.argv; -} - int do_rm (const char *path) { diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 4fe6ae1a..4f920902 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -2059,6 +2059,51 @@ buffer. Unlike C<guestfs_cat>, this function can correctly handle files that contain embedded ASCII NUL characters." }; + { defaults with + name = "read_lines"; + style = RStringList "lines", [Pathname "path"], []; + tests = [ + InitISOFS, Always, TestOutputList ( + [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]); + InitISOFS, Always, TestOutputList ( + [["read_lines"; "/empty"]], []); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines1"; "\n"]; + ["read_lines"; "/read_lines1"]], [""]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines2"; "\r\n"]; + ["read_lines"; "/read_lines2"]], [""]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines3"; "\n\r\n"]; + ["read_lines"; "/read_lines3"]], [""; ""]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines4"; "a"]; + ["read_lines"; "/read_lines4"]], ["a"]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines5"; "a\nb"]; + ["read_lines"; "/read_lines5"]], ["a"; "b"]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines6"; "a\nb\n"]; + ["read_lines"; "/read_lines6"]], ["a"; "b"]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines7"; "a\nb\r\n"]; + ["read_lines"; "/read_lines7"]], ["a"; "b"]); + InitScratchFS, Always, TestOutputList ( + [["write"; "/read_lines8"; "a\nb\r\n\n"]; + ["read_lines"; "/read_lines8"]], ["a"; "b"; ""]); + ]; + shortdesc = "read file as lines"; + longdesc = "\ +Return the contents of the file named C<path>. + +The file contents are returned as a list of lines. Trailing +C<LF> and C<CRLF> character sequences are I<not> returned. + +Note that this function cannot correctly handle binary files +(specifically, files containing C<\\0> character which is treated +as end of string). For those you need to use the C<guestfs_read_file> +function and split the buffer into lines yourself." }; + ] (* daemon_functions are any functions which cause some action @@ -2333,28 +2378,6 @@ List all the logical volumes detected. This is the equivalent of the L<lvs(8)> command. The \"full\" version includes all fields." }; { defaults with - name = "read_lines"; - style = RStringList "lines", [Pathname "path"], []; - proc_nr = Some 15; - tests = [ - InitISOFS, Always, TestOutputList ( - [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]); - InitISOFS, Always, TestOutputList ( - [["read_lines"; "/empty"]], []) - ]; - shortdesc = "read file as lines"; - longdesc = "\ -Return the contents of the file named C<path>. - -The file contents are returned as a list of lines. Trailing -C<LF> and C<CRLF> character sequences are I<not> returned. - -Note that this function cannot correctly handle binary files -(specifically, files containing C<\\0> character which is treated -as end of line). For those you need to use the C<guestfs_read_file> -function which has a more complex interface." }; - - { defaults with name = "aug_init"; style = RErr, [Pathname "root"; Int "flags"], []; proc_nr = Some 16; @@ -123,6 +123,72 @@ guestfs__read_file (guestfs_h *g, const char *path, size_t *size_r) } char ** +guestfs__read_lines (guestfs_h *g, const char *file) +{ + size_t i, count, size, len; + char *buf = NULL; + char **ret = NULL; + + /* Read the whole file into memory. */ + buf = guestfs__read_file (g, file, &size); + if (buf == NULL) + return NULL; + + /* 'buf' contains the list of strings, separated by LF or CRLF + * characters. Convert this to a list of lines. Note we have to + * handle the cases where the buffer is zero length and where the + * final string is not terminated. + */ + count = 0; + for (i = 0; i < size; ++i) + if (buf[i] == '\n') + count++; + if (size > 0 && buf[size-1] != '\n') + count++; + + ret = malloc ((count + 1) * sizeof (char *)); + if (!ret) { + perrorf (g, "malloc"); + goto err; + } + + count = 0; + if (size > 0) { + ret[count++] = buf; + for (i = 0; i < size; ++i) { + if (buf[i] == '\n') { + buf[i] = '\0'; + if (i+1 < size) + ret[count++] = &buf[i+1]; + } + } + } + ret[count] = NULL; + + /* Duplicate the strings, and remove the trailing \r characters if any. */ + for (i = 0; ret[i] != NULL; ++i) { + ret[i] = strdup (ret[i]); + if (ret[i] == NULL) { + perrorf (g, "strdup"); + while (i > 0) + free (ret[--i]); + goto err; + } + len = strlen (ret[i]); + if (len > 0 && ret[i][len-1] == '\r') + ret[i][len-1] = '\0'; + } + free (buf); + + return ret; + + err: + free (buf); + free (ret); + return NULL; +} + +char ** guestfs__find (guestfs_h *g, const char *directory) { int fd = -1; |