summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>2002-10-04 03:06:16 +0000
committerwollman <wollman@FreeBSD.org>2002-10-04 03:06:16 +0000
commit2c7ac0ae064ce7ab8b30d7c30473f92d799a1485 (patch)
tree2189299fc82e0bcd16c86d7d8e6c7c57127f77e3 /tools
parent99055665a7aea346d3414d262cd72d274cab11c9 (diff)
downloadFreeBSD-src-2c7ac0ae064ce7ab8b30d7c30473f92d799a1485.zip
FreeBSD-src-2c7ac0ae064ce7ab8b30d7c30473f92d799a1485.tar.gz
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.
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/README1
-rw-r--r--tools/tools/find-sb/Makefile5
-rw-r--r--tools/tools/find-sb/README18
-rw-r--r--tools/tools/find-sb/find-sb.c95
4 files changed, 119 insertions, 0 deletions
diff --git a/tools/tools/README b/tools/tools/README
index 6e2eeed..1954550 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 0000000..26d4706
--- /dev/null
+++ b/tools/tools/find-sb/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+PROG= find-sb
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/find-sb/README b/tools/tools/find-sb/README
new file mode 100644
index 0000000..fae701c
--- /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 0000000..72a5546
--- /dev/null
+++ b/tools/tools/find-sb/find-sb.c
@@ -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;
+ }
+ }
+}
OpenPOWER on IntegriCloud