From 4dddc2d4aa37367432f719b7c84cb8084bd7a109 Mon Sep 17 00:00:00 2001 From: Jason Borden Date: Fri, 2 Apr 2010 15:52:45 +0200 Subject: [PATCH] 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 Signed-off-by: Karel Zak --- AUTHORS | 2 + disk-utils/.gitignore | 1 + disk-utils/Makefile.am | 36 ++++--- disk-utils/swaplabel.8 | 66 ++++++++++++ disk-utils/swaplabel.c | 226 +++++++++++++++++++++++++++++++++++++++++ include/swapheader.h | 8 +- 6 files changed, 325 insertions(+), 14 deletions(-) create mode 100644 disk-utils/swaplabel.8 create mode 100644 disk-utils/swaplabel.c diff --git a/AUTHORS b/AUTHORS index 803a76d095..b4fbee6c30 100644 --- a/AUTHORS +++ b/AUTHORS @@ -35,6 +35,8 @@ AUTHORS (merged projects & commands): Jeremy Katz unshare: Mikhail Gusarov wipefs: Karel Zak + swaplabel: Jason Borden + Karel Zak CONTRIBUTORS: diff --git a/disk-utils/.gitignore b/disk-utils/.gitignore index 726008f669..c97b3421a0 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 ed0a6e4b8a..67aeae40ed 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 0000000000..aade3ca233 --- /dev/null +++ b/disk-utils/swaplabel.8 @@ -0,0 +1,66 @@ +.\" Copyright 2010 Jason Borden +.\" +.\" 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 and Karel Zak . +.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 0000000000..6341972265 --- /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 + * Copyright (C) 2010 Karel Zak + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBUUID +# ifdef HAVE_UUID_UUID_H +# include +# else +# include +# 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] \n\nOptions:\n"), + program_invocation_short_name); + + fprintf(out, _( + " -h, --help this help\n" + " -L, --label