X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fdd.c;h=f08eb36e1519680d8a1ab377a29679e110a83c67;hp=0a53b3160572d14eeaa117054fa259335d5f8675;hb=428a45c3e15f03e9861e1b551e1ae8da821dba5f;hpb=a9519654032d2f09e76870d5d04dae2dff752c5b diff --git a/daemon/dd.c b/daemon/dd.c index 0a53b31..f08eb36 100644 --- a/daemon/dd.c +++ b/daemon/dd.c @@ -21,8 +21,9 @@ #include #include #include +#include -#include "../src/guestfs_protocol.h" +#include "guestfs_protocol.h" #include "daemon.h" #include "actions.h" @@ -62,7 +63,7 @@ do_dd (const char *src, const char *dest) free (of_arg); if (r == -1) { - reply_with_error ("dd: %s: %s: %s", src, dest, err); + reply_with_error ("%s: %s: %s", src, dest, err); free (err); return -1; } @@ -70,3 +71,94 @@ do_dd (const char *src, const char *dest) return 0; } + +int +do_copy_size (const char *src, const char *dest, int64_t ssize) +{ + 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; + } + + uint64_t position = 0, size = (uint64_t) ssize; + + while (position < size) { + char buf[1024*1024]; + + /* 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); + 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; + } + + position += r; + notify_progress ((uint64_t) position, (uint64_t) size); + } + + 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; +}