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>
38 #include "strtosize.h"
41 loff_t offset
; /* magic string offset */
42 size_t len
; /* length of magic string */
43 unsigned char *magic
; /* magic string */
45 int zap
; /* zap this offset? */
46 char *usage
; /* raid, filesystem, ... */
47 char *type
; /* FS type */
48 char *label
; /* FS label */
49 char *uuid
; /* FS uuid */
51 struct wipe_desc
*next
;
54 #define WP_MODE_PRETTY 0 /* default */
55 #define WP_MODE_PARSABLE 1
58 print_pretty(struct wipe_desc
*wp
, int line
)
61 printf("offset type\n");
62 printf("----------------------------------------------------------------\n");
65 printf("0x%-17jx %s [%s]", wp
->offset
, wp
->type
, wp
->usage
);
67 if (wp
->label
&& *wp
->label
)
68 printf("\n%27s %s", "LABEL:", wp
->label
);
70 printf("\n%27s %s", "UUID: ", wp
->uuid
);
75 print_parsable(struct wipe_desc
*wp
, int line
)
80 printf("# offset,uuid,label,type\n");
82 printf("0x%jx,", wp
->offset
);
85 blkid_encode_string(wp
->uuid
, enc
, sizeof(enc
));
91 blkid_encode_string(wp
->label
, enc
, sizeof(enc
));
96 blkid_encode_string(wp
->type
, enc
, sizeof(enc
));
101 print_all(struct wipe_desc
*wp
, int mode
)
108 print_pretty(wp
, n
++);
110 case WP_MODE_PARSABLE
:
111 print_parsable(wp
, n
++);
118 static struct wipe_desc
*
119 add_offset(struct wipe_desc
*wp0
, loff_t offset
, int zap
)
121 struct wipe_desc
*wp
= wp0
;
124 if (wp
->offset
== offset
)
129 wp
= calloc(1, sizeof(struct wipe_desc
));
131 err(EXIT_FAILURE
, _("calloc failed"));
140 xstrdup(const char *s
)
144 err(EXIT_FAILURE
, _("strdup failed"));
148 static struct wipe_desc
*
149 get_offset_from_probe(struct wipe_desc
*wp
, blkid_probe pr
, int zap
)
151 const char *off
, *type
, *usage
, *mag
;
154 if (blkid_probe_lookup_value(pr
, "TYPE", &type
, NULL
) == 0 &&
155 blkid_probe_lookup_value(pr
, "SBMAGIC_OFFSET", &off
, NULL
) == 0 &&
156 blkid_probe_lookup_value(pr
, "SBMAGIC", &mag
, &len
) == 0 &&
157 blkid_probe_lookup_value(pr
, "USAGE", &usage
, NULL
) == 0) {
159 loff_t offset
= strtoll(off
, NULL
, 10);
162 wp
= add_offset(wp
, offset
, zap
);
166 wp
->usage
= xstrdup(usage
);
167 wp
->type
= xstrdup(type
);
169 wp
->magic
= xmalloc(len
);
170 memcpy(wp
->magic
, mag
, len
);
173 if (blkid_probe_lookup_value(pr
, "LABEL", &p
, NULL
) == 0)
174 wp
->label
= xstrdup(p
);
176 if (blkid_probe_lookup_value(pr
, "UUID", &p
, NULL
) == 0)
177 wp
->uuid
= xstrdup(p
);
183 static struct wipe_desc
*
184 read_offsets(struct wipe_desc
*wp
, const char *fname
, int zap
)
192 pr
= blkid_new_probe_from_filename(fname
);
194 errx(EXIT_FAILURE
, _("error: %s: probing initialization failed"), fname
);
196 blkid_probe_enable_superblocks(pr
, 0); /* enabled by default ;-( */
198 blkid_probe_enable_partitions(pr
, 1);
199 rc
= blkid_do_fullprobe(pr
);
200 blkid_probe_enable_partitions(pr
, 0);
203 const char *type
= NULL
;
204 blkid_probe_lookup_value(pr
, "PTTYPE", &type
, NULL
);
205 warnx(_("WARNING: %s: appears to contain '%s' "
206 "partition table"), fname
, type
);
209 blkid_probe_enable_superblocks(pr
, 1);
210 blkid_probe_set_superblocks_flags(pr
, BLKID_SUBLKS_MAGIC
|
211 BLKID_SUBLKS_TYPE
| BLKID_SUBLKS_USAGE
|
212 BLKID_SUBLKS_LABEL
| BLKID_SUBLKS_UUID
);
214 while (blkid_do_probe(pr
) == 0) {
215 wp
= get_offset_from_probe(wp
, pr
, zap
);
220 blkid_free_probe(pr
);
225 write_all(int fd
, const void *buf
, size_t count
)
231 tmp
= write(fd
, buf
, count
);
236 } else if (errno
!= EINTR
&& errno
!= EAGAIN
)
243 do_wipe_offset(int fd
, struct wipe_desc
*wp
, const char *fname
, int noact
)
251 warnx(_("no magic string found at offset "
252 "0x%jx -- ignored"), wp
->offset
);
256 l
= lseek(fd
, wp
->offset
, SEEK_SET
);
258 err(EXIT_FAILURE
, _("%s: failed to seek to offset 0x%jx"),
261 len
= wp
->len
> sizeof(buf
) ? sizeof(buf
) : wp
->len
;
264 if (noact
== 0 && write_all(fd
, buf
, len
))
265 err(EXIT_FAILURE
, _("%s: write failed"), fname
);
267 printf(_("%zd bytes ["), wp
->len
);
269 for (i
= 0; i
< len
; i
++) {
270 printf("%02x", wp
->magic
[i
]);
275 printf(_("] erased at offset 0x%jx (%s)\n"), wp
->offset
, wp
->type
);
280 do_wipe(struct wipe_desc
*wp
, const char *fname
, int noact
)
284 fd
= open(fname
, O_WRONLY
);
286 err(EXIT_FAILURE
, _("%s: open failed"), fname
);
290 do_wipe_offset(fd
, wp
, fname
, noact
);
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 fprintf(out
, _("Usage: %s [options] <device>\n\nOptions:\n"),
330 program_invocation_short_name
);
333 " -a, --all wipe all magic strings (BE CAREFUL!)\n"
334 " -h, --help show this help text\n"
335 " -n, --no-act do everything except the actual write() call\n"
336 " -o, --offset <num> offset to erase, in bytes\n"
337 " -p, --parsable print out in parsable instead of printable format\n"));
339 fprintf(out
, _("\nFor more information see wipefs(8).\n"));
341 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
346 main(int argc
, char **argv
)
348 struct wipe_desc
*wp
= NULL
;
349 int c
, all
= 0, has_offset
= 0, noact
= 0, mode
= 0;
352 struct option longopts
[] = {
353 { "all", 0, 0, 'a' },
354 { "help", 0, 0, 'h' },
355 { "no-act", 0, 0, 'n' },
356 { "offset", 1, 0, 'o' },
357 { "parsable", 0, 0, 'p' },
361 setlocale(LC_ALL
, "");
362 bindtextdomain(PACKAGE
, LOCALEDIR
);
365 while ((c
= getopt_long(argc
, argv
, "ahno:p", longopts
, NULL
)) != -1) {
377 wp
= add_offset(wp
, strtoll_offset(optarg
), 1);
381 mode
= WP_MODE_PARSABLE
;
390 errx(EXIT_FAILURE
, _("--offset and --all are mutually exclusive"));
394 fname
= argv
[optind
++];
396 wp
= read_offsets(wp
, fname
, all
);
399 if (has_offset
|| all
)
400 do_wipe(wp
, fname
, noact
);