New API call: pread
authorRichard Jones <rjones@redhat.com>
Mon, 2 Nov 2009 17:02:32 +0000 (17:02 +0000)
committerRichard Jones <rjones@redhat.com>
Mon, 2 Nov 2009 17:48:39 +0000 (17:48 +0000)
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
src/MAX_PROC_NR
src/generator.ml

index 7e2f062..7854ade 100644 (file)
@@ -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)
index b35cfaf..c92ba56 100644 (file)
@@ -1 +1 @@
-206
+207
index 001d021..bbdb330 100755 (executable)
@@ -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<count>
+bytes of the file, starting at C<offset>, from file C<path>.
+
+This may read fewer bytes than requested.  For further details
+see the L<pread(2)> system call.");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions