]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
swaplabel: new command
authorJason Borden <jborden@bluehost.com>
Fri, 2 Apr 2010 13:52:45 +0000 (15:52 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 2 Apr 2010 14:16:59 +0000 (16:16 +0200)
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>
AUTHORS
disk-utils/.gitignore
disk-utils/Makefile.am
disk-utils/swaplabel.8 [new file with mode: 0644]
disk-utils/swaplabel.c [new file with mode: 0644]
include/swapheader.h

diff --git a/AUTHORS b/AUTHORS
index 803a76d0956fe81d14eb17c2961f5d717b459dbe..b4fbee6c301a7d53e9f1cde6edef38c9601606ba 100644 (file)
--- 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:
index 726008f669100fe0f58cacb928a4828f7f90d9f8..c97b3421a01b5dbeebd10ad7c3b9ab6d0ff7285d 100644 (file)
@@ -10,3 +10,4 @@ mkswap
 mkfs.cramfs
 elvtune
 raw
+swaplabel
index ed0a6e4b8a803c6bfe6d378b8c8d010bacacb658..67aeae40edfab71144bcf18c77e894bb0cb06544 100644 (file)
@@ -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 (file)
index 0000000..aade3ca
--- /dev/null
@@ -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 (file)
index 0000000..6341972
--- /dev/null
@@ -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;
+}
+
index 6ff5390f5b0b218fcdbc4f95b701a2430fc81b67..42d521a490e0ad094e8a088b4beb33fd26923f64 100644 (file)
@@ -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];
 };