summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemon/dd.c81
-rw-r--r--src/MAX_PROC_NR2
-rwxr-xr-xsrc/generator.ml15
3 files changed, 96 insertions, 2 deletions
diff --git a/daemon/dd.c b/daemon/dd.c
index d92dac0f..2bbe8551 100644
--- a/daemon/dd.c
+++ b/daemon/dd.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
#include "../src/guestfs_protocol.h"
#include "daemon.h"
@@ -70,3 +71,83 @@ do_dd (const char *src, const char *dest)
return 0;
}
+
+int
+do_copy_size (const char *src, const char *dest, int64_t size)
+{
+ char *buf;
+ int src_fd, dest_fd;
+
+ if (STRPREFIX (src, "/dev/"))
+ src_fd = open (src, O_RDONLY);
+ else {
+ buf = sysroot_path (src);
+ if (!buf) {
+ reply_with_perror ("malloc");
+ return -1;
+ }
+ src_fd = open (buf, O_RDONLY);
+ free (buf);
+ }
+ if (src_fd == -1) {
+ reply_with_perror ("%s", src);
+ return -1;
+ }
+
+ if (STRPREFIX (dest, "/dev/"))
+ dest_fd = open (dest, O_WRONLY);
+ else {
+ buf = sysroot_path (dest);
+ if (!buf) {
+ reply_with_perror ("malloc");
+ close (src_fd);
+ return -1;
+ }
+ dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
+ free (buf);
+ }
+ if (dest_fd == -1) {
+ reply_with_perror ("%s", dest);
+ close (src_fd);
+ return -1;
+ }
+
+ while (size > 0) {
+ char buf[1024*1024];
+ size_t n = size > (int64_t) (sizeof buf) ? sizeof buf : (size_t) size;
+ ssize_t r = read (src_fd, buf, n);
+ if (r == -1) {
+ reply_with_perror ("%s: read", src);
+ close (src_fd);
+ close (dest_fd);
+ return -1;
+ }
+ if (r == 0) {
+ reply_with_error ("%s: input file too short", src);
+ close (src_fd);
+ close (dest_fd);
+ return -1;
+ }
+
+ if (xwrite (dest_fd, buf, r) == -1) {
+ reply_with_perror ("%s: write", dest);
+ close (src_fd);
+ close (dest_fd);
+ return -1;
+ }
+
+ size -= r;
+ }
+
+ if (close (src_fd) == -1) {
+ reply_with_perror ("%s: close", src);
+ close (dest_fd);
+ return -1;
+ }
+ if (close (dest_fd) == -1) {
+ reply_with_perror ("%s: close", dest);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index f4146713..2c36bbda 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-226
+227
diff --git a/src/generator.ml b/src/generator.ml
index 551b6bc6..5f5b4370 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -4240,7 +4240,7 @@ example to duplicate a filesystem.
If the destination is a device, it must be as large or larger
than the source file or device, otherwise the copy will fail.
-This command cannot do partial copies.");
+This command cannot do partial copies (see C<guestfs_copy_size>).");
("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
[InitBasicFS, Always, TestOutputInt (
@@ -4333,6 +4333,19 @@ 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, [],
+ [InitBasicFS, Always, TestOutputBuffer (
+ [["write_file"; "/src"; "hello, world"; "0"];
+ ["copy_size"; "/src"; "/dest"; "5"];
+ ["read_file"; "/dest"]], "hello")],
+ "copy size bytes from source to destination using dd",
+ "\
+This command copies exactly C<size> bytes from one source device
+or file C<src> to another destination device or file C<dest>.
+
+Note this will fail if the source is too short or if the destination
+is not large enough.");
+
]
let all_functions = non_daemon_functions @ daemon_functions