2 * wipefs - utility to wipe filesystems from device
4 * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
5 * Written by Karel Zak <kzak@redhat.com>
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.
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.
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
22 #include <sys/types.h>
42 loff_t offset
; /* magic string offset */
43 size_t len
; /* length of magic string */
44 unsigned char *magic
; /* magic string */
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 */
54 struct wipe_desc
*next
;
57 #define WP_MODE_PRETTY 0 /* default */
58 #define WP_MODE_PARSABLE 1
61 print_pretty(struct wipe_desc
*wp
, int line
)
64 printf("offset type\n");
65 printf("----------------------------------------------------------------\n");
68 printf("0x%-17jx %s [%s]", wp
->offset
, wp
->type
, wp
->usage
);
70 if (wp
->label
&& *wp
->label
)
71 printf("\n%27s %s", "LABEL:", wp
->label
);
73 printf("\n%27s %s", "UUID: ", wp
->uuid
);
78 print_parsable(struct wipe_desc
*wp
, int line
)
83 printf("# offset,uuid,label,type\n");
85 printf("0x%jx,", wp
->offset
);
88 blkid_encode_string(wp
->uuid
, enc
, sizeof(enc
));
94 blkid_encode_string(wp
->label
, enc
, sizeof(enc
));
99 blkid_encode_string(wp
->type
, enc
, sizeof(enc
));
104 print_all(struct wipe_desc
*wp
, int mode
)
111 print_pretty(wp
, n
++);
113 case WP_MODE_PARSABLE
:
114 print_parsable(wp
, n
++);
121 static struct wipe_desc
*
122 add_offset(struct wipe_desc
*wp0
, loff_t offset
, int zap
)
124 struct wipe_desc
*wp
= wp0
;
127 if (wp
->offset
== offset
)
132 wp
= calloc(1, sizeof(struct wipe_desc
));
134 err(EXIT_FAILURE
, _("calloc failed"));
142 static struct wipe_desc
*
143 get_desc_for_probe(struct wipe_desc
*wp
, blkid_probe pr
)
145 const char *off
, *type
, *mag
, *p
, *usage
= NULL
;
151 if (blkid_probe_lookup_value(pr
, "TYPE", &type
, NULL
) == 0) {
152 rc
= blkid_probe_lookup_value(pr
, "SBMAGIC_OFFSET", &off
, NULL
);
154 rc
= blkid_probe_lookup_value(pr
, "SBMAGIC", &mag
, &len
);
159 } else if (blkid_probe_lookup_value(pr
, "PTTYPE", &type
, NULL
) == 0) {
160 rc
= blkid_probe_lookup_value(pr
, "PTMAGIC_OFFSET", &off
, NULL
);
162 rc
= blkid_probe_lookup_value(pr
, "PTMAGIC", &mag
, &len
);
165 usage
= "partition table";
169 offset
= strtoll(off
, NULL
, 10);
171 wp
= add_offset(wp
, offset
, 0);
175 if (usage
|| blkid_probe_lookup_value(pr
, "USAGE", &usage
, NULL
) == 0)
176 wp
->usage
= xstrdup(usage
);
178 wp
->type
= xstrdup(type
);
181 wp
->magic
= xmalloc(len
);
182 memcpy(wp
->magic
, mag
, len
);
185 if (blkid_probe_lookup_value(pr
, "LABEL", &p
, NULL
) == 0)
186 wp
->label
= xstrdup(p
);
188 if (blkid_probe_lookup_value(pr
, "UUID", &p
, NULL
) == 0)
189 wp
->uuid
= xstrdup(p
);
195 new_probe(const char *devname
, int mode
)
203 int fd
= open(devname
, mode
);
207 pr
= blkid_new_probe();
208 if (pr
&& blkid_probe_set_device(pr
, fd
, 0, 0))
211 pr
= blkid_new_probe_from_filename(devname
);
216 blkid_probe_enable_superblocks(pr
, 1);
217 blkid_probe_set_superblocks_flags(pr
, BLKID_SUBLKS_MAGIC
|
218 BLKID_SUBLKS_TYPE
| BLKID_SUBLKS_USAGE
|
219 BLKID_SUBLKS_LABEL
| BLKID_SUBLKS_UUID
);
221 blkid_probe_enable_partitions(pr
, 1);
222 blkid_probe_set_partitions_flags(pr
, BLKID_PARTS_MAGIC
);
226 err(EXIT_FAILURE
, _("error: %s: probing initialization failed"), devname
);
230 static struct wipe_desc
*
231 read_offsets(struct wipe_desc
*wp
, const char *devname
)
233 blkid_probe pr
= new_probe(devname
, 0);
238 while (blkid_do_probe(pr
) == 0) {
239 wp
= get_desc_for_probe(wp
, pr
);
244 blkid_free_probe(pr
);
248 static struct wipe_desc
*
249 do_wipe(struct wipe_desc
*wp
, const char *devname
, int noact
, int all
)
251 blkid_probe pr
= new_probe(devname
, O_RDWR
);
257 while (blkid_do_probe(pr
) == 0) {
258 w
= get_desc_for_probe(wp
, pr
);
264 wp
->zap
= all
? 1 : wp
->zap
;
268 if (blkid_do_wipe(pr
, noact
))
269 warn(_("failed to erase %s magic string at offset 0x%08jx"),
270 wp
->type
, wp
->offset
);
274 printf(_("%zd bytes were erased at offset 0x%08jx (%s): "),
275 wp
->len
, wp
->offset
, wp
->type
);
277 for (i
= 0; i
< wp
->len
; i
++) {
278 printf("%02x", wp
->magic
[i
]);
286 for (w
= wp
; w
!= NULL
; w
= w
->next
) {
288 warnx(_("offset 0x%jx not found"), w
->offset
);
291 fsync(blkid_probe_get_fd(pr
));
292 close(blkid_probe_get_fd(pr
));
293 blkid_free_probe(pr
);
299 free_wipe(struct wipe_desc
*wp
)
302 struct wipe_desc
*next
= wp
->next
;
316 strtoll_offset(const char *str
)
320 if (strtosize(str
, &sz
))
321 errx(EXIT_FAILURE
, _("invalid offset value '%s' specified"), str
);
326 static void __attribute__((__noreturn__
))
329 fputs(_("\nUsage:\n"), out
);
331 _(" %s [options] <device>\n"), program_invocation_short_name
);
333 fputs(_("\nOptions:\n"), out
);
334 fputs(_(" -a, --all wipe all magic strings (BE CAREFUL!)\n"
335 " -h, --help show this help text\n"
336 " -n, --no-act do everything except the actual write() call\n"
337 " -o, --offset <num> offset to erase, in bytes\n"
338 " -p, --parsable print out in parsable instead of printable format\n"
339 " -V, --version output version information and exit\n"), out
);
341 fprintf(out
, _("\nFor more information see wipefs(8).\n"));
343 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
348 main(int argc
, char **argv
)
350 struct wipe_desc
*wp
= NULL
;
351 int c
, all
= 0, has_offset
= 0, noact
= 0, mode
= 0;
354 static const struct option longopts
[] = {
355 { "all", 0, 0, 'a' },
356 { "help", 0, 0, 'h' },
357 { "no-act", 0, 0, 'n' },
358 { "offset", 1, 0, 'o' },
359 { "parsable", 0, 0, 'p' },
360 { "version", 0, 0, 'V' },
364 setlocale(LC_ALL
, "");
365 bindtextdomain(PACKAGE
, LOCALEDIR
);
368 while ((c
= getopt_long(argc
, argv
, "ahno:pV", longopts
, NULL
)) != -1) {
380 wp
= add_offset(wp
, strtoll_offset(optarg
), 1);
384 mode
= WP_MODE_PARSABLE
;
387 printf(_("%s from %s\n"), program_invocation_short_name
,
397 errx(EXIT_FAILURE
, _("--offset and --all are mutually exclusive"));
401 devname
= argv
[optind
++];
404 errx(EXIT_FAILURE
, _("only one device as argument is currently supported."));
406 if (!all
&& !has_offset
) {
410 wp
= read_offsets(wp
, devname
);
417 wp
= do_wipe(wp
, devname
, noact
, all
);