1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2009 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., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "../src/guestfs_protocol.h"
31 write_cb (void *fd_ptr, const void *buf, size_t len)
33 int fd = *(int *)fd_ptr;
34 return xwrite (fd, buf, len);
37 /* Has one FileIn parameter. */
39 do_tar_in (const char *dir)
45 /* "tar -C /sysroot%s -xf -" but we have to quote the dir. */
46 if (asprintf_nowarn (&cmd, "tar -C %R -xf -", dir) == -1) {
50 reply_with_perror ("asprintf");
55 fprintf (stderr, "%s\n", cmd);
57 fp = popen (cmd, "w");
62 reply_with_perror ("%s", cmd);
68 /* The semantics of fwrite are too undefined, so write to the
69 * file descriptor directly instead.
73 r = receive_file (write_cb, &fd);
74 if (r == -1) { /* write error */
76 reply_with_error ("write error on directory: %s", dir);
80 if (r == -2) { /* cancellation from library */
82 /* Do NOT send any error. */
86 if (pclose (fp) != 0) {
87 if (r == -1) /* if r == 0, file transfer ended already */
89 reply_with_error ("tar subcommand failed on directory: %s", dir);
96 /* Has one FileOut parameter. */
98 do_tar_out (const char *dir)
103 char buf[GUESTFS_MAX_CHUNK_SIZE];
105 /* "tar -C /sysroot%s -cf - ." but we have to quote the dir. */
106 if (asprintf_nowarn (&cmd, "tar -C %R -cf - .", dir) == -1) {
107 reply_with_perror ("asprintf");
112 fprintf (stderr, "%s\n", cmd);
114 fp = popen (cmd, "r");
116 reply_with_perror ("%s", cmd);
122 /* Now we must send the reply message, before the file contents. After
123 * this there is no opportunity in the protocol to send any error
124 * message back. Instead we can only cancel the transfer.
128 while ((r = fread (buf, 1, sizeof buf, fp)) > 0) {
129 if (send_file_write (buf, r) < 0) {
137 send_file_end (1); /* Cancel. */
142 if (pclose (fp) != 0) {
144 send_file_end (1); /* Cancel. */
148 if (send_file_end (0)) /* Normal end of file. */
154 /* Has one FileIn parameter. */
156 do_tXz_in (const char *dir, char filter)
162 /* "tar -C /sysroot%s -zxf -" but we have to quote the dir. */
163 if (asprintf_nowarn (&cmd, "tar -C %R -%cxf -", dir, filter) == -1) {
167 reply_with_perror ("asprintf");
172 fprintf (stderr, "%s\n", cmd);
174 fp = popen (cmd, "w");
179 reply_with_perror ("%s", cmd);
185 int fd = fileno (fp);
187 r = receive_file (write_cb, &fd);
188 if (r == -1) { /* write error */
190 reply_with_error ("write error on directory: %s", dir);
194 if (r == -2) { /* cancellation from library */
196 /* Do NOT send any error. */
200 if (pclose (fp) != 0) {
201 if (r == -1) /* if r == 0, file transfer ended already */
203 reply_with_error ("tar subcommand failed on directory: %s", dir);
210 /* Has one FileIn parameter. */
212 do_tgz_in (const char *dir)
214 return do_tXz_in (dir, 'z');
217 /* Has one FileIn parameter. */
219 do_txz_in (const char *dir)
221 return do_tXz_in (dir, 'J');
224 /* Has one FileOut parameter. */
226 do_tXz_out (const char *dir, char filter)
231 char buf[GUESTFS_MAX_CHUNK_SIZE];
233 /* "tar -C /sysroot%s -zcf - ." but we have to quote the dir. */
234 if (asprintf_nowarn (&cmd, "tar -C %R -%ccf - .", dir, filter) == -1) {
235 reply_with_perror ("asprintf");
240 fprintf (stderr, "%s\n", cmd);
242 fp = popen (cmd, "r");
244 reply_with_perror ("%s", cmd);
250 /* Now we must send the reply message, before the file contents. After
251 * this there is no opportunity in the protocol to send any error
252 * message back. Instead we can only cancel the transfer.
256 while ((r = fread (buf, 1, sizeof buf, fp)) > 0) {
257 if (send_file_write (buf, r) < 0) {
265 send_file_end (1); /* Cancel. */
270 if (pclose (fp) != 0) {
272 send_file_end (1); /* Cancel. */
276 if (send_file_end (0)) /* Normal end of file. */
282 /* Has one FileOut parameter. */
284 do_tgz_out (const char *dir)
286 return do_tXz_out (dir, 'z');
289 /* Has one FileOut parameter. */
291 do_txz_out (const char *dir)
293 return do_tXz_out (dir, 'J');