1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2011 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
28 #include "guestfs_protocol.h"
32 #define DEST_FILE_FLAGS O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666
33 #define DEST_DEVICE_FLAGS O_WRONLY, 0
35 /* NB: We cheat slightly by assuming that optargs_bitmask is
36 * compatible for all four of the calls. This is true provided they
37 * all take the same set of optional arguments.
40 /* Takes optional arguments, consult optargs_bitmask. */
42 copy (const char *src, const char *src_display,
43 const char *dest, const char *dest_display,
44 int wrflags, int wrmode,
45 int64_t srcoffset, int64_t destoffset, int64_t size)
47 int64_t saved_size = size;
53 if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SRCOFFSET_BITMASK)) {
55 reply_with_error ("srcoffset is negative");
62 if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_DESTOFFSET_BITMASK)) {
64 reply_with_error ("destoffset is negative");
71 if ((optargs_bitmask & GUESTFS_COPY_DEVICE_TO_DEVICE_SIZE_BITMASK)) {
73 reply_with_error ("size is negative");
80 /* Open source and destination. */
81 src_fd = open (src, O_RDONLY);
83 reply_with_perror ("%s", src_display);
87 if (srcoffset > 0 && lseek (src_fd, srcoffset, SEEK_SET) == (off_t) -1) {
88 reply_with_perror ("lseek: %s", src_display);
93 dest_fd = open (dest, wrflags, wrmode);
95 reply_with_perror ("%s", dest_display);
100 if (destoffset > 0 && lseek (dest_fd, destoffset, SEEK_SET) == (off_t) -1) {
101 reply_with_perror ("lseek: %s", dest_display);
111 /* Calculate bytes to copy. */
112 if (size == -1 || size > (int64_t) sizeof buf)
117 r = read (src_fd, buf, n);
120 pulse_mode_cancel ();
121 reply_with_perror ("read: %s", src_display);
128 if (size == -1) /* if size == -1, this is normal end of loop */
130 reply_with_error ("%s: input too short", src_display);
136 if (xwrite (dest_fd, buf, r) == -1) {
138 pulse_mode_cancel ();
139 reply_with_perror ("%s: write", dest_display);
147 notify_progress ((uint64_t) (saved_size - size), (uint64_t) saved_size);
154 if (close (src_fd) == -1) {
155 reply_with_perror ("close: %s", src_display);
160 if (close (dest_fd) == -1) {
161 reply_with_perror ("close: %s", dest_display);
169 do_copy_device_to_device (const char *src, const char *dest,
170 int64_t srcoffset, int64_t destoffset, int64_t size)
172 return copy (src, src, dest, dest, DEST_DEVICE_FLAGS,
173 srcoffset, destoffset, size);
177 do_copy_device_to_file (const char *src, const char *dest,
178 int64_t srcoffset, int64_t destoffset, int64_t size)
183 dest_buf = sysroot_path (dest);
185 reply_with_perror ("malloc");
189 r = copy (src, src, dest_buf, dest, DEST_FILE_FLAGS,
190 srcoffset, destoffset, size);
197 do_copy_file_to_device (const char *src, const char *dest,
198 int64_t srcoffset, int64_t destoffset, int64_t size)
203 src_buf = sysroot_path (src);
205 reply_with_perror ("malloc");
209 r = copy (src_buf, src, dest, dest, DEST_DEVICE_FLAGS,
210 srcoffset, destoffset, size);
217 do_copy_file_to_file (const char *src, const char *dest,
218 int64_t srcoffset, int64_t destoffset, int64_t size)
220 char *src_buf, *dest_buf;
223 src_buf = sysroot_path (src);
225 reply_with_perror ("malloc");
229 dest_buf = sysroot_path (dest);
231 reply_with_perror ("malloc");
236 r = copy (src_buf, src, dest_buf, dest, DEST_FILE_FLAGS,
237 srcoffset, destoffset, size);