Deleted Added
full compact
ufsread.c (97864) ufsread.c (98542)
1/*
1/*
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by Marshall
6 * Kirk McKusick and Network Associates Laboratories, the Security
7 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
8 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
9 * research program
10 *
2 * Copyright (c) 1998 Robert Nordier
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are freely
6 * permitted provided that the above copyright notice and this
7 * paragraph and the following disclaimer are duplicated in all
8 * such forms.
9 *
10 * This software is provided "AS IS" and without any express or
11 * implied warranties, including, without limitation, the implied
12 * warranties of merchantability and fitness for a particular
13 * purpose.
14 */
15
16/*
11 * Copyright (c) 1998 Robert Nordier
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms are freely
15 * permitted provided that the above copyright notice and this
16 * paragraph and the following disclaimer are duplicated in all
17 * such forms.
18 *
19 * This software is provided "AS IS" and without any express or
20 * implied warranties, including, without limitation, the implied
21 * warranties of merchantability and fitness for a particular
22 * purpose.
23 */
24
25/*
17 * $FreeBSD: head/sys/boot/common/ufsread.c 97864 2002-06-05 12:00:53Z phk $
26 * $FreeBSD: head/sys/boot/common/ufsread.c 98542 2002-06-21 06:18:05Z mckusick $
18 */
19
27 */
28
20#include <ufs/ffs/fs.h>
21#include <ufs/ufs/dinode.h>
29#include <ufs/ufs/dinode.h>
30#include <ufs/ffs/fs.h>
22
23/*
24 * We use 4k `virtual' blocks for filesystem data, whatever the actual
25 * filesystem block size. FFS blocks are always a multiple of 4k.
26 */
27#define VBLKSIZE 4096
31
32/*
33 * We use 4k `virtual' blocks for filesystem data, whatever the actual
34 * filesystem block size. FFS blocks are always a multiple of 4k.
35 */
36#define VBLKSIZE 4096
37#define VBLKSHIFT 12
28#define VBLKMASK (VBLKSIZE - 1)
29#define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
38#define VBLKMASK (VBLKSIZE - 1)
39#define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
30#define IPERVBLK (VBLKSIZE / sizeof(struct dinode))
31#define INDIRPERVBLK (VBLKSIZE / sizeof(ufs_daddr_t))
32#define INO_TO_VBA(fs, x) (fsbtodb(fs, ino_to_fsba(fs, x)) + \
33 (ino_to_fsbo(fs, x) / IPERVBLK) * DBPERVBLK)
34#define INO_TO_VBO(fs, x) (ino_to_fsbo(fs, x) % IPERVBLK)
40#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize / VBLKSIZE))
41#define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize / VBLKSIZE))
42#define INO_TO_VBA(fs, ipervblk, x) \
43 (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
44 (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
45#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
35#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
36 ((off) / VBLKSIZE) * DBPERVBLK)
37#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
38
39/* Buffers that must not span a 64k boundary. */
40struct dmadat {
46#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
47 ((off) / VBLKSIZE) * DBPERVBLK)
48#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
49
50/* Buffers that must not span a 64k boundary. */
51struct dmadat {
41 char blkbuf[VBLKSIZE]; /* filesystem blocks */
42 ufs_daddr_t indbuf[VBLKSIZE / sizeof(ufs_daddr_t)]; /* indir blocks */
43 char sbbuf[SBSIZE]; /* superblock */
44 char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
52 char blkbuf[VBLKSIZE]; /* filesystem blocks */
53 char indbuf[VBLKSIZE]; /* indir blocks */
54 char sbbuf[SBLOCKSIZE]; /* superblock */
55 char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
45};
46static struct dmadat *dmadat;
47
48static ino_t lookup(const char *);
49static ssize_t fsread(ino_t, void *, size_t);
50
51static int ls, dsk_meta;
52static uint32_t fs_off;
53
54static inline int
55fsfind(const char *name, ino_t * ino)
56{
57 char buf[DEV_BSIZE];
58 struct dirent *d;
59 char *s;
60 ssize_t n;
61
62 fs_off = 0;
63 while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
56};
57static struct dmadat *dmadat;
58
59static ino_t lookup(const char *);
60static ssize_t fsread(ino_t, void *, size_t);
61
62static int ls, dsk_meta;
63static uint32_t fs_off;
64
65static inline int
66fsfind(const char *name, ino_t * ino)
67{
68 char buf[DEV_BSIZE];
69 struct dirent *d;
70 char *s;
71 ssize_t n;
72
73 fs_off = 0;
74 while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
64 for (s = buf; s < buf + DEV_BSIZE;) {
65 d = (void *)s;
66 if (ls)
67 printf("%s ", d->d_name);
68 else if (!strcmp(name, d->d_name)) {
69 *ino = d->d_fileno;
70 return d->d_type;
75 for (s = buf; s < buf + DEV_BSIZE;) {
76 d = (void *)s;
77 if (ls)
78 printf("%s ", d->d_name);
79 else if (!strcmp(name, d->d_name)) {
80 *ino = d->d_fileno;
81 return d->d_type;
82 }
83 s += d->d_reclen;
71 }
84 }
72 s += d->d_reclen;
73 }
74 if (n != -1 && ls)
75 printf("\n");
76 return 0;
77}
78
79static ino_t
80lookup(const char *path)
81{

--- 8 unchanged lines hidden (view full) ---

90 name[0] = '/';
91 name[1] = '\0';
92 for (;;) {
93 if (*path == '/')
94 path++;
95 if (!*path)
96 break;
97 for (s = path; *s && *s != '/'; s++);
85 if (n != -1 && ls)
86 printf("\n");
87 return 0;
88}
89
90static ino_t
91lookup(const char *path)
92{

--- 8 unchanged lines hidden (view full) ---

101 name[0] = '/';
102 name[1] = '\0';
103 for (;;) {
104 if (*path == '/')
105 path++;
106 if (!*path)
107 break;
108 for (s = path; *s && *s != '/'; s++);
98 if ((n = s - path) > MAXNAMLEN)
99 return 0;
109 if ((n = s - path) > MAXNAMLEN)
110 return 0;
100 ls = *path == '?' && n == 1 && !*s;
101 memcpy(name, path, n);
102 name[n] = 0;
103 if (dt != DT_DIR) {
104 printf("%s: not a directory.\n", name);
105 return (0);
106 }
107 if ((dt = fsfind(name, &ino)) <= 0)
108 break;
109 path = s;
110 }
111 return dt == DT_REG ? ino : 0;
112}
113
111 ls = *path == '?' && n == 1 && !*s;
112 memcpy(name, path, n);
113 name[n] = 0;
114 if (dt != DT_DIR) {
115 printf("%s: not a directory.\n", name);
116 return (0);
117 }
118 if ((dt = fsfind(name, &ino)) <= 0)
119 break;
120 path = s;
121 }
122 return dt == DT_REG ? ino : 0;
123}
124
125#define UFS1_ONLY
126#ifdef UFS1_ONLY
127
114static ssize_t
115fsread(ino_t inode, void *buf, size_t nbyte)
116{
128static ssize_t
129fsread(ino_t inode, void *buf, size_t nbyte)
130{
117 static struct dinode din;
131 static struct ufs1_dinode dp1;
118 static ino_t inomap;
132 static ino_t inomap;
119 static daddr_t blkmap, indmap;
120 char *blkbuf;
133 char *blkbuf;
121 ufs_daddr_t *indbuf;
134 caddr_t indbuf;
122 struct fs *fs;
123 char *s;
135 struct fs *fs;
136 char *s;
124 ufs_daddr_t lbn, addr;
125 daddr_t vbaddr;
126 size_t n, nb, off, vboff;
137 size_t n, nb, size, off, vboff;
138 long lbn;
139 ufs1_daddr_t addr, vbaddr;
140 static ufs1_daddr_t blkmap, indmap;
127
128 blkbuf = dmadat->blkbuf;
129 indbuf = dmadat->indbuf;
130 fs = (struct fs *)dmadat->sbbuf;
131 if (!dsk_meta) {
132 inomap = 0;
141
142 blkbuf = dmadat->blkbuf;
143 indbuf = dmadat->indbuf;
144 fs = (struct fs *)dmadat->sbbuf;
145 if (!dsk_meta) {
146 inomap = 0;
133 if (dskread(fs, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE))
147 if (dskread(fs, SBLOCK_UFS1 / DEV_BSIZE, SBLOCKSIZE / DEV_BSIZE))
134 return -1;
148 return -1;
135 if (fs->fs_magic != FS_MAGIC) {
149 if (fs->fs_magic != FS_UFS1_MAGIC) {
136 printf("Not ufs\n");
137 return -1;
138 }
139 dsk_meta++;
140 }
141 if (!inode)
142 return 0;
143 if (inomap != inode) {
150 printf("Not ufs\n");
151 return -1;
152 }
153 dsk_meta++;
154 }
155 if (!inode)
156 return 0;
157 if (inomap != inode) {
144 if (dskread(blkbuf, INO_TO_VBA(fs, inode), DBPERVBLK))
158 n = IPERVBLK(fs);
159 if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
145 return -1;
160 return -1;
146 din = ((struct dinode *)blkbuf)[INO_TO_VBO(fs, inode)];
161 dp1 = ((struct ufs1_dinode *)blkbuf)[INO_TO_VBO(n, inode)];
147 inomap = inode;
148 fs_off = 0;
149 blkmap = indmap = 0;
150 }
151 s = buf;
162 inomap = inode;
163 fs_off = 0;
164 blkmap = indmap = 0;
165 }
166 s = buf;
152 if (nbyte > (n = din.di_size - fs_off))
167 size = dp1.di_size;
168 n = size - fs_off;
169 if (nbyte > n)
153 nbyte = n;
154 nb = nbyte;
155 while (nb) {
156 lbn = lblkno(fs, fs_off);
157 off = blkoff(fs, fs_off);
170 nbyte = n;
171 nb = nbyte;
172 while (nb) {
173 lbn = lblkno(fs, fs_off);
174 off = blkoff(fs, fs_off);
158 if (lbn < NDADDR)
159 addr = din.di_db[lbn];
160 else {
161 vbaddr = FS_TO_VBA(fs, din.di_ib[0], sizeof(indbuf[0]) *
162 ((lbn - NDADDR) % NINDIR(fs)));
175 if (lbn < NDADDR) {
176 addr = dp1.di_db[lbn];
177 } else {
178 n = INDIRPERVBLK(fs);
179 addr = dp1.di_ib[0];
180 vbaddr = fsbtodb(fs, addr) +
181 (lbn - NDADDR) / n * DBPERVBLK;
163 if (indmap != vbaddr) {
164 if (dskread(indbuf, vbaddr, DBPERVBLK))
165 return -1;
166 indmap = vbaddr;
167 }
182 if (indmap != vbaddr) {
183 if (dskread(indbuf, vbaddr, DBPERVBLK))
184 return -1;
185 indmap = vbaddr;
186 }
168 addr = indbuf[(lbn - NDADDR) % INDIRPERVBLK];
187 addr = ((ufs1_daddr_t *)indbuf)[(lbn - NDADDR) % n];
169 }
188 }
170 vbaddr = FS_TO_VBA(fs, addr, off);
171 vboff = FS_TO_VBO(fs, addr, off);
172 n = dblksize(fs, &din, lbn) - (off & ~VBLKMASK);
189 vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
190 vboff = off & VBLKMASK;
191 n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
173 if (n > VBLKSIZE)
174 n = VBLKSIZE;
175 if (blkmap != vbaddr) {
176 if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
177 return -1;
178 blkmap = vbaddr;
179 }
180 n -= vboff;
181 if (n > nb)
182 n = nb;
183 memcpy(s, blkbuf + vboff, n);
184 s += n;
185 fs_off += n;
186 nb -= n;
187 }
188 return nbyte;
189}
192 if (n > VBLKSIZE)
193 n = VBLKSIZE;
194 if (blkmap != vbaddr) {
195 if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
196 return -1;
197 blkmap = vbaddr;
198 }
199 n -= vboff;
200 if (n > nb)
201 n = nb;
202 memcpy(s, blkbuf + vboff, n);
203 s += n;
204 fs_off += n;
205 nb -= n;
206 }
207 return nbyte;
208}
209
210#else /* UFS1_AND_UFS2 */
211
212/*
213 * Possible superblock locations ordered from most to least likely.
214 */
215static int sblock_try[] = SBLOCKSEARCH;
216
217#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
218
219static ssize_t
220fsread(ino_t inode, void *buf, size_t nbyte)
221{
222 static struct ufs1_dinode dp1;
223 static struct ufs2_dinode dp2;
224 static ino_t inomap;
225 char *blkbuf;
226 caddr_t indbuf;
227 struct fs *fs;
228 char *s;
229 size_t n, nb, size, off, vboff;
230 ufs_lbn_t lbn;
231 ufs2_daddr_t addr, vbaddr;
232 static ufs2_daddr_t blkmap, indmap;
233
234 blkbuf = dmadat->blkbuf;
235 indbuf = dmadat->indbuf;
236 fs = (struct fs *)dmadat->sbbuf;
237 if (!dsk_meta) {
238 inomap = 0;
239 for (n = 0; sblock_try[n] != -1; n++) {
240 if (dskread(fs, sblock_try[n] / DEV_BSIZE,
241 SBLOCKSIZE / DEV_BSIZE))
242 return -1;
243 if ((fs->fs_magic == FS_UFS1_MAGIC ||
244 (fs->fs_magic == FS_UFS2_MAGIC &&
245 fs->fs_sblockloc == numfrags(fs, sblock_try[n]))) &&
246 fs->fs_bsize <= MAXBSIZE &&
247 fs->fs_bsize >= sizeof(struct fs))
248 break;
249 }
250 if (sblock_try[n] == -1) {
251 printf("Not ufs\n");
252 return -1;
253 }
254 dsk_meta++;
255 }
256 if (!inode)
257 return 0;
258 if (inomap != inode) {
259 n = IPERVBLK(fs);
260 if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
261 return -1;
262 n = INO_TO_VBO(n, inode);
263 if (fs->fs_magic == FS_UFS1_MAGIC)
264 dp1 = ((struct ufs1_dinode *)blkbuf)[n];
265 else
266 dp2 = ((struct ufs2_dinode *)blkbuf)[n];
267 inomap = inode;
268 fs_off = 0;
269 blkmap = indmap = 0;
270 }
271 s = buf;
272 size = DIP(di_size);
273 n = size - fs_off;
274 if (nbyte > n)
275 nbyte = n;
276 nb = nbyte;
277 while (nb) {
278 lbn = lblkno(fs, fs_off);
279 off = blkoff(fs, fs_off);
280 if (lbn < NDADDR) {
281 addr = DIP(di_db[lbn]);
282 } else if (lbn < NDADDR + NINDIR(fs)) {
283 n = INDIRPERVBLK(fs);
284 addr = DIP(di_ib[0]);
285 vbaddr = fsbtodb(fs, addr) +
286 (lbn - NDADDR) / n * DBPERVBLK;
287 if (indmap != vbaddr) {
288 if (dskread(indbuf, vbaddr, DBPERVBLK))
289 return -1;
290 indmap = vbaddr;
291 }
292 n = (lbn - NDADDR) % n;
293 if (fs->fs_magic == FS_UFS1_MAGIC)
294 addr = ((ufs1_daddr_t *)indbuf)[n];
295 else
296 addr = ((ufs2_daddr_t *)indbuf)[n];
297 } else {
298 printf("file too big\n");
299 return -1;
300 }
301 vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
302 vboff = off & VBLKMASK;
303 n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
304 if (n > VBLKSIZE)
305 n = VBLKSIZE;
306 if (blkmap != vbaddr) {
307 if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
308 return -1;
309 blkmap = vbaddr;
310 }
311 n -= vboff;
312 if (n > nb)
313 n = nb;
314 memcpy(s, blkbuf + vboff, n);
315 s += n;
316 fs_off += n;
317 nb -= n;
318 }
319 return nbyte;
320}
321
322#endif /* UFS1_AND_UFS2 */