1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* 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 General 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);
fprintf(out, USAGE_HELP_OPTIONS(21));
fprintf(out, 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;
}
|