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.
29 #include "../src/guestfs_protocol.h"
34 do_initrd_list (const char *path)
38 char filename[PATH_MAX];
39 char **filenames = NULL;
40 int size = 0, alloc = 0;
43 /* "zcat /sysroot/<path> | cpio --quiet -it", but path must be quoted. */
44 if (asprintf_nowarn (&cmd, "zcat %R | cpio --quiet -it", path) == -1) {
45 reply_with_perror ("asprintf");
50 fprintf (stderr, "%s\n", cmd);
52 fp = popen (cmd, "r");
54 reply_with_perror ("popen: %s", cmd);
60 while (fgets (filename, sizeof filename, fp) != NULL) {
61 len = strlen (filename);
62 if (len > 0 && filename[len-1] == '\n')
63 filename[len-1] = '\0';
65 if (add_string (&filenames, &size, &alloc, filename) == -1) {
71 if (add_string (&filenames, &size, &alloc, NULL) == -1) {
76 if (pclose (fp) != 0) {
77 reply_with_perror ("pclose");
78 free_strings (filenames);
86 do_initrd_cat (const char *path, const char *filename, size_t *size_r)
88 char tmpdir[] = "/tmp/initrd-cat-XXXXXX";
89 if (mkdtemp (tmpdir) == NULL) {
90 reply_with_perror ("mkdtemp");
94 /* "zcat /sysroot/<path> | cpio --quiet -id file", but paths must be quoted */
96 if (asprintf_nowarn (&cmd, "cd %Q && zcat %R | cpio --quiet -id %Q",
97 tmpdir, path, filename) == -1) {
98 reply_with_perror ("asprintf");
103 /* Extract file into temporary directory. This may create subdirs.
104 * It's also possible that this doesn't create anything at all
105 * (eg. if the named file does not exist in the cpio archive) --
106 * cpio is silent in this case.
108 int r = system (cmd);
110 reply_with_perror ("command failed: %s", cmd);
114 if (WEXITSTATUS (r) != 0) {
115 reply_with_perror ("command failed with return code %d",
121 /* See if we got a file. */
122 char fullpath[PATH_MAX];
123 snprintf (fullpath, sizeof fullpath, "%s/%s", tmpdir, filename);
128 fd = open (fullpath, O_RDONLY);
130 reply_with_perror ("open: %s:%s", path, filename);
135 /* From this point, we know the file exists, so we require full
140 if (fstat (fd, &statbuf) == -1) {
141 reply_with_perror ("fstat: %s:%s", path, filename);
145 /* The actual limit on messages is smaller than this. This
146 * check just limits the amount of memory we'll try and allocate
147 * here. If the message is larger than the real limit, that will
148 * be caught later when we try to serialize the message.
150 if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) {
151 reply_with_error ("%s:%s: file is too large for the protocol",
156 ret = malloc (statbuf.st_size);
158 reply_with_perror ("malloc");
162 if (xread (fd, ret, statbuf.st_size) == -1) {
163 reply_with_perror ("read: %s:%s", path, filename);
169 if (close (fd) == -1) {
170 reply_with_perror ("close: %s:%s", path, filename);
177 /* Mustn't touch *size_r until we are sure that we won't return any
178 * error (RHBZ#589039).
180 *size_r = statbuf.st_size;
186 /* Remove the file. */
187 if (unlink (fullpath) == -1) {
188 fprintf (stderr, "unlink: ");
193 /* Remove the directories up to and including the temp directory. */
195 char *p = strrchr (fullpath, '/');
198 if (rmdir (fullpath) == -1) {
199 fprintf (stderr, "rmdir: ");
203 } while (STRNEQ (fullpath, tmpdir));