readufs.c revision 1.1.6.2 1 1.1.6.2 thorpej /* $Id: readufs.c,v 1.1.6.2 2002/01/10 19:50:29 thorpej Exp $ */
2 1.1.6.2 thorpej
3 1.1.6.2 thorpej /*
4 1.1.6.2 thorpej * Read UFS (FFS / LFS)
5 1.1.6.2 thorpej *
6 1.1.6.2 thorpej * Written by ITOH, Yasufumi (itohy (at) netbsd.org).
7 1.1.6.2 thorpej * Public domain.
8 1.1.6.2 thorpej *
9 1.1.6.2 thorpej * Intended to be used for boot programs (first stage).
10 1.1.6.2 thorpej * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
11 1.1.6.2 thorpej */
12 1.1.6.2 thorpej
13 1.1.6.2 thorpej #include <sys/types.h>
14 1.1.6.2 thorpej #include <sys/param.h>
15 1.1.6.2 thorpej #include <ufs/ufs/dinode.h>
16 1.1.6.2 thorpej
17 1.1.6.2 thorpej #include "readufs.h"
18 1.1.6.2 thorpej
19 1.1.6.2 thorpej #define fs ufs_info
20 1.1.6.2 thorpej
21 1.1.6.2 thorpej static void raw_read_queue __P((void *buf, ufs_daddr_t blkpos, size_t bytelen));
22 1.1.6.2 thorpej static int ufs_read_indirect __P((ufs_daddr_t blk, int level, caddr_t *buf,
23 1.1.6.2 thorpej unsigned *poff, size_t count));
24 1.1.6.2 thorpej
25 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
26 1.1.6.2 thorpej void ufs_list_dir __P((ino_t dirino));
27 1.1.6.2 thorpej int main __P((int argc, char *argv[]));
28 1.1.6.2 thorpej #endif
29 1.1.6.2 thorpej
30 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
31 1.1.6.2 thorpej int fd;
32 1.1.6.2 thorpej
33 1.1.6.2 thorpej void
34 1.1.6.2 thorpej RAW_READ(buf, blkpos, bytelen)
35 1.1.6.2 thorpej void *buf;
36 1.1.6.2 thorpej u_int32_t blkpos;
37 1.1.6.2 thorpej size_t bytelen;
38 1.1.6.2 thorpej {
39 1.1.6.2 thorpej if (pread(fd, buf, bytelen, (off_t)dbtob(blkpos)) != (ssize_t) bytelen)
40 1.1.6.2 thorpej err(1, "pread: buf %p, blk %u, len %u", buf, blkpos, bytelen);
41 1.1.6.2 thorpej }
42 1.1.6.2 thorpej #endif
43 1.1.6.2 thorpej
44 1.1.6.2 thorpej struct ufs_info fs;
45 1.1.6.2 thorpej
46 1.1.6.2 thorpej /*
47 1.1.6.2 thorpej * Read contiguous sectors at once for speedup.
48 1.1.6.2 thorpej */
49 1.1.6.2 thorpej static size_t rq_len;
50 1.1.6.2 thorpej
51 1.1.6.2 thorpej static void
52 1.1.6.2 thorpej raw_read_queue(buf, blkpos, bytelen)
53 1.1.6.2 thorpej void *buf;
54 1.1.6.2 thorpej ufs_daddr_t blkpos;
55 1.1.6.2 thorpej size_t bytelen; /* must be DEV_BSIZE aligned */
56 1.1.6.2 thorpej {
57 1.1.6.2 thorpej static ufs_daddr_t rq_start;
58 1.1.6.2 thorpej static char *rq_buf;
59 1.1.6.2 thorpej
60 1.1.6.2 thorpej if (rq_len) {
61 1.1.6.2 thorpej if (bytelen && blkpos == rq_start + (ssize_t) btodb(rq_len)
62 1.1.6.2 thorpej && buf == rq_buf + rq_len) {
63 1.1.6.2 thorpej rq_len += bytelen;
64 1.1.6.2 thorpej return;
65 1.1.6.2 thorpej } else {
66 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
67 1.1.6.2 thorpej printf("raw_read_queue: read: buf %p, blk %d, len %d\n",
68 1.1.6.2 thorpej rq_buf, rq_start, rq_len);
69 1.1.6.2 thorpej #endif
70 1.1.6.2 thorpej RAW_READ(rq_buf, (unsigned int) rq_start, rq_len);
71 1.1.6.2 thorpej }
72 1.1.6.2 thorpej }
73 1.1.6.2 thorpej rq_buf = buf;
74 1.1.6.2 thorpej rq_start = blkpos;
75 1.1.6.2 thorpej rq_len = bytelen;
76 1.1.6.2 thorpej }
77 1.1.6.2 thorpej
78 1.1.6.2 thorpej #define RAW_READ_QUEUE_INIT() (rq_len = 0)
79 1.1.6.2 thorpej #define RAW_READ_QUEUE_FLUSH() \
80 1.1.6.2 thorpej raw_read_queue((void *) 0, (u_int32_t) 0, (size_t) 0)
81 1.1.6.2 thorpej
82 1.1.6.2 thorpej
83 1.1.6.2 thorpej /*
84 1.1.6.2 thorpej * Read a file, specified by dinode.
85 1.1.6.2 thorpej * No support for holes or (short) symbolic links.
86 1.1.6.2 thorpej */
87 1.1.6.2 thorpej size_t
88 1.1.6.2 thorpej ufs_read(di, buf, off, count)
89 1.1.6.2 thorpej struct dinode *di;
90 1.1.6.2 thorpej void *buf;
91 1.1.6.2 thorpej unsigned off; /* position in block */
92 1.1.6.2 thorpej size_t count;
93 1.1.6.2 thorpej {
94 1.1.6.2 thorpej size_t bsize = fs.bsize;
95 1.1.6.2 thorpej caddr_t b = buf;
96 1.1.6.2 thorpej int i;
97 1.1.6.2 thorpej size_t nread;
98 1.1.6.2 thorpej
99 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
100 1.1.6.2 thorpej printf("ufs_read: off: %d, count %u\n", off, count);
101 1.1.6.2 thorpej #endif
102 1.1.6.2 thorpej if ((size_t) di->di_size < count + off * bsize)
103 1.1.6.2 thorpej count = (size_t) di->di_size - off * bsize;
104 1.1.6.2 thorpej
105 1.1.6.2 thorpej /* FS block size alignment. */
106 1.1.6.2 thorpej nread = count;
107 1.1.6.2 thorpej count = (count + bsize - 1) & ~(bsize - 1);
108 1.1.6.2 thorpej
109 1.1.6.2 thorpej RAW_READ_QUEUE_INIT();
110 1.1.6.2 thorpej
111 1.1.6.2 thorpej /* Read direct blocks. */
112 1.1.6.2 thorpej for ( ; off < NDADDR && count > 0; off++) {
113 1.1.6.2 thorpej #if 0
114 1.1.6.2 thorpej printf("ufs_read: read: blk: %d\n",
115 1.1.6.2 thorpej di->di_db[off] << fs.iblkshift);
116 1.1.6.2 thorpej #endif
117 1.1.6.2 thorpej raw_read_queue(b, di->di_db[off] << fs.iblkshift, bsize);
118 1.1.6.2 thorpej b += bsize;
119 1.1.6.2 thorpej count -= bsize;
120 1.1.6.2 thorpej }
121 1.1.6.2 thorpej off -= NDADDR;
122 1.1.6.2 thorpej
123 1.1.6.2 thorpej /* Read indirect blocks. */
124 1.1.6.2 thorpej for (i = 0; i < NIADDR && count > 0; i++)
125 1.1.6.2 thorpej count = ufs_read_indirect(di->di_ib[i], i, &b, &off, count);
126 1.1.6.2 thorpej
127 1.1.6.2 thorpej RAW_READ_QUEUE_FLUSH();
128 1.1.6.2 thorpej
129 1.1.6.2 thorpej return (size_t) nread;
130 1.1.6.2 thorpej }
131 1.1.6.2 thorpej
132 1.1.6.2 thorpej static int
133 1.1.6.2 thorpej ufs_read_indirect(blk, level, buf, poff, count)
134 1.1.6.2 thorpej ufs_daddr_t blk;
135 1.1.6.2 thorpej int level;
136 1.1.6.2 thorpej caddr_t *buf;
137 1.1.6.2 thorpej unsigned *poff; /* position in block */
138 1.1.6.2 thorpej size_t count;
139 1.1.6.2 thorpej {
140 1.1.6.2 thorpej size_t bsize = fs.bsize;
141 1.1.6.2 thorpej ufs_daddr_t *idbuf = alloca(bsize);
142 1.1.6.2 thorpej unsigned off = *poff;
143 1.1.6.2 thorpej unsigned b;
144 1.1.6.2 thorpej
145 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
146 1.1.6.2 thorpej printf("ufs_read_indirect: off: %d, count %u\n", off, count);
147 1.1.6.2 thorpej #endif
148 1.1.6.2 thorpej if (off) {
149 1.1.6.2 thorpej unsigned subindirsize = 1, indirsize;
150 1.1.6.2 thorpej int i;
151 1.1.6.2 thorpej
152 1.1.6.2 thorpej for (i = level; i > 0; i--)
153 1.1.6.2 thorpej subindirsize *= fs.nindir;
154 1.1.6.2 thorpej indirsize = subindirsize * fs.nindir;
155 1.1.6.2 thorpej if (off >= indirsize) {
156 1.1.6.2 thorpej /* no need to read any data */
157 1.1.6.2 thorpej *poff = off - indirsize;
158 1.1.6.2 thorpej return 0;
159 1.1.6.2 thorpej }
160 1.1.6.2 thorpej
161 1.1.6.2 thorpej b = off / subindirsize;
162 1.1.6.2 thorpej off -= b * subindirsize;
163 1.1.6.2 thorpej *poff = 0;
164 1.1.6.2 thorpej } else
165 1.1.6.2 thorpej b = 0;
166 1.1.6.2 thorpej
167 1.1.6.2 thorpej /* read the indirect block */
168 1.1.6.2 thorpej RAW_READ(idbuf, (unsigned int) blk << fs.iblkshift, bsize);
169 1.1.6.2 thorpej
170 1.1.6.2 thorpej for ( ; b < fs.nindir && count > 0; b++) {
171 1.1.6.2 thorpej if (level)
172 1.1.6.2 thorpej count = ufs_read_indirect(idbuf[b], level - 1, buf, &off, count);
173 1.1.6.2 thorpej else {
174 1.1.6.2 thorpej #if 0
175 1.1.6.2 thorpej printf("ufs_read: read: blk: %d\n",
176 1.1.6.2 thorpej idbuf[b] << fs.iblkshift);
177 1.1.6.2 thorpej #endif
178 1.1.6.2 thorpej raw_read_queue(*buf, idbuf[b] << fs.iblkshift, bsize);
179 1.1.6.2 thorpej *buf += bsize;
180 1.1.6.2 thorpej count -= bsize;
181 1.1.6.2 thorpej }
182 1.1.6.2 thorpej }
183 1.1.6.2 thorpej
184 1.1.6.2 thorpej return count;
185 1.1.6.2 thorpej }
186 1.1.6.2 thorpej
187 1.1.6.2 thorpej /*
188 1.1.6.2 thorpej * look-up fn in directory dirino
189 1.1.6.2 thorpej */
190 1.1.6.2 thorpej ino_t
191 1.1.6.2 thorpej ufs_lookup(dirino, fn)
192 1.1.6.2 thorpej ino_t dirino;
193 1.1.6.2 thorpej const char *fn;
194 1.1.6.2 thorpej {
195 1.1.6.2 thorpej struct dinode dirdi;
196 1.1.6.2 thorpej struct direct *pdir;
197 1.1.6.2 thorpej char *p;
198 1.1.6.2 thorpej
199 1.1.6.2 thorpej if (ufs_get_inode(dirino, &dirdi))
200 1.1.6.2 thorpej return 0;
201 1.1.6.2 thorpej
202 1.1.6.2 thorpej if ((dirdi.di_mode & IFMT) != IFDIR)
203 1.1.6.2 thorpej return 0; /* Not a directory */
204 1.1.6.2 thorpej
205 1.1.6.2 thorpej #if 0
206 1.1.6.2 thorpej p = alloca(((size_t) dirdi.di_size + fs.bsize - 1) & ~(fs.bsize - 1));
207 1.1.6.2 thorpej #else /* simplify calculation to reduce code size */
208 1.1.6.2 thorpej p = alloca((size_t) dirdi.di_size + fs.bsize);
209 1.1.6.2 thorpej #endif
210 1.1.6.2 thorpej ufs_read(&dirdi, p, 0, (size_t) dirdi.di_size);
211 1.1.6.2 thorpej for ( ; pdir = (void *) p, pdir->d_ino; p += pdir->d_reclen) {
212 1.1.6.2 thorpej if (!strcmp(fn, pdir->d_name))
213 1.1.6.2 thorpej return pdir->d_ino;
214 1.1.6.2 thorpej }
215 1.1.6.2 thorpej return 0; /* No such file or directory */
216 1.1.6.2 thorpej }
217 1.1.6.2 thorpej
218 1.1.6.2 thorpej /*
219 1.1.6.2 thorpej * look-up a file in absolute pathname from the root directory
220 1.1.6.2 thorpej */
221 1.1.6.2 thorpej ino_t
222 1.1.6.2 thorpej ufs_lookup_path(path)
223 1.1.6.2 thorpej const char *path;
224 1.1.6.2 thorpej {
225 1.1.6.2 thorpej char fn[MAXNAMLEN + 1];
226 1.1.6.2 thorpej char *p;
227 1.1.6.2 thorpej ino_t ino = ROOTINO;
228 1.1.6.2 thorpej
229 1.1.6.2 thorpej do {
230 1.1.6.2 thorpej while (*path == '/')
231 1.1.6.2 thorpej path++;
232 1.1.6.2 thorpej for (p = fn; *path && *path != '/'; )
233 1.1.6.2 thorpej *p++ = *path++;
234 1.1.6.2 thorpej *p++ = '\0';
235 1.1.6.2 thorpej ino = ufs_lookup(ino, fn);
236 1.1.6.2 thorpej } while (ino && *path);
237 1.1.6.2 thorpej
238 1.1.6.2 thorpej return ino;
239 1.1.6.2 thorpej }
240 1.1.6.2 thorpej
241 1.1.6.2 thorpej #if 0
242 1.1.6.2 thorpej size_t
243 1.1.6.2 thorpej ufs_load_file(buf, dirino, fn)
244 1.1.6.2 thorpej void *buf;
245 1.1.6.2 thorpej ino_t dirino;
246 1.1.6.2 thorpej const char *fn;
247 1.1.6.2 thorpej {
248 1.1.6.2 thorpej size_t cnt;
249 1.1.6.2 thorpej struct dinode dinode;
250 1.1.6.2 thorpej
251 1.1.6.2 thorpej if (ufs_fn_inode(dirino, fn, &dinode))
252 1.1.6.2 thorpej return (unsigned) 0;
253 1.1.6.2 thorpej cnt = ufs_read(&dinode, buf, 0, (size_t) dinode.di_size);
254 1.1.6.2 thorpej
255 1.1.6.2 thorpej return cnt;
256 1.1.6.2 thorpej }
257 1.1.6.2 thorpej #endif
258 1.1.6.2 thorpej
259 1.1.6.2 thorpej int
260 1.1.6.2 thorpej ufs_init()
261 1.1.6.2 thorpej {
262 1.1.6.2 thorpej return 1
263 1.1.6.2 thorpej #ifdef USE_FFS
264 1.1.6.2 thorpej && try_ffs()
265 1.1.6.2 thorpej #endif
266 1.1.6.2 thorpej #ifdef USE_LFS
267 1.1.6.2 thorpej && try_lfs()
268 1.1.6.2 thorpej #endif
269 1.1.6.2 thorpej ;
270 1.1.6.2 thorpej }
271 1.1.6.2 thorpej
272 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
273 1.1.6.2 thorpej void
274 1.1.6.2 thorpej ufs_list_dir(dirino)
275 1.1.6.2 thorpej ino_t dirino;
276 1.1.6.2 thorpej {
277 1.1.6.2 thorpej struct dinode dirdi;
278 1.1.6.2 thorpej struct direct *pdir;
279 1.1.6.2 thorpej char *p;
280 1.1.6.2 thorpej
281 1.1.6.2 thorpej if (ufs_get_inode(dirino, &dirdi))
282 1.1.6.2 thorpej errx(1, "ino = %d: not found", dirino);
283 1.1.6.2 thorpej
284 1.1.6.2 thorpej p = alloca(((size_t) dirdi.di_size + fs.bsize - 1) & ~(fs.bsize - 1));
285 1.1.6.2 thorpej ufs_read(&dirdi, p, 0, (size_t) dirdi.di_size);
286 1.1.6.2 thorpej for ( ; pdir = (void *) p, pdir->d_ino; p += pdir->d_reclen) {
287 1.1.6.2 thorpej printf("%6d %s\n", pdir->d_ino, pdir->d_name);
288 1.1.6.2 thorpej }
289 1.1.6.2 thorpej }
290 1.1.6.2 thorpej #endif
291 1.1.6.2 thorpej
292 1.1.6.2 thorpej #ifdef DEBUG_WITH_STDIO
293 1.1.6.2 thorpej int
294 1.1.6.2 thorpej main(argc, argv)
295 1.1.6.2 thorpej int argc __attribute__((unused));
296 1.1.6.2 thorpej char *argv[];
297 1.1.6.2 thorpej {
298 1.1.6.2 thorpej struct dinode dinode;
299 1.1.6.2 thorpej
300 1.1.6.2 thorpej if ((fd = open(argv[1], O_RDONLY)) < 0)
301 1.1.6.2 thorpej err(1, "open: %s", argv[1]);
302 1.1.6.2 thorpej
303 1.1.6.2 thorpej if (ufs_init())
304 1.1.6.2 thorpej errx(1, "%s: unknown fs", argv[1]);
305 1.1.6.2 thorpej
306 1.1.6.2 thorpej #if 1
307 1.1.6.2 thorpej ufs_list_dir(ROOTINO);
308 1.1.6.2 thorpej {
309 1.1.6.2 thorpej void *p;
310 1.1.6.2 thorpej size_t cnt;
311 1.1.6.2 thorpej ino_t ino;
312 1.1.6.2 thorpej
313 1.1.6.2 thorpej if ((ino = ufs_lookup_path(argv[2])) == 0)
314 1.1.6.2 thorpej errx(1, "%s: not found", argv[2]);
315 1.1.6.2 thorpej ufs_get_inode(ino, &dinode);
316 1.1.6.2 thorpej p = malloc(((size_t) dinode.di_size + fs.bsize - 1) & ~(fs.bsize - 1));
317 1.1.6.2 thorpej cnt = ufs_read(&dinode, p, 0, (size_t) dinode.di_size);
318 1.1.6.2 thorpej write(3, p, cnt);
319 1.1.6.2 thorpej free(p);
320 1.1.6.2 thorpej }
321 1.1.6.2 thorpej #endif
322 1.1.6.2 thorpej
323 1.1.6.2 thorpej return 0;
324 1.1.6.2 thorpej }
325 1.1.6.2 thorpej #endif
326