scan_ffs.c revision 1.1 1 1.1 xtraeme /* $NetBSD: scan_ffs.c,v 1.1 2005/06/15 18:06:19 xtraeme Exp $ */
2 1.1 xtraeme /* $OpenBSD: scan_ffs.c,v 1.11 2004/02/16 19:13:03 deraadt Exp$ */
3 1.1 xtraeme
4 1.1 xtraeme /*
5 1.1 xtraeme * Copyright (c) 2005 Juan Romero Pardines
6 1.1 xtraeme * Copyright (c) 1998 Niklas Hallqvist, Tobias Weingartner
7 1.1 xtraeme * All rights reserved.
8 1.1 xtraeme *
9 1.1 xtraeme * Redistribution and use in source and binary forms, with or without
10 1.1 xtraeme * modification, are permitted provided that the following conditions
11 1.1 xtraeme * are met:
12 1.1 xtraeme * 1. Redistributions of source code must retain the above copyright
13 1.1 xtraeme * notice, this list of conditions and the following disclaimer.
14 1.1 xtraeme * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 xtraeme * notice, this list of conditions and the following disclaimer in the
16 1.1 xtraeme * documentation and/or other materials provided with the distribution.
17 1.1 xtraeme *
18 1.1 xtraeme * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 xtraeme * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 xtraeme * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 xtraeme * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 xtraeme * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 xtraeme * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 xtraeme * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 xtraeme * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 xtraeme * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.1 xtraeme * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 xtraeme */
29 1.1 xtraeme
30 1.1 xtraeme /*
31 1.1 xtraeme * Currently it can detect:
32 1.1 xtraeme * o FFSv1 with fragsize/blocksize: 512/4096, 1024/8192, 2048/16384.
33 1.1 xtraeme * o FFSv2 with fragsize/blocksize: 512/4096, 1024/8192, 2048/16384,
34 1.1 xtraeme * 4096/32768, 8192/65536.
35 1.1 xtraeme * TODO:
36 1.1 xtraeme * o Detect FFSv1 partitions with fsize/bsize > 2048/16384.
37 1.1 xtraeme * o Detect FFSv2 partitions with fsize/bsize > 8192/65536.
38 1.1 xtraeme */
39 1.1 xtraeme
40 1.1 xtraeme #include <sys/cdefs.h>
41 1.1 xtraeme #ifndef lint
42 1.1 xtraeme __RCSID("$NetBSD: scan_ffs.c,v 1.1 2005/06/15 18:06:19 xtraeme Exp $");
43 1.1 xtraeme #endif /* not lint */
44 1.1 xtraeme
45 1.1 xtraeme #include <sys/types.h>
46 1.1 xtraeme #include <sys/param.h>
47 1.1 xtraeme
48 1.1 xtraeme #include <sys/disklabel.h>
49 1.1 xtraeme #include <sys/dkio.h>
50 1.1 xtraeme #include <sys/ioctl.h>
51 1.1 xtraeme #include <sys/fcntl.h>
52 1.1 xtraeme #include <ufs/ffs/fs.h>
53 1.1 xtraeme #include <unistd.h>
54 1.1 xtraeme #include <stdlib.h>
55 1.1 xtraeme #include <stdio.h>
56 1.1 xtraeme #include <string.h>
57 1.1 xtraeme #include <err.h>
58 1.1 xtraeme #include <util.h>
59 1.1 xtraeme
60 1.1 xtraeme enum { NADA, VERBOSE, LABELS };
61 1.1 xtraeme
62 1.1 xtraeme #define SBCOUNT 64 /* XXX should be configurable */
63 1.1 xtraeme
64 1.1 xtraeme static void printpart(int, int, int);
65 1.1 xtraeme static void ufsmagic(int);
66 1.1 xtraeme static void usage(void) __attribute__((__noreturn__));
67 1.1 xtraeme static int checkfstype(void);
68 1.1 xtraeme static int ufsscan(int, daddr_t, daddr_t, int);
69 1.1 xtraeme
70 1.1 xtraeme static char lastmount[MAXMNTLEN];
71 1.1 xtraeme static char device[MAXPATHLEN];
72 1.1 xtraeme static const char *fstype = NULL;
73 1.1 xtraeme
74 1.1 xtraeme static int eflag = 0;
75 1.1 xtraeme static int flags = 0;
76 1.1 xtraeme
77 1.1 xtraeme static daddr_t blk, lastblk;
78 1.1 xtraeme
79 1.1 xtraeme static struct fs *sb;
80 1.1 xtraeme
81 1.1 xtraeme static int
82 1.1 xtraeme checkfstype(void)
83 1.1 xtraeme {
84 1.1 xtraeme switch (sb->fs_magic) {
85 1.1 xtraeme case FS_UFS1_MAGIC:
86 1.1 xtraeme case FS_UFS1_MAGIC_SWAPPED:
87 1.1 xtraeme sb->fs_size = sb->fs_old_size;
88 1.1 xtraeme fstype = "FFSv1";
89 1.1 xtraeme return 1;
90 1.1 xtraeme case FS_UFS2_MAGIC:
91 1.1 xtraeme case FS_UFS2_MAGIC_SWAPPED:
92 1.1 xtraeme fstype = "FFSv2";
93 1.1 xtraeme return 2;
94 1.1 xtraeme default:
95 1.1 xtraeme return -1;
96 1.1 xtraeme }
97 1.1 xtraeme }
98 1.1 xtraeme
99 1.1 xtraeme static void
100 1.1 xtraeme printpart(int flag, int ffsize, int n)
101 1.1 xtraeme {
102 1.1 xtraeme
103 1.1 xtraeme int fsrv = checkfstype();
104 1.1 xtraeme
105 1.1 xtraeme if (flag == VERBOSE) {
106 1.1 xtraeme (void)printf("block: %" PRIu64" "
107 1.1 xtraeme "id %x,%x size %" PRIu64"\n",
108 1.1 xtraeme blk + (n / 512), sb->fs_id[0],
109 1.1 xtraeme sb->fs_id[1], sb->fs_size);
110 1.1 xtraeme } else if (flag == LABELS) {
111 1.1 xtraeme (void)printf("X: %9" PRIu64 "",
112 1.1 xtraeme (uint64_t)((off_t)sb->fs_size * sb->fs_fsize / 512));
113 1.1 xtraeme if (fsrv == 1) /* FFSv1 */
114 1.1 xtraeme (void)printf(" %9" PRIu64 "",
115 1.1 xtraeme blk + (n / 512)-(2 * SBLOCKSIZE / 512));
116 1.1 xtraeme else if (fsrv == 2) /* FFSv2 */
117 1.1 xtraeme (void)printf(" %9" PRIu64 "",
118 1.1 xtraeme blk + (n / 512)-(ffsize * SBLOCKSIZE / 512 + 128));
119 1.1 xtraeme (void)printf(" 4.2BSD %6d %5d%4d # %s [%s]\n",
120 1.1 xtraeme sb->fs_fsize, sb->fs_bsize,
121 1.1 xtraeme sb->fs_old_cpg, lastmount, fstype);
122 1.1 xtraeme } else {
123 1.1 xtraeme printf("%s ", fstype);
124 1.1 xtraeme if (fsrv == 1) /* FFSv1 */
125 1.1 xtraeme (void)printf("at %" PRIu64 "",
126 1.1 xtraeme blk + (n / 512) - (2 * SBLOCKSIZE / 512));
127 1.1 xtraeme else if (fsrv == 2) /* FFSv2 */
128 1.1 xtraeme (void)printf("at %" PRIu64 "",
129 1.1 xtraeme blk + (n / 512) - (ffsize * SBLOCKSIZE / 512 + 128));
130 1.1 xtraeme (void)printf(" size %" PRIu64 ", last mounted on %s\n",
131 1.1 xtraeme (uint64_t)((off_t)sb->fs_size * sb->fs_fsize / 512),
132 1.1 xtraeme lastmount);
133 1.1 xtraeme }
134 1.1 xtraeme }
135 1.1 xtraeme
136 1.1 xtraeme static void
137 1.1 xtraeme ufsmagic(int n)
138 1.1 xtraeme {
139 1.1 xtraeme int fsrv = checkfstype();
140 1.1 xtraeme
141 1.1 xtraeme /*
142 1.1 xtraeme * FIXME:
143 1.1 xtraeme * It cannot find FFSv1 partitions with fsize/bsize > 2048/16384,
144 1.1 xtraeme * same problem found in the original program that comes from
145 1.1 xtraeme * OpenBSD (scan_ffs(1)).
146 1.1 xtraeme */
147 1.1 xtraeme if (flags & VERBOSE)
148 1.1 xtraeme printpart(VERBOSE, NADA, n);
149 1.1 xtraeme if (fsrv == 1) { /* FFSv1 */
150 1.1 xtraeme if (((blk + (n / 512)) - lastblk) == (SBLOCKSIZE / 512)) {
151 1.1 xtraeme if (flags & LABELS)
152 1.1 xtraeme printpart(LABELS, NADA, n);
153 1.1 xtraeme else
154 1.1 xtraeme printpart(NADA, NADA, n);
155 1.1 xtraeme }
156 1.1 xtraeme } else if (fsrv == 2) { /* FFSv2 */
157 1.1 xtraeme /*
158 1.1 xtraeme * That checks for FFSv2 partitions with fragsize/blocksize:
159 1.1 xtraeme * 512/4096, 1024/8192, 2048/16384, 4096/32768 and 8192/65536.
160 1.1 xtraeme * Really enough for now.
161 1.1 xtraeme */
162 1.1 xtraeme if (((blk + (n / 512)) - lastblk) == (SBLOCKSIZE / 512)) {
163 1.1 xtraeme if (flags & LABELS)
164 1.1 xtraeme printpart(LABELS, 1, n);
165 1.1 xtraeme else
166 1.1 xtraeme printpart(NADA, 1, n);
167 1.1 xtraeme } else if (((blk + (n / 512)) - lastblk) == (2 * SBLOCKSIZE / 512)) {
168 1.1 xtraeme if (flags & LABELS)
169 1.1 xtraeme printpart(LABELS, 2, n);
170 1.1 xtraeme else
171 1.1 xtraeme printpart(NADA, 2, n);
172 1.1 xtraeme } else if (((blk + (n / 512)) - lastblk) == (4 * SBLOCKSIZE / 512)) {
173 1.1 xtraeme if (flags & LABELS)
174 1.1 xtraeme printpart(LABELS, 4, n);
175 1.1 xtraeme else
176 1.1 xtraeme printpart(NADA, 4, n);
177 1.1 xtraeme } else if (((blk + (n / 512)) - lastblk) == (8 * SBLOCKSIZE / 512)) {
178 1.1 xtraeme if (flags & LABELS)
179 1.1 xtraeme printpart(LABELS, 8, n);
180 1.1 xtraeme else
181 1.1 xtraeme printpart(NADA, 8, n);
182 1.1 xtraeme }
183 1.1 xtraeme }
184 1.1 xtraeme }
185 1.1 xtraeme
186 1.1 xtraeme static int
187 1.1 xtraeme ufsscan(int fd, daddr_t beg, daddr_t end, int fflags)
188 1.1 xtraeme {
189 1.1 xtraeme
190 1.1 xtraeme u_int8_t buf[SBLOCKSIZE * SBCOUNT];
191 1.1 xtraeme int n, fsrv;
192 1.1 xtraeme
193 1.1 xtraeme lastblk = -1;
194 1.1 xtraeme memset(lastmount, 0, MAXMNTLEN);
195 1.1 xtraeme
196 1.1 xtraeme if (fflags & LABELS)
197 1.1 xtraeme (void)printf("# size offset fstype [fsize bsize cpg]\n");
198 1.1 xtraeme
199 1.1 xtraeme for (blk = beg; blk <= ((end < 0) ? blk: end);
200 1.1 xtraeme blk += (SBCOUNT * SBLOCKSIZE / 512)) {
201 1.1 xtraeme memset(buf, 0, sizeof(buf));
202 1.1 xtraeme
203 1.1 xtraeme if (lseek(fd, (off_t)blk * 512, SEEK_SET) < 0)
204 1.1 xtraeme err(1, "lseek");
205 1.1 xtraeme /* NOTREACHED */
206 1.1 xtraeme
207 1.1 xtraeme if (read(fd, buf, sizeof(buf)) < 0)
208 1.1 xtraeme err(1, "read");
209 1.1 xtraeme /* NOTREACHED */
210 1.1 xtraeme
211 1.1 xtraeme for (n = 0; n < (SBLOCKSIZE * SBCOUNT); n += 512) {
212 1.1 xtraeme sb = (struct fs*)(&buf[n]);
213 1.1 xtraeme fsrv = checkfstype();
214 1.1 xtraeme
215 1.1 xtraeme if (fsrv >= 1) { /* found! */
216 1.1 xtraeme ufsmagic(n);
217 1.1 xtraeme /* Update last potential FS SBs seen */
218 1.1 xtraeme lastblk = blk + (n / 512);
219 1.1 xtraeme memcpy(lastmount, sb->fs_fsmnt, MAXMNTLEN);
220 1.1 xtraeme }
221 1.1 xtraeme }
222 1.1 xtraeme }
223 1.1 xtraeme return 0;
224 1.1 xtraeme }
225 1.1 xtraeme
226 1.1 xtraeme
227 1.1 xtraeme static void
228 1.1 xtraeme usage(void)
229 1.1 xtraeme {
230 1.1 xtraeme (void)fprintf(stderr,
231 1.1 xtraeme "usage: %s [-lv] [-s start] [-e end] device", getprogname());
232 1.1 xtraeme exit(1);
233 1.1 xtraeme }
234 1.1 xtraeme
235 1.1 xtraeme
236 1.1 xtraeme int
237 1.1 xtraeme main(int argc, char **argv)
238 1.1 xtraeme {
239 1.1 xtraeme int ch, fd;
240 1.1 xtraeme daddr_t end = -1, beg = 0;
241 1.1 xtraeme struct disklabel dl;
242 1.1 xtraeme
243 1.1 xtraeme setprogname(argv[0]);
244 1.1 xtraeme
245 1.1 xtraeme while ((ch = getopt(argc, argv, "e:ls:v")) != -1)
246 1.1 xtraeme switch(ch) {
247 1.1 xtraeme case 'e':
248 1.1 xtraeme eflag = 1;
249 1.1 xtraeme end = atoi(optarg);
250 1.1 xtraeme break;
251 1.1 xtraeme case 'l':
252 1.1 xtraeme flags |= LABELS;
253 1.1 xtraeme break;
254 1.1 xtraeme case 's':
255 1.1 xtraeme beg = atoi(optarg);
256 1.1 xtraeme break;
257 1.1 xtraeme case 'v':
258 1.1 xtraeme flags |= VERBOSE;
259 1.1 xtraeme break;
260 1.1 xtraeme default:
261 1.1 xtraeme usage();
262 1.1 xtraeme /* NOTREACHED */
263 1.1 xtraeme }
264 1.1 xtraeme argc -= optind;
265 1.1 xtraeme argv += optind;
266 1.1 xtraeme
267 1.1 xtraeme if (argc != 1)
268 1.1 xtraeme usage();
269 1.1 xtraeme
270 1.1 xtraeme fd = opendisk(argv[0], O_RDONLY, device, sizeof(device), 0);
271 1.1 xtraeme
272 1.1 xtraeme if (fd < 0)
273 1.1 xtraeme err(1, "%s", device);
274 1.1 xtraeme /* NOTREACHED */
275 1.1 xtraeme
276 1.1 xtraeme if (ioctl(fd, DIOCGDINFO, &dl) == -1)
277 1.1 xtraeme warn("couldn't retrieve disklabel.\n");
278 1.1 xtraeme else {
279 1.1 xtraeme (void)printf("Disk: %s\n", dl.d_typename);
280 1.1 xtraeme (void)printf("Total sectors on disk: %" PRIu32 "\n\n",
281 1.1 xtraeme dl.d_secperunit);
282 1.1 xtraeme }
283 1.1 xtraeme
284 1.1 xtraeme if (!eflag)
285 1.1 xtraeme end = dl.d_secperunit; /* default to max sectors */
286 1.1 xtraeme
287 1.1 xtraeme return (ufsscan(fd, beg, end, flags));
288 1.1 xtraeme }
289