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 */ |
|