Annotation of qemu/roms/openbios/fs/grubfs/fsys_reiserfs.c, revision 1.1

1.1     ! root        1: /* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */
        !             2: /*
        !             3:  *  GRUB  --  GRand Unified Bootloader
        !             4:  *  Copyright (C) 2000, 2001  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_REISERFS
        !            23: #include "shared.h"
        !            24: #include "filesys.h"
        !            25: 
        !            26: #undef REISERDEBUG
        !            27: 
        !            28: /* Some parts of this code (mainly the structures and defines) are
        !            29:  * from the original reiser fs code, as found in the linux kernel.
        !            30:  */
        !            31: 
        !            32: /* include/asm-i386/types.h */
        !            33: typedef __signed__ char __s8;
        !            34: typedef unsigned char __u8;
        !            35: typedef __signed__ short __s16;
        !            36: typedef unsigned short __u16;
        !            37: typedef __signed__ int __s32;
        !            38: typedef unsigned int __u32;
        !            39: typedef unsigned long long __u64;
        !            40: 
        !            41: /* linux/posix_type.h */
        !            42: typedef long linux_off_t;
        !            43: 
        !            44: #include "libc/byteorder.h"
        !            45: 
        !            46: /* include/linux/reiser_fs.h */
        !            47: /* This is the new super block of a journaling reiserfs system */
        !            48: struct reiserfs_super_block
        !            49: {
        !            50:   __u32 s_block_count;                 /* blocks count         */
        !            51:   __u32 s_free_blocks;                  /* free blocks count    */
        !            52:   __u32 s_root_block;                  /* root block number    */
        !            53:   __u32 s_journal_block;               /* journal block number    */
        !            54:   __u32 s_journal_dev;                 /* journal device number  */
        !            55:   __u32 s_journal_size;                /* size of the journal on FS creation.  used to make sure they don't overflow it */
        !            56:   __u32 s_journal_trans_max;            /* max number of blocks in a transaction.  */
        !            57:   __u32 s_journal_magic;                /* random value made on fs creation */
        !            58:   __u32 s_journal_max_batch;            /* max number of blocks to batch into a trans */
        !            59:   __u32 s_journal_max_commit_age;       /* in seconds, how old can an async commit be */
        !            60:   __u32 s_journal_max_trans_age;        /* in seconds, how old can a transaction be */
        !            61:   __u16 s_blocksize;                           /* block size           */
        !            62:   __u16 s_oid_maxsize;                 /* max size of object id array  */
        !            63:   __u16 s_oid_cursize;                 /* current size of object id array */
        !            64:   __u16 s_state;                               /* valid or error       */
        !            65:   char s_magic[16];                     /* reiserfs magic string indicates that file system is reiserfs */
        !            66:   __u16 s_tree_height;                  /* height of disk tree */
        !            67:   __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
        !            68:   __u16 s_version;
        !            69:   char s_unused[128];                  /* zero filled by mkreiserfs */
        !            70: };
        !            71: 
        !            72: #define REISERFS_MAX_SUPPORTED_VERSION 2
        !            73: #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
        !            74: #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
        !            75: 
        !            76: #define MAX_HEIGHT 7
        !            77: 
        !            78: /* must be correct to keep the desc and commit structs at 4k */
        !            79: #define JOURNAL_TRANS_HALF 1018
        !            80: 
        !            81: /* first block written in a commit.  */
        !            82: struct reiserfs_journal_desc {
        !            83:   __u32 j_trans_id;                    /* id of commit */
        !            84:   __u32 j_len;                         /* length of commit. len +1 is the commit block */
        !            85:   __u32 j_mount_id;                    /* mount id of this trans*/
        !            86:   __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
        !            87:   char j_magic[12];
        !            88: };
        !            89: 
        !            90: /* last block written in a commit */
        !            91: struct reiserfs_journal_commit {
        !            92:   __u32 j_trans_id;                    /* must match j_trans_id from the desc block */
        !            93:   __u32 j_len;                 /* ditto */
        !            94:   __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
        !            95:   char j_digest[16];                   /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
        !            96: };
        !            97: 
        !            98: /* this header block gets written whenever a transaction is considered
        !            99:    fully flushed, and is more recent than the last fully flushed
        !           100:    transaction.
        !           101:    fully flushed means all the log blocks and all the real blocks are
        !           102:    on disk, and this transaction does not need to be replayed.
        !           103: */
        !           104: struct reiserfs_journal_header {
        !           105:   /* id of last fully flushed transaction */
        !           106:   __u32 j_last_flush_trans_id;
        !           107:   /* offset in the log of where to start replay after a crash */
        !           108:   __u32 j_first_unflushed_offset;
        !           109:   /* mount id to detect very old transactions */
        !           110:   __u32 j_mount_id;
        !           111: };
        !           112: 
        !           113: /* magic string to find desc blocks in the journal */
        !           114: #define JOURNAL_DESC_MAGIC "ReIsErLB"
        !           115: 
        !           116: 
        !           117: /*
        !           118:  * directories use this key as well as old files
        !           119:  */
        !           120: struct offset_v1
        !           121: {
        !           122:   /*
        !           123:    * for regular files this is the offset to the first byte of the
        !           124:    * body, contained in the object-item, as measured from the start of
        !           125:    * the entire body of the object.
        !           126:    *
        !           127:    * for directory entries, k_offset consists of hash derived from
        !           128:    * hashing the name and using few bits (23 or more) of the resulting
        !           129:    * hash, and generation number that allows distinguishing names with
        !           130:    * hash collisions. If number of collisions overflows generation
        !           131:    * number, we return EEXIST.  High order bit is 0 always
        !           132:    */
        !           133:   __u32 k_offset;
        !           134:   __u32 k_uniqueness;
        !           135: };
        !           136: 
        !           137: struct offset_v2
        !           138: {
        !           139:   /*
        !           140:    * for regular files this is the offset to the first byte of the
        !           141:    * body, contained in the object-item, as measured from the start of
        !           142:    * the entire body of the object.
        !           143:    *
        !           144:    * for directory entries, k_offset consists of hash derived from
        !           145:    * hashing the name and using few bits (23 or more) of the resulting
        !           146:    * hash, and generation number that allows distinguishing names with
        !           147:    * hash collisions. If number of collisions overflows generation
        !           148:    * number, we return EEXIST.  High order bit is 0 always
        !           149:    */
        !           150:   __u64 k_offset:60;
        !           151:   __u64 k_type: 4;
        !           152: };
        !           153: 
        !           154: 
        !           155: struct key
        !           156: {
        !           157:   /* packing locality: by default parent directory object id */
        !           158:   __u32 k_dir_id;
        !           159:   /* object identifier */
        !           160:   __u32 k_objectid;
        !           161:   /* the offset and node type (old and new form) */
        !           162:   union
        !           163:   {
        !           164:     struct offset_v1 v1;
        !           165:     struct offset_v2 v2;
        !           166:   }
        !           167:   u;
        !           168: };
        !           169: 
        !           170: #define KEY_SIZE (sizeof (struct key))
        !           171: 
        !           172: /* Header of a disk block.  More precisely, header of a formatted leaf
        !           173:    or internal node, and not the header of an unformatted node. */
        !           174: struct block_head
        !           175: {
        !           176:   __u16 blk_level;        /* Level of a block in the tree. */
        !           177:   __u16 blk_nr_item;      /* Number of keys/items in a block. */
        !           178:   __u16 blk_free_space;   /* Block free space in bytes. */
        !           179:   struct key  blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
        !           180:                                      only) */
        !           181: };
        !           182: #define BLKH_SIZE (sizeof (struct block_head))
        !           183: #define DISK_LEAF_NODE_LEVEL  1 /* Leaf node level.                       */
        !           184: 
        !           185: struct item_head
        !           186: {
        !           187:   struct key ih_key;   /* Everything in the tree is found by searching for it based on its key.*/
        !           188: 
        !           189:   union
        !           190:   {
        !           191:     __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this
        !           192:                            is an indirect item.  This equals 0xFFFF iff this is a direct item or
        !           193:                            stat data item. Note that the key, not this field, is used to determine
        !           194:                            the item type, and thus which field this union contains. */
        !           195:     __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory
        !           196:                             entries in the directory item. */
        !           197:   }
        !           198:   u;
        !           199:   __u16 ih_item_len;           /* total size of the item body                  */
        !           200:   __u16 ih_item_location;      /* an offset to the item body within the block  */
        !           201:   __u16 ih_version;           /* ITEM_VERSION_1 for all old items,
        !           202:                                  ITEM_VERSION_2 for new ones.
        !           203:                                  Highest bit is set by fsck
        !           204:                                   temporary, cleaned after all done */
        !           205: };
        !           206: /* size of item header     */
        !           207: #define IH_SIZE (sizeof (struct item_head))
        !           208: 
        !           209: #define ITEM_VERSION_1 0
        !           210: #define ITEM_VERSION_2 1
        !           211: #define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \
        !           212:                           ? (ih)->ih_key.u.v1.k_offset \
        !           213:                           : (ih)->ih_key.u.v2.k_offset)
        !           214: 
        !           215: #define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \
        !           216:                                 ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \
        !           217:                                 : (ih)->ih_key.u.v2.k_type == V2_##type)
        !           218: 
        !           219: /* FIXME these types look wrong. */
        !           220: struct disk_child
        !           221: {
        !           222:   unsigned long       dc_block_number;              /* Disk child's block number. */
        !           223:   unsigned short      dc_size;                     /* Disk child's used space.   */
        !           224: };
        !           225: 
        !           226: #define DC_SIZE (sizeof (struct disk_child))
        !           227: 
        !           228: /* Stat Data on disk.
        !           229:  *
        !           230:  * Note that reiserfs has two different forms of stat data.  Luckily
        !           231:  * the fields needed by grub are at the same position.
        !           232:  */
        !           233: struct stat_data
        !           234: {
        !           235:   __u16 sd_mode;       /* file type, permissions */
        !           236:   __u16 sd_notused1[3]; /* fields not needed by reiserfs */
        !           237:   __u32 sd_size;       /* file size */
        !           238:   __u32 sd_size_hi;    /* file size high 32 bits (since version 2) */
        !           239: };
        !           240: 
        !           241: struct reiserfs_de_head
        !           242: {
        !           243:   __u32 deh_offset;  /* third component of the directory entry key */
        !           244:   __u32 deh_dir_id;  /* objectid of the parent directory of the
        !           245:                        object, that is referenced by directory entry */
        !           246:   __u32 deh_objectid;/* objectid of the object, that is referenced by
        !           247:                         directory entry */
        !           248:   __u16 deh_location;/* offset of name in the whole item */
        !           249:   __u16 deh_state;   /* whether 1) entry contains stat data (for
        !           250:                        future), and 2) whether entry is hidden
        !           251:                        (unlinked) */
        !           252: };
        !           253: 
        !           254: #define DEH_SIZE (sizeof (struct reiserfs_de_head))
        !           255: 
        !           256: #define DEH_Statdata (1 << 0)                  /* not used now */
        !           257: #define DEH_Visible  (1 << 2)
        !           258: 
        !           259: #define SD_OFFSET  0
        !           260: #define SD_UNIQUENESS 0
        !           261: #define DOT_OFFSET 1
        !           262: #define DOT_DOT_OFFSET 2
        !           263: #define DIRENTRY_UNIQUENESS 500
        !           264: 
        !           265: #define V1_TYPE_STAT_DATA 0x0
        !           266: #define V1_TYPE_DIRECT 0xffffffff
        !           267: #define V1_TYPE_INDIRECT 0xfffffffe
        !           268: #define V1_TYPE_DIRECTORY_MAX 0xfffffffd
        !           269: #define V2_TYPE_STAT_DATA 0
        !           270: #define V2_TYPE_INDIRECT 1
        !           271: #define V2_TYPE_DIRECT 2
        !           272: #define V2_TYPE_DIRENTRY 3
        !           273: 
        !           274: #define REISERFS_ROOT_OBJECTID 2
        !           275: #define REISERFS_ROOT_PARENT_OBJECTID 1
        !           276: #define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
        !           277: /* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
        !           278: #define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
        !           279: #define REISERFS_OLD_BLOCKSIZE 4096
        !           280: 
        !           281: #define S_ISREG(mode) (((mode) & 0170000) == 0100000)
        !           282: #define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
        !           283: #define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
        !           284: 
        !           285: #define PATH_MAX       1024    /* include/linux/limits.h */
        !           286: #define MAX_LINK_COUNT    5    /* number of symbolic links to follow */
        !           287: 
        !           288: /* The size of the node cache */
        !           289: #define FSYSREISER_CACHE_SIZE 24*1024
        !           290: #define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
        !           291: #define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
        !           292: 
        !           293: /* Info about currently opened file */
        !           294: struct fsys_reiser_fileinfo
        !           295: {
        !           296:   __u32 k_dir_id;
        !           297:   __u32 k_objectid;
        !           298: };
        !           299: 
        !           300: /* In memory info about the currently mounted filesystem */
        !           301: struct fsys_reiser_info
        !           302: {
        !           303:   /* The last read item head */
        !           304:   struct item_head *current_ih;
        !           305:   /* The last read item */
        !           306:   char *current_item;
        !           307:   /* The information for the currently opened file */
        !           308:   struct fsys_reiser_fileinfo fileinfo;
        !           309:   /* The start of the journal */
        !           310:   __u32 journal_block;
        !           311:   /* The size of the journal */
        !           312:   __u32 journal_block_count;
        !           313:   /* The first valid descriptor block in journal
        !           314:      (relative to journal_block) */
        !           315:   __u32 journal_first_desc;
        !           316: 
        !           317:   /* The ReiserFS version. */
        !           318:   __u16 version;
        !           319:   /* The current depth of the reiser tree. */
        !           320:   __u16 tree_depth;
        !           321:   /* SECTOR_SIZE << blocksize_shift == blocksize. */
        !           322:   __u8  blocksize_shift;
        !           323:   /* 1 << full_blocksize_shift == blocksize. */
        !           324:   __u8  fullblocksize_shift;
        !           325:   /* The reiserfs block size  (must be a power of 2) */
        !           326:   __u16 blocksize;
        !           327:   /* The number of cached tree nodes */
        !           328:   __u16 cached_slots;
        !           329:   /* The number of valid transactions in journal */
        !           330:   __u16 journal_transactions;
        !           331: 
        !           332:   unsigned int blocks[MAX_HEIGHT];
        !           333:   unsigned int next_key_nr[MAX_HEIGHT];
        !           334: };
        !           335: 
        !           336: /* The cached s+tree blocks in FSYS_BUF,  see below
        !           337:  * for a more detailed description.
        !           338:  */
        !           339: #define ROOT     ((char *)FSYS_BUF)
        !           340: #define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
        !           341: #define LEAF     CACHE (DISK_LEAF_NODE_LEVEL)
        !           342: 
        !           343: #define BLOCKHEAD(cache) ((struct block_head *) cache)
        !           344: #define ITEMHEAD         ((struct item_head  *) ((char *) LEAF + BLKH_SIZE))
        !           345: #define KEY(cache)       ((struct key        *) ((char *) cache + BLKH_SIZE))
        !           346: #define DC(cache)        ((struct disk_child *) \
        !           347:                          ((char *) cache + BLKH_SIZE + KEY_SIZE * nr_item))
        !           348: /* The fsys_reiser_info block.
        !           349:  */
        !           350: #define INFO \
        !           351:     ((struct fsys_reiser_info *) ((char *) FSYS_BUF + FSYSREISER_CACHE_SIZE))
        !           352: /*
        !           353:  * The journal cache.  For each transaction it contains the number of
        !           354:  * blocks followed by the real block numbers of this transaction.
        !           355:  *
        !           356:  * If the block numbers of some transaction won't fit in this space,
        !           357:  * this list is stopped with a 0xffffffff marker and the remaining
        !           358:  * uncommitted transactions aren't cached.
        !           359:  */
        !           360: #define JOURNAL_START    ((__u32 *) (INFO + 1))
        !           361: #define JOURNAL_END      ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
        !           362: 
        !           363: static __inline__ int
        !           364: is_power_of_two (unsigned long word)
        !           365: {
        !           366:   return (word & -word) == word;
        !           367: }
        !           368: 
        !           369: static int
        !           370: journal_read (int block, int len, char *buffer)
        !           371: {
        !           372:   return devread ((INFO->journal_block + block) << INFO->blocksize_shift,
        !           373:                  0, len, buffer);
        !           374: }
        !           375: 
        !           376: /* Read a block from ReiserFS file system, taking the journal into
        !           377:  * account.  If the block nr is in the journal, the block from the
        !           378:  * journal taken.
        !           379:  */
        !           380: static int
        !           381: block_read (int blockNr, int start, int len, char *buffer)
        !           382: {
        !           383:   int transactions = INFO->journal_transactions;
        !           384:   int desc_block = INFO->journal_first_desc;
        !           385:   int journal_mask = INFO->journal_block_count - 1;
        !           386:   int translatedNr = blockNr;
        !           387:   __u32 *journal_table = JOURNAL_START;
        !           388:   while (transactions-- > 0)
        !           389:     {
        !           390:       int i = 0;
        !           391:       int j_len;
        !           392:       if (*journal_table != 0xffffffff)
        !           393:        {
        !           394:          /* Search for the blockNr in cached journal */
        !           395:          j_len = *journal_table++;
        !           396:          while (i++ < j_len)
        !           397:            {
        !           398:              if (*journal_table++ == blockNr)
        !           399:                {
        !           400:                  journal_table += j_len - i;
        !           401:                  goto found;
        !           402:                }
        !           403:            }
        !           404:        }
        !           405:       else
        !           406:        {
        !           407:          /* This is the end of cached journal marker.  The remaining
        !           408:           * transactions are still on disk.
        !           409:           */
        !           410:          struct reiserfs_journal_desc   desc;
        !           411:          struct reiserfs_journal_commit commit;
        !           412: 
        !           413:          if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
        !           414:            return 0;
        !           415: 
        !           416:          j_len = desc.j_len;
        !           417:          while (i < j_len && i < JOURNAL_TRANS_HALF)
        !           418:            if (desc.j_realblock[i++] == blockNr)
        !           419:              goto found;
        !           420: 
        !           421:          if (j_len >= JOURNAL_TRANS_HALF)
        !           422:            {
        !           423:              int commit_block = (desc_block + 1 + j_len) & journal_mask;
        !           424:              if (! journal_read (commit_block,
        !           425:                                  sizeof (commit), (char *) &commit))
        !           426:                return 0;
        !           427:              while (i < j_len)
        !           428:                if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr)
        !           429:                  goto found;
        !           430:            }
        !           431:        }
        !           432:       goto not_found;
        !           433: 
        !           434:     found:
        !           435:       translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
        !           436: #ifdef REISERDEBUG
        !           437:       printf ("block_read: block %d is mapped to journal block %d.\n",
        !           438:              blockNr, translatedNr - INFO->journal_block);
        !           439: #endif
        !           440:       /* We must continue the search, as this block may be overwritten
        !           441:        * in later transactions.
        !           442:        */
        !           443:     not_found:
        !           444:       desc_block = (desc_block + 2 + j_len) & journal_mask;
        !           445:     }
        !           446:   return devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
        !           447: }
        !           448: 
        !           449: /* Init the journal data structure.  We try to cache as much as
        !           450:  * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
        !           451:  * we can still read the rest from the disk on demand.
        !           452:  *
        !           453:  * The first number of valid transactions and the descriptor block of the
        !           454:  * first valid transaction are held in INFO.  The transactions are all
        !           455:  * adjacent, but we must take care of the journal wrap around.
        !           456:  */
        !           457: static int
        !           458: journal_init (void)
        !           459: {
        !           460:   unsigned int block_count = INFO->journal_block_count;
        !           461:   unsigned int desc_block;
        !           462:   unsigned int commit_block;
        !           463:   unsigned int next_trans_id;
        !           464:   struct reiserfs_journal_header header;
        !           465:   struct reiserfs_journal_desc   desc;
        !           466:   struct reiserfs_journal_commit commit;
        !           467:   __u32 *journal_table = JOURNAL_START;
        !           468: 
        !           469:   journal_read (block_count, sizeof (header), (char *) &header);
        !           470:   desc_block = header.j_first_unflushed_offset;
        !           471:   if (desc_block >= block_count)
        !           472:     return 0;
        !           473: 
        !           474:   INFO->journal_first_desc = desc_block;
        !           475:   next_trans_id = header.j_last_flush_trans_id + 1;
        !           476: 
        !           477: #ifdef REISERDEBUG
        !           478:   printf ("journal_init: last flushed %d\n",
        !           479:          header.j_last_flush_trans_id);
        !           480: #endif
        !           481: 
        !           482:   while (1)
        !           483:     {
        !           484:       journal_read (desc_block, sizeof (desc), (char *) &desc);
        !           485:       if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
        !           486:          || desc.j_trans_id != next_trans_id
        !           487:          || desc.j_mount_id != header.j_mount_id)
        !           488:        /* no more valid transactions */
        !           489:        break;
        !           490: 
        !           491:       commit_block = (desc_block + desc.j_len + 1) & (block_count - 1);
        !           492:       journal_read (commit_block, sizeof (commit), (char *) &commit);
        !           493:       if (desc.j_trans_id != commit.j_trans_id
        !           494:          || desc.j_len != commit.j_len)
        !           495:        /* no more valid transactions */
        !           496:        break;
        !           497: 
        !           498: #ifdef REISERDEBUG
        !           499:       printf ("Found valid transaction %d/%d at %d.\n",
        !           500:              desc.j_trans_id, desc.j_mount_id, desc_block);
        !           501: #endif
        !           502: 
        !           503:       next_trans_id++;
        !           504:       if (journal_table < JOURNAL_END)
        !           505:        {
        !           506:          if ((journal_table + 1 + desc.j_len) >= JOURNAL_END)
        !           507:            {
        !           508:              /* The table is almost full; mark the end of the cached
        !           509:               * journal.*/
        !           510:              *journal_table = 0xffffffff;
        !           511:              journal_table = JOURNAL_END;
        !           512:            }
        !           513:          else
        !           514:            {
        !           515:              int i;
        !           516:              /* Cache the length and the realblock numbers in the table.
        !           517:               * The block number of descriptor can easily be computed.
        !           518:               * and need not to be stored here.
        !           519:               */
        !           520:              *journal_table++ = desc.j_len;
        !           521:              for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
        !           522:                {
        !           523:                  *journal_table++ = desc.j_realblock[i];
        !           524: #ifdef REISERDEBUG
        !           525:                  printf ("block %d is in journal %d.\n",
        !           526:                          desc.j_realblock[i], desc_block);
        !           527: #endif
        !           528:                }
        !           529:              for (     ; i < desc.j_len; i++)
        !           530:                {
        !           531:                  *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
        !           532: #ifdef REISERDEBUG
        !           533:                  printf ("block %d is in journal %d.\n",
        !           534:                          commit.j_realblock[i-JOURNAL_TRANS_HALF],
        !           535:                          desc_block);
        !           536: #endif
        !           537:                }
        !           538:            }
        !           539:        }
        !           540:       desc_block = (commit_block + 1) & (block_count - 1);
        !           541:     }
        !           542: #ifdef REISERDEBUG
        !           543:   printf ("Transaction %d/%d at %d isn't valid.\n",
        !           544:          desc.j_trans_id, desc.j_mount_id, desc_block);
        !           545: #endif
        !           546: 
        !           547:   INFO->journal_transactions
        !           548:     = next_trans_id - header.j_last_flush_trans_id - 1;
        !           549:   return errnum == 0;
        !           550: }
        !           551: 
        !           552: /* check filesystem types and read superblock into memory buffer */
        !           553: int
        !           554: reiserfs_mount (void)
        !           555: {
        !           556:   struct reiserfs_super_block super;
        !           557:   int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
        !           558: 
        !           559:   if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
        !           560:       || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
        !           561:                (char *) &super)
        !           562:       || (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
        !           563:          && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
        !           564:       || (/* check that this is not a copy inside the journal log */
        !           565:          super.s_journal_block * super.s_blocksize
        !           566:          <= REISERFS_DISK_OFFSET_IN_BYTES))
        !           567:     {
        !           568:       /* Try old super block position */
        !           569:       superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
        !           570:       if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
        !           571:          || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
        !           572:                        (char *) &super))
        !           573:        return 0;
        !           574: 
        !           575:       if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
        !           576:          && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
        !           577:        {
        !           578:          /* pre journaling super block ? */
        !           579:          if (substring (REISERFS_SUPER_MAGIC_STRING,
        !           580:                         (char*) ((char *) &super + 20)) > 0)
        !           581:            return 0;
        !           582: 
        !           583:          super.s_blocksize = REISERFS_OLD_BLOCKSIZE;
        !           584:          super.s_journal_block = 0;
        !           585:          super.s_version = 0;
        !           586:        }
        !           587:     }
        !           588: 
        !           589:   /* check the version number.  */
        !           590:   if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION)
        !           591:     return 0;
        !           592: 
        !           593:   INFO->version = super.s_version;
        !           594:   INFO->blocksize = super.s_blocksize;
        !           595:   INFO->fullblocksize_shift = log2 (super.s_blocksize);
        !           596:   INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
        !           597:   INFO->cached_slots =
        !           598:     (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
        !           599: 
        !           600: #ifdef REISERDEBUG
        !           601:   printf ("reiserfs_mount: version=%d, blocksize=%d\n",
        !           602:          INFO->version, INFO->blocksize);
        !           603: #endif /* REISERDEBUG */
        !           604: 
        !           605:   /* Clear node cache. */
        !           606:   memset (INFO->blocks, 0, sizeof (INFO->blocks));
        !           607: 
        !           608:   if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE
        !           609:       || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE
        !           610:       || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
        !           611:     return 0;
        !           612: 
        !           613:   /* Initialize journal code.  If something fails we end with zero
        !           614:    * journal_transactions, so we don't access the journal at all.
        !           615:    */
        !           616:   INFO->journal_transactions = 0;
        !           617:   if (super.s_journal_block != 0 && super.s_journal_dev == 0)
        !           618:     {
        !           619:       INFO->journal_block = super.s_journal_block;
        !           620:       INFO->journal_block_count = super.s_journal_size;
        !           621:       if (is_power_of_two (INFO->journal_block_count))
        !           622:        journal_init ();
        !           623: 
        !           624:       /* Read in super block again, maybe it is in the journal */
        !           625:       block_read (superblock >> INFO->blocksize_shift,
        !           626:                  0, sizeof (struct reiserfs_super_block), (char *) &super);
        !           627:     }
        !           628: 
        !           629:   if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT))
        !           630:     return 0;
        !           631: 
        !           632:   INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level;
        !           633: 
        !           634: #ifdef REISERDEBUG
        !           635:   printf ("root read_in: block=%d, depth=%d\n",
        !           636:          super.s_root_block, INFO->tree_depth);
        !           637: #endif /* REISERDEBUG */
        !           638: 
        !           639:   if (INFO->tree_depth >= MAX_HEIGHT)
        !           640:     return 0;
        !           641:   if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
        !           642:     {
        !           643:       /* There is only one node in the whole filesystem,
        !           644:        * which is simultanously leaf and root */
        !           645:       memcpy (LEAF, ROOT, INFO->blocksize);
        !           646:     }
        !           647:   return 1;
        !           648: }
        !           649: 
        !           650: /***************** TREE ACCESSING METHODS *****************************/
        !           651: 
        !           652: /* I assume you are familiar with the ReiserFS tree, if not go to
        !           653:  * http://www.namesys.com/content_table.html
        !           654:  *
        !           655:  * My tree node cache is organized as following
        !           656:  *   0   ROOT node
        !           657:  *   1   LEAF node  (if the ROOT is also a LEAF it is copied here
        !           658:  *   2-n other nodes on current path from bottom to top.
        !           659:  *       if there is not enough space in the cache, the top most are
        !           660:  *       omitted.
        !           661:  *
        !           662:  * I have only two methods to find a key in the tree:
        !           663:  *   search_stat(dir_id, objectid) searches for the stat entry (always
        !           664:  *       the first entry) of an object.
        !           665:  *   next_key() gets the next key in tree order.
        !           666:  *
        !           667:  * This means, that I can only sequential reads of files are
        !           668:  * efficient, but this really doesn't hurt for grub.
        !           669:  */
        !           670: 
        !           671: /* Read in the node at the current path and depth into the node cache.
        !           672:  * You must set INFO->blocks[depth] before.
        !           673:  */
        !           674: static char *
        !           675: read_tree_node (unsigned int blockNr, int depth)
        !           676: {
        !           677:   char* cache = CACHE(depth);
        !           678:   int num_cached = INFO->cached_slots;
        !           679:   if (depth < num_cached)
        !           680:     {
        !           681:       /* This is the cached part of the path.  Check if same block is
        !           682:        * needed.
        !           683:        */
        !           684:       if (blockNr == INFO->blocks[depth])
        !           685:        return cache;
        !           686:     }
        !           687:   else
        !           688:     cache = CACHE(num_cached);
        !           689: 
        !           690: #ifdef REISERDEBUG
        !           691:   printf ("  next read_in: block=%d (depth=%d)\n",
        !           692:          blockNr, depth);
        !           693: #endif /* REISERDEBUG */
        !           694:   if (! block_read (blockNr, 0, INFO->blocksize, cache))
        !           695:       return NULL;
        !           696:   /* Make sure it has the right node level */
        !           697:   if (BLOCKHEAD (cache)->blk_level != depth)
        !           698:     {
        !           699:       errnum = ERR_FSYS_CORRUPT;
        !           700:       return NULL;
        !           701:     }
        !           702: 
        !           703:   INFO->blocks[depth] = blockNr;
        !           704:   return cache;
        !           705: }
        !           706: 
        !           707: /* Get the next key, i.e. the key following the last retrieved key in
        !           708:  * tree order.  INFO->current_ih and
        !           709:  * INFO->current_info are adapted accordingly.  */
        !           710: static int
        !           711: next_key (void)
        !           712: {
        !           713:   int depth;
        !           714:   struct item_head *ih = INFO->current_ih + 1;
        !           715:   char *cache;
        !           716: 
        !           717: #ifdef REISERDEBUG
        !           718:   printf ("next_key:\n  old ih: key %d:%d:%d:%d version:%d\n",
        !           719:          INFO->current_ih->ih_key.k_dir_id,
        !           720:          INFO->current_ih->ih_key.k_objectid,
        !           721:          INFO->current_ih->ih_key.u.v1.k_offset,
        !           722:          INFO->current_ih->ih_key.u.v1.k_uniqueness,
        !           723:          INFO->current_ih->ih_version);
        !           724: #endif /* REISERDEBUG */
        !           725: 
        !           726:   if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item])
        !           727:     {
        !           728:       depth = DISK_LEAF_NODE_LEVEL;
        !           729:       /* The last item, was the last in the leaf node.
        !           730:        * Read in the next block
        !           731:        */
        !           732:       do
        !           733:        {
        !           734:          if (depth == INFO->tree_depth)
        !           735:            {
        !           736:              /* There are no more keys at all.
        !           737:               * Return a dummy item with MAX_KEY */
        !           738:              ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
        !           739:              goto found;
        !           740:            }
        !           741:          depth++;
        !           742: #ifdef REISERDEBUG
        !           743:          printf ("  depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
        !           744: #endif /* REISERDEBUG */
        !           745:        }
        !           746:       while (INFO->next_key_nr[depth] == 0);
        !           747: 
        !           748:       if (depth == INFO->tree_depth)
        !           749:        cache = ROOT;
        !           750:       else if (depth <= INFO->cached_slots)
        !           751:        cache = CACHE (depth);
        !           752:       else
        !           753:        {
        !           754:          cache = read_tree_node (INFO->blocks[depth], depth);
        !           755:          if (! cache)
        !           756:            return 0;
        !           757:        }
        !           758: 
        !           759:       do
        !           760:        {
        !           761:          int nr_item = BLOCKHEAD (cache)->blk_nr_item;
        !           762:          int key_nr = INFO->next_key_nr[depth]++;
        !           763: #ifdef REISERDEBUG
        !           764:          printf ("  depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
        !           765: #endif /* REISERDEBUG */
        !           766:          if (key_nr == nr_item)
        !           767:            /* This is the last item in this block, set the next_key_nr to 0 */
        !           768:            INFO->next_key_nr[depth] = 0;
        !           769: 
        !           770:          cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth);
        !           771:          if (! cache)
        !           772:            return 0;
        !           773:        }
        !           774:       while (depth > DISK_LEAF_NODE_LEVEL);
        !           775: 
        !           776:       ih = ITEMHEAD;
        !           777:     }
        !           778:  found:
        !           779:   INFO->current_ih   = ih;
        !           780:   INFO->current_item = &LEAF[ih->ih_item_location];
        !           781: #ifdef REISERDEBUG
        !           782:   printf ("  new ih: key %d:%d:%d:%d version:%d\n",
        !           783:          INFO->current_ih->ih_key.k_dir_id,
        !           784:          INFO->current_ih->ih_key.k_objectid,
        !           785:          INFO->current_ih->ih_key.u.v1.k_offset,
        !           786:          INFO->current_ih->ih_key.u.v1.k_uniqueness,
        !           787:          INFO->current_ih->ih_version);
        !           788: #endif /* REISERDEBUG */
        !           789:   return 1;
        !           790: }
        !           791: 
        !           792: /* preconditions: reiserfs_mount already executed, therefore
        !           793:  *   INFO block is valid
        !           794:  * returns: 0 if error (errnum is set),
        !           795:  *   nonzero iff we were able to find the key successfully.
        !           796:  * postconditions: on a nonzero return, the current_ih and
        !           797:  *   current_item fields describe the key that equals the
        !           798:  *   searched key.  INFO->next_key contains the next key after
        !           799:  *   the searched key.
        !           800:  * side effects: messes around with the cache.
        !           801:  */
        !           802: static int
        !           803: search_stat (__u32 dir_id, __u32 objectid)
        !           804: {
        !           805:   char *cache;
        !           806:   int depth;
        !           807:   int nr_item;
        !           808:   int i;
        !           809:   struct item_head *ih;
        !           810: #ifdef REISERDEBUG
        !           811:   printf ("search_stat:\n  key %d:%d:0:0\n", dir_id, objectid);
        !           812: #endif /* REISERDEBUG */
        !           813: 
        !           814:   depth = INFO->tree_depth;
        !           815:   cache = ROOT;
        !           816: 
        !           817:   while (depth > DISK_LEAF_NODE_LEVEL)
        !           818:     {
        !           819:       struct key *key;
        !           820:       nr_item = BLOCKHEAD (cache)->blk_nr_item;
        !           821: 
        !           822:       key = KEY (cache);
        !           823: 
        !           824:       for (i = 0; i < nr_item; i++)
        !           825:        {
        !           826:          if (key->k_dir_id > dir_id
        !           827:              || (key->k_dir_id == dir_id
        !           828:                  && (key->k_objectid > objectid
        !           829:                      || (key->k_objectid == objectid
        !           830:                          && (key->u.v1.k_offset
        !           831:                              | key->u.v1.k_uniqueness) > 0))))
        !           832:            break;
        !           833:          key++;
        !           834:        }
        !           835: 
        !           836: #ifdef REISERDEBUG
        !           837:       printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
        !           838: #endif /* REISERDEBUG */
        !           839:       INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
        !           840:       cache = read_tree_node (DC (cache)[i].dc_block_number, --depth);
        !           841:       if (! cache)
        !           842:        return 0;
        !           843:     }
        !           844: 
        !           845:   /* cache == LEAF */
        !           846:   nr_item = BLOCKHEAD (LEAF)->blk_nr_item;
        !           847:   ih = ITEMHEAD;
        !           848:   for (i = 0; i < nr_item; i++)
        !           849:     {
        !           850:       if (ih->ih_key.k_dir_id == dir_id
        !           851:          && ih->ih_key.k_objectid == objectid
        !           852:          && ih->ih_key.u.v1.k_offset == 0
        !           853:          && ih->ih_key.u.v1.k_uniqueness == 0)
        !           854:        {
        !           855: #ifdef REISERDEBUG
        !           856:          printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
        !           857: #endif /* REISERDEBUG */
        !           858:          INFO->current_ih   = ih;
        !           859:          INFO->current_item = &LEAF[ih->ih_item_location];
        !           860:          return 1;
        !           861:        }
        !           862:       ih++;
        !           863:     }
        !           864:   errnum = ERR_FSYS_CORRUPT;
        !           865:   return 0;
        !           866: }
        !           867: 
        !           868: int
        !           869: reiserfs_read (char *buf, int len)
        !           870: {
        !           871:   unsigned int blocksize;
        !           872:   unsigned int offset;
        !           873:   unsigned int to_read;
        !           874:   char *prev_buf = buf;
        !           875: 
        !           876: #ifdef REISERDEBUG
        !           877:   printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n",
        !           878:          filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
        !           879: #endif /* REISERDEBUG */
        !           880: 
        !           881:   if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
        !           882:       || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
        !           883:     {
        !           884:       search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
        !           885:       goto get_next_key;
        !           886:     }
        !           887: 
        !           888:   while (! errnum)
        !           889:     {
        !           890:       if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid)
        !           891:        break;
        !           892: 
        !           893:       offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
        !           894:       blocksize = INFO->current_ih->ih_item_len;
        !           895: 
        !           896: #ifdef REISERDEBUG
        !           897:       printf ("  loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
        !           898:              filepos, len, offset, blocksize);
        !           899: #endif /* REISERDEBUG */
        !           900: 
        !           901:       if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
        !           902:          && offset < blocksize)
        !           903:        {
        !           904: #ifdef REISERDEBUG
        !           905:          printf ("direct_read: offset=%d, blocksize=%d\n",
        !           906:                  offset, blocksize);
        !           907: #endif /* REISERDEBUG */
        !           908:          to_read = blocksize - offset;
        !           909:          if (to_read > len)
        !           910:            to_read = len;
        !           911: 
        !           912:          if (disk_read_hook != NULL)
        !           913:            {
        !           914:              disk_read_func = disk_read_hook;
        !           915: 
        !           916:              block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL],
        !           917:                          (INFO->current_item - LEAF + offset), to_read, buf);
        !           918: 
        !           919:              disk_read_func = NULL;
        !           920:            }
        !           921:          else
        !           922:            memcpy (buf, INFO->current_item + offset, to_read);
        !           923:          goto update_buf_len;
        !           924:        }
        !           925:       else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
        !           926:        {
        !           927:          blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
        !           928: #ifdef REISERDEBUG
        !           929:          printf ("indirect_read: offset=%d, blocksize=%d\n",
        !           930:                  offset, blocksize);
        !           931: #endif /* REISERDEBUG */
        !           932: 
        !           933:          while (offset < blocksize)
        !           934:            {
        !           935:              __u32 blocknr = ((__u32 *) INFO->current_item)
        !           936:                [offset >> INFO->fullblocksize_shift];
        !           937:              int blk_offset = offset & (INFO->blocksize-1);
        !           938: 
        !           939:              to_read = INFO->blocksize - blk_offset;
        !           940:              if (to_read > len)
        !           941:                to_read = len;
        !           942: 
        !           943:              disk_read_func = disk_read_hook;
        !           944: 
        !           945:              /* Journal is only for meta data.  Data blocks can be read
        !           946:               * directly without using block_read
        !           947:               */
        !           948:              devread (blocknr << INFO->blocksize_shift,
        !           949:                       blk_offset, to_read, buf);
        !           950: 
        !           951:              disk_read_func = NULL;
        !           952:            update_buf_len:
        !           953:              len -= to_read;
        !           954:              buf += to_read;
        !           955:              offset += to_read;
        !           956:              filepos += to_read;
        !           957:              if (len == 0)
        !           958:                goto done;
        !           959:            }
        !           960:        }
        !           961:     get_next_key:
        !           962:       next_key ();
        !           963:     }
        !           964:  done:
        !           965:   return errnum ? 0 : buf - prev_buf;
        !           966: }
        !           967: 
        !           968: 
        !           969: /* preconditions: reiserfs_mount already executed, therefore
        !           970:  *   INFO block is valid
        !           971:  * returns: 0 if error, nonzero iff we were able to find the file successfully
        !           972:  * postconditions: on a nonzero return, INFO->fileinfo contains the info
        !           973:  *   of the file we were trying to look up, filepos is 0 and filemax is
        !           974:  *   the size of the file.
        !           975:  */
        !           976: int
        !           977: reiserfs_dir (char *dirname)
        !           978: {
        !           979:   struct reiserfs_de_head *de_head;
        !           980:   char *rest, ch;
        !           981:   __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
        !           982: #ifndef STAGE1_5
        !           983:   int do_possibilities = 0;
        !           984: #endif /* ! STAGE1_5 */
        !           985:   char linkbuf[PATH_MAX];      /* buffer for following symbolic links */
        !           986:   int link_count = 0;
        !           987:   int mode;
        !           988: 
        !           989:   dir_id = REISERFS_ROOT_PARENT_OBJECTID;
        !           990:   objectid = REISERFS_ROOT_OBJECTID;
        !           991: 
        !           992:   while (1)
        !           993:     {
        !           994: #ifdef REISERDEBUG
        !           995:       printf ("dirname=%s\n", dirname);
        !           996: #endif /* REISERDEBUG */
        !           997: 
        !           998:       /* Search for the stat info first. */
        !           999:       if (! search_stat (dir_id, objectid))
        !          1000:        return 0;
        !          1001: 
        !          1002: #ifdef REISERDEBUG
        !          1003:       printf ("sd_mode=%x sd_size=%d\n",
        !          1004:              ((struct stat_data *) INFO->current_item)->sd_mode,
        !          1005:              ((struct stat_data *) INFO->current_item)->sd_size);
        !          1006: #endif /* REISERDEBUG */
        !          1007: 
        !          1008:       mode = ((struct stat_data *) INFO->current_item)->sd_mode;
        !          1009: 
        !          1010:       /* If we've got a symbolic link, then chase it. */
        !          1011:       if (S_ISLNK (mode))
        !          1012:        {
        !          1013:          int len;
        !          1014:          if (++link_count > MAX_LINK_COUNT)
        !          1015:            {
        !          1016:              errnum = ERR_SYMLINK_LOOP;
        !          1017:              return 0;
        !          1018:            }
        !          1019: 
        !          1020:          /* Get the symlink size. */
        !          1021:          filemax = ((struct stat_data *) INFO->current_item)->sd_size;
        !          1022: 
        !          1023:          /* Find out how long our remaining name is. */
        !          1024:          len = 0;
        !          1025:          while (dirname[len] && !isspace (dirname[len]))
        !          1026:            len++;
        !          1027: 
        !          1028:          if (filemax + len > sizeof (linkbuf) - 1)
        !          1029:            {
        !          1030:              errnum = ERR_FILELENGTH;
        !          1031:              return 0;
        !          1032:            }
        !          1033: 
        !          1034:          /* Copy the remaining name to the end of the symlink data.
        !          1035:             Note that DIRNAME and LINKBUF may overlap! */
        !          1036:          grub_memmove (linkbuf + filemax, dirname, len+1);
        !          1037: 
        !          1038:          INFO->fileinfo.k_dir_id = dir_id;
        !          1039:          INFO->fileinfo.k_objectid = objectid;
        !          1040:          filepos = 0;
        !          1041:          if (! next_key ()
        !          1042:              || reiserfs_read (linkbuf, filemax) != filemax)
        !          1043:            {
        !          1044:              if (! errnum)
        !          1045:                errnum = ERR_FSYS_CORRUPT;
        !          1046:              return 0;
        !          1047:            }
        !          1048: 
        !          1049: #ifdef REISERDEBUG
        !          1050:          printf ("symlink=%s\n", linkbuf);
        !          1051: #endif /* REISERDEBUG */
        !          1052: 
        !          1053:          dirname = linkbuf;
        !          1054:          if (*dirname == '/')
        !          1055:            {
        !          1056:              /* It's an absolute link, so look it up in root. */
        !          1057:              dir_id = REISERFS_ROOT_PARENT_OBJECTID;
        !          1058:              objectid = REISERFS_ROOT_OBJECTID;
        !          1059:            }
        !          1060:          else
        !          1061:            {
        !          1062:              /* Relative, so look it up in our parent directory. */
        !          1063:              dir_id   = parent_dir_id;
        !          1064:              objectid = parent_objectid;
        !          1065:            }
        !          1066: 
        !          1067:          /* Now lookup the new name. */
        !          1068:          continue;
        !          1069:        }
        !          1070: 
        !          1071:       /* if we have a real file (and we're not just printing possibilities),
        !          1072:         then this is where we want to exit */
        !          1073: 
        !          1074:       if (! *dirname || isspace (*dirname))
        !          1075:        {
        !          1076:          if (! S_ISREG (mode))
        !          1077:            {
        !          1078:              errnum = ERR_BAD_FILETYPE;
        !          1079:              return 0;
        !          1080:            }
        !          1081: 
        !          1082:          filepos = 0;
        !          1083:          filemax = ((struct stat_data *) INFO->current_item)->sd_size;
        !          1084: 
        !          1085:          /* If this is a new stat data and size is > 4GB set filemax to
        !          1086:           * maximum
        !          1087:           */
        !          1088:          if (INFO->current_ih->ih_version == ITEM_VERSION_2
        !          1089:              && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0)
        !          1090:            filemax = 0xffffffff;
        !          1091: 
        !          1092:          INFO->fileinfo.k_dir_id = dir_id;
        !          1093:          INFO->fileinfo.k_objectid = objectid;
        !          1094:          return next_key ();
        !          1095:        }
        !          1096: 
        !          1097:       /* continue with the file/directory name interpretation */
        !          1098:       while (*dirname == '/')
        !          1099:        dirname++;
        !          1100:       if (! S_ISDIR (mode))
        !          1101:        {
        !          1102:          errnum = ERR_BAD_FILETYPE;
        !          1103:          return 0;
        !          1104:        }
        !          1105:       for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
        !          1106:       *rest = 0;
        !          1107: 
        !          1108: # ifndef STAGE1_5
        !          1109:       if (print_possibilities && ch != '/')
        !          1110:        do_possibilities = 1;
        !          1111: # endif /* ! STAGE1_5 */
        !          1112: 
        !          1113:       while (1)
        !          1114:        {
        !          1115:          char *name_end;
        !          1116:          int num_entries;
        !          1117: 
        !          1118:          if (! next_key ())
        !          1119:            return 0;
        !          1120: #ifdef REISERDEBUG
        !          1121:          printf ("ih: key %d:%d:%d:%d version:%d\n",
        !          1122:                  INFO->current_ih->ih_key.k_dir_id,
        !          1123:                  INFO->current_ih->ih_key.k_objectid,
        !          1124:                  INFO->current_ih->ih_key.u.v1.k_offset,
        !          1125:                  INFO->current_ih->ih_key.u.v1.k_uniqueness,
        !          1126:                  INFO->current_ih->ih_version);
        !          1127: #endif /* REISERDEBUG */
        !          1128: 
        !          1129:          if (INFO->current_ih->ih_key.k_objectid != objectid)
        !          1130:            break;
        !          1131: 
        !          1132:          name_end = INFO->current_item + INFO->current_ih->ih_item_len;
        !          1133:          de_head = (struct reiserfs_de_head *) INFO->current_item;
        !          1134:          num_entries = INFO->current_ih->u.ih_entry_count;
        !          1135:          while (num_entries > 0)
        !          1136:            {
        !          1137:              char *filename = INFO->current_item + de_head->deh_location;
        !          1138:              char  tmp = *name_end;
        !          1139:              if ((de_head->deh_state & DEH_Visible))
        !          1140:                {
        !          1141:                  int cmp;
        !          1142:                  /* Directory names in ReiserFS are not null
        !          1143:                   * terminated.  We write a temporary 0 behind it.
        !          1144:                   * NOTE: that this may overwrite the first block in
        !          1145:                   * the tree cache.  That doesn't hurt as long as we
        !          1146:                   * don't call next_key () in between.
        !          1147:                   */
        !          1148:                  *name_end = 0;
        !          1149:                  cmp = substring (dirname, filename);
        !          1150:                  *name_end = tmp;
        !          1151: # ifndef STAGE1_5
        !          1152:                  if (do_possibilities)
        !          1153:                    {
        !          1154:                      if (cmp <= 0)
        !          1155:                        {
        !          1156:                          if (print_possibilities > 0)
        !          1157:                            print_possibilities = -print_possibilities;
        !          1158:                          *name_end = 0;
        !          1159:                          print_a_completion (filename);
        !          1160:                          *name_end = tmp;
        !          1161:                        }
        !          1162:                    }
        !          1163:                  else
        !          1164: # endif /* ! STAGE1_5 */
        !          1165:                    if (cmp == 0)
        !          1166:                      goto found;
        !          1167:                }
        !          1168:              /* The beginning of this name marks the end of the next name.
        !          1169:               */
        !          1170:              name_end = filename;
        !          1171:              de_head++;
        !          1172:              num_entries--;
        !          1173:            }
        !          1174:        }
        !          1175: 
        !          1176: # ifndef STAGE1_5
        !          1177:       if (print_possibilities < 0)
        !          1178:        return 1;
        !          1179: # endif /* ! STAGE1_5 */
        !          1180: 
        !          1181:       errnum = ERR_FILE_NOT_FOUND;
        !          1182:       *rest = ch;
        !          1183:       return 0;
        !          1184: 
        !          1185:     found:
        !          1186: 
        !          1187:       *rest = ch;
        !          1188:       dirname = rest;
        !          1189: 
        !          1190:       parent_dir_id = dir_id;
        !          1191:       parent_objectid = objectid;
        !          1192:       dir_id = de_head->deh_dir_id;
        !          1193:       objectid = de_head->deh_objectid;
        !          1194:     }
        !          1195: }
        !          1196: 
        !          1197: int
        !          1198: reiserfs_embed (int *start_sector, int needed_sectors)
        !          1199: {
        !          1200:   struct reiserfs_super_block super;
        !          1201:   int num_sectors;
        !          1202: 
        !          1203:   if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0,
        !          1204:                 sizeof (struct reiserfs_super_block), (char *) &super))
        !          1205:     return 0;
        !          1206: 
        !          1207:   *start_sector = 1; /* reserve first sector for stage1 */
        !          1208:   if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0
        !          1209:        || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0)
        !          1210:       && (/* check that this is not a super block copy inside
        !          1211:           * the journal log */
        !          1212:          super.s_journal_block * super.s_blocksize
        !          1213:          > REISERFS_DISK_OFFSET_IN_BYTES))
        !          1214:     num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
        !          1215:   else
        !          1216:     num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
        !          1217: 
        !          1218:   return (needed_sectors <= num_sectors);
        !          1219: }
        !          1220: #endif /* FSYS_REISERFS */

unix.superglobalmegacorp.com

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