]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/wipefs.c
whereis: cleanup usage()
[thirdparty/util-linux.git] / misc-utils / wipefs.c
CommitLineData
c49057d2 1/*
870768ad 2 * wipefs - utility to wipe filesystems from device
c49057d2
KZ
3 *
4 * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
5 * Written by Karel Zak <kzak@redhat.com>
6 *
bfbe2933
KZ
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
c49057d2
KZ
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <ctype.h>
24#include <errno.h>
25#include <fcntl.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <getopt.h>
c49057d2
KZ
30#include <string.h>
31#include <limits.h>
32
33#include <blkid.h>
34
35#include "nls.h"
87f3feac 36#include "xalloc.h"
8abcf290 37#include "strutils.h"
0239ac01 38#include "writeall.h"
eb76ca98 39#include "c.h"
c49057d2
KZ
40
41struct wipe_desc {
42 loff_t offset; /* magic string offset */
43 size_t len; /* length of magic string */
44 unsigned char *magic; /* magic string */
45
46 int zap; /* zap this offset? */
47 char *usage; /* raid, filesystem, ... */
48 char *type; /* FS type */
49 char *label; /* FS label */
50 char *uuid; /* FS uuid */
51
52 struct wipe_desc *next;
53};
54
55#define WP_MODE_PRETTY 0 /* default */
56#define WP_MODE_PARSABLE 1
57
58static void
59print_pretty(struct wipe_desc *wp, int line)
60{
61 if (!line) {
62 printf("offset type\n");
63 printf("----------------------------------------------------------------\n");
64 }
65
66 printf("0x%-17jx %s [%s]", wp->offset, wp->type, wp->usage);
67
68 if (wp->label && *wp->label)
69 printf("\n%27s %s", "LABEL:", wp->label);
70 if (wp->uuid)
71 printf("\n%27s %s", "UUID: ", wp->uuid);
72 puts("\n");
73}
74
75static void
76print_parsable(struct wipe_desc *wp, int line)
77{
78 char enc[256];
79
80 if (!line)
81 printf("# offset,uuid,label,type\n");
82
83 printf("0x%jx,", wp->offset);
84
85 if (wp->uuid) {
86 blkid_encode_string(wp->uuid, enc, sizeof(enc));
87 printf("%s,", enc);
88 } else
89 fputc(',', stdout);
90
91 if (wp->label) {
92 blkid_encode_string(wp->label, enc, sizeof(enc));
93 printf("%s,", enc);
94 } else
95 fputc(',', stdout);
96
97 blkid_encode_string(wp->type, enc, sizeof(enc));
98 printf("%s\n", enc);
99}
100
101static void
102print_all(struct wipe_desc *wp, int mode)
103{
104 int n = 0;
105
106 while (wp) {
107 switch (mode) {
108 case WP_MODE_PRETTY:
109 print_pretty(wp, n++);
110 break;
111 case WP_MODE_PARSABLE:
112 print_parsable(wp, n++);
113 break;
114 }
115 wp = wp->next;
116 }
117}
118
119static struct wipe_desc *
120add_offset(struct wipe_desc *wp0, loff_t offset, int zap)
121{
122 struct wipe_desc *wp = wp0;
123
124 while (wp) {
125 if (wp->offset == offset)
126 return wp;
127 wp = wp->next;
128 }
129
130 wp = calloc(1, sizeof(struct wipe_desc));
131 if (!wp)
132 err(EXIT_FAILURE, _("calloc failed"));
133
134 wp->offset = offset;
135 wp->next = wp0;
136 wp->zap = zap;
137 return wp;
138}
139
c49057d2
KZ
140static struct wipe_desc *
141get_offset_from_probe(struct wipe_desc *wp, blkid_probe pr, int zap)
142{
143 const char *off, *type, *usage, *mag;
144 size_t len;
145
146 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0 &&
147 blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL) == 0 &&
148 blkid_probe_lookup_value(pr, "SBMAGIC", &mag, &len) == 0 &&
149 blkid_probe_lookup_value(pr, "USAGE", &usage, NULL) == 0) {
150
151 loff_t offset = strtoll(off, NULL, 10);
152 const char *p;
153
154 wp = add_offset(wp, offset, zap);
155 if (!wp)
156 return NULL;
157
158 wp->usage = xstrdup(usage);
159 wp->type = xstrdup(type);
160
9683e327 161 wp->magic = xmalloc(len);
c49057d2
KZ
162 memcpy(wp->magic, mag, len);
163 wp->len = len;
164
165 if (blkid_probe_lookup_value(pr, "LABEL", &p, NULL) == 0)
166 wp->label = xstrdup(p);
167
168 if (blkid_probe_lookup_value(pr, "UUID", &p, NULL) == 0)
169 wp->uuid = xstrdup(p);
170 }
171
172 return wp;
173}
174
175static struct wipe_desc *
176read_offsets(struct wipe_desc *wp, const char *fname, int zap)
177{
178 blkid_probe pr;
269c1a2a 179 int rc;
c49057d2
KZ
180
181 if (!fname)
182 return NULL;
183
184 pr = blkid_new_probe_from_filename(fname);
185 if (!pr)
269c1a2a
KZ
186 errx(EXIT_FAILURE, _("error: %s: probing initialization failed"), fname);
187
188 blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */
189
190 blkid_probe_enable_partitions(pr, 1);
191 rc = blkid_do_fullprobe(pr);
192 blkid_probe_enable_partitions(pr, 0);
193
194 if (rc == 0) {
195 const char *type = NULL;
196 blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL);
70601bb6 197 warnx(_("WARNING: %s: appears to contain '%s' "
269c1a2a
KZ
198 "partition table"), fname, type);
199 }
c49057d2
KZ
200
201 blkid_probe_enable_superblocks(pr, 1);
202 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |
203 BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE |
204 BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID);
205
206 while (blkid_do_probe(pr) == 0) {
207 wp = get_offset_from_probe(wp, pr, zap);
208 if (!wp)
209 break;
210 }
211
212 blkid_free_probe(pr);
213 return wp;
214}
215
c49057d2
KZ
216static int
217do_wipe_offset(int fd, struct wipe_desc *wp, const char *fname, int noact)
218{
219 char buf[BUFSIZ];
c49057d2 220 off_t l;
09467812 221 size_t i, len;
c49057d2
KZ
222
223 if (!wp->type) {
d0bb6987
BS
224 warnx(_("no magic string found at offset "
225 "0x%jx -- ignored"), wp->offset);
c49057d2
KZ
226 return 0;
227 }
228
229 l = lseek(fd, wp->offset, SEEK_SET);
230 if (l == (off_t) -1)
231 err(EXIT_FAILURE, _("%s: failed to seek to offset 0x%jx"),
232 fname, wp->offset);
233
234 len = wp->len > sizeof(buf) ? sizeof(buf) : wp->len;
235
236 memset(buf, 0, len);
237 if (noact == 0 && write_all(fd, buf, len))
238 err(EXIT_FAILURE, _("%s: write failed"), fname);
239
340b3b0a
BS
240 printf(_("%zd bytes were erased at offset 0x%jx (%s)\nthey were: "),
241 wp->len, wp->offset, wp->type);
c49057d2
KZ
242
243 for (i = 0; i < len; i++) {
244 printf("%02x", wp->magic[i]);
245 if (i + 1 < len)
246 fputc(' ', stdout);
247 }
248
340b3b0a 249 printf("\n");
c49057d2
KZ
250 return 0;
251}
252
253static int
254do_wipe(struct wipe_desc *wp, const char *fname, int noact)
255{
256 int fd;
257
258 fd = open(fname, O_WRONLY);
259 if (fd < 0)
260 err(EXIT_FAILURE, _("%s: open failed"), fname);
261
262 while (wp) {
263 if (wp->zap)
264 do_wipe_offset(fd, wp, fname, noact);
265 wp = wp->next;
266 }
267
268 close(fd);
269 return 0;
270}
271
770af396
KZ
272static void
273free_wipe(struct wipe_desc *wp)
274{
275 while (wp) {
276 struct wipe_desc *next = wp->next;
277
278 free(wp->usage);
279 free(wp->type);
280 free(wp->magic);
281 free(wp->label);
282 free(wp->uuid);
283 free(wp);
284
285 wp = next;
286 }
287}
288
c49057d2
KZ
289static loff_t
290strtoll_offset(const char *str)
291{
69cc2ec0 292 uintmax_t sz;
c49057d2 293
69cc2ec0 294 if (strtosize(str, &sz))
d0bb6987 295 errx(EXIT_FAILURE, _("invalid offset value '%s' specified"), str);
69cc2ec0 296 return sz;
c49057d2
KZ
297}
298
69cc2ec0 299
c49057d2
KZ
300static void __attribute__((__noreturn__))
301usage(FILE *out)
302{
f5b1bab1 303 fprintf(out, _("Usage: %s [options] <device>\n\nOptions:\n"),
c49057d2
KZ
304 program_invocation_short_name);
305
306 fprintf(out, _(
307 " -a, --all wipe all magic strings (BE CAREFUL!)\n"
d0bb6987
BS
308 " -h, --help show this help text\n"
309 " -n, --no-act do everything except the actual write() call\n"
c49057d2 310 " -o, --offset <num> offset to erase, in bytes\n"
09467812 311 " -p, --parsable print out in parsable instead of printable format\n"
11295cd1 312 " -V, --version output version information and exit\n"));
c49057d2 313
04c94441 314 fprintf(out, _("\nFor more information see wipefs(8).\n"));
c49057d2
KZ
315
316 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
317}
318
319
320int
321main(int argc, char **argv)
322{
323 struct wipe_desc *wp = NULL;
324 int c, all = 0, has_offset = 0, noact = 0, mode = 0;
325 const char *fname;
326
6c7d5ae9 327 static const struct option longopts[] = {
c49057d2
KZ
328 { "all", 0, 0, 'a' },
329 { "help", 0, 0, 'h' },
330 { "no-act", 0, 0, 'n' },
331 { "offset", 1, 0, 'o' },
332 { "parsable", 0, 0, 'p' },
11295cd1 333 { "version", 0, 0, 'V' },
c49057d2
KZ
334 { NULL, 0, 0, 0 }
335 };
336
337 setlocale(LC_ALL, "");
338 bindtextdomain(PACKAGE, LOCALEDIR);
339 textdomain(PACKAGE);
340
11295cd1 341 while ((c = getopt_long(argc, argv, "ahno:pV", longopts, NULL)) != -1) {
c49057d2
KZ
342 switch(c) {
343 case 'a':
344 all++;
345 break;
346 case 'h':
347 usage(stdout);
348 break;
349 case 'n':
350 noact++;
351 break;
352 case 'o':
353 wp = add_offset(wp, strtoll_offset(optarg), 1);
354 has_offset++;
355 break;
356 case 'p':
357 mode = WP_MODE_PARSABLE;
358 break;
11295cd1 359 case 'V':
09467812
SK
360 printf(_("%s from %s\n"), program_invocation_short_name,
361 PACKAGE_STRING);
362 return EXIT_SUCCESS;
c49057d2
KZ
363 default:
364 usage(stderr);
365 break;
366 }
367 }
368
369 if (wp && all)
370 errx(EXIT_FAILURE, _("--offset and --all are mutually exclusive"));
371 if (optind == argc)
372 usage(stderr);
373
374 fname = argv[optind++];
375
6ebe8f63
MB
376 if (optind != argc)
377 errx(EXIT_FAILURE, _("only one device as argument is currently supported."));
378
c49057d2
KZ
379 wp = read_offsets(wp, fname, all);
380
381 if (wp) {
382 if (has_offset || all)
383 do_wipe(wp, fname, noact);
384 else
385 print_all(wp, mode);
770af396
KZ
386
387 free_wipe(wp);
c49057d2
KZ
388 }
389 return EXIT_SUCCESS;
390}