|
|
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.