From 96d3ac28d636290e9478ac27226862e627682025 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 17 Aug 2012 10:36:23 +0100 Subject: [PATCH] guestfs_read_file: Reimplement to avoid protocol limits. --- TODO | 1 - daemon/file.c | 59 ---------------------------------- generator/generator_actions.ml | 47 +++++++++------------------ src/file.c | 12 +++++++ 4 files changed, 27 insertions(+), 92 deletions(-) diff --git a/TODO b/TODO index 4362529e2..451ca6562 100644 --- a/TODO +++ b/TODO @@ -567,7 +567,6 @@ the p.o.v of the API and ABI. - guestfs_lstatlist - guestfs_lxattrlist - - guestfs_read_file - guestfs_read_lines - guestfs_readlinklist - guestfs_write diff --git a/daemon/file.c b/daemon/file.c index 2ea8b738a..42c13c9cc 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -314,65 +314,6 @@ do_write_append (const char *path, const char *content, size_t size) return 0; } -char * -do_read_file (const char *path, size_t *size_r) -{ - int fd; - struct stat statbuf; - char *r; - - CHROOT_IN; - fd = open (path, O_RDONLY|O_CLOEXEC); - CHROOT_OUT; - - if (fd == -1) { - reply_with_perror ("open: %s", path); - return NULL; - } - - if (fstat (fd, &statbuf) == -1) { - reply_with_perror ("fstat: %s", path); - close (fd); - return NULL; - } - - /* The actual limit on messages is smaller than this. This - * check just limits the amount of memory we'll try and allocate - * here. If the message is larger than the real limit, that will - * be caught later when we try to serialize the message. - */ - if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) { - reply_with_error ("%s: file is too large for the protocol, use guestfs_download instead", path); - close (fd); - return NULL; - } - r = malloc (statbuf.st_size); - if (r == NULL) { - reply_with_perror ("malloc"); - close (fd); - return NULL; - } - - if (xread (fd, r, statbuf.st_size) == -1) { - reply_with_perror ("read: %s", path); - close (fd); - free (r); - return NULL; - } - - if (close (fd) == -1) { - reply_with_perror ("close: %s", path); - free (r); - return NULL; - } - - /* Mustn't touch *size_r until we are sure that we won't return any - * error (RHBZ#589039). - */ - *size_r = statbuf.st_size; - return r; -} - static char * pread_fd (int fd, int count, int64_t offset, size_t *size_r, const char *display_path) diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 173c6ec41..4fe6ae1a6 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -2044,6 +2044,21 @@ this limit has been lifted and the call can download and return an arbitrary list of files (limited by the amount of memory available)." }; + { defaults with + name = "read_file"; + style = RBufferOut "content", [Pathname "path"], []; + tests = [ + InitISOFS, Always, TestOutputBuffer ( + [["read_file"; "/known-4"]], "abc\ndef\nghi") + ]; + shortdesc = "read a file"; + longdesc = "\ +This calls returns the contents of the file C as a +buffer. + +Unlike C, this function can correctly +handle files that contain embedded ASCII NUL characters." }; + ] (* daemon_functions are any functions which cause some action @@ -5168,38 +5183,6 @@ This calls removes a mountpoint that was previously created with C. See C for full details." }; - { defaults with - name = "read_file"; - style = RBufferOut "content", [Pathname "path"], []; - proc_nr = Some 150; - protocol_limit_warning = true; - tests = [ - InitISOFS, Always, TestOutputBuffer ( - [["read_file"; "/known-4"]], "abc\ndef\nghi"); - (* Test various near large, large and too large files (RHBZ#589039). *) - InitScratchFS, Always, TestLastFail ( - [["touch"; "/read_file"]; - ["truncate_size"; "/read_file"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *) - ["read_file"; "/read_file"]]); - InitScratchFS, Always, TestLastFail ( - [["touch"; "/read_file2"]; - ["truncate_size"; "/read_file2"; "4194304"]; (* GUESTFS_MESSAGE_MAX *) - ["read_file"; "/read_file2"]]); - InitScratchFS, Always, TestLastFail ( - [["touch"; "/read_file3"]; - ["truncate_size"; "/read_file3"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *) - ["read_file"; "/read_file3"]]) - ]; - shortdesc = "read a file"; - longdesc = "\ -This calls returns the contents of the file C as a -buffer. - -Unlike C, this function can correctly -handle files that contain embedded ASCII NUL characters. -However unlike C, this function is limited -in the total size of file that can be handled." }; - { defaults with name = "grep"; style = RStringList "lines", [String "regex"; Pathname "path"], [OBool "extended"; OBool "fixed"; OBool "insensitive"; OBool "compressed"]; diff --git a/src/file.c b/src/file.c index ed157592f..84edc403a 100644 --- a/src/file.c +++ b/src/file.c @@ -50,6 +50,14 @@ sort_strings (char **argv, size_t len) char * guestfs__cat (guestfs_h *g, const char *path) +{ + size_t size; + + return guestfs_read_file (g, path, &size); +} + +char * +guestfs__read_file (guestfs_h *g, const char *path, size_t *size_r) { int fd = -1; size_t size; @@ -97,6 +105,10 @@ guestfs__cat (guestfs_h *g, const char *path) goto err; } + /* Mustn't touch *size_r until we are sure that we won't return any + * error (RHBZ#589039). + */ + *size_r = size; return ret; err: