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