195 lines
4.4 KiB
C
195 lines
4.4 KiB
C
/*
|
|
* 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 <getopt.h>
|
|
|
|
#ifdef HAVE_LIBUUID
|
|
# include <uuid.h>
|
|
#endif
|
|
|
|
#include "c.h"
|
|
#include "nls.h"
|
|
#include "all-io.h"
|
|
#include "strutils.h"
|
|
#include "closestream.h"
|
|
|
|
#include "swapheader.h"
|
|
#include "swapprober.h"
|
|
|
|
#define SWAP_UUID_OFFSET (offsetof(struct swap_header_v1_2, uuid))
|
|
#define SWAP_LABEL_OFFSET (offsetof(struct swap_header_v1_2, volume_name))
|
|
|
|
/* Print the swap partition information */
|
|
static int print_info(blkid_probe pr)
|
|
{
|
|
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 */
|
|
#ifdef HAVE_LIBUUID
|
|
static int change_info(const char *devname, const char *label, const char *uuid)
|
|
#else
|
|
static int change_info(const char *devname, const char *label,
|
|
const char *uuid __attribute__((__unused__)))
|
|
#endif
|
|
{
|
|
int fd;
|
|
|
|
fd = open(devname, O_RDWR);
|
|
if (fd < 0) {
|
|
warn(_("cannot open %s"), 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;
|
|
}
|
|
}
|
|
|
|
if (close_fd(fd) != 0) {
|
|
warn(_("write failed: %s"), devname);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
err:
|
|
if (fd >= 0)
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
static void __attribute__((__noreturn__)) usage(void)
|
|
{
|
|
FILE *out = stdout;
|
|
fputs(USAGE_HEADER, out);
|
|
fprintf(out, _(" %s [options] <device>\n"),
|
|
program_invocation_short_name);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
fputs(_("Display or change the label or UUID of a swap area.\n"), out);
|
|
|
|
fputs(USAGE_OPTIONS, out);
|
|
fputs(_(" -L, --label <label> specify a new label\n"
|
|
" -U, --uuid <uuid> specify a new uuid\n"), out);
|
|
fputs(USAGE_SEPARATOR, out);
|
|
printf(USAGE_HELP_OPTIONS(21));
|
|
printf(USAGE_MAN_TAIL("swaplabel(8)"));
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
blkid_probe pr = NULL;
|
|
char *uuid = NULL, *label = NULL, *devname;
|
|
int c, rc = -1;
|
|
|
|
static const struct option longopts[] = {
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "version", no_argument, NULL, 'V' },
|
|
{ "label", required_argument, NULL, 'L' },
|
|
{ "uuid", required_argument, NULL, 'U' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
setlocale(LC_ALL, "");
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
textdomain(PACKAGE);
|
|
close_stdout_atexit();
|
|
|
|
while ((c = getopt_long(argc, argv, "hVL:U:", longopts, NULL)) != -1) {
|
|
switch (c) {
|
|
case 'h':
|
|
usage();
|
|
break;
|
|
case 'V':
|
|
print_version(EXIT_SUCCESS);
|
|
case 'L':
|
|
label = optarg;
|
|
break;
|
|
case 'U':
|
|
#ifdef HAVE_LIBUUID
|
|
uuid = optarg;
|
|
#else
|
|
warnx(_("ignore -U (UUIDs are unsupported)"));
|
|
#endif
|
|
break;
|
|
default:
|
|
errtryhelp(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (optind == argc) {
|
|
warnx(_("no device specified"));
|
|
errtryhelp(EXIT_FAILURE);
|
|
}
|
|
devname = argv[optind];
|
|
pr = get_swap_prober(devname);
|
|
if (pr) {
|
|
if (uuid || label)
|
|
rc = change_info(devname, label, uuid);
|
|
else
|
|
rc = print_info(pr);
|
|
blkid_free_probe(pr);
|
|
}
|
|
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
|