Annotation of qemu/roms/openbios/fs/grubfs/fsys_jfs.c, revision 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.