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>
This commit is contained in:
Jason Borden 2010-04-02 15:52:45 +02:00 committed by Karel Zak
parent 1f7a33f135
commit 4dddc2d4aa
6 changed files with 325 additions and 14 deletions

View File

@ -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:

View File

@ -10,3 +10,4 @@ mkswap
mkfs.cramfs
elvtune
raw
swaplabel

View 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)

66
disk-utils/swaplabel.8 Normal file
View File

@ -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)

226
disk-utils/swaplabel.c Normal file
View File

@ -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;
}

View 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];
};