From 90cf7fc904fca42665fe04cdd90a4c547d23b00c Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 2 Nov 2009 17:02:32 +0000 Subject: [PATCH] New API call: pread guestfs_pread lets you do partial file reads from arbitrary places within a file. It works like the pread(2) system call. --- daemon/file.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/MAX_PROC_NR | 2 +- src/generator.ml | 11 +++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/daemon/file.c b/daemon/file.c index 7e2f062..7854ade 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -369,6 +369,58 @@ do_read_file (const char *path, size_t *size_r) return r; } +char * +do_pread (const char *path, int count, int64_t offset, size_t *size_r) +{ + int fd; + ssize_t r; + char *buf; + + /* The actual limit on messages is smaller than this. This check + * just limits the amount of memory we'll try and allocate in the + * function. If the message is larger than the real limit, that + * will be caught later when we try to serialize the message. + */ + if (count >= GUESTFS_MESSAGE_MAX) { + reply_with_error ("pread: %s: count is too large for the protocol, use smaller reads", path); + return NULL; + } + + CHROOT_IN; + fd = open (path, O_RDONLY); + CHROOT_OUT; + + if (fd == -1) { + reply_with_perror ("open: %s", path); + return NULL; + } + + buf = malloc (count); + if (buf == NULL) { + reply_with_perror ("malloc"); + close (fd); + return NULL; + } + + r = pread (fd, buf, count, offset); + if (r == -1) { + reply_with_perror ("pread: %s", path); + close (fd); + free (buf); + return NULL; + } + + if (close (fd) == -1) { + reply_with_perror ("close: %s", path); + close (fd); + free (buf); + return NULL; + } + + *size_r = r; + return buf; +} + /* This runs the 'file' command. */ char * do_file (const char *path) diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index b35cfaf..c92ba56 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -206 +207 diff --git a/src/generator.ml b/src/generator.ml index 001d021..bbdb330 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -3856,6 +3856,17 @@ message size to be exceeded, causing this call to fail. The caller must split up such requests into smaller groups of names."); + ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning], + [InitISOFS, Always, TestOutputBuffer ( + [["pread"; "/known-4"; "1"; "3"]], "\n")], + "read part of a file", + "\ +This command lets you read part of a file. It reads C +bytes of the file, starting at C, from file C. + +This may read fewer bytes than requested. For further details +see the L system call."); + ] let all_functions = non_daemon_functions @ daemon_functions -- 1.8.3.1