Add progress messages to copy-size command.
authorRichard Jones <rjones@redhat.com>
Sat, 28 Aug 2010 10:11:32 +0000 (11:11 +0100)
committerRichard Jones <rjones@redhat.com>
Tue, 31 Aug 2010 18:27:35 +0000 (19:27 +0100)
daemon/dd.c
src/generator.ml

index 2bbe855..c004d92 100644 (file)
@@ -73,7 +73,7 @@ do_dd (const char *src, const char *dest)
 }
 
 int
-do_copy_size (const char *src, const char *dest, int64_t size)
+do_copy_size (const char *src, const char *dest, int64_t ssize)
 {
   char *buf;
   int src_fd, dest_fd;
@@ -112,9 +112,19 @@ do_copy_size (const char *src, const char *dest, int64_t size)
     return -1;
   }
 
-  while (size > 0) {
+  uint64_t position = 0, size = (uint64_t) ssize;
+
+  while (position < size) {
     char buf[1024*1024];
-    size_t n = size > (int64_t) (sizeof buf) ? sizeof buf : (size_t) size;
+
+    /* Calculate bytes to copy. */
+    uint64_t n64 = size - position;
+    size_t n;
+    if (n64 > sizeof buf)
+      n = sizeof buf;
+    else
+      n = (size_t) n64; /* safe because of if condition */
+
     ssize_t r = read (src_fd, buf, n);
     if (r == -1) {
       reply_with_perror ("%s: read", src);
@@ -136,7 +146,8 @@ do_copy_size (const char *src, const char *dest, int64_t size)
       return -1;
     }
 
-    size -= r;
+    position += r;
+    notify_progress ((uint64_t) position, (uint64_t) size);
   }
 
   if (close (src_fd) == -1) {
index bbf313a..ec93850 100755 (executable)
@@ -192,6 +192,7 @@ type flags =
   | NotInDocs            (* do not add this function to documentation *)
   | DeprecatedBy of string (* function is deprecated, use .. instead *)
   | Optional of string   (* function is part of an optional group *)
+  | Progress              (* function can generate progress messages *)
 
 and fish_output_t =
   | FishOutputOctal       (* for int return, print in octal *)
@@ -4875,7 +4876,7 @@ calls to associate logical volumes and volume groups.
 
 See also C<guestfs_vgpvuuids>.");
 
-  ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
+  ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [Progress],
    [InitBasicFS, Always, TestOutputBuffer (
       [["write"; "/src"; "hello, world"];
        ["copy_size"; "/src"; "/dest"; "5"];
@@ -5799,6 +5800,12 @@ let seq_of_test = function
   | TestLastFail s -> s
 
 (* Handling for function flags. *)
+let progress_message =
+  "This long-running command can generate progress notification messages
+so that the caller can display a progress bar or indicator.
+To receive these messages, the caller must register a progress
+callback.  See L<guestfs(3)/guestfs_set_progress_callback>."
+
 let protocol_limit_warning =
   "Because of the message protocol, there is a transfer limit
 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
@@ -6133,6 +6140,8 @@ I<The caller must free the strings and the array after use>.\n\n"
 The size of the returned buffer is written to C<*size_r>.
 I<The caller must free the returned buffer after use>.\n\n"
         );
+        if List.mem Progress flags then
+          pr "%s\n\n" progress_message;
         if List.mem ProtocolLimitWarning flags then
           pr "%s\n\n" protocol_limit_warning;
         if List.mem DangerWillRobinson flags then