summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--daemon/file.c48
-rw-r--r--generator/generator_actions.ml67
-rw-r--r--src/file.c66
4 files changed, 111 insertions, 71 deletions
diff --git a/TODO b/TODO
index 451ca656..73cccf69 100644
--- a/TODO
+++ b/TODO
@@ -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;
diff --git a/src/file.c b/src/file.c
index 84edc403..13f08cd6 100644
--- a/src/file.c
+++ b/src/file.c
@@ -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;