]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/tools/find-sb/find-sb.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / tools / find-sb / find-sb.c
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 }