]> git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/swaplabel.c
Merge branch 'master' of https://github.com/jhuntwork/util-linux
[thirdparty/util-linux.git] / disk-utils / swaplabel.c
1 /*
2 * swaplabel.c - Print or change the label / UUID of a swap partition
3 *
4 * Copyright (C) 2010 Jason Borden <jborden@bluehost.com>
5 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
6 *
7 * Usage: swaplabel [-L label] [-U UUID] device
8 *
9 * This file may be redistributed under the terms of the GNU Public License
10 * version 2 or later.
11 *
12 */
13 #include <stdio.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <blkid.h>
22 #include <getopt.h>
23
24 #ifdef HAVE_LIBUUID
25 # include <uuid.h>
26 #endif
27
28 #include "c.h"
29 #include "closestream.h"
30 #include "all-io.h"
31 #include "swapheader.h"
32 #include "strutils.h"
33 #include "nls.h"
34
35 #define SWAP_UUID_OFFSET (offsetof(struct swap_header_v1_2, uuid))
36 #define SWAP_LABEL_OFFSET (offsetof(struct swap_header_v1_2, volume_name))
37
38 /*
39 * Returns new libblkid prober. This function call exit() on error.
40 */
41 static blkid_probe get_swap_prober(const char *devname)
42 {
43 blkid_probe pr;
44 int rc;
45 const char *version = NULL;
46 char *swap_filter[] = { "swap", NULL };
47
48 pr = blkid_new_probe_from_filename(devname);
49 if (!pr) {
50 warn(_("%s: unable to probe device"), devname);
51 return NULL;
52 }
53
54 blkid_probe_enable_superblocks(pr, TRUE);
55 blkid_probe_set_superblocks_flags(pr,
56 BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
57 BLKID_SUBLKS_VERSION);
58
59 blkid_probe_filter_superblocks_type(pr, BLKID_FLTR_ONLYIN, swap_filter);
60
61 rc = blkid_do_safeprobe(pr);
62 if (rc == -1)
63 warn(_("%s: unable to probe device"), devname);
64 else if (rc == -2)
65 warnx(_("%s: ambivalent probing result, use wipefs(8)"), devname);
66 else if (rc == 1)
67 warnx(_("%s: not a valid swap partition"), devname);
68
69 if (rc == 0) {
70 /* supported is SWAPSPACE2 only */
71 blkid_probe_lookup_value(pr, "VERSION", &version, NULL);
72 if (strcmp(version, "2"))
73 warnx(_("%s: unsupported swap version '%s'"),
74 devname, version);
75 else
76 return pr;
77 }
78
79 blkid_free_probe(pr);
80 return NULL;
81 }
82
83 /* Print the swap partition information */
84 static int print_info(blkid_probe pr)
85 {
86 const char *data;
87
88 if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
89 printf("LABEL: %s\n", data);
90
91 if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL))
92 printf("UUID: %s\n", data);
93
94 return 0;
95 }
96
97 /* Change the swap partition info */
98 static int change_info(const char *devname, const char *label, const char *uuid)
99 {
100 int fd;
101
102 fd = open(devname, O_RDWR);
103 if (fd < 0) {
104 warn(_("%s: failed to open"), devname);
105 goto err;
106 }
107 #ifdef HAVE_LIBUUID
108 /* Write the uuid if it was provided */
109 if (uuid) {
110 uuid_t newuuid;
111
112 if (uuid_parse(uuid, newuuid) == -1)
113 warnx(_("failed to parse UUID: %s"), uuid);
114 else {
115 if (lseek(fd, SWAP_UUID_OFFSET, SEEK_SET) !=
116 SWAP_UUID_OFFSET) {
117 warn(_("%s: failed to seek to swap UUID"), devname);
118 goto err;
119
120 } else if (write_all(fd, newuuid, sizeof(newuuid))) {
121 warn(_("%s: failed to write UUID"), devname);
122 goto err;
123 }
124 }
125 }
126 #endif
127 /* Write the label if it was provided */
128 if (label) {
129 char newlabel[SWAP_LABEL_LENGTH];
130
131 if (lseek(fd, SWAP_LABEL_OFFSET, SEEK_SET) != SWAP_LABEL_OFFSET) {
132 warn(_("%s: failed to seek to swap label "), devname);
133 goto err;
134 }
135 memset(newlabel, 0, sizeof(newlabel));
136 xstrncpy(newlabel, label, sizeof(newlabel));
137
138 if (strlen(label) > strlen(newlabel))
139 warnx(_("label is too long. Truncating it to '%s'"),
140 newlabel);
141 if (write_all(fd, newlabel, sizeof(newlabel))) {
142 warn(_("%s: failed to write label"), devname);
143 goto err;
144 }
145 }
146
147 close(fd);
148 return 0;
149 err:
150 if (fd >= 0)
151 close(fd);
152 return -1;
153 }
154
155 static void __attribute__((__noreturn__)) usage(FILE *out)
156 {
157 fputs(USAGE_HEADER, out);
158 fprintf(out, _(" %s [options] <device>\n"),
159 program_invocation_short_name);
160 fputs(USAGE_OPTIONS, out);
161 fputs(_(" -L, --label <label> specify a new label\n"
162 " -U, --uuid <uuid> specify a new uuid\n"), out);
163 fputs(USAGE_SEPARATOR, out);
164 fputs(USAGE_HELP, out);
165 fputs(USAGE_VERSION, out);
166 fprintf(out, USAGE_MAN_TAIL("swaplabel(8)"));
167 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
168 }
169
170 int main(int argc, char *argv[])
171 {
172 blkid_probe pr = NULL;
173 char *uuid = NULL, *label = NULL, *devname;
174 int c, rc = -1;
175
176 static const struct option longopts[] = {
177 { "help", 0, 0, 'h' },
178 { "version", 0, 0, 'V' },
179 { "label", 1, 0, 'L' },
180 { "uuid", 1, 0, 'U' },
181 { NULL, 0, 0, 0 }
182 };
183
184 setlocale(LC_ALL, "");
185 bindtextdomain(PACKAGE, LOCALEDIR);
186 textdomain(PACKAGE);
187 atexit(close_stdout);
188
189 while ((c = getopt_long(argc, argv, "hVL:U:", longopts, NULL)) != -1) {
190 switch (c) {
191 case 'h':
192 usage(stdout);
193 break;
194 case 'V':
195 printf(UTIL_LINUX_VERSION);
196 return EXIT_SUCCESS;
197 case 'L':
198 label = optarg;
199 break;
200 case 'U':
201 #ifdef HAVE_LIBUUID
202 uuid = optarg;
203 #else
204 warnx(_("ignore -U (UUIDs are unsupported)"));
205 #endif
206 break;
207 default:
208 usage(stderr);
209 break;
210 }
211 }
212
213 if (optind == argc)
214 usage(stderr);
215
216 devname = argv[optind];
217 pr = get_swap_prober(devname);
218 if (pr) {
219 if (uuid || label)
220 rc = change_info(devname, label, uuid);
221 else
222 rc = print_info(pr);
223 blkid_free_probe(pr);
224 }
225 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
226 }
227