From b6483061c25e90ae1b9e016812dea8e3756d6c23 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 22 Mar 2010 18:36:16 +0000 Subject: [PATCH] New API: guestfs_copy_size to copy a fixed number of bytes. This is similar to 'guestfs_dd', but it copies just a fixed number of bytes from the source to the destination. It's an error if the source is too short or if the destination is too small. --- daemon/dd.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/MAX_PROC_NR | 2 +- src/generator.ml | 15 ++++++++++- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/daemon/dd.c b/daemon/dd.c index d92dac0..2bbe855 100644 --- a/daemon/dd.c +++ b/daemon/dd.c @@ -21,6 +21,7 @@ #include #include #include +#include #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 f414671..2c36bbd 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 551b6bc..5f5b437 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)."); ("filesize", (RInt64 "size", [Pathname "file"]), 218, [], [InitBasicFS, Always, TestOutputInt ( @@ -4333,6 +4333,19 @@ calls to associate logical volumes and volume groups. See also C."); + ("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 bytes from one source device +or file C to another destination device or file C. + +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 -- 1.8.3.1