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.
25 #include "../src/guestfs_protocol.h"
31 do_tune2fs_l (const char *device)
35 char *p, *pend, *colon;
37 int size = 0, alloc = 0;
39 r = command (&out, &err, "/sbin/tune2fs", "-l", device, NULL);
41 reply_with_error ("tune2fs: %s", err);
50 /* Discard the first line if it contains "tune2fs ...". */
51 if (strncmp (p, "tune2fs ", 8) == 0) {
55 reply_with_error ("tune2fs: truncated output");
61 /* Read the lines and split into "key: value". */
63 pend = strchrnul (p, '\n');
71 colon = strchr (p, ':');
75 do { colon++; } while (*colon && c_isspace (*colon));
77 if (add_string (&ret, &size, &alloc, p) == -1) {
81 if (strcmp (colon, "<none>") == 0 ||
82 strcmp (colon, "<not available>") == 0 ||
83 strcmp (colon, "(none)") == 0) {
84 if (add_string (&ret, &size, &alloc, "") == -1) {
89 if (add_string (&ret, &size, &alloc, colon) == -1) {
96 if (add_string (&ret, &size, &alloc, p) == -1) {
100 if (add_string (&ret, &size, &alloc, "") == -1) {
111 if (add_string (&ret, &size, &alloc, NULL) == -1)
118 do_set_e2label (const char *device, const char *label)
123 r = command (NULL, &err, "/sbin/e2label", device, label, NULL);
125 reply_with_error ("e2label: %s", err);
135 do_get_e2label (const char *device)
140 r = command (&out, &err, "/sbin/e2label", device, NULL);
142 reply_with_error ("e2label: %s", err);
150 /* Remove any trailing \n from the label. */
152 if (len > 0 && out[len-1] == '\n')
155 return out; /* caller frees */
159 do_set_e2uuid (const char *device, const char *uuid)
164 r = command (NULL, &err, "/sbin/tune2fs", "-U", uuid, device, NULL);
166 reply_with_error ("tune2fs -U: %s", err);
176 do_get_e2uuid (const char *device)
179 char *out, *err, *p, *q;
181 /* It's not so straightforward to get the volume UUID. We have
182 * to use tune2fs -l and then look for a particular string in
186 r = command (&out, &err, "/sbin/tune2fs", "-l", device, NULL);
188 reply_with_error ("tune2fs -l: %s", err);
196 /* Look for /\nFilesystem UUID:\s+/ in the output. */
197 p = strstr (out, "\nFilesystem UUID:");
199 reply_with_error ("no Filesystem UUID in the output of tune2fs -l");
205 while (*p && c_isspace (*p))
208 reply_with_error ("malformed Filesystem UUID in the output of tune2fs -l");
213 /* Now 'p' hopefully points to the start of the UUID. */
215 while (*q && (c_isxdigit (*q) || *q == '-'))
218 reply_with_error ("malformed Filesystem UUID in the output of tune2fs -l");
227 reply_with_perror ("strdup");
233 return p; /* caller frees */
237 do_resize2fs (const char *device)
242 r = command (NULL, &err, "/sbin/resize2fs", device, NULL);
244 reply_with_error ("resize2fs: %s", err);
254 do_e2fsck_f (const char *device)
259 r = command (NULL, &err, "/sbin/e2fsck", "-p", "-f", device, NULL);
261 reply_with_error ("e2fsck: %s", err);
271 do_mke2journal (int blocksize, const char *device)
276 char blocksize_s[32];
277 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
279 r = command (NULL, &err,
280 "/sbin/mke2fs", "-O", "journal_dev", "-b", blocksize_s,
283 reply_with_error ("mke2journal: %s", err);
293 do_mke2journal_L (int blocksize, const char *label, const char *device)
298 char blocksize_s[32];
299 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
301 r = command (NULL, &err,
302 "/sbin/mke2fs", "-O", "journal_dev", "-b", blocksize_s,
306 reply_with_error ("mke2journal_L: %s", err);
316 do_mke2journal_U (int blocksize, const char *uuid, const char *device)
321 char blocksize_s[32];
322 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
324 r = command (NULL, &err,
325 "/sbin/mke2fs", "-O", "journal_dev", "-b", blocksize_s,
329 reply_with_error ("mke2journal_U: %s", err);
338 /* Run mke2fs to create a filesystem of type fstype, where fstype
339 * is the string "ext2", "ext3" or "ext4".
341 * This is more complex than it seems.
343 * On RHEL 5, the -t option was deprecated. Moreover RHEL <= 5.4
344 * systems have a bug where the -t option doesn't work (it doesn't
345 * correctly ignore the following argument).
347 * On RHEL 5, to create an ext4dev filesystem you have to use
348 * the special command /sbin/mke4fs. This can also create ext2/3
349 * using the '-t fstype' option.
351 * On Fedora 11+, mke4fs was renamed mke2fs, and it can use the
352 * '-t fstype' option to specify the filesystem type.
354 * So it seems best to run /sbin/mke4fs if it exists, or /sbin/mke2fs
355 * otherwise. We specify e4fsprogs in the package list to ensure it
356 * is loaded if it exists.
361 static const char *const progs[] = { "/sbin/mke4fs", "/sbin/mke2fs", NULL };
364 for (i = 0; progs[i]; ++i)
365 if (access (progs[i], F_OK) == 0)
368 reply_with_error ("mke2fs: no mke2fs binary found in appliance");
373 do_mke2fs_J (const char *fstype, int blocksize, const char *device,
379 const char *prog = get_mke2fs ();
380 if (!prog) return -1;
382 char blocksize_s[32];
383 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
385 int len = strlen (journal);
387 snprintf (jdev, len+32, "device=%s", journal);
389 r = command (NULL, &err,
390 prog, "-t", fstype, "-J", jdev, "-b", blocksize_s,
393 reply_with_error ("mke2fs_J: %s", err);
403 do_mke2fs_JL (const char *fstype, int blocksize, const char *device,
409 const char *prog = get_mke2fs ();
410 if (!prog) return -1;
412 char blocksize_s[32];
413 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
415 int len = strlen (label);
417 snprintf (jdev, len+32, "device=LABEL=%s", label);
419 r = command (NULL, &err,
420 prog, "-t", fstype, "-J", jdev, "-b", blocksize_s,
423 reply_with_error ("mke2fs_JL: %s", err);
433 do_mke2fs_JU (const char *fstype, int blocksize, const char *device,
439 const char *prog = get_mke2fs ();
440 if (!prog) return -1;
442 char blocksize_s[32];
443 snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);
445 int len = strlen (uuid);
447 snprintf (jdev, len+32, "device=UUID=%s", uuid);
449 r = command (NULL, &err,
450 prog, "-t", fstype, "-J", jdev, "-b", blocksize_s,
453 reply_with_error ("mke2fs_JU: %s", err);