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

1.1       root        1: /* fsys_xfs.c - an implementation for the SGI XFS 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_XFS
                     23: 
                     24: #include "shared.h"
                     25: #include "filesys.h"
                     26: #include "xfs.h"
                     27: 
                     28: #define MAX_LINK_COUNT 8
                     29: 
                     30: typedef struct xad {
                     31:        xfs_fileoff_t offset;
                     32:        xfs_fsblock_t start;
                     33:        xfs_filblks_t len;
                     34: } xad_t;
                     35: 
                     36: struct xfs_info {
                     37:        int bsize;
                     38:        int dirbsize;
                     39:        int isize;
                     40:        unsigned int agblocks;
                     41:        int bdlog;
                     42:        int blklog;
                     43:        int inopblog;
                     44:        int agblklog;
                     45:        int agnolog;
                     46:        unsigned int nextents;
                     47:        xfs_daddr_t next;
                     48:        xfs_daddr_t daddr;
                     49:        xfs_dablk_t forw;
                     50:        xfs_dablk_t dablk;
                     51:        xfs_bmbt_rec_32_t *xt;
                     52:        xfs_bmbt_ptr_t ptr0;
                     53:        int btnode_ptr0_off;
                     54:        int i8param;
                     55:        int dirpos;
                     56:        int dirmax;
                     57:        int blkoff;
                     58:        int fpos;
                     59:        xfs_ino_t rootino;
                     60: };
                     61: 
                     62: static struct xfs_info xfs;
                     63: 
                     64: #define dirbuf         ((char *)FSYS_BUF)
                     65: #define filebuf                ((char *)FSYS_BUF + 4096)
                     66: #define inode          ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
                     67: #define icore          (inode->di_core)
                     68: 
                     69: #define        mask32lo(n)     (((__uint32_t)1 << (n)) - 1)
                     70: 
                     71: #define        XFS_INO_MASK(k)         ((__uint32_t)((1ULL << (k)) - 1))
                     72: #define        XFS_INO_OFFSET_BITS     xfs.inopblog
                     73: #define        XFS_INO_AGBNO_BITS      xfs.agblklog
                     74: #define        XFS_INO_AGINO_BITS      (xfs.agblklog + xfs.inopblog)
                     75: #define        XFS_INO_AGNO_BITS       xfs.agnolog
                     76: 
                     77: static inline xfs_agblock_t
                     78: agino2agbno (xfs_agino_t agino)
                     79: {
                     80:        return agino >> XFS_INO_OFFSET_BITS;
                     81: }
                     82: 
                     83: static inline xfs_agnumber_t
                     84: ino2agno (xfs_ino_t ino)
                     85: {
                     86:        return ino >> XFS_INO_AGINO_BITS;
                     87: }
                     88: 
                     89: static inline xfs_agino_t
                     90: ino2agino (xfs_ino_t ino)
                     91: {
                     92:        return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
                     93: }
                     94: 
                     95: static inline int
                     96: ino2offset (xfs_ino_t ino)
                     97: {
                     98:        return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
                     99: }
                    100: 
                    101: static inline __uint16_t
                    102: le16 (__uint16_t x)
                    103: {
                    104: #ifdef __i386__
                    105:        __asm__("xchgb %b0,%h0" \
                    106:                : "=q" (x) \
                    107:                :  "0" (x)); \
                    108:                return x;
                    109: #else
                    110:        return __be16_to_cpu(x);
                    111: #endif
                    112: }
                    113: 
                    114: static inline __uint32_t
                    115: le32 (__uint32_t x)
                    116: {
                    117: #ifdef __i386__
                    118: #if 1
                    119:         /* 386 doesn't have bswap. So what. */
                    120:        __asm__("bswap %0" : "=r" (x) : "0" (x));
                    121: #else
                    122:        /* This is slower but this works on all x86 architectures.  */
                    123:        __asm__("xchgb %b0, %h0" \
                    124:                "\n\troll $16, %0" \
                    125:                "\n\txchgb %b0, %h0" \
                    126:                : "=q" (x) : "0" (x));
                    127: #endif
                    128:        return x;
                    129: #else
                    130:        return __be32_to_cpu(x);
                    131: #endif
                    132: }
                    133: 
                    134: static inline __uint64_t
                    135: le64 (__uint64_t x)
                    136: {
                    137:        __uint32_t h = x >> 32;
                    138:         __uint32_t l = x & ((1ULL<<32)-1);
                    139:         return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h)));
                    140: }
                    141: 
                    142: 
                    143: static xfs_fsblock_t
                    144: xt_start (xfs_bmbt_rec_32_t *r)
                    145: {
                    146:        return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
                    147:               (((xfs_fsblock_t)le32 (r->l2)) << 11) |
                    148:               (((xfs_fsblock_t)le32 (r->l3)) >> 21);
                    149: }
                    150: 
                    151: static xfs_fileoff_t
                    152: xt_offset (xfs_bmbt_rec_32_t *r)
                    153: {
                    154:        return (((xfs_fileoff_t)le32 (r->l0) &
                    155:                mask32lo(31)) << 23) |
                    156:                (((xfs_fileoff_t)le32 (r->l1)) >> 9);
                    157: }
                    158: 
                    159: static xfs_filblks_t
                    160: xt_len (xfs_bmbt_rec_32_t *r)
                    161: {
                    162:        return le32(r->l3) & mask32lo(21);
                    163: }
                    164: 
                    165: static inline int
                    166: xfs_highbit32(__uint32_t v)
                    167: {
                    168:        int i;
                    169: 
                    170:        if (--v) {
                    171:                for (i = 0; i < 31; i++, v >>= 1) {
                    172:                        if (v == 0)
                    173:                                return i;
                    174:                }
                    175:        }
                    176:        return 0;
                    177: }
                    178: 
                    179: static int
                    180: isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
                    181: {
                    182:        return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
                    183: }
                    184: 
                    185: static xfs_daddr_t
                    186: agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
                    187: {
                    188:        return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
                    189: }
                    190: 
                    191: static xfs_daddr_t
                    192: fsb2daddr (xfs_fsblock_t fsbno)
                    193: {
                    194:        return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
                    195:                         (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
                    196: }
                    197: 
                    198: #undef offsetof
                    199: #define offsetof(t,m)  ((long)&(((t *)0)->m))
                    200: 
                    201: static inline int
                    202: btroot_maxrecs (void)
                    203: {
                    204:        int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
                    205: 
                    206:        return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
                    207:                (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
                    208: }
                    209: 
                    210: static int
                    211: di_read (xfs_ino_t ino)
                    212: {
                    213:        xfs_agino_t agino;
                    214:        xfs_agnumber_t agno;
                    215:        xfs_agblock_t agbno;
                    216:        xfs_daddr_t daddr;
                    217:        int offset;
                    218: 
                    219:        agno = ino2agno (ino);
                    220:        agino = ino2agino (ino);
                    221:        agbno = agino2agbno (agino);
                    222:        offset = ino2offset (ino);
                    223:        daddr = agb2daddr (agno, agbno);
                    224: 
                    225:        devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
                    226: 
                    227:        xfs.ptr0 = *(xfs_bmbt_ptr_t *)
                    228:                    (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
                    229:                    + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
                    230: 
                    231:        return 1;
                    232: }
                    233: 
                    234: static void
                    235: init_extents (void)
                    236: {
                    237:        xfs_bmbt_ptr_t ptr0;
                    238:        xfs_btree_lblock_t h;
                    239: 
                    240:        switch (icore.di_format) {
                    241:        case XFS_DINODE_FMT_EXTENTS:
                    242:                xfs.xt = inode->di_u.di_bmx;
                    243:                xfs.nextents = le32 (icore.di_nextents);
                    244:                break;
                    245:        case XFS_DINODE_FMT_BTREE:
                    246:                ptr0 = xfs.ptr0;
                    247:                for (;;) {
                    248:                        xfs.daddr = fsb2daddr (le64(ptr0));
                    249:                        devread (xfs.daddr, 0,
                    250:                                 sizeof(xfs_btree_lblock_t), (char *)&h);
                    251:                        if (!h.bb_level) {
                    252:                                xfs.nextents = le16(h.bb_numrecs);
                    253:                                xfs.next = fsb2daddr (le64(h.bb_rightsib));
                    254:                                xfs.fpos = sizeof(xfs_btree_block_t);
                    255:                                return;
                    256:                        }
                    257:                        devread (xfs.daddr, xfs.btnode_ptr0_off,
                    258:                                 sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
                    259:                }
                    260:        }
                    261: }
                    262: 
                    263: static xad_t *
                    264: next_extent (void)
                    265: {
                    266:        static xad_t xad;
                    267: 
                    268:        switch (icore.di_format) {
                    269:        case XFS_DINODE_FMT_EXTENTS:
                    270:                if (xfs.nextents == 0)
                    271:                        return NULL;
                    272:                break;
                    273:        case XFS_DINODE_FMT_BTREE:
                    274:                if (xfs.nextents == 0) {
                    275:                        xfs_btree_lblock_t h;
                    276:                        if (xfs.next == 0)
                    277:                                return NULL;
                    278:                        xfs.daddr = xfs.next;
                    279:                        devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
                    280:                        xfs.nextents = le16(h.bb_numrecs);
                    281:                        xfs.next = fsb2daddr (le64(h.bb_rightsib));
                    282:                        xfs.fpos = sizeof(xfs_btree_block_t);
                    283:                }
                    284:                /* Yeah, I know that's slow, but I really don't care */
                    285:                devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
                    286:                xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
                    287:                xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
                    288:        }
                    289:        xad.offset = xt_offset (xfs.xt);
                    290:        xad.start = xt_start (xfs.xt);
                    291:        xad.len = xt_len (xfs.xt);
                    292:        ++xfs.xt;
                    293:        --xfs.nextents;
                    294: 
                    295:        return &xad;
                    296: }
                    297: 
                    298: /*
                    299:  * Name lies - the function reads only first 100 bytes
                    300:  */
                    301: static void
                    302: xfs_dabread (void)
                    303: {
                    304:        xad_t *xad;
                    305:        xfs_fileoff_t offset;;
                    306: 
                    307:        init_extents ();
                    308:        while ((xad = next_extent ())) {
                    309:                offset = xad->offset;
                    310:                if (isinxt (xfs.dablk, offset, xad->len)) {
                    311:                        devread (fsb2daddr (xad->start + xfs.dablk - offset),
                    312:                                 0, 100, dirbuf);
                    313:                        break;
                    314:                }
                    315:        }
                    316: }
                    317: 
                    318: static inline xfs_ino_t
                    319: sf_ino (char *sfe, int namelen)
                    320: {
                    321:        void *p = sfe + namelen + 3;
                    322: 
                    323:        return (xfs.i8param == 0)
                    324:                ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p);
                    325: }
                    326: 
                    327: static inline xfs_ino_t
                    328: sf_parent_ino (void)
                    329: {
                    330:        return (xfs.i8param == 0)
                    331:                ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
                    332:                : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
                    333: }
                    334: 
                    335: static inline int
                    336: roundup8 (int n)
                    337: {
                    338:        return ((n+7)&~7);
                    339: }
                    340: 
                    341: static char *
                    342: next_dentry (xfs_ino_t *ino)
                    343: {
                    344:        int namelen = 1;
                    345:        int toread;
                    346:         static char *usual[2];
                    347:        static xfs_dir2_sf_entry_t *sfe;
                    348:         char *name;
                    349: 
                    350:         if (!usual[0]) {
                    351:             usual[0] = strdup(".");
                    352:             usual[1] = strdup("..");
                    353:         }
                    354:         name = usual[0];
                    355: 
                    356:        if (xfs.dirpos >= xfs.dirmax) {
                    357:                if (xfs.forw == 0)
                    358:                        return NULL;
                    359:                xfs.dablk = xfs.forw;
                    360:                xfs_dabread ();
                    361: #define h      ((xfs_dir2_leaf_hdr_t *)dirbuf)
                    362:                xfs.dirmax = le16 (h->count) - le16 (h->stale);
                    363:                xfs.forw = le32 (h->info.forw);
                    364: #undef h
                    365:                xfs.dirpos = 0;
                    366:        }
                    367: 
                    368:        switch (icore.di_format) {
                    369:        case XFS_DINODE_FMT_LOCAL:
                    370:                switch (xfs.dirpos) {
                    371:                case -2:
                    372:                        *ino = 0;
                    373:                        break;
                    374:                case -1:
                    375:                        *ino = sf_parent_ino ();
                    376:                        ++name;
                    377:                        ++namelen;
                    378:                        sfe = (xfs_dir2_sf_entry_t *)
                    379:                                (inode->di_u.di_c
                    380:                                 + sizeof(xfs_dir2_sf_hdr_t)
                    381:                                 - xfs.i8param);
                    382:                        break;
                    383:                default:
                    384:                        namelen = sfe->namelen;
                    385:                        *ino = sf_ino ((char *)sfe, namelen);
                    386:                        name = (char *)sfe->name;
                    387:                        sfe = (xfs_dir2_sf_entry_t *)
                    388:                                  ((char *)sfe + namelen + 11 - xfs.i8param);
                    389:                }
                    390:                break;
                    391:        case XFS_DINODE_FMT_BTREE:
                    392:        case XFS_DINODE_FMT_EXTENTS:
                    393: #define dau    ((xfs_dir2_data_union_t *)dirbuf)
                    394:                for (;;) {
                    395:                        if (xfs.blkoff >= xfs.dirbsize) {
                    396:                                xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
                    397:                                filepos &= ~(xfs.dirbsize - 1);
                    398:                                filepos |= xfs.blkoff;
                    399:                        }
                    400:                        xfs_read (dirbuf, 4);
                    401:                        xfs.blkoff += 4;
                    402:                        if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
                    403:                                toread = roundup8 (le16(dau->unused.length)) - 4;
                    404:                                xfs.blkoff += toread;
                    405:                                filepos += toread;
                    406:                                continue;
                    407:                        }
                    408:                        break;
                    409:                }
                    410:                xfs_read ((char *)dirbuf + 4, 5);
                    411:                *ino = le64 (dau->entry.inumber);
                    412:                namelen = dau->entry.namelen;
                    413: #undef dau
                    414:                toread = roundup8 (namelen + 11) - 9;
                    415:                xfs_read (dirbuf, toread);
                    416:                name = (char *)dirbuf;
                    417:                xfs.blkoff += toread + 5;
                    418:        }
                    419:        ++xfs.dirpos;
                    420:        name[namelen] = 0;
                    421: 
                    422:        return name;
                    423: }
                    424: 
                    425: static char *
                    426: first_dentry (xfs_ino_t *ino)
                    427: {
                    428:        xfs.forw = 0;
                    429:        switch (icore.di_format) {
                    430:        case XFS_DINODE_FMT_LOCAL:
                    431:                xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
                    432:                xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
                    433:                xfs.dirpos = -2;
                    434:                break;
                    435:        case XFS_DINODE_FMT_EXTENTS:
                    436:        case XFS_DINODE_FMT_BTREE:
                    437:                filepos = 0;
                    438:                xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
                    439:                if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
                    440: #define tail           ((xfs_dir2_block_tail_t *)dirbuf)
                    441:                        filepos = xfs.dirbsize - sizeof(*tail);
                    442:                        xfs_read (dirbuf, sizeof(*tail));
                    443:                        xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
                    444: #undef tail
                    445:                } else {
                    446:                        xfs.dablk = (1ULL << 35) >> xfs.blklog;
                    447: #define h              ((xfs_dir2_leaf_hdr_t *)dirbuf)
                    448: #define n              ((xfs_da_intnode_t *)dirbuf)
                    449:                        for (;;) {
                    450:                                xfs_dabread ();
                    451:                                if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
                    452:                                    || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
                    453:                                        xfs.dirmax = le16 (h->count) - le16 (h->stale);
                    454:                                        xfs.forw = le32 (h->info.forw);
                    455:                                        break;
                    456:                                }
                    457:                                xfs.dablk = le32 (n->btree[0].before);
                    458:                        }
                    459: #undef n
                    460: #undef h
                    461:                }
                    462:                xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
                    463:                filepos = xfs.blkoff;
                    464:                xfs.dirpos = 0;
                    465:        }
                    466:        return next_dentry (ino);
                    467: }
                    468: 
                    469: int
                    470: xfs_mount (void)
                    471: {
                    472:        xfs_sb_t super;
                    473: 
                    474:        if (!devread (0, 0, sizeof(super), (char *)&super)
                    475:            || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
                    476:            || ((le16(super.sb_versionnum)
                    477:                & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
                    478:                return 0;
                    479:        }
                    480: 
                    481:        xfs.bsize = le32 (super.sb_blocksize);
                    482:        xfs.blklog = super.sb_blocklog;
                    483:        xfs.bdlog = xfs.blklog - SECTOR_BITS;
                    484:        xfs.rootino = le64 (super.sb_rootino);
                    485:        xfs.isize = le16 (super.sb_inodesize);
                    486:        xfs.agblocks = le32 (super.sb_agblocks);
                    487:        xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
                    488: 
                    489:        xfs.inopblog = super.sb_inopblog;
                    490:        xfs.agblklog = super.sb_agblklog;
                    491:        xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
                    492: 
                    493:        xfs.btnode_ptr0_off =
                    494:                ((xfs.bsize - sizeof(xfs_btree_block_t)) /
                    495:                (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
                    496:                 * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
                    497: 
                    498:        return 1;
                    499: }
                    500: 
                    501: int
                    502: xfs_read (char *buf, int len)
                    503: {
                    504:        xad_t *xad;
                    505:        xfs_fileoff_t endofprev, endofcur, offset;
                    506:        xfs_filblks_t xadlen;
                    507:        int toread, startpos, endpos;
                    508: 
                    509:        if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
                    510:                grub_memmove (buf, inode->di_u.di_c + filepos, len);
                    511:                filepos += len;
                    512:                return len;
                    513:        }
                    514: 
                    515:        startpos = filepos;
                    516:        endpos = filepos + len;
                    517:        endofprev = (xfs_fileoff_t)-1;
                    518:        init_extents ();
                    519:        while (len > 0 && (xad = next_extent ())) {
                    520:                offset = xad->offset;
                    521:                xadlen = xad->len;
                    522:                if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
                    523:                        endofcur = (offset + xadlen) << xfs.blklog;
                    524:                        toread = (endofcur >= endpos)
                    525:                                  ? len : (endofcur - filepos);
                    526: 
                    527:                        disk_read_func = disk_read_hook;
                    528:                        devread (fsb2daddr (xad->start),
                    529:                                 filepos - (offset << xfs.blklog), toread, buf);
                    530:                        disk_read_func = NULL;
                    531: 
                    532:                        buf += toread;
                    533:                        len -= toread;
                    534:                        filepos += toread;
                    535:                } else if (offset > endofprev) {
                    536:                        toread = ((offset << xfs.blklog) >= endpos)
                    537:                                  ? len : ((offset - endofprev) << xfs.blklog);
                    538:                        len -= toread;
                    539:                        filepos += toread;
                    540:                        for (; toread; toread--) {
                    541:                                *buf++ = 0;
                    542:                        }
                    543:                        continue;
                    544:                }
                    545:                endofprev = offset + xadlen;
                    546:        }
                    547: 
                    548:        return filepos - startpos;
                    549: }
                    550: 
                    551: int
                    552: xfs_dir (char *dirname)
                    553: {
                    554:        xfs_ino_t ino, parent_ino, new_ino;
                    555:        xfs_fsize_t di_size;
                    556:        int di_mode;
                    557:        int cmp, n, link_count;
                    558:        char linkbuf[xfs.bsize];
                    559:        char *rest, *name, ch;
                    560: 
                    561:        parent_ino = ino = xfs.rootino;
                    562:        link_count = 0;
                    563:        for (;;) {
                    564:                di_read (ino);
                    565:                di_size = le64 (icore.di_size);
                    566:                di_mode = le16 (icore.di_mode);
                    567: 
                    568:                if ((di_mode & IFMT) == IFLNK) {
                    569:                        if (++link_count > MAX_LINK_COUNT) {
                    570:                                errnum = ERR_SYMLINK_LOOP;
                    571:                                return 0;
                    572:                        }
                    573:                        if (di_size < xfs.bsize - 1) {
                    574:                                filepos = 0;
                    575:                                filemax = di_size;
                    576:                                n = xfs_read (linkbuf, filemax);
                    577:                        } else {
                    578:                                errnum = ERR_FILELENGTH;
                    579:                                return 0;
                    580:                        }
                    581: 
                    582:                        ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
                    583:                        while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
                    584:                        linkbuf[n] = 0;
                    585:                        dirname = linkbuf;
                    586:                        continue;
                    587:                }
                    588: 
                    589:                if (!*dirname || isspace (*dirname)) {
                    590:                        if ((di_mode & IFMT) != IFREG) {
                    591:                                errnum = ERR_BAD_FILETYPE;
                    592:                                return 0;
                    593:                        }
                    594:                        filepos = 0;
                    595:                        filemax = di_size;
                    596:                        return 1;
                    597:                }
                    598: 
                    599:                if ((di_mode & IFMT) != IFDIR) {
                    600:                        errnum = ERR_BAD_FILETYPE;
                    601:                        return 0;
                    602:                }
                    603: 
                    604:                for (; *dirname == '/'; dirname++);
                    605: 
                    606:                for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
                    607:                *rest = 0;
                    608: 
                    609:                name = first_dentry (&new_ino);
                    610:                for (;;) {
                    611:                        cmp = (!*dirname) ? -1 : substring (dirname, name);
                    612: #ifndef STAGE1_5
                    613:                        if (print_possibilities && ch != '/' && cmp <= 0) {
                    614:                                if (print_possibilities > 0)
                    615:                                        print_possibilities = -print_possibilities;
                    616:                                print_a_completion (name);
                    617:                        } else
                    618: #endif
                    619:                        if (cmp == 0) {
                    620:                                parent_ino = ino;
                    621:                                if (new_ino)
                    622:                                        ino = new_ino;
                    623:                                *(dirname = rest) = ch;
                    624:                                break;
                    625:                        }
                    626:                        name = next_dentry (&new_ino);
                    627:                        if (name == NULL) {
                    628:                                if (print_possibilities < 0)
                    629:                                        return 1;
                    630: 
                    631:                                errnum = ERR_FILE_NOT_FOUND;
                    632:                                *rest = ch;
                    633:                                return 0;
                    634:                        }
                    635:                }
                    636:        }
                    637: }
                    638: 
                    639: #endif /* FSYS_XFS */

unix.superglobalmegacorp.com

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