Annotation of qemu/roms/openbios/fs/grubfs/fsys_jfs.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.