]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/wipefs.c
docs: AUTHORS: remove four duplicate entries
[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 *
7cebf0bb
SK
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
c49057d2
KZ
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"
e12c9866 38#include "all-io.h"
f126cd46 39#include "match.h"
eb76ca98 40#include "c.h"
c05a80ca 41#include "closestream.h"
58f0252a 42#include "optutils.h"
c49057d2
KZ
43
44struct wipe_desc {
45 loff_t offset; /* magic string offset */
46 size_t len; /* length of magic string */
47 unsigned char *magic; /* magic string */
48
49 int zap; /* zap this offset? */
50 char *usage; /* raid, filesystem, ... */
51 char *type; /* FS type */
52 char *label; /* FS label */
53 char *uuid; /* FS uuid */
54
6611a3dd
KZ
55 int on_disk;
56
c49057d2
KZ
57 struct wipe_desc *next;
58};
59
4f053737
SK
60enum {
61 WP_MODE_PRETTY, /* default */
62 WP_MODE_PARSABLE
63};
c49057d2 64
f126cd46
KZ
65static const char *type_pattern;
66
c49057d2
KZ
67static void
68print_pretty(struct wipe_desc *wp, int line)
69{
70 if (!line) {
71 printf("offset type\n");
72 printf("----------------------------------------------------------------\n");
73 }
74
75 printf("0x%-17jx %s [%s]", wp->offset, wp->type, wp->usage);
76
77 if (wp->label && *wp->label)
78 printf("\n%27s %s", "LABEL:", wp->label);
79 if (wp->uuid)
80 printf("\n%27s %s", "UUID: ", wp->uuid);
81 puts("\n");
82}
83
84static void
85print_parsable(struct wipe_desc *wp, int line)
86{
87 char enc[256];
88
89 if (!line)
90 printf("# offset,uuid,label,type\n");
91
92 printf("0x%jx,", wp->offset);
93
94 if (wp->uuid) {
95 blkid_encode_string(wp->uuid, enc, sizeof(enc));
96 printf("%s,", enc);
97 } else
98 fputc(',', stdout);
99
100 if (wp->label) {
101 blkid_encode_string(wp->label, enc, sizeof(enc));
102 printf("%s,", enc);
103 } else
104 fputc(',', stdout);
105
106 blkid_encode_string(wp->type, enc, sizeof(enc));
107 printf("%s\n", enc);
108}
109
110static void
111print_all(struct wipe_desc *wp, int mode)
112{
113 int n = 0;
114
115 while (wp) {
116 switch (mode) {
117 case WP_MODE_PRETTY:
118 print_pretty(wp, n++);
119 break;
120 case WP_MODE_PARSABLE:
121 print_parsable(wp, n++);
122 break;
4f053737
SK
123 default:
124 abort();
c49057d2
KZ
125 }
126 wp = wp->next;
127 }
128}
129
130static struct wipe_desc *
131add_offset(struct wipe_desc *wp0, loff_t offset, int zap)
132{
133 struct wipe_desc *wp = wp0;
134
135 while (wp) {
136 if (wp->offset == offset)
137 return wp;
138 wp = wp->next;
139 }
140
a2f5c221 141 wp = xcalloc(1, sizeof(struct wipe_desc));
c49057d2
KZ
142 wp->offset = offset;
143 wp->next = wp0;
144 wp->zap = zap;
145 return wp;
146}
147
c10695f8
MB
148static struct wipe_desc *
149clone_offset(struct wipe_desc *wp0)
150{
151 struct wipe_desc *wp = NULL;
152
153 while(wp0) {
154 wp = add_offset(wp, wp0->offset, wp0->zap);
155 wp0 = wp0->next;
156 }
157
158 return wp;
159}
160
c49057d2 161static struct wipe_desc *
6611a3dd 162get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr)
c49057d2 163{
44765fdd 164 const char *off, *type, *mag, *p, *usage = NULL;
c49057d2 165 size_t len;
44765fdd
KZ
166 loff_t offset;
167 int rc;
c49057d2 168
44765fdd
KZ
169 /* superblocks */
170 if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0) {
171 rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
172 if (!rc)
173 rc = blkid_probe_lookup_value(pr, "SBMAGIC", &mag, &len);
174 if (rc)
175 return wp;
c49057d2 176
44765fdd
KZ
177 /* partitions */
178 } else if (blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL) == 0) {
179 rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
180 if (!rc)
181 rc = blkid_probe_lookup_value(pr, "PTMAGIC", &mag, &len);
182 if (rc)
183 return wp;
184 usage = "partition table";
185 } else
186 return wp;
c49057d2 187
f126cd46
KZ
188 if (type_pattern && !match_fstype(type, type_pattern))
189 return wp;
190
44765fdd 191 offset = strtoll(off, NULL, 10);
c49057d2 192
44765fdd
KZ
193 wp = add_offset(wp, offset, 0);
194 if (!wp)
195 return NULL;
196
197 if (usage || blkid_probe_lookup_value(pr, "USAGE", &usage, NULL) == 0)
c49057d2 198 wp->usage = xstrdup(usage);
c49057d2 199
44765fdd
KZ
200 wp->type = xstrdup(type);
201 wp->on_disk = 1;
c49057d2 202
44765fdd
KZ
203 wp->magic = xmalloc(len);
204 memcpy(wp->magic, mag, len);
205 wp->len = len;
c49057d2 206
44765fdd
KZ
207 if (blkid_probe_lookup_value(pr, "LABEL", &p, NULL) == 0)
208 wp->label = xstrdup(p);
209
210 if (blkid_probe_lookup_value(pr, "UUID", &p, NULL) == 0)
211 wp->uuid = xstrdup(p);
c49057d2
KZ
212
213 return wp;
214}
215
6611a3dd
KZ
216static blkid_probe
217new_probe(const char *devname, int mode)
c49057d2
KZ
218{
219 blkid_probe pr;
220
6611a3dd 221 if (!devname)
c49057d2
KZ
222 return NULL;
223
6611a3dd
KZ
224 if (mode) {
225 int fd = open(devname, mode);
226 if (fd < 0)
227 goto error;
228
229 pr = blkid_new_probe();
230 if (pr && blkid_probe_set_device(pr, fd, 0, 0))
231 goto error;
232 } else
233 pr = blkid_new_probe_from_filename(devname);
234
c49057d2 235 if (!pr)
6611a3dd 236 goto error;
269c1a2a 237
c49057d2
KZ
238 blkid_probe_enable_superblocks(pr, 1);
239 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |
240 BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE |
241 BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID);
242
44765fdd
KZ
243 blkid_probe_enable_partitions(pr, 1);
244 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
245
6611a3dd
KZ
246 return pr;
247error:
248 err(EXIT_FAILURE, _("error: %s: probing initialization failed"), devname);
249 return NULL;
250}
251
252static struct wipe_desc *
253read_offsets(struct wipe_desc *wp, const char *devname)
254{
255 blkid_probe pr = new_probe(devname, 0);
256
257 if (!pr)
258 return NULL;
259
c49057d2 260 while (blkid_do_probe(pr) == 0) {
6611a3dd 261 wp = get_desc_for_probe(wp, pr);
c49057d2
KZ
262 if (!wp)
263 break;
264 }
265
266 blkid_free_probe(pr);
267 return wp;
268}
269
24df2633
MB
270static void
271free_wipe(struct wipe_desc *wp)
272{
273 while (wp) {
274 struct wipe_desc *next = wp->next;
275
276 free(wp->usage);
277 free(wp->type);
278 free(wp->magic);
279 free(wp->label);
280 free(wp->uuid);
281 free(wp);
282
283 wp = next;
284 }
285}
286
287static void do_wipe_real(blkid_probe pr, const char *devname, struct wipe_desc *w, int noact, int quiet)
288{
289 size_t i;
290
291 if (blkid_do_wipe(pr, noact))
292 warn(_("%s: failed to erase %s magic string at offset 0x%08jx"),
293 devname, w->type, w->offset);
294
295 if (quiet)
296 return;
297
298 printf(_("%s: %zd bytes were erased at offset 0x%08jx (%s): "),
299 devname, w->len, w->offset, w->type);
300
301 for (i = 0; i < w->len; i++) {
302 printf("%02x", w->magic[i]);
303 if (i + 1 < w->len)
304 fputc(' ', stdout);
305 }
306 putchar('\n');
307}
308
6611a3dd 309static struct wipe_desc *
2968c3fc 310do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet, int force)
c49057d2 311{
2968c3fc
RJ
312 int flags;
313 blkid_probe pr;
24df2633
MB
314 struct wipe_desc *w, *wp0 = clone_offset(wp);
315 int zap = all ? 1 : wp->zap;
c49057d2 316
2968c3fc
RJ
317 flags = O_RDWR;
318 if (!force)
319 flags |= O_EXCL;
320 pr = new_probe(devname, flags);
6611a3dd
KZ
321 if (!pr)
322 return NULL;
c49057d2 323
6611a3dd 324 while (blkid_do_probe(pr) == 0) {
24df2633
MB
325 wp = get_desc_for_probe(wp, pr);
326 if (!wp)
6611a3dd 327 break;
24df2633
MB
328
329 /* Check if offset is in provided list */
330 w = wp0;
331 while(w && w->offset != wp->offset)
332 w = w->next;
333 if (wp0 && !w)
6611a3dd 334 continue;
24df2633
MB
335
336 /* Mark done if found in provided list */
337 if (w)
338 w->on_disk = wp->on_disk;
339
340 if (!wp->on_disk)
6611a3dd
KZ
341 continue;
342
24df2633
MB
343 if (zap)
344 do_wipe_real(pr, devname, wp, noact, quiet);
c49057d2
KZ
345 }
346
24df2633 347 for (w = wp0; w != NULL; w = w->next) {
0fd93af6 348 if (!w->on_disk && !quiet)
c10695f8 349 warnx(_("%s: offset 0x%jx not found"), devname, w->offset);
c49057d2
KZ
350 }
351
6611a3dd
KZ
352 fsync(blkid_probe_get_fd(pr));
353 close(blkid_probe_get_fd(pr));
354 blkid_free_probe(pr);
24df2633 355 free_wipe(wp0);
6611a3dd
KZ
356
357 return wp;
c49057d2
KZ
358}
359
69cc2ec0 360
c49057d2
KZ
361static void __attribute__((__noreturn__))
362usage(FILE *out)
363{
dcd16b0f
KZ
364 fputs(_("\nUsage:\n"), out);
365 fprintf(out,
366 _(" %s [options] <device>\n"), program_invocation_short_name);
367
368 fputs(_("\nOptions:\n"), out);
369 fputs(_(" -a, --all wipe all magic strings (BE CAREFUL!)\n"
2968c3fc 370 " -f, --force force erasure\n"
dcd16b0f
KZ
371 " -h, --help show this help text\n"
372 " -n, --no-act do everything except the actual write() call\n"
373 " -o, --offset <num> offset to erase, in bytes\n"
374 " -p, --parsable print out in parsable instead of printable format\n"
0fd93af6 375 " -q, --quiet suppress output messages\n"
f126cd46 376 " -t, --types <list> limit the set of filesystem, RAIDs or partition tables\n"
dcd16b0f 377 " -V, --version output version information and exit\n"), out);
c49057d2 378
04c94441 379 fprintf(out, _("\nFor more information see wipefs(8).\n"));
c49057d2
KZ
380
381 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
382}
383
384
385int
386main(int argc, char **argv)
387{
c10695f8 388 struct wipe_desc *wp0 = NULL, *wp;
2968c3fc 389 int c, all = 0, force = 0, has_offset = 0, noact = 0, quiet = 0;
4f053737 390 int mode = WP_MODE_PRETTY;
c49057d2 391
6c7d5ae9 392 static const struct option longopts[] = {
c49057d2 393 { "all", 0, 0, 'a' },
2968c3fc 394 { "force", 0, 0, 'f' },
c49057d2
KZ
395 { "help", 0, 0, 'h' },
396 { "no-act", 0, 0, 'n' },
397 { "offset", 1, 0, 'o' },
398 { "parsable", 0, 0, 'p' },
0fd93af6 399 { "quiet", 0, 0, 'q' },
f126cd46 400 { "types", 1, 0, 't' },
11295cd1 401 { "version", 0, 0, 'V' },
c49057d2
KZ
402 { NULL, 0, 0, 0 }
403 };
404
abb7b98c
KZ
405 static const ul_excl_t excl[] = { /* rows and cols in in ASCII order */
406 { 'a','o' },
407 { 0 }
408 };
409 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
410
c49057d2
KZ
411 setlocale(LC_ALL, "");
412 bindtextdomain(PACKAGE, LOCALEDIR);
413 textdomain(PACKAGE);
c05a80ca 414 atexit(close_stdout);
c49057d2 415
0fd93af6 416 while ((c = getopt_long(argc, argv, "ahno:pqt:V", longopts, NULL)) != -1) {
abb7b98c
KZ
417
418 err_exclusive_options(c, longopts, excl, excl_st);
419
c49057d2
KZ
420 switch(c) {
421 case 'a':
422 all++;
423 break;
2968c3fc
RJ
424 case 'f':
425 force++;
426 break;
c49057d2
KZ
427 case 'h':
428 usage(stdout);
429 break;
430 case 'n':
431 noact++;
432 break;
433 case 'o':
99727496 434 wp0 = add_offset(wp0, strtosize_or_err(optarg,
db41a429 435 _("invalid offset argument")), 1);
c49057d2
KZ
436 has_offset++;
437 break;
438 case 'p':
439 mode = WP_MODE_PARSABLE;
440 break;
0fd93af6
MB
441 case 'q':
442 quiet++;
443 break;
f126cd46
KZ
444 case 't':
445 type_pattern = optarg;
446 break;
11295cd1 447 case 'V':
e421313d 448 printf(UTIL_LINUX_VERSION);
09467812 449 return EXIT_SUCCESS;
c49057d2
KZ
450 default:
451 usage(stderr);
452 break;
453 }
454 }
455
c49057d2
KZ
456 if (optind == argc)
457 usage(stderr);
458
6611a3dd
KZ
459 if (!all && !has_offset) {
460 /*
461 * Print only
462 */
c10695f8
MB
463 while (optind < argc) {
464 wp0 = read_offsets(NULL, argv[optind++]);
465 if (wp0)
466 print_all(wp0, mode);
467 free_wipe(wp0);
468 }
6611a3dd
KZ
469 } else {
470 /*
471 * Erase
472 */
c10695f8
MB
473 while (optind < argc) {
474 wp = clone_offset(wp0);
2968c3fc
RJ
475 wp = do_wipe(wp, argv[optind++], noact, all, quiet,
476 force);
c10695f8
MB
477 free_wipe(wp);
478 }
c49057d2 479 }
6611a3dd 480
c49057d2
KZ
481 return EXIT_SUCCESS;
482}