1 /* guestfish - the filesystem interactive shell
2 * Copyright (C) 2010 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 static prep_data *parse_type_string (const char *type_string);
30 static void prep_error (prep_data *data, const char *filename, const char *fs, ...) __attribute__((noreturn, format (printf,3,4)));
33 const char *name; /* eg. "fs" */
35 size_t nr_params; /* optional parameters */
38 const char *shortdesc; /* short description */
39 const char *longdesc; /* long description */
41 /* functions to implement it */
42 void (*prelaunch) (const char *filename, prep_data *);
43 void (*postlaunch) (const char *filename, prep_data *, const char *device);
47 const char *pname; /* parameter name */
48 const char *pdefault; /* parameter default */
49 const char *pdesc; /* parameter description */
52 static void prelaunch_disk (const char *filename, prep_data *data);
53 static struct param disk_params[] = {
54 { "size", "100M", "the size of the disk image" },
57 static void prelaunch_part (const char *filename, prep_data *data);
58 static void postlaunch_part (const char *filename, prep_data *data, const char *device);
59 static struct param part_params[] = {
60 { "size", "100M", "the size of the disk image" },
61 { "partition", "mbr", "partition table type" },
64 static void prelaunch_fs (const char *filename, prep_data *data);
65 static void postlaunch_fs (const char *filename, prep_data *data, const char *device);
66 static struct param fs_params[] = {
67 { "filesystem", "ext2", "the type of filesystem to use" },
68 { "size", "100M", "the size of the disk image" },
69 { "partition", "mbr", "partition table type" },
72 static const struct prep preps[] = {
75 "create a blank disk",
77 Create a blank disk, size 100MB (by default).\n\
79 The default size can be changed by supplying an optional parameter.",
84 "create a partitioned disk",
86 Create a disk with a single partition. By default the size of the disk\n\
87 is 100MB (the available space in the partition will be a tiny bit smaller)\n\
88 and the partition table will be MBR (old DOS-style).\n\
90 These defaults can be changed by supplying optional parameters.",
91 prelaunch_part, postlaunch_part
95 "create a filesystem",
97 Create a disk with a single partition, with the partition containing\n\
98 an empty filesystem. This defaults to creating a 100MB disk (the available\n\
99 space in the filesystem will be a tiny bit smaller) with an MBR (old\n\
100 DOS-style) partition table and an ext2 filesystem.\n\
102 These defaults can be changed by supplying optional parameters.",
103 prelaunch_fs, postlaunch_fs
108 list_prepared_drives (void)
112 printf (_("List of available prepared disk images:\n\n"));
114 for (i = 0; i < sizeof preps / sizeof preps[0]; ++i) {
116 guestfish -N %-16s %s\n\
119 preps[i].name, preps[i].shortdesc, preps[i].longdesc);
121 if (preps[i].nr_params > 0) {
123 printf (_(" Optional parameters:\n"));
124 printf (" -N %s", preps[i].name);
125 for (j = 0; j < preps[i].nr_params; ++j)
126 printf (":<%s>", preps[i].params[j].pname);
128 for (j = 0; j < preps[i].nr_params; ++j) {
130 printf (_("<%s> %s (default: %s)\n"),
131 preps[i].params[j].pname,
132 preps[i].params[j].pdesc,
133 preps[i].params[j].pdefault);
141 Prepared disk images are written to file \"test1.img\" in the local\n\
142 directory. (\"test2.img\" etc if -N option is given multiple times).\n\
143 For more information see the guestfish(1) manual.\n"));
147 const struct prep *prep;
148 const char *orig_type_string;
152 /* Parse the type string (from the command line) and create the output
153 * file 'filename'. This is called before launch. Return the opaque
154 * prep_data which will be passed back to us in prepare_drive below.
157 create_prepared_file (const char *type_string, const char *filename)
159 prep_data *data = parse_type_string (type_string);
160 if (data->prep->prelaunch)
161 data->prep->prelaunch (filename, data);
166 parse_type_string (const char *type_string)
170 /* Match on the type part (without parameters). */
171 size_t len = strcspn (type_string, ":");
172 for (i = 0; i < sizeof preps / sizeof preps[0]; ++i)
173 if (STRCASEEQLEN (type_string, preps[i].name, len))
176 if (preps[i].name == NULL) {
177 fprintf (stderr, _("\
178 guestfish: -N parameter '%s': no such prepared disk image known.\n\
179 Use 'guestfish -N list' to list possible values for the -N parameter.\n"),
184 prep_data *data = malloc (sizeof *data);
189 data->prep = &preps[i];
190 data->orig_type_string = type_string;
192 /* Set up the optional parameters to all-defaults. */
193 data->params = malloc (data->prep->nr_params * sizeof (char *));
194 if (data->params == NULL) {
199 for (i = 0; i < data->prep->nr_params; ++i)
200 data->params[i] = data->prep->params[i].pdefault;
202 /* Parse the optional parameters. */
203 const char *p = type_string + len;
204 if (*p) p++; /* skip colon char */
208 len = strcspn (p, ":");
209 data->params[i] = strndup (p, len);
210 if (data->params[i] == NULL) {
216 if (*p) p++; /* skip colon char */
223 /* Prepare a drive. The appliance has been launched, and 'device' is
224 * the libguestfs device. 'data' is the requested type. 'filename'
225 * is just used for error messages.
228 prepare_drive (const char *filename, prep_data *data,
231 if (data->prep->postlaunch)
232 data->prep->postlaunch (filename, data, device);
236 prep_error (prep_data *data, const char *filename, const char *fs, ...)
239 _("guestfish: error creating prepared disk image '%s' on '%s': "),
240 data->orig_type_string, filename);
244 vfprintf (stderr, fs, args);
247 fprintf (stderr, "\n");
253 prelaunch_disk (const char *filename, prep_data *data)
255 if (alloc_disk (filename, data->params[0], 0, 1) == -1)
256 prep_error (data, filename, _("failed to allocate disk"));
260 prelaunch_part (const char *filename, prep_data *data)
262 if (alloc_disk (filename, data->params[0], 0, 1) == -1)
263 prep_error (data, filename, _("failed to allocate disk"));
267 postlaunch_part (const char *filename, prep_data *data, const char *device)
269 if (guestfs_part_disk (g, device, data->params[2]) == -1)
270 prep_error (data, filename, _("failed to partition disk: %s"),
271 guestfs_last_error (g));
275 prelaunch_fs (const char *filename, prep_data *data)
277 if (alloc_disk (filename, data->params[1], 0, 1) == -1)
278 prep_error (data, filename, _("failed to allocate disk"));
282 postlaunch_fs (const char *filename, prep_data *data, const char *device)
284 if (guestfs_part_disk (g, device, data->params[2]) == -1)
285 prep_error (data, filename, _("failed to partition disk: %s"),
286 guestfs_last_error (g));
289 if (asprintf (&part, "%s1", device) == -1) {
294 if (guestfs_mkfs (g, data->params[0], part) == -1)
295 prep_error (data, filename, _("failed to create filesystem (%s): %s"),
296 data->params[0], guestfs_last_error (g));