summaryrefslogtreecommitdiffstats
path: root/disk-utils/swaplabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'disk-utils/swaplabel.c')
-rw-r--r--disk-utils/swaplabel.c195
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;
+}
+