diff options
Diffstat (limited to 'disk-utils/swaplabel.c')
-rw-r--r-- | disk-utils/swaplabel.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/disk-utils/swaplabel.c b/disk-utils/swaplabel.c new file mode 100644 index 0000000..ccc226a --- /dev/null +++ b/disk-utils/swaplabel.c @@ -0,0 +1,195 @@ +/* + * 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); + atexit(close_stdout); + + while ((c = getopt_long(argc, argv, "hVL:U:", longopts, NULL)) != -1) { + switch (c) { + case 'h': + usage(); + break; + case 'V': + printf(UTIL_LINUX_VERSION); + return 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; +} + |