mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
guestfs_read_file: Reimplement to avoid protocol limits.
This commit is contained in:
1
TODO
1
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<path> as a
|
||||
buffer.
|
||||
|
||||
Unlike C<guestfs_cat>, 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<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
|
||||
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<path> as a
|
||||
buffer.
|
||||
|
||||
Unlike C<guestfs_cat>, this function can correctly
|
||||
handle files that contain embedded ASCII NUL characters.
|
||||
However unlike C<guestfs_download>, 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"];
|
||||
|
||||
12
src/file.c
12
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:
|
||||
|
||||
Reference in New Issue
Block a user