1 /* $NetBSD: readufs.c,v 1.8 2009/03/18 10:22:28 cegger Exp $ */
2 /* from Id: readufs.c,v 1.9 2003/12/16 13:54:11 itohy Exp */
7 * Written in 1999, 2002, 2003 by ITOH Yasufumi (itohy@NetBSD.org).
10 * Intended to be used for boot programs (first stage).
11 * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
18 static void raw_read_queue(void *buf
, daddr_t blkpos
, size_t bytelen
);
19 static int ufs_read_indirect(daddr_t blk
, int level
, void **buf
,
20 unsigned *poff
, size_t count
);
22 #ifdef DEBUG_WITH_STDIO
23 void ufs_list_dir(ino32_t dirino
);
24 int main(int argc
, char *argv
[]);
27 #ifdef DEBUG_WITH_STDIO
31 RAW_READ(void *buf
, daddr_t blkpos
, size_t bytelen
)
34 if (pread(fd
, buf
, bytelen
, (off_t
)dbtob(blkpos
)) != (ssize_t
) bytelen
)
35 err(1, "pread: buf %p, blk %d, len %u",
36 buf
, (int) blkpos
, bytelen
);
43 * Read contiguous sectors at once for speedup.
48 raw_read_queue(void *buf
, daddr_t blkpos
, size_t bytelen
)
49 /* bytelen: must be DEV_BSIZE aligned */
51 static daddr_t rq_start
;
55 if (bytelen
&& blkpos
== rq_start
+ (ssize_t
) btodb(rq_len
)
56 && buf
== rq_buf
+ rq_len
) {
60 #ifdef DEBUG_WITH_STDIO
61 printf("raw_read_queue: read: buf %p, blk %d, len %d\n",
62 rq_buf
, (int) rq_start
, rq_len
);
64 RAW_READ(rq_buf
, rq_start
, rq_len
);
72 #define RAW_READ_QUEUE_INIT() (rq_len = 0)
73 #define RAW_READ_QUEUE_FLUSH() \
74 raw_read_queue((void *) 0, (daddr_t) 0, (size_t) 0)
78 * Read a file, specified by dinode.
79 * No support for holes or (short) symbolic links.
82 ufs_read(union ufs_dinode
*di
, void *buf
, unsigned off
, size_t count
)
83 /* off: position in block */
85 struct ufs_info
*ufsinfo
= &fs
;
86 size_t bsize
= ufsinfo
->bsize
;
91 #if defined(USE_UFS1) && defined(USE_UFS2)
92 enum ufs_ufstype uver
= ufsinfo
->ufstype
;
95 #ifdef DEBUG_WITH_STDIO
96 printf("ufs_read: off: %d, count %u\n", off
, count
);
101 if (disize
< count
+ off
* bsize
)
102 count
= disize
- off
* bsize
;
104 /* FS block size alignment. */
106 count
= (count
+ bsize
- 1) & ~(bsize
- 1);
108 RAW_READ_QUEUE_INIT();
110 /* Read direct blocks. */
111 for ( ; off
< NDADDR
&& count
> 0; off
++) {
112 #if defined(USE_UFS1) && defined(USE_UFS2)
113 if (uver
== UFSTYPE_UFS1
)
114 pos
= di
->di1
.di_db
[off
];
116 pos
= di
->di2
.di_db
[off
];
118 pos
= di
->di_thisver
.di_db
[off
];
121 printf("ufs_read: read: blk: %d\n",
122 (int) pos
<< ufsinfo
->fsbtodb
);
124 raw_read_queue(b
, pos
<< ufsinfo
->fsbtodb
, bsize
);
130 /* Read indirect blocks. */
131 for (i
= 0; i
< NIADDR
&& count
> 0; i
++) {
132 #if defined(USE_UFS1) && defined(USE_UFS2)
133 if (uver
== UFSTYPE_UFS1
)
134 pos
= di
->di1
.di_ib
[i
];
136 pos
= di
->di2
.di_ib
[i
];
138 pos
= di
->di_thisver
.di_ib
[i
];
140 count
= ufs_read_indirect(pos
, i
, &b
, &off
, count
);
143 RAW_READ_QUEUE_FLUSH();
149 ufs_read_indirect(daddr_t blk
, int level
, void **buf
, unsigned *poff
, size_t count
)
150 /* poff: position in block */
152 struct ufs_info
*ufsinfo
= &fs
;
153 size_t bsize
= ufsinfo
->bsize
;
154 void *idbuf
= alloca(bsize
);
156 int32_t *idbuf1
= idbuf
;
159 int64_t *idbuf2
= idbuf
;
162 unsigned off
= *poff
;
165 #ifdef DEBUG_WITH_STDIO
166 printf("ufs_read_indirect: off: %d, count %u\n", off
, count
);
169 unsigned subindirsize
= 1, indirsize
;
172 for (i
= level
; i
> 0; i
--)
173 subindirsize
*= ufsinfo
->nindir
;
174 indirsize
= subindirsize
* ufsinfo
->nindir
;
175 if (off
>= indirsize
) {
176 /* no need to read any data */
177 *poff
= off
- indirsize
;
181 b
= off
/ subindirsize
;
182 off
-= b
* subindirsize
;
187 /* read the indirect block */
188 RAW_READ(idbuf
, blk
<< ufsinfo
->fsbtodb
, bsize
);
190 for ( ; b
< ufsinfo
->nindir
&& count
> 0; b
++) {
191 #if defined(USE_UFS1) && defined(USE_UFS2)
192 if (ufsinfo
->ufstype
== UFSTYPE_UFS1
)
197 #if defined(USE_UFS1) && defined(USE_UFS2)
205 count
= ufs_read_indirect(pos
, level
- 1, buf
, &off
, count
);
208 printf("ufs_read: read: blk: %d\n",
209 (int) pos
<< ufsinfo
->fsbtodb
);
211 raw_read_queue(*buf
, pos
<< ufsinfo
->fsbtodb
, bsize
);
221 * look-up fn in directory dirino
224 ufs_lookup(ino32_t dirino
, const char *fn
)
226 union ufs_dinode dirdi
;
231 if (ufs_get_inode(dirino
, &dirdi
))
234 if ((dirdi
.di_common
.di_mode
& IFMT
) != IFDIR
)
235 return 0; /* Not a directory */
237 disize
= DI_SIZE(&dirdi
);
239 p
= alloca((disize
+ fs
.bsize
- 1) & ~(fs
.bsize
- 1));
240 ufs_read(&dirdi
, p
, 0, disize
);
242 for ( ; pdir
= (void *) p
, p
< endp
; p
+= pdir
->d_reclen
) {
243 if (pdir
->d_ino
&& !strcmp(fn
, pdir
->d_name
))
246 return 0; /* No such file or directory */
250 * look-up a file in absolute pathname from the root directory
253 ufs_lookup_path(const char *path
)
255 char fn
[FFS_MAXNAMLEN
+ 1];
257 ino32_t ino
= ROOTINO
;
262 for (p
= fn
; *path
&& *path
!= '/'; )
265 ino
= ufs_lookup(ino
, fn
);
266 } while (ino
&& *path
);
273 ufs_load_file(void *buf
, ino32_t dirino
, const char *fn
)
276 union ufs_dinode dinode
;
278 if (ufs_fn_inode(dirino
, fn
, &dinode
))
280 disize
= DI_SIZE(&dinode
);
281 cnt
= ufs_read(&dinode
, buf
, 0, disize
);
300 #ifdef DEBUG_WITH_STDIO
302 ufs_list_dir(ino32_t dirino
)
304 union ufs_dinode dirdi
;
309 if (ufs_get_inode(dirino
, &dirdi
))
310 errx(1, "ino = %d: not found", dirino
);
312 disize
= DI_SIZE(&dirdi
);
313 p
= alloca((disize
+ fs
.bsize
- 1) & ~(fs
.bsize
- 1));
314 ufs_read(&dirdi
, p
, 0, disize
);
316 for ( ; pdir
= (void *) p
, p
< endp
; p
+= pdir
->d_reclen
) {
318 printf("%6d %s\n", pdir
->d_ino
, pdir
->d_name
);
323 #ifdef DEBUG_WITH_STDIO
326 int argc
__attribute__((unused
));
329 union ufs_dinode dinode
;
331 if ((fd
= open(argv
[1], O_RDONLY
)) < 0)
332 err(1, "open: %s", argv
[1]);
335 errx(1, "%s: unknown fs", argv
[1]);
338 ufs_list_dir(ROOTINO
);
345 if ((ino
= ufs_lookup_path(argv
[2])) == 0)
346 errx(1, "%s: not found", argv
[2]);
347 ufs_get_inode(ino
, &dinode
);
348 disize
= DI_SIZE(&dinode
);
349 p
= malloc((disize
+ fs
.bsize
- 1) & ~(fs
.bsize
- 1));
350 cnt
= ufs_read(&dinode
, p
, 0, disize
);