New API: pread-device, partial read for devices.
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 27 Sep 2010 11:00:10 +0000 (12:00 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 27 Sep 2010 11:04:44 +0000 (12:04 +0100)
daemon/file.c
generator/generator_actions.ml
src/MAX_PROC_NR

index 5bc5f41..c16a00a 100644 (file)
@@ -408,20 +408,22 @@ 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)
+static char *
+pread_fd (int fd, int count, int64_t offset, size_t *size_r,
+          const char *display_path)
 {
-  int fd;
   ssize_t r;
   char *buf;
 
   if (count < 0) {
     reply_with_error ("count is negative");
+    close (fd);
     return NULL;
   }
 
   if (offset < 0) {
     reply_with_error ("offset is negative");
+    close (fd);
     return NULL;
   }
 
@@ -431,16 +433,8 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r)
    * will be caught later when we try to serialize the message.
    */
   if (count >= GUESTFS_MESSAGE_MAX) {
-    reply_with_error ("%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);
+    reply_with_error ("%s: count is too large for the protocol, use smaller reads", display_path);
+    close (fd);
     return NULL;
   }
 
@@ -453,14 +447,14 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r)
 
   r = pread (fd, buf, count, offset);
   if (r == -1) {
-    reply_with_perror ("pread: %s", path);
+    reply_with_perror ("pread: %s", display_path);
     close (fd);
     free (buf);
     return NULL;
   }
 
   if (close (fd) == -1) {
-    reply_with_perror ("close: %s", path);
+    reply_with_perror ("close: %s", display_path);
     close (fd);
     free (buf);
     return NULL;
@@ -473,6 +467,35 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r)
   return buf;
 }
 
+char *
+do_pread (const char *path, int count, int64_t offset, size_t *size_r)
+{
+  int fd;
+
+  CHROOT_IN;
+  fd = open (path, O_RDONLY);
+  CHROOT_OUT;
+
+  if (fd == -1) {
+    reply_with_perror ("open: %s", path);
+    return NULL;
+  }
+
+  return pread_fd (fd, count, offset, size_r, path);
+}
+
+char *
+do_pread_device (const char *device, int count, int64_t offset, size_t *size_r)
+{
+  int fd = open (device, O_RDONLY);
+  if (fd == -1) {
+    reply_with_perror ("open: %s", device);
+    return NULL;
+  }
+
+  return pread_fd (fd, count, offset, size_r, device);
+}
+
 static int
 pwrite_fd (int fd, const char *content, size_t size, int64_t offset,
            const char *display_path)
index e94fcbd..c9890a6 100644 (file)
@@ -4190,7 +4190,7 @@ 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.
 
-See also C<guestfs_pwrite>.");
+See also C<guestfs_pwrite>, C<guestfs_pread_device>.");
 
   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
    [InitEmpty, Always, TestRun (
@@ -5183,6 +5183,19 @@ probably impossible with standard Linux kernels).
 
 See also C<guestfs_pwrite>.");
 
+  ("pread_device", (RBufferOut "content", [Device "device"; Int "count"; Int64 "offset"]), 276, [ProtocolLimitWarning],
+   [InitEmpty, Always, TestOutputBuffer (
+      [["pread_device"; "/dev/sdd"; "8"; "32768"]], "\001CD001\001\000")],
+   "read part of a device",
+   "\
+This command lets you read part of a file.  It reads C<count>
+bytes of C<device>, starting at C<offset>.
+
+This may read fewer bytes than requested.  For further details
+see the L<pread(2)> system call.
+
+See also C<guestfs_pread>.");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
index 4c738e3..15007f1 100644 (file)
@@ -1 +1 @@
-275
+276