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.
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) {
69 flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | fd;
70 r = commandf (&out, &err, flags, program, NULL);
72 reply_with_error ("%s: %s", program, err);
80 /* Split it at the first whitespace. */
81 len = strcspn (out, " \t\n");
84 return out; /* Caller frees. */
88 do_checksum (const char *csumtype, const char *path)
93 fd = open (path, O_RDONLY);
97 reply_with_perror ("%s", path);
101 return checksum (csumtype, fd);
105 do_checksum_device (const char *csumtype, const char *device)
109 fd = open (device, O_RDONLY);
111 reply_with_perror ("%s", device);
115 return checksum (csumtype, fd);
118 /* Has one FileOut parameter. */
120 do_checksums_out (const char *csumtype, const char *dir)
125 const char *program = program_of_csum (csumtype);
129 char *sysrootdir = sysroot_path (dir);
131 reply_with_perror ("malloc");
135 r = stat (sysrootdir, &statbuf);
137 reply_with_perror ("%s", dir);
141 if (!S_ISDIR (statbuf.st_mode)) {
142 reply_with_error ("%s: not a directory", dir);
148 if (asprintf_nowarn (&cmd, "cd %Q && find -type f -print0 | xargs -0 %s",
149 sysrootdir, program) == -1) {
150 reply_with_perror ("asprintf");
157 fprintf (stderr, "%s\n", cmd);
159 FILE *fp = popen (cmd, "r");
161 reply_with_perror ("%s", cmd);
167 /* Now we must send the reply message, before the file contents. After
168 * this there is no opportunity in the protocol to send any error
169 * message back. Instead we can only cancel the transfer.
173 char str[GUESTFS_MAX_CHUNK_SIZE];
175 while ((r = fread (str, 1, GUESTFS_MAX_CHUNK_SIZE, fp)) > 0) {
176 if (send_file_write (str, r) < 0) {
184 send_file_end (1); /* Cancel. */
189 if (pclose (fp) != 0) {
191 send_file_end (1); /* Cancel. */
195 if (send_file_end (0)) /* Normal end of file. */