1 /* fsys_jfs.c - an implementation for the IBM JFS file system */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2001,2002 Free Software Foundation, Inc.
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.
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.
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,
28 #define MAX_LINK_COUNT 8
30 #define DTTYPE_INLINE 0
48 static struct jfs_info jfs;
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))
56 static ldtentry_t de_always[2] = {
57 {1, -1, 2, {'.', '.'}, 0},
62 isinxt (s64 key, s64 offset, s64 len)
64 return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
68 first_extent (dinode_t *di)
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;
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;
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];
107 di_read (u32 inum, dinode_t *di)
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);
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);
128 } while ((xad = next_extent ()));
137 if (jfs.dttype == DTTYPE_INLINE) {
138 if (jfs.sindex < jfs.slastindex) {
139 return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]];
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;
151 return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]];
155 return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL;
165 dtr = (dtroot_t *)&inode->di_btroot;
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;
175 de = (idtentry_t *)dtpage->slot;
176 jfs.dttype = DTTYPE_PAGE;
177 xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd;
179 devread (addressPXD (xd) << jfs.bdlog, 0,
180 sizeof(dtpage_t), (char *)dtpage);
181 if (dtpage->header.flag & BT_LEAF)
183 xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd;
185 jfs.slastindex = dtpage->header.nextindex;
188 return next_dentry ();
193 next_dslot (int next)
195 return (jfs.dttype == DTTYPE_INLINE)
196 ? (dtslot_t *)&dtroot->slot[next]
197 : &((dtslot_t *)dtpage->slot)[next];
201 uni2ansi (UniChar *uni, char *ansi, int len)
203 for (; len; len--, uni++)
204 *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni;
210 struct jfs_superblock super;
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)) {
221 jfs.bsize = super.s_bsize;
222 jfs.l2bsize = super.s_l2bsize;
223 jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
229 jfs_read (char *buf, int len)
232 s64 endofprev, endofcur;
234 int toread, startpos, endpos;
237 endpos = filepos + len;
238 endofprev = (1ULL << 62) - 1;
239 xad = first_extent (inode);
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);
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;
256 } else if (offset > endofprev) {
257 toread = ((offset << jfs.l2bsize) >= endpos)
258 ? len : ((offset - endofprev) << jfs.l2bsize);
261 for (; toread; toread--) {
266 endofprev = offset + xadlen;
267 xad = next_extent ();
268 } while (len > 0 && xad);
270 return filepos - startpos;
274 jfs_dir (char *dirname)
276 char *ptr, *rest, ch;
279 u32 inum, parent_inum;
282 int namlen, cmp, n, link_count;
283 char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX];
285 parent_inum = inum = ROOT_I;
288 di_read (inum, inode);
289 di_size = inode->di_size;
290 di_mode = inode->di_mode;
292 if ((di_mode & IFMT) == IFLNK) {
293 if (++link_count > MAX_LINK_COUNT) {
294 errnum = ERR_SYMLINK_LOOP;
297 if (di_size < (di_mode & INLINEEA ? 256 : 128)) {
298 grub_memmove (linkbuf, inode->di_fastsymlink, di_size);
300 } else if (di_size < JFS_PATH_MAX - 1) {
303 n = jfs_read (linkbuf, filemax);
305 errnum = ERR_FILELENGTH;
309 inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum;
310 while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++));
316 if (!*dirname || isspace (*dirname)) {
317 if ((di_mode & IFMT) != IFREG) {
318 errnum = ERR_BAD_FILETYPE;
326 if ((di_mode & IFMT) != IFDIR) {
327 errnum = ERR_BAD_FILETYPE;
331 for (; *dirname == '/'; dirname++);
333 for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
336 de = first_dentry ();
339 if (de->next == -1) {
340 uni2ansi (de->name, namebuf, namlen);
343 uni2ansi (de->name, namebuf, DTLHDRDATALEN);
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);
354 uni2ansi (ds->name, ptr, namlen);
359 cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
361 if (print_possibilities && ch != '/'
363 if (print_possibilities > 0)
364 print_possibilities = -print_possibilities;
365 print_a_completion (namebuf);
371 *(dirname = rest) = ch;
376 if (print_possibilities < 0)
379 errnum = ERR_FILE_NOT_FOUND;
388 jfs_embed (int *start_sector, int needed_sectors)
390 struct jfs_superblock super;
392 if (needed_sectors > 63
393 || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
394 sizeof (struct jfs_superblock),
396 || (super.s_magic != JFS_MAGIC)) {
404 #endif /* FSYS_JFS */