Richard W.M. Jones
2012-Feb-27 17:34 UTC
[Libguestfs] [PATCH 0/4] Add various ntfs* tools and unify label setting.
This miscellaneous patch adds bindings for: - ntfsfix - ntfsclone - ntfslabel and unifies filesystem label setting through a single API 'set-label' which replaces 'set-e2label' and is also able to set labels on NTFS using the ntfslabel program. 'ntfsfix' has been added as a possible way to fix RHBZ#797760. However I have not found a way to fully fix this bug. See discussion in the bug. 'ntfsclone-in' and 'ntfsclone-out' have been added at the request of a user. Rich.
From: "Richard W.M. Jones" <rjones at redhat.com> --- TODO | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/TODO b/TODO index b9a4ee9..9506673 100644 --- a/TODO +++ b/TODO @@ -387,6 +387,8 @@ ntfslabel: display or change filesystem label (we should unify all ntfsclone: clone, image, restore, rescue NTFS +ntfscluster: display file(s) that occupy a cluster or sector + ntfsinfo: print various information about NTFS volume and files ntfs streams: extract alternate streams from NTFS files -- 1.7.9.1
Richard W.M. Jones
2012-Feb-27 17:34 UTC
[Libguestfs] [PATCH 2/4] New API: ntfsfix for fixing problems on NTFS.
From: "Richard W.M. Jones" <rjones at redhat.com>
Note this is not a "chkdsk" equivalent tool.
---
daemon/ntfs.c | 29 +++++++++++++++++++++++++++++
generator/generator_actions.ml | 16 ++++++++++++++++
src/MAX_PROC_NR | 2 +-
3 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/daemon/ntfs.c b/daemon/ntfs.c
index e8be344..235ecbc 100644
--- a/daemon/ntfs.c
+++ b/daemon/ntfs.c
@@ -115,3 +115,32 @@ do_ntfsresize_size (const char *device, int64_t size)
optargs_bitmask = GUESTFS_NTFSRESIZE_OPTS_SIZE_BITMASK;
return do_ntfsresize_opts (device, size, 0);
}
+
+/* Takes optional arguments, consult optargs_bitmask. */
+int
+do_ntfsfix (const char *device, int clearbadsectors)
+{
+ const char *argv[MAX_ARGS];
+ size_t i = 0;
+ int r;
+ char *err;
+
+ ADD_ARG (argv, i, "ntfsfix");
+
+ if ((optargs_bitmask & GUESTFS_NTFSFIX_CLEARBADSECTORS_BITMASK)
&&
+ clearbadsectors)
+ ADD_ARG (argv, i, "-b");
+
+ ADD_ARG (argv, i, device);
+ ADD_ARG (argv, i, NULL);
+
+ r = commandv (NULL, &err, argv);
+ if (r == -1) {
+ reply_with_error ("%s: %s", device, err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 9baf081..9df9ea5 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -6666,6 +6666,22 @@ C<device>.
Compare with C<guestfs_zero> which zeroes the first few blocks of a
device.");
+ ("ntfsfix", (RErr, [Device "device"], [OBool
"clearbadsectors"]), 307, [Optional "ntfs3g"],
+ [InitPartition, IfAvailable "ntfs3g", TestRun (
+ [["mkfs"; "ntfs"; "/dev/sda1"];
+ ["ntfsfix"; "/dev/sda1"; "false"]])],
+ "fix common errors and force Windows to check NTFS",
+ "\
+This command repairs some fundamental NTFS inconsistencies,
+resets the NTFS journal file, and schedules an NTFS consistency
+check for the first boot into Windows.
+
+This is I<not> an equivalent of Windows C<chkdsk>. It does
I<not>
+scan the filesystem for inconsistencies.
+
+The optional C<clearbadsectors> flag clears the list of bad sectors.
+This is useful after cloning a disk with bad sectors to a new disk.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index cd30709..ae4cf41 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-306
+307
--
1.7.9.1
Richard W.M. Jones
2012-Feb-27 17:34 UTC
[Libguestfs] [PATCH 3/4] New APIs: ntfsclone-in, ntfsclone-out.
From: "Richard W.M. Jones" <rjones at redhat.com>
---
Makefile.am | 1 +
TODO | 2 -
configure.ac | 1 +
daemon/Makefile.am | 1 +
daemon/ntfsclone.c | 212 +++++++++++++++++++++++++++++++++++++
generator/generator_actions.ml | 27 +++++
po/POTFILES.in | 1 +
src/MAX_PROC_NR | 2 +-
tests/ntfsclone/Makefile.am | 30 +++++
tests/ntfsclone/test-ntfsclone.sh | 54 ++++++++++
10 files changed, 328 insertions(+), 3 deletions(-)
create mode 100644 daemon/ntfsclone.c
create mode 100644 tests/ntfsclone/Makefile.am
create mode 100755 tests/ntfsclone/test-ntfsclone.sh
diff --git a/Makefile.am b/Makefile.am
index e621145..dfee9c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ SUBDIRS += tests/protocol
SUBDIRS += tests/lvm
SUBDIRS += tests/luks
SUBDIRS += tests/md
+SUBDIRS += tests/ntfsclone
SUBDIRS += tests/regressions
endif
diff --git a/TODO b/TODO
index 9506673..9dafb4d 100644
--- a/TODO
+++ b/TODO
@@ -385,8 +385,6 @@ ntfslabel: display or change filesystem label (we should
unify all
set*label APIs into a single set_vfs_label which can deal with any
filesystem)
-ntfsclone: clone, image, restore, rescue NTFS
-
ntfscluster: display file(s) that occupy a cluster or sector
ntfsinfo: print various information about NTFS volume and files
diff --git a/configure.ac b/configure.ac
index 31a2cc5..c07609a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1146,6 +1146,7 @@ AC_CONFIG_FILES([Makefile
tests/luks/Makefile
tests/lvm/Makefile
tests/md/Makefile
+ tests/ntfsclone/Makefile
tests/protocol/Makefile
tests/qemu/Makefile
tests/regressions/Makefile
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3a698cc..2dd8149 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -137,6 +137,7 @@ guestfsd_SOURCES = \
mount.c \
names.c \
ntfs.c \
+ ntfsclone.c \
optgroups.c \
optgroups.h \
parted.c \
diff --git a/daemon/ntfsclone.c b/daemon/ntfsclone.c
new file mode 100644
index 0000000..4287edb
--- /dev/null
+++ b/daemon/ntfsclone.c
@@ -0,0 +1,212 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "read-file.h"
+
+#include "daemon.h"
+#include "actions.h"
+#include "optgroups.h"
+
+/* Read the error file. Returns a string that the caller must free. */
+static char *
+read_error_file (char *error_file)
+{
+ size_t len;
+ char *str;
+
+ str = read_file (error_file, &len);
+ if (str == NULL) {
+ str = strdup ("(no error)");
+ if (str == NULL) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
+ len = strlen (str);
+ }
+
+ /* Remove trailing \n character if any. */
+ if (len > 0 && str[len-1] == '\n')
+ str[--len] = '\0';
+
+ return str; /* caller frees */
+}
+
+static int
+write_cb (void *fd_ptr, const void *buf, size_t len)
+{
+ int fd = *(int *)fd_ptr;
+ return xwrite (fd, buf, len);
+}
+
+/* Has one FileIn parameter. */
+int
+do_ntfsclone_in (const char *device)
+{
+ int err, r;
+ FILE *fp;
+ char *cmd;
+ char error_file[] = "/tmp/ntfscloneXXXXXX";
+ int fd;
+
+ fd = mkstemp (error_file);
+ if (fd == -1) {
+ reply_with_perror ("mkstemp");
+ return -1;
+ }
+
+ close (fd);
+
+ /* Construct the command. */
+ if (asprintf_nowarn (&cmd, "ntfsclone -O %s --restore-image - 2>
%s",
+ device, error_file) == -1) {
+ err = errno;
+ r = cancel_receive ();
+ errno = err;
+ reply_with_perror ("asprintf");
+ unlink (error_file);
+ return -1;
+ }
+
+ if (verbose)
+ fprintf (stderr, "%s\n", cmd);
+
+ fp = popen (cmd, "w");
+ if (fp == NULL) {
+ err = errno;
+ r = cancel_receive ();
+ errno = err;
+ reply_with_perror ("%s", cmd);
+ unlink (error_file);
+ free (cmd);
+ return -1;
+ }
+ free (cmd);
+
+ /* The semantics of fwrite are too undefined, so write to the
+ * file descriptor directly instead.
+ */
+ fd = fileno (fp);
+
+ r = receive_file (write_cb, &fd);
+ if (r == -1) { /* write error */
+ cancel_receive ();
+ char *errstr = read_error_file (error_file);
+ reply_with_error ("write error on device: %s: %s", device,
errstr);
+ free (errstr);
+ unlink (error_file);
+ pclose (fp);
+ return -1;
+ }
+ if (r == -2) { /* cancellation from library */
+ /* This error is ignored by the library since it initiated the
+ * cancel. Nevertheless we must send an error reply here.
+ */
+ reply_with_error ("ntfsclone cancelled");
+ pclose (fp);
+ unlink (error_file);
+ return -1;
+ }
+
+ if (pclose (fp) != 0) {
+ char *errstr = read_error_file (error_file);
+ reply_with_error ("ntfsclone subcommand failed on device: %s:
%s",
+ device, errstr);
+ free (errstr);
+ unlink (error_file);
+ return -1;
+ }
+
+ unlink (error_file);
+
+ return 0;
+}
+
+/* Has one FileOut parameter. */
+/* Takes optional arguments, consult optargs_bitmask. */
+int
+do_ntfsclone_out (const char *device,
+ int metadataonly, int rescue, int ignorefscheck,
+ int preservetimestamps, int force)
+{
+ int r;
+ FILE *fp;
+ char *cmd;
+ char buf[GUESTFS_MAX_CHUNK_SIZE];
+
+ /* Construct the ntfsclone command. */
+ if (asprintf (&cmd, "ntfsclone -o - --save-image%s%s%s%s%s %s",
+ (optargs_bitmask &
GUESTFS_NTFSCLONE_OUT_METADATAONLY_BITMASK) && metadataonly ? "
--metadata" : "",
+ (optargs_bitmask & GUESTFS_NTFSCLONE_OUT_RESCUE_BITMASK)
&& rescue ? " --rescue" : "",
+ (optargs_bitmask &
GUESTFS_NTFSCLONE_OUT_IGNOREFSCHECK_BITMASK) && ignorefscheck ? "
--ignore-fs-check" : "",
+ (optargs_bitmask &
GUESTFS_NTFSCLONE_OUT_PRESERVETIMESTAMPS_BITMASK) && preservetimestamps
? " --preserve-timestamps" : "",
+ (optargs_bitmask & GUESTFS_NTFSCLONE_OUT_FORCE_BITMASK)
&& force ? " --force" : "",
+ device) == -1) {
+ reply_with_perror ("asprintf");
+ return -1;
+ }
+
+ if (verbose)
+ fprintf (stderr, "%s\n", cmd);
+
+ fp = popen (cmd, "r");
+ if (fp == NULL) {
+ reply_with_perror ("%s", cmd);
+ free (cmd);
+ return -1;
+ }
+ free (cmd);
+
+ /* Now we must send the reply message, before the file contents. After
+ * this there is no opportunity in the protocol to send any error
+ * message back. Instead we can only cancel the transfer.
+ */
+ reply (NULL, NULL);
+
+ while ((r = fread (buf, 1, sizeof buf, fp)) > 0) {
+ if (send_file_write (buf, r) < 0) {
+ pclose (fp);
+ return -1;
+ }
+ }
+
+ if (ferror (fp)) {
+ perror (device);
+ send_file_end (1); /* Cancel. */
+ pclose (fp);
+ return -1;
+ }
+
+ if (pclose (fp) != 0) {
+ perror (device);
+ send_file_end (1); /* Cancel. */
+ return -1;
+ }
+
+ if (send_file_end (0)) /* Normal end of file. */
+ return -1;
+
+ return 0;
+}
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 9df9ea5..2d24e6a 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -6682,6 +6682,33 @@ scan the filesystem for inconsistencies.
The optional C<clearbadsectors> flag clears the list of bad sectors.
This is useful after cloning a disk with bad sectors to a new disk.");
+ ("ntfsclone_out", (RErr, [Device "device"; FileOut
"backupfile"], [OBool "metadataonly"; OBool
"rescue"; OBool "ignorefscheck"; OBool
"preservetimestamps"; OBool "force"]), 308, [Optional
"ntfs3g"; Cancellable],
+ [], (* tested in tests/ntfsclone *)
+ "save NTFS to backup file",
+ "\
+Stream the NTFS filesystem C<device> to the local file
+C<backupfile>. The format used for the backup file is a
+special format used by the L<ntfsclone(8)> tool.
+
+If the optional C<metadataonly> flag is true, then I<only> the
+metadata is saved, losing all the user data (this is useful
+for diagnosing some filesystem problems).
+
+The optional C<rescue>, C<ignorefscheck>,
C<preservetimestamps>
+and C<force> flags have precise meanings detailed in the
+L<ntfsclone(8)> man page.
+
+Use C<guestfs_ntfsclone_in> to restore the file back to a
+libguestfs device.");
+
+ ("ntfsclone_in", (RErr, [FileIn "backupfile"; Device
"device"], []), 309, [Optional "ntfs3g"; Cancellable],
+ [], (* tested in tests/ntfsclone *)
+ "restore NTFS from backup file",
+ "\
+Restore the C<backupfile> (from a previous call to
+C<guestfs_ntfsclone_out>) to C<device>, overwriting
+any existing contents of this device.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3a43d17..bed1f65 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -56,6 +56,7 @@ daemon/modprobe.c
daemon/mount.c
daemon/names.c
daemon/ntfs.c
+daemon/ntfsclone.c
daemon/optgroups.c
daemon/parted.c
daemon/pingdaemon.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index ae4cf41..7536e3d 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-307
+309
diff --git a/tests/ntfsclone/Makefile.am b/tests/ntfsclone/Makefile.am
new file mode 100644
index 0000000..637b247
--- /dev/null
+++ b/tests/ntfsclone/Makefile.am
@@ -0,0 +1,30 @@
+# libguestfs
+# Copyright (C) 2012 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+include $(top_srcdir)/subdir-rules.mk
+
+TESTS = \
+ test-ntfsclone.sh
+
+random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}'
< /dev/null)
+
+TESTS_ENVIRONMENT = \
+ MALLOC_PERTURB_=$(random_val) \
+ $(top_builddir)/run
+
+EXTRA_DIST = \
+ $(TESTS)
diff --git a/tests/ntfsclone/test-ntfsclone.sh
b/tests/ntfsclone/test-ntfsclone.sh
new file mode 100755
index 0000000..2dc4fe8
--- /dev/null
+++ b/tests/ntfsclone/test-ntfsclone.sh
@@ -0,0 +1,54 @@
+#!/bin/bash -
+# libguestfs
+# Copyright (C) 2012 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test the ntfsclone-in/-out commands.
+
+set -e
+
+rm -f test1.img backup1 backup2
+
+guestfish=../../fish/guestfish
+
+# Skip if ntfs-3g is not supported by the appliance.
+if ! $guestfish add /dev/null : run : available "ntfs3g"; then
+ echo "$0: skipped because ntfs-3g is not supported by the
appliance"
+ exit 0
+fi
+
+# Export the filesystems to the backup file.
+$guestfish --ro -a ../guests/windows.img <<EOF
+run
+ntfsclone-out /dev/sda1 backup1 preservetimestamps:true force:true
+ntfsclone-out /dev/sda2 backup2 metadataonly:true ignorefscheck:true
+EOF
+
+# Restore to another disk image.
+output=$($guestfish -N part:300M <<EOF
+ntfsclone-in backup1 /dev/sda1
+vfs-type /dev/sda1
+EOF
+)
+
+if [ "$output" != "ntfs" ]; then
+ echo "$0: unexpected filesystem type after restore: $output"
+ exit 1
+fi
+
+#ls -lh backup[12]
+
+rm -f test1.img backup1 backup2
--
1.7.9.1
Richard W.M. Jones
2012-Feb-27 17:34 UTC
[Libguestfs] [PATCH 4/4] New API: set-label, for setting a label on any filesystem.
From: "Richard W.M. Jones" <rjones at redhat.com>
Currently only ext2/3/4 and (newly) NTFS are supported.
This change also deprecates set-e2label.
---
TODO | 4 -
daemon/Makefile.am | 1 +
daemon/daemon.h | 3 +
daemon/ext2.c | 26 +-------
daemon/labels.c | 100 +++++++++++++++++++++++++++++
generator/generator_actions.ml | 28 ++++++++-
po/POTFILES.in | 1 +
src/MAX_PROC_NR | 2 +-
tests/guests/guest-aux/make-debian-img.sh | 2 +-
tests/guests/guest-aux/make-fedora-img.pl | 4 +-
tests/guests/guest-aux/make-ubuntu-img.sh | 2 +-
11 files changed, 137 insertions(+), 36 deletions(-)
create mode 100644 daemon/labels.c
diff --git a/TODO b/TODO
index 9dafb4d..499c345 100644
--- a/TODO
+++ b/TODO
@@ -381,10 +381,6 @@ More ntfs tools
ntfsprogs actually has a lot more useful tools than we currently
use. Interesting ones are:
-ntfslabel: display or change filesystem label (we should unify all
- set*label APIs into a single set_vfs_label which can deal with any
- filesystem)
-
ntfscluster: display file(s) that occupy a cluster or sector
ntfsinfo: print various information about NTFS volume and files
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 2dd8149..74d24fc 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -125,6 +125,7 @@ guestfsd_SOURCES = \
inotify.c \
internal.c \
is.c \
+ labels.c \
link.c \
ls.c \
luks.c \
diff --git a/daemon/daemon.h b/daemon/daemon.h
index c92e110..c45a7fe 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -132,6 +132,9 @@ extern int sync_disks (void);
/*-- in ext2.c --*/
extern int e2prog (char *name); /* Massive hack for RHEL 5. */
+/* Confirmed this is true up to ext4 from the Linux sources. */
+#define EXT2_LABEL_MAX 16
+
/*-- in lvm.c --*/
extern int lv_canonical (const char *device, char **ret);
diff --git a/daemon/ext2.c b/daemon/ext2.c
index a643935..02cd68a 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -29,9 +29,6 @@
#include "c-ctype.h"
#include "actions.h"
-/* Confirmed this is true up to ext4 from the Linux sources. */
-#define EXT2_LABEL_MAX 16
-
#define MAX_ARGS 64
/* Choose which tools like mke2fs to use. For RHEL 5 (only) there
@@ -154,28 +151,7 @@ do_tune2fs_l (const char *device)
int
do_set_e2label (const char *device, const char *label)
{
- int r;
- char *err;
-
- char prog[] = "e2label";
- if (e2prog (prog) == -1)
- return -1;
-
- if (strlen (label) > EXT2_LABEL_MAX) {
- reply_with_error ("%s: ext2 labels are limited to %d bytes",
- label, EXT2_LABEL_MAX);
- return -1;
- }
-
- r = command (NULL, &err, prog, device, label, NULL);
- if (r == -1) {
- reply_with_error ("%s", err);
- free (err);
- return -1;
- }
-
- free (err);
- return 0;
+ return do_set_label (device, label);
}
char *
diff --git a/daemon/labels.c b/daemon/labels.c
new file mode 100644
index 0000000..7117698
--- /dev/null
+++ b/daemon/labels.c
@@ -0,0 +1,100 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "daemon.h"
+#include "actions.h"
+#include "optgroups.h"
+
+static int
+e2label (const char *device, const char *label)
+{
+ int r;
+ char *err;
+
+ char prog[] = "e2label";
+ if (e2prog (prog) == -1)
+ return -1;
+
+ if (strlen (label) > EXT2_LABEL_MAX) {
+ reply_with_error ("%s: ext2 labels are limited to %d bytes",
+ label, EXT2_LABEL_MAX);
+ return -1;
+ }
+
+ r = command (NULL, &err, prog, device, label, NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+static int
+ntfslabel (const char *device, const char *label)
+{
+ int r;
+ char *err;
+
+ /* XXX We should check if the label is longer than 128 unicode
+ * characters and return an error. This is not so easy since we
+ * don't have the required libraries.
+ */
+ r = command (NULL, &err, "ntfslabel", device, label, NULL);
+ if (r == -1) {
+ reply_with_error ("%s", err);
+ free (err);
+ return -1;
+ }
+
+ free (err);
+ return 0;
+}
+
+int
+do_set_label (const char *device, const char *label)
+{
+ char *vfs_type;
+
+ /* How we set the label depends on the filesystem type. */
+ vfs_type = do_vfs_type (device);
+ if (vfs_type == NULL)
+ return -1;
+
+ if (STREQ (vfs_type, "ext2") || STREQ (vfs_type, "ext3")
+ || STREQ (vfs_type, "ext4"))
+ return e2label (device, label);
+
+ else if (STREQ (vfs_type, "ntfs"))
+ return ntfslabel (device, label);
+
+ else {
+ reply_with_error ("don't know how to set the label for
'%s' filesystems",
+ vfs_type);
+ return -1;
+ }
+}
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 2d24e6a..d9f88af 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -3007,7 +3007,7 @@ The implementation uses the C<pvremove> command
which refuses to
wipe physical volumes that contain any volume groups, so you have
to remove those first.");
- ("set_e2label", (RErr, [Device "device"; String
"label"], []), 80, [],
+ ("set_e2label", (RErr, [Device "device"; String
"label"], []), 80, [DeprecatedBy "set_label"],
[InitBasicFS, Always, TestOutput (
[["set_e2label"; "/dev/sda1"; "testlabel"];
["get_e2label"; "/dev/sda1"]],
"testlabel")],
@@ -5698,7 +5698,7 @@ a file in the host and attach it as a device.");
("vfs_label", (RString "label", [Device
"device"], []), 253, [],
[InitBasicFS, Always, TestOutput (
- [["set_e2label"; "/dev/sda1"; "LTEST"];
+ [["set_label"; "/dev/sda1"; "LTEST"];
["vfs_label"; "/dev/sda1"]], "LTEST")],
"get the filesystem label",
"\
@@ -6709,6 +6709,30 @@ Restore the C<backupfile> (from a previous call to
C<guestfs_ntfsclone_out>) to C<device>, overwriting
any existing contents of this device.");
+ ("set_label", (RErr, [Device "device"; String
"label"], []), 310, [],
+ [InitBasicFS, Always, TestOutput (
+ [["set_label"; "/dev/sda1"; "testlabel"];
+ ["vfs_label"; "/dev/sda1"]], "testlabel");
+ InitPartition, IfAvailable "ntfs3g", TestOutput (
+ [["mkfs"; "ntfs"; "/dev/sda1"];
+ ["set_label"; "/dev/sda1"; "testlabel2"];
+ ["vfs_label"; "/dev/sda1"]], "testlabel2");
+ InitPartition, Always, TestLastFail (
+ [["zero"; "/dev/sda1"];
+ ["set_label"; "/dev/sda1";
"testlabel2"]])],
+ "set filesystem label",
+ "\
+Set the filesystem label on C<device> to C<label>.
+
+Only some filesystem types support labels, and libguestfs supports
+setting labels on only a subset of these.
+
+On ext2/3/4 filesystems, labels are limited to 16 bytes.
+
+On NTFS filesystems, labels are limited to 128 unicode characters.
+
+To read the label on a filesystem, call C<guestfs_vfs_label>.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bed1f65..22e39b1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -44,6 +44,7 @@ daemon/initrd.c
daemon/inotify.c
daemon/internal.c
daemon/is.c
+daemon/labels.c
daemon/link.c
daemon/ls.c
daemon/luks.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 7536e3d..54ea97e 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-309
+310
diff --git a/tests/guests/guest-aux/make-debian-img.sh
b/tests/guests/guest-aux/make-debian-img.sh
index 9449d0f..f0c1597 100755
--- a/tests/guests/guest-aux/make-debian-img.sh
+++ b/tests/guests/guest-aux/make-debian-img.sh
@@ -49,7 +49,7 @@ lvcreate home debian 32
# Phony /boot filesystem.
mkfs-opts ext2 /dev/sda1 blocksize:4096
-set-e2label /dev/sda1 BOOT
+set-label /dev/sda1 BOOT
set-e2uuid /dev/sda1 01234567-0123-0123-0123-012345678901
# Phony root and other filesystems.
diff --git a/tests/guests/guest-aux/make-fedora-img.pl
b/tests/guests/guest-aux/make-fedora-img.pl
index 90010ef..fbc189d 100755
--- a/tests/guests/guest-aux/make-fedora-img.pl
+++ b/tests/guests/guest-aux/make-fedora-img.pl
@@ -126,12 +126,12 @@ $g->lvcreate('LV3', 'VG', 64);
# Phony /boot filesystem
$g->mkfs_opts('ext2', $bootdev, blocksize => 4096);
-$g->set_e2label($bootdev, 'BOOT');
+$g->set_label($bootdev, 'BOOT');
$g->set_e2uuid($bootdev, '01234567-0123-0123-0123-012345678901');
# Phony root filesystem.
$g->mkfs_opts('ext2', '/dev/VG/Root', blocksize => 4096);
-$g->set_e2label('/dev/VG/Root', 'ROOT');
+$g->set_label('/dev/VG/Root', 'ROOT');
$g->set_e2uuid('/dev/VG/Root',
'01234567-0123-0123-0123-012345678902');
# Enough to fool inspection API.
diff --git a/tests/guests/guest-aux/make-ubuntu-img.sh
b/tests/guests/guest-aux/make-ubuntu-img.sh
index c2831aa..a2b4d17 100755
--- a/tests/guests/guest-aux/make-ubuntu-img.sh
+++ b/tests/guests/guest-aux/make-ubuntu-img.sh
@@ -47,7 +47,7 @@ part-add /dev/sda p 524288 -64
# Phony /boot filesystem.
mkfs-opts ext2 /dev/sda1 blocksize:4096
-set-e2label /dev/sda1 BOOT
+set-label /dev/sda1 BOOT
set-e2uuid /dev/sda1 01234567-0123-0123-0123-012345678901
# Phony root filesystem (Ubuntu doesn't use LVM by default).
--
1.7.9.1