Yesterday, FreeBSD-current ate my disklabel.

Today, I wrote a program to tell me where the partitions used to be.
Now I have my /media filesystem back.
This commit is contained in:
Garrett Wollman 2002-10-04 03:06:16 +00:00
parent efe66a4be9
commit 92d0f59903
4 changed files with 119 additions and 0 deletions

View File

@ -11,6 +11,7 @@ commitsdb A tool for reconstructing commit history using md5
checksums of the commit logs.
editing Editor modes and the like to help editing FreeBSD code.
epfe Extract printing filter examples from printing.sgml.
find-sb Scan a disk for possible filesystem superblocks.
html-mv Rename HTML generated filenames to human readable filenames.
ifinfo Uses the interface MIB to print out all the information
an interface exports in an ugly form.

View File

@ -0,0 +1,5 @@
# $FreeBSD$
PROG= find-sb
NOMAN=
.include <bsd.prog.mk>

View File

@ -0,0 +1,18 @@
$FreeBSD$
find-sb is a program which scans the input file you specify (normally a
raw disk slice) for filesystems. It's not very smart, nor particularly
efficient. All it does is read the input file one device block at a time,
and when it reads a block that has a UFS superblock magic number in the
right place, it tells you about it. It helped me find an important partition
after the disklabel got somehow trashed. It might not work for you. After
looking carefully at the output of this program and creating a new disklabel,
you should use `fsck -n' or a tool like ffsinfo(8) to verify that there is
in fact something vaguely sane located at that spot on the disk. (There are
checks that fsck can do to verify the validity of the superblock which
this program does not even attempt.)
If you use this program and as a result trash what was left of your disk,
well, too bad. You should have kept a backup anyway. If you read the source
code and don't immediately understand how it works and what it's doing, then
DON'T USE IT.

View File

@ -0,0 +1,95 @@
/*
* This program, created 2002-10-03 by Garrett A. Wollman
* <wollman@FreeBSD.org>, is in the public domain. Use at your own risk.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static union {
char buf[SBLOCKSIZE];
struct fs sblock;
} u;
int
main(int argc, char **argv)
{
off_t end, last;
size_t len;
ssize_t justread;
int fd;
if (argv[1] == NULL)
errx(1, "usage");
fd = open(argv[1], O_RDONLY, 0);
if (fd < 0)
err(1, "%s", argv[1]);
end = len = 0;
last = -1;
while (1) {
justread = read(fd, &u.buf[len], DEV_BSIZE);
if (justread != DEV_BSIZE) {
if (justread == 0) {
printf("reached end-of-file at %jd\n",
(intmax_t)end);
exit (0);
}
if (justread < 0)
err(1, "read");
errx(1, "short read %jd (wanted %d) at %jd",
(intmax_t)justread, DEV_BSIZE, (intmax_t)end);
}
len += DEV_BSIZE;
end += DEV_BSIZE;
if (len >= sizeof(struct fs)) {
intmax_t offset = end - len;
if (u.sblock.fs_magic == FS_UFS1_MAGIC) {
intmax_t fsbegin = offset - SBLOCK_UFS1;
printf("Found UFS1 superblock at offset %jd, "
"block %jd\n", offset,
offset / DEV_BSIZE);
printf("Filesystem might begin at offset %jd, "
"block %jd\n", fsbegin,
fsbegin / DEV_BSIZE);
if (last >= 0) {
printf("%jd blocks from last guess\n",
fsbegin / DEV_BSIZE - last);
}
last = fsbegin / DEV_BSIZE;
} else if (u.sblock.fs_magic == FS_UFS2_MAGIC) {
intmax_t fsbegin = offset - SBLOCK_UFS1;
printf("Found UFS2 superblock at offset %jd, "
"block %jd\n", offset,
offset / DEV_BSIZE);
printf("Filesystem might begin at offset %jd, "
"block %jd\n", fsbegin,
fsbegin / DEV_BSIZE);
if (last >= 0) {
printf("%jd blocks from last guess\n",
fsbegin / DEV_BSIZE - last);
}
last = fsbegin / DEV_BSIZE;
}
}
if (len >= SBLOCKSIZE) {
memmove(u.buf, &u.buf[DEV_BSIZE],
SBLOCKSIZE - DEV_BSIZE);
len -= DEV_BSIZE;
}
}
}