|
|
1.1 root 1: /* fsys_jfs.c - an implementation for the IBM JFS file system */
2: /*
3: * GRUB -- GRand Unified Bootloader
4: * Copyright (C) 2001,2002 Free Software Foundation, Inc.
5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License as published by
8: * the Free Software Foundation; either version 2 of the License, or
9: * (at your option) any later version.
10: *
11: * This program is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: * GNU General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with this program; if not, write to the Free Software
18: * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19: * MA 02110-1301, USA.
20: */
21:
22: #ifdef FSYS_JFS
23:
24: #include "shared.h"
25: #include "filesys.h"
26: #include "jfs.h"
27:
28: #define MAX_LINK_COUNT 8
29:
30: #define DTTYPE_INLINE 0
31: #define DTTYPE_PAGE 1
32:
33: struct jfs_info
34: {
35: int bsize;
36: int l2bsize;
37: int bdlog;
38: int xindex;
39: int xlastindex;
40: int sindex;
41: int slastindex;
42: int de_index;
43: int dttype;
44: xad_t *xad;
45: ldtentry_t *de;
46: };
47:
48: static struct jfs_info jfs;
49:
50: #define xtpage ((xtpage_t *)FSYS_BUF)
51: #define dtpage ((dtpage_t *)((char *)FSYS_BUF + 4096))
52: #define fileset ((dinode_t *)((char *)FSYS_BUF + 8192))
53: #define inode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t)))
54: #define dtroot ((dtroot_t *)(&inode->di_btroot))
55:
56: static ldtentry_t de_always[2] = {
57: {1, -1, 2, {'.', '.'}, 0},
58: {1, -1, 1, {'.'}, 0}
59: };
60:
61: static int
62: isinxt (s64 key, s64 offset, s64 len)
63: {
64: return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
65: }
66:
67: static xad_t *
68: first_extent (dinode_t *di)
69: {
70: xtpage_t *xtp;
71:
72: jfs.xindex = 2;
73: xtp = (xtpage_t *)&di->di_btroot;
74: jfs.xad = &xtp->xad[2];
75: if (xtp->header.flag & BT_LEAF) {
76: jfs.xlastindex = xtp->header.nextindex;
77: } else {
78: do {
79: devread (addressXAD (jfs.xad) << jfs.bdlog, 0,
80: sizeof(xtpage_t), (char *)xtpage);
81: jfs.xad = &xtpage->xad[2];
82: } while (!(xtpage->header.flag & BT_LEAF));
83: jfs.xlastindex = xtpage->header.nextindex;
84: }
85:
86: return jfs.xad;
87: }
88:
89: static xad_t *
90: next_extent (void)
91: {
92: if (++jfs.xindex < jfs.xlastindex) {
93: } else if (xtpage->header.next) {
94: devread (xtpage->header.next << jfs.bdlog, 0,
95: sizeof(xtpage_t), (char *)xtpage);
96: jfs.xlastindex = xtpage->header.nextindex;
97: jfs.xindex = XTENTRYSTART;
98: jfs.xad = &xtpage->xad[XTENTRYSTART];
99: } else {
100: return NULL;
101: }
102: return ++jfs.xad;
103: }
104:
105:
106: static void
107: di_read (u32 inum, dinode_t *di)
108: {
109: s64 key;
110: u32 xd, ioffset;
111: s64 offset;
112: xad_t *xad;
113: pxd_t pxd;
114:
115: key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize;
116: xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT;
117: ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE;
118: xad = first_extent (fileset);
119: do {
120: offset = offsetXAD (xad);
121: if (isinxt (key, offset, lengthXAD (xad))) {
122: devread ((addressXAD (xad) + key - offset) << jfs.bdlog,
123: 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd);
124: devread (addressPXD (&pxd) << jfs.bdlog,
125: ioffset, DISIZE, (char *)di);
126: break;
127: }
128: } while ((xad = next_extent ()));
129: }
130:
131: static ldtentry_t *
132: next_dentry (void)
133: {
134: ldtentry_t *de;
135: s8 *stbl;
136:
137: if (jfs.dttype == DTTYPE_INLINE) {
138: if (jfs.sindex < jfs.slastindex) {
139: return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]];
140: }
141: } else {
142: de = (ldtentry_t *)dtpage->slot;
143: stbl = (s8 *)&de[(int)dtpage->header.stblindex];
144: if (jfs.sindex < jfs.slastindex) {
145: return &de[(int)stbl[jfs.sindex++]];
146: } else if (dtpage->header.next) {
147: devread (dtpage->header.next << jfs.bdlog, 0,
148: sizeof(dtpage_t), (char *)dtpage);
149: jfs.slastindex = dtpage->header.nextindex;
150: jfs.sindex = 1;
151: return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]];
152: }
153: }
154:
155: return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL;
156: }
157:
158: static ldtentry_t *
159: first_dentry (void)
160: {
161: dtroot_t *dtr;
162: pxd_t *xd;
163: idtentry_t *de;
164:
165: dtr = (dtroot_t *)&inode->di_btroot;
166: jfs.sindex = 0;
167: jfs.de_index = 0;
168:
169: de_always[0].inumber = inode->di_parent;
170: de_always[1].inumber = inode->di_number;
171: if (dtr->header.flag & BT_LEAF) {
172: jfs.dttype = DTTYPE_INLINE;
173: jfs.slastindex = dtr->header.nextindex;
174: } else {
175: de = (idtentry_t *)dtpage->slot;
176: jfs.dttype = DTTYPE_PAGE;
177: xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd;
178: for (;;) {
179: devread (addressPXD (xd) << jfs.bdlog, 0,
180: sizeof(dtpage_t), (char *)dtpage);
181: if (dtpage->header.flag & BT_LEAF)
182: break;
183: xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd;
184: }
185: jfs.slastindex = dtpage->header.nextindex;
186: }
187:
188: return next_dentry ();
189: }
190:
191:
192: static dtslot_t *
193: next_dslot (int next)
194: {
195: return (jfs.dttype == DTTYPE_INLINE)
196: ? (dtslot_t *)&dtroot->slot[next]
197: : &((dtslot_t *)dtpage->slot)[next];
198: }
199:
200: static void
201: uni2ansi (UniChar *uni, char *ansi, int len)
202: {
203: for (; len; len--, uni++)
204: *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni;
205: }
206:
207: int
208: jfs_mount (void)
209: {
210: struct jfs_superblock super;
211:
212: if (part_length < MINJFS >> SECTOR_BITS
213: || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
214: sizeof(struct jfs_superblock), (char *)&super)
215: || (super.s_magic != JFS_MAGIC)
216: || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I,
217: 0, DISIZE, (char*)fileset)) {
218: return 0;
219: }
220:
221: jfs.bsize = super.s_bsize;
222: jfs.l2bsize = super.s_l2bsize;
223: jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
224:
225: return 1;
226: }
227:
228: int
229: jfs_read (char *buf, int len)
230: {
231: xad_t *xad;
232: s64 endofprev, endofcur;
233: s64 offset, xadlen;
234: int toread, startpos, endpos;
235:
236: startpos = filepos;
237: endpos = filepos + len;
238: endofprev = (1ULL << 62) - 1;
239: xad = first_extent (inode);
240: do {
241: offset = offsetXAD (xad);
242: xadlen = lengthXAD (xad);
243: if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) {
244: endofcur = (offset + xadlen) << jfs.l2bsize;
245: toread = (endofcur >= endpos)
246: ? len : (endofcur - filepos);
247:
248: disk_read_func = disk_read_hook;
249: devread (addressXAD (xad) << jfs.bdlog,
250: filepos - (offset << jfs.l2bsize), toread, buf);
251: disk_read_func = NULL;
252:
253: buf += toread;
254: len -= toread;
255: filepos += toread;
256: } else if (offset > endofprev) {
257: toread = ((offset << jfs.l2bsize) >= endpos)
258: ? len : ((offset - endofprev) << jfs.l2bsize);
259: len -= toread;
260: filepos += toread;
261: for (; toread; toread--) {
262: *buf++ = 0;
263: }
264: continue;
265: }
266: endofprev = offset + xadlen;
267: xad = next_extent ();
268: } while (len > 0 && xad);
269:
270: return filepos - startpos;
271: }
272:
273: int
274: jfs_dir (char *dirname)
275: {
276: char *ptr, *rest, ch;
277: ldtentry_t *de;
278: dtslot_t *ds;
279: u32 inum, parent_inum;
280: s64 di_size;
281: u32 di_mode;
282: int namlen, cmp, n, link_count;
283: char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX];
284:
285: parent_inum = inum = ROOT_I;
286: link_count = 0;
287: for (;;) {
288: di_read (inum, inode);
289: di_size = inode->di_size;
290: di_mode = inode->di_mode;
291:
292: if ((di_mode & IFMT) == IFLNK) {
293: if (++link_count > MAX_LINK_COUNT) {
294: errnum = ERR_SYMLINK_LOOP;
295: return 0;
296: }
297: if (di_size < (di_mode & INLINEEA ? 256 : 128)) {
298: grub_memmove (linkbuf, inode->di_fastsymlink, di_size);
299: n = di_size;
300: } else if (di_size < JFS_PATH_MAX - 1) {
301: filepos = 0;
302: filemax = di_size;
303: n = jfs_read (linkbuf, filemax);
304: } else {
305: errnum = ERR_FILELENGTH;
306: return 0;
307: }
308:
309: inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum;
310: while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++));
311: linkbuf[n] = 0;
312: dirname = linkbuf;
313: continue;
314: }
315:
316: if (!*dirname || isspace (*dirname)) {
317: if ((di_mode & IFMT) != IFREG) {
318: errnum = ERR_BAD_FILETYPE;
319: return 0;
320: }
321: filepos = 0;
322: filemax = di_size;
323: return 1;
324: }
325:
326: if ((di_mode & IFMT) != IFDIR) {
327: errnum = ERR_BAD_FILETYPE;
328: return 0;
329: }
330:
331: for (; *dirname == '/'; dirname++);
332:
333: for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
334: *rest = 0;
335:
336: de = first_dentry ();
337: for (;;) {
338: namlen = de->namlen;
339: if (de->next == -1) {
340: uni2ansi (de->name, namebuf, namlen);
341: namebuf[namlen] = 0;
342: } else {
343: uni2ansi (de->name, namebuf, DTLHDRDATALEN);
344: ptr = namebuf;
345: ptr += DTLHDRDATALEN;
346: namlen -= DTLHDRDATALEN;
347: ds = next_dslot (de->next);
348: while (ds->next != -1) {
349: uni2ansi (ds->name, ptr, DTSLOTDATALEN);
350: ptr += DTSLOTDATALEN;
351: namlen -= DTSLOTDATALEN;
352: ds = next_dslot (ds->next);
353: }
354: uni2ansi (ds->name, ptr, namlen);
355: ptr += namlen;
356: *ptr = 0;
357: }
358:
359: cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
360: #ifndef STAGE1_5
361: if (print_possibilities && ch != '/'
362: && cmp <= 0) {
363: if (print_possibilities > 0)
364: print_possibilities = -print_possibilities;
365: print_a_completion (namebuf);
366: } else
367: #endif
368: if (cmp == 0) {
369: parent_inum = inum;
370: inum = de->inumber;
371: *(dirname = rest) = ch;
372: break;
373: }
374: de = next_dentry ();
375: if (de == NULL) {
376: if (print_possibilities < 0)
377: return 1;
378:
379: errnum = ERR_FILE_NOT_FOUND;
380: *rest = ch;
381: return 0;
382: }
383: }
384: }
385: }
386:
387: int
388: jfs_embed (int *start_sector, int needed_sectors)
389: {
390: struct jfs_superblock super;
391:
392: if (needed_sectors > 63
393: || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
394: sizeof (struct jfs_superblock),
395: (char *)&super)
396: || (super.s_magic != JFS_MAGIC)) {
397: return 0;
398: }
399:
400: *start_sector = 1;
401: return 1;
402: }
403:
404: #endif /* FSYS_JFS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.