xref: /freebsd/tools/tools/find-sb/find-sb.c (revision c697fb7f)
1 /*
2  * This program, created 2002-10-03 by Garrett A. Wollman
3  * <wollman@FreeBSD.org>, is in the public domain.  Use at your own risk.
4  *
5  * $FreeBSD$
6  */
7 
8 #ifdef __FreeBSD__
9 #include <sys/param.h>
10 
11 #include <ufs/ufs/dinode.h>
12 #include <ufs/ffs/fs.h>
13 #else
14 #include "mini_ufs.h"
15 #endif
16 
17 #include <err.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 static union {
26 	char buf[SBLOCKSIZE];
27 	struct fs sblock;
28 } u;
29 
30 int
31 main(int argc, char **argv)
32 {
33 	off_t end, last1, last2;
34 	size_t len;
35 	ssize_t justread;
36 	int fd;
37 	char *ch;
38 	char c;
39 	intmax_t offset;
40 
41 	offset = 0;
42 	while ((c = getopt(argc, argv, "o:")) != -1) {
43 		switch (c) {
44 		case 'o':
45 			if (optarg[0] == '\0')
46 				errx(1, "usage");
47 			offset = strtoimax(optarg, &ch, 10);
48 			if (*ch != '\0' || offset < 0)
49 				errx(1, "usage");
50 			offset -= offset % DEV_BSIZE;
51 			break;
52 
53 		default:
54 			errx(1, "usage");
55 		}
56 	}
57 	argc -= optind;
58 	argv += optind;
59 
60 	if (argc != 1)
61 		errx(1, "usage");
62 
63 	fd = open(argv[0], O_RDONLY, 0);
64 	if (fd < 0)
65 		err(1, "%s", argv[0]);
66 
67 	if (offset != 0) {
68 		end = lseek(fd, offset, SEEK_SET);
69 		if (end == -1)
70 			err(1, "%s", argv[0]);
71 	} else {
72 		end = 0;
73 	}
74 	len = 0;
75 	last1 = last2 = -1;
76 
77 	while (1) {
78 		justread = read(fd, &u.buf[len], DEV_BSIZE);
79 		if (justread != DEV_BSIZE) {
80 			if (justread == 0) {
81 				printf("reached end-of-file at %jd\n",
82 				       (intmax_t)end);
83 				exit (0);
84 			}
85 			if (justread < 0)
86 				err(1, "read");
87 			errx(1, "short read %jd (wanted %d) at %jd",
88 			     (intmax_t)justread, DEV_BSIZE, (intmax_t)end);
89 		}
90 		len += DEV_BSIZE;
91 		end += DEV_BSIZE;
92 		if (len >= sizeof(struct fs)) {
93 			offset = end - len;
94 
95 			if (u.sblock.fs_magic == FS_UFS1_MAGIC) {
96 				intmax_t fsbegin = offset - SBLOCK_UFS1;
97 				printf("Found UFS1 superblock at offset %jd, "
98 				       "block %jd\n", offset,
99 				       offset / DEV_BSIZE);
100 				printf("Filesystem might begin at offset %jd, "
101 				       "block %jd\n", fsbegin,
102 				       fsbegin / DEV_BSIZE);
103 				if (last1 >= 0) {
104 					printf("%jd blocks from last guess\n",
105 					       fsbegin / DEV_BSIZE - last1);
106 				}
107 				last1 = fsbegin / DEV_BSIZE;
108 				len -= DEV_BSIZE;
109 				memmove(u.buf, &u.buf[DEV_BSIZE], len);
110 			} else if (u.sblock.fs_magic == FS_UFS2_MAGIC) {
111 				intmax_t fsbegin = offset - SBLOCK_UFS2;
112 				printf("Found UFS2 superblock at offset %jd, "
113 				       "block %jd\n", offset,
114 				       offset / DEV_BSIZE);
115 				printf("Filesystem might begin at offset %jd, "
116 				       "block %jd\n", fsbegin,
117 				       fsbegin / DEV_BSIZE);
118 				if (last2 >= 0) {
119 					printf("%jd blocks from last guess\n",
120 					       fsbegin / DEV_BSIZE - last2);
121 				}
122 				last2 = fsbegin / DEV_BSIZE;
123 				len -= DEV_BSIZE;
124 				memmove(u.buf, &u.buf[DEV_BSIZE], len);
125 			}
126 		}
127 		if (len >= SBLOCKSIZE) {
128 			memmove(u.buf, &u.buf[DEV_BSIZE],
129 				SBLOCKSIZE - DEV_BSIZE);
130 			len -= DEV_BSIZE;
131 		}
132 	}
133 }
134