diff --git a/tools/tools/README b/tools/tools/README index 6e2eeeded613..1954550d4932 100644 --- a/tools/tools/README +++ b/tools/tools/README @@ -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. diff --git a/tools/tools/find-sb/Makefile b/tools/tools/find-sb/Makefile new file mode 100644 index 000000000000..26d4706de30b --- /dev/null +++ b/tools/tools/find-sb/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ +PROG= find-sb +NOMAN= + +.include diff --git a/tools/tools/find-sb/README b/tools/tools/find-sb/README new file mode 100644 index 000000000000..fae701c816c3 --- /dev/null +++ b/tools/tools/find-sb/README @@ -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. diff --git a/tools/tools/find-sb/find-sb.c b/tools/tools/find-sb/find-sb.c new file mode 100644 index 000000000000..72a5546c8258 --- /dev/null +++ b/tools/tools/find-sb/find-sb.c @@ -0,0 +1,95 @@ +/* + * This program, created 2002-10-03 by Garrett A. Wollman + * , is in the public domain. Use at your own risk. + * + * $FreeBSD$ + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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; + } + } +}