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