summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Borden2010-04-02 15:52:45 +0200
committerKarel Zak2010-04-02 16:16:59 +0200
commit4dddc2d4aa37367432f719b7c84cb8084bd7a109 (patch)
treee64068e6bc9fbc3989895193ad80cbc5e81eed13
parentmkswap: zap bootbits on regular files (diff)
downloadkernel-qcow2-util-linux-4dddc2d4aa37367432f719b7c84cb8084bd7a109.tar.gz
kernel-qcow2-util-linux-4dddc2d4aa37367432f719b7c84cb8084bd7a109.tar.xz
kernel-qcow2-util-linux-4dddc2d4aa37367432f719b7c84cb8084bd7a109.zip
swaplabel: new command
Print or change the label / UUID of a swap area. [kzak@redhat.com: - code refactoring - add long options - clean up Makefile.am] Signed-off-by: Jason Borden <jborden@bluehost.com> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--AUTHORS2
-rw-r--r--disk-utils/.gitignore1
-rw-r--r--disk-utils/Makefile.am36
-rw-r--r--disk-utils/swaplabel.866
-rw-r--r--disk-utils/swaplabel.c226
-rw-r--r--include/swapheader.h8
6 files changed, 325 insertions, 14 deletions
diff --git a/AUTHORS b/AUTHORS
index 803a76d09..b4fbee6c3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,8 @@ AUTHORS (merged projects & commands):
Jeremy Katz <katzj@redhat.com>
unshare: Mikhail Gusarov <dottedmag@dottedmag.net>
wipefs: Karel Zak <kzak@redhat.com>
+ swaplabel: Jason Borden <jborden@bluehost.com>
+ Karel Zak <kzak@redhat.com>
CONTRIBUTORS:
diff --git a/disk-utils/.gitignore b/disk-utils/.gitignore
index 726008f66..c97b3421a 100644
--- a/disk-utils/.gitignore
+++ b/disk-utils/.gitignore
@@ -10,3 +10,4 @@ mkswap
mkfs.cramfs
elvtune
raw
+swaplabel
diff --git a/disk-utils/Makefile.am b/disk-utils/Makefile.am
index ed0a6e4b8..67aeae40e 100644
--- a/disk-utils/Makefile.am
+++ b/disk-utils/Makefile.am
@@ -5,17 +5,32 @@ if LINUX
utils_common += ../lib/linux_version.c
endif
+if HAVE_UUID
+if BUILD_LIBUUID
+uuid_cflags = -I$(ul_libuuid_srcdir)
+uuid_ldadd = $(ul_libuuid_la)
+else
+uuid_cflags = $(UUID_CFLAGS)
+uuid_ldadd = $(UUID_LIBS)
+endif
+endif
+
dist_man_MANS = isosize.8 mkfs.8 mkswap.8 \
fsck.minix.8 mkfs.minix.8 mkfs.bfs.8
sbin_PROGRAMS = mkfs mkswap fsck.minix mkfs.minix mkfs.bfs
+
fsck_minix_SOURCES = fsck.minix.c minix.h
mkfs_minix_SOURCES = mkfs.minix.c minix.h $(utils_common)
mkfs_bfs_SOURCES = mkfs.bfs.c $(utils_common)
+swaplabel_SOURCES = swaplabel.c $(utils_common)
+swaplabel_LDADD = $(uuid_ldadd)
+swaplabel_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
+
mkswap_SOURCES = mkswap.c $(utils_common) ../lib/wholedisk.c
-mkswap_LDADD =
-mkswap_CFLAGS = $(AM_CFLAGS)
+mkswap_LDADD = $(uuid_ldadd)
+mkswap_CFLAGS = $(AM_CFLAGS) $(uuid_cflags)
usrbin_exec_PROGRAMS = isosize
usrsbin_exec_PROGRAMS =
@@ -27,6 +42,13 @@ usrsbin_exec_PROGRAMS += fdformat
blockdev_SOURCES = blockdev.c $(utils_common)
endif
+if BUILD_LIBBLKID
+sbin_PROGRAMS += swaplabel
+dist_man_MANS += swaplabel.8
+swaplabel_LDADD += $(ul_libblkid_la)
+swaplabel_CFLAGS += -I$(ul_libblkid_incdir)
+endif
+
if BUILD_ELVTUNE
sbin_PROGRAMS += elvtune
dist_man_MANS += elvtune.8
@@ -49,16 +71,6 @@ fsck_cramfs_LDADD = -lz
mkfs_cramfs_LDADD = -lz
endif
-if HAVE_UUID
-if BUILD_LIBUUID
-mkswap_LDADD += $(ul_libuuid_la)
-mkswap_CFLAGS += -I$(ul_libuuid_srcdir)
-else
-mkswap_LDADD += $(UUID_LIBS)
-mkswap_CFLAGS += $(UUID_CFLAGS)
-endif
-endif
-
if BUILD_LIBBLKID
# only in-tree libblkid has partitions parsing support
mkswap_LDADD += $(ul_libblkid_la)
diff --git a/disk-utils/swaplabel.8 b/disk-utils/swaplabel.8
new file mode 100644
index 000000000..aade3ca23
--- /dev/null
+++ b/disk-utils/swaplabel.8
@@ -0,0 +1,66 @@
+.\" Copyright 2010 Jason Borden <jborden@bluehost.com>
+.\"
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH SWAPLABEL 8 "2 April 2010" "Linux" "Linux Programmer's Manual"
+.SH NAME
+swaplabel \- Print or change the label / UUID of a swap area
+.SH SYNOPSIS
+.B swaplabel
+.RB [ \-L
+.IR label ]
+.RB [ \-U
+.IR UUID ]
+.I device
+.SH DESCRIPTION
+.B swaplabel
+will display or change the label / UUID of a swap partition located on
+.IR device
+(or regular file).
+.PP
+If the optional arguments
+.B \-L
+and
+.B \-U
+are not present,
+.B swaplabel
+will simply display the awap area label and UUID of
+.IR device .
+.PP
+If an optional argument is present, then
+.B swaplabel
+will change the appropriate value of
+.IR device .
+These values can also be set during swap creation using
+.BR mkswap (8).
+The
+.B swaplabel
+utility allows to change the label or UUID on actively used swap device.
+.SH OPTIONS
+.IP "\fB\-h, \-\-help\fP"
+Print help and exit.
+.IP "\fB\-L, \-\-label\fP \fIlabel\fP"
+Specify a new label for
+.IR device .
+Swap partition labels can be at most 16 characters long. If
+.IR label
+is longer than 16 characters,
+.B swapinfo
+will truncate it and print a warning message.
+.IP "\fB\-U, \-\-uuid\fP \fIuuid\fP"
+Specify a new UUID for
+.IR device .
+.IR UUID
+must be in the standard 8-4-4-4-12 character format, such as is ouput by
+.BR uuidgen (1) .
+.PP
+.SH AUTHOR
+.B swaplabel
+was written by Jason Borden <jborden@bluehost.com> and Karel Zak <kzak@redhat.com>.
+.SH AVAILABILITY
+.B swaplabel
+is part of the util-linux-ng package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
+.SH SEE ALSO
+.BR mkswap (8),
+.BR swapon (8),
+.BR uuidgen (1)
diff --git a/disk-utils/swaplabel.c b/disk-utils/swaplabel.c
new file mode 100644
index 000000000..634197226
--- /dev/null
+++ b/disk-utils/swaplabel.c
@@ -0,0 +1,226 @@
+/*
+ * swaplabel.c - Print or change the label / UUID of a swap partition
+ *
+ * Copyright (C) 2010 Jason Borden <jborden@bluehost.com>
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * Usage: swaplabel [-L label] [-U UUID] device
+ *
+ * This file may be redistributed under the terms of the GNU Public License
+ * version 2 or later.
+ *
+ */
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include <blkid.h>
+#include <getopt.h>
+
+#ifdef HAVE_LIBUUID
+# ifdef HAVE_UUID_UUID_H
+# include <uuid/uuid.h>
+# else
+# include <uuid.h>
+# endif
+#endif
+
+#include "c.h"
+#include "writeall.h"
+#include "swapheader.h"
+#include "xstrncpy.h"
+#include "nls.h"
+
+#define SWAP_UUID_OFFSET (offsetof(struct swap_header_v1_2, uuid))
+#define SWAP_LABEL_OFFSET (offsetof(struct swap_header_v1_2, volume_name))
+
+/*
+ * Returns new libblkid prober. This function call exit() on error.
+ */
+static blkid_probe get_swap_prober(const char *devname)
+{
+ blkid_probe pr;
+ int rc;
+ const char *version = NULL;
+ char *swap_filter[] = { "swap", NULL };
+
+ pr = blkid_new_probe_from_filename(devname);
+ if (!pr) {
+ warn(_("%s: unable to probe device"), devname);
+ return NULL;
+ }
+
+ blkid_probe_enable_superblocks(pr, TRUE);
+ blkid_probe_set_superblocks_flags(pr,
+ BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
+ BLKID_SUBLKS_VERSION);
+
+ blkid_probe_filter_superblocks_type(pr, BLKID_FLTR_ONLYIN, swap_filter);
+
+ rc = blkid_do_safeprobe(pr);
+ if (rc == -1)
+ warn(_("%s: unable to probe device"), devname);
+ else if (rc == -2)
+ warnx(_("%s: ambivalent probing result, use wipefs(8)"), devname);
+ else if (rc == 1)
+ warnx(_("%s: not a valid swap partition"), devname);
+
+ if (rc == 0) {
+ /* supported is SWAPSPACE2 only */
+ blkid_probe_lookup_value(pr, "VERSION", &version, NULL);
+ if (strcmp(version, "2"))
+ warnx(_("%s: unsupported swap version '%s'"),
+ devname, version);
+ else
+ return pr;
+ }
+
+ blkid_free_probe(pr);
+ return NULL;
+}
+
+/* Print the swap partition information */
+static int print_info(blkid_probe pr, const char *devname)
+{
+ const char *data;
+
+ if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
+ printf("LABEL: %s\n", data);
+
+ if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL))
+ printf("UUID: %s\n", data);
+
+ return 0;
+}
+
+/* Change the swap partition info */
+static int change_info(const char *devname, const char *label, const char *uuid)
+{
+ int fd;
+
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ warn(_("%s: failed to open"), devname);
+ goto err;
+ }
+#ifdef HAVE_LIBUUID
+ /* Write the uuid if it was provided */
+ if (uuid) {
+ uuid_t newuuid;
+
+ if (uuid_parse(uuid, newuuid) == -1)
+ warnx(_("failed to parse UUID: %s"), uuid);
+ else {
+ if (lseek(fd, SWAP_UUID_OFFSET, SEEK_SET) !=
+ SWAP_UUID_OFFSET) {
+ warn(_("%s: failed to seek to swap UUID"), devname);
+ goto err;
+
+ } else if (write_all(fd, newuuid, sizeof(newuuid))) {
+ warn(_("%s: failed to write UUID"), devname);
+ goto err;
+ }
+ }
+ }
+#endif
+ /* Write the label if it was provided */
+ if (label) {
+ char newlabel[SWAP_LABEL_LENGTH];
+
+ if (lseek(fd, SWAP_LABEL_OFFSET, SEEK_SET) != SWAP_LABEL_OFFSET) {
+ warn(_("%s: failed to seek to swap label "), devname);
+ goto err;
+ }
+ memset(newlabel, 0, sizeof(newlabel));
+ xstrncpy(newlabel, label, sizeof(newlabel));
+
+ if (strlen(label) > strlen(newlabel))
+ warnx(_("label is too long. Truncating it to '%s'"),
+ newlabel);
+ if (write_all(fd, newlabel, sizeof(newlabel))) {
+ warn(_("%s: failed to write label"), devname);
+ goto err;
+ }
+ }
+
+ close(fd);
+ return 0;
+err:
+ if (fd >= 0)
+ close(fd);
+ return -1;
+}
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+ fprintf(out, _("Usage: %s [options] <device>\n\nOptions:\n"),
+ program_invocation_short_name);
+
+ fprintf(out, _(
+ " -h, --help this help\n"
+ " -L, --label <label> specify a new label\n"
+ " -U, --uuid <uuid> specify a new uuid\n"));
+
+ fprintf(out, _("\nFor more information see swaplabel(8).\n"));
+
+ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ blkid_probe pr = NULL;
+ char *uuid = NULL, *label = NULL, *devname;
+ int c, rc = -1;
+
+ struct option longopts[] = {
+ { "help", 0, 0, 'h' },
+ { "label", 1, 0, 'L' },
+ { "uuid", 1, 0, 'U' },
+ { NULL, 0, 0, 0 }
+ };
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ while ((c = getopt_long(argc, argv, "hL:U:", longopts, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ usage(stdout);
+ break;
+ case 'L':
+ label = optarg;
+ break;
+ case 'U':
+#ifdef HAVE_LIBUUID
+ uuid = optarg;
+#else
+ warnx(_("ignore -U (UUIDs are unsupported)"));
+#endif
+ break;
+ default:
+ usage(stderr);
+ break;
+ }
+ }
+
+ if (optind == argc)
+ usage(stderr);
+
+ devname = argv[optind];
+ pr = get_swap_prober(devname);
+ if (pr) {
+ if (uuid || label)
+ rc = change_info(devname, label, uuid);
+ else
+ rc = print_info(pr, devname);
+ blkid_free_probe(pr);
+ }
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
diff --git a/include/swapheader.h b/include/swapheader.h
index 6ff5390f5..42d521a49 100644
--- a/include/swapheader.h
+++ b/include/swapheader.h
@@ -10,13 +10,17 @@ struct swap_header_v1 {
unsigned int badpages[1];
};
+
+#define SWAP_UUID_LENGTH 16
+#define SWAP_LABEL_LENGTH 16
+
struct swap_header_v1_2 {
char bootbits[1024]; /* Space for disklabel etc. */
unsigned int version;
unsigned int last_page;
unsigned int nr_badpages;
- unsigned char uuid[16];
- char volume_name[16];
+ unsigned char uuid[SWAP_UUID_LENGTH];
+ char volume_name[SWAP_LABEL_LENGTH];
unsigned int padding[117];
unsigned int badpages[1];
};