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