1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2009-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., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "guestfs_protocol.h"
33 program_of_csum (const char *csumtype)
35 if (STRCASEEQ (csumtype, "crc"))
37 else if (STRCASEEQ (csumtype, "md5"))
39 else if (STRCASEEQ (csumtype, "sha1"))
41 else if (STRCASEEQ (csumtype, "sha224"))
43 else if (STRCASEEQ (csumtype, "sha256"))
45 else if (STRCASEEQ (csumtype, "sha384"))
47 else if (STRCASEEQ (csumtype, "sha512"))
50 reply_with_error ("unknown checksum type, expecting crc|md5|sha1|sha224|sha256|sha384|sha512");
56 checksum (const char *csumtype, int fd)
63 program = program_of_csum (csumtype);
64 if (program == NULL) {
71 flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | fd;
72 r = commandf (&out, &err, flags, program, NULL);
75 reply_with_error ("%s: %s", program, err);
83 /* Split it at the first whitespace. */
84 len = strcspn (out, " \t\n");
89 return out; /* Caller frees. */
93 do_checksum (const char *csumtype, const char *path)
98 fd = open (path, O_RDONLY);
102 reply_with_perror ("%s", path);
106 return checksum (csumtype, fd);
110 do_checksum_device (const char *csumtype, const char *device)
114 fd = open (device, O_RDONLY);
116 reply_with_perror ("%s", device);
120 return checksum (csumtype, fd);
123 /* Has one FileOut parameter. */
125 do_checksums_out (const char *csumtype, const char *dir)
130 const char *program = program_of_csum (csumtype);
134 char *sysrootdir = sysroot_path (dir);
136 reply_with_perror ("malloc");
140 r = stat (sysrootdir, &statbuf);
142 reply_with_perror ("%s", dir);
146 if (!S_ISDIR (statbuf.st_mode)) {
147 reply_with_error ("%s: not a directory", dir);
153 if (asprintf_nowarn (&cmd, "cd %Q && find -type f -print0 | xargs -0 %s",
154 sysrootdir, program) == -1) {
155 reply_with_perror ("asprintf");
162 fprintf (stderr, "%s\n", cmd);
164 FILE *fp = popen (cmd, "r");
166 reply_with_perror ("%s", cmd);
172 /* Now we must send the reply message, before the file contents. After
173 * this there is no opportunity in the protocol to send any error
174 * message back. Instead we can only cancel the transfer.
178 char str[GUESTFS_MAX_CHUNK_SIZE];
180 while ((r = fread (str, 1, GUESTFS_MAX_CHUNK_SIZE, fp)) > 0) {
181 if (send_file_write (str, r) < 0) {
189 send_file_end (1); /* Cancel. */
194 if (pclose (fp) != 0) {
196 send_file_end (1); /* Cancel. */
200 if (send_file_end (0)) /* Normal end of file. */