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

1.1       root        1: /*
                      2:  *  GRUB  --  GRand Unified Bootloader
                      3:  *  Copyright (C) 1999, 2001  Free Software Foundation, Inc.
                      4:  *
                      5:  *  This program is free software; you can redistribute it and/or modify
                      6:  *  it under the terms of the GNU General Public License as published by
                      7:  *  the Free Software Foundation; either version 2 of the License, or
                      8:  *  (at your option) any later version.
                      9:  *
                     10:  *  This program is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:  *  GNU General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU General Public License
                     16:  *  along with this program; if not, write to the Free Software
                     17:  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     18:  *  MA 02110-1301, USA.
                     19:  */
                     20: 
                     21: #ifdef FSYS_EXT2FS
                     22: 
                     23: #include "config.h"
                     24: #include "shared.h"
                     25: #include "filesys.h"
                     26: #include "libc/byteorder.h"
                     27: 
                     28: #ifdef CONFIG_DEBUG_EXT2FS
                     29: #define E2DEBUG
                     30: #endif
                     31: 
                     32: static int mapblock1, mapblock2;
                     33: 
                     34: /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
                     35: #define DEV_BSIZE 512
                     36: 
                     37: /* include/linux/fs.h */
                     38: #define BLOCK_SIZE 1024                /* initial block size for superblock read */
                     39: /* made up, defaults to 1 but can be passed via mount_opts */
                     40: #define WHICH_SUPER 1
                     41: /* kind of from fs/ext2/super.c */
                     42: #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)  /* = 2 */
                     43: 
                     44: /* include/asm-i386/types.h */
                     45: typedef __signed__ char __s8;
                     46: typedef unsigned char __u8;
                     47: typedef __signed__ short __s16;
                     48: typedef unsigned short __u16;
                     49: typedef __signed__ int __s32;
                     50: typedef unsigned int __u32;
                     51: 
                     52: /*
                     53:  * Constants relative to the data blocks, from ext2_fs.h
                     54:  */
                     55: #define EXT2_NDIR_BLOCKS                12
                     56: #define EXT2_IND_BLOCK                  EXT2_NDIR_BLOCKS
                     57: #define EXT2_DIND_BLOCK                 (EXT2_IND_BLOCK + 1)
                     58: #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
                     59: #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
                     60: 
                     61: /* include/linux/ext2_fs.h */
                     62: struct ext2_super_block
                     63:   {
                     64:     __u32 s_inodes_count;      /* Inodes count */
                     65:     __u32 s_blocks_count;      /* Blocks count */
                     66:     __u32 s_r_blocks_count;    /* Reserved blocks count */
                     67:     __u32 s_free_blocks_count; /* Free blocks count */
                     68:     __u32 s_free_inodes_count; /* Free inodes count */
                     69:     __u32 s_first_data_block;  /* First Data Block */
                     70:     __u32 s_log_block_size;    /* Block size */
                     71:     __s32 s_log_frag_size;     /* Fragment size */
                     72:     __u32 s_blocks_per_group;  /* # Blocks per group */
                     73:     __u32 s_frags_per_group;   /* # Fragments per group */
                     74:     __u32 s_inodes_per_group;  /* # Inodes per group */
                     75:     __u32 s_mtime;             /* Mount time */
                     76:     __u32 s_wtime;             /* Write time */
                     77:     __u16 s_mnt_count;         /* Mount count */
                     78:     __s16 s_max_mnt_count;     /* Maximal mount count */
                     79:     __u16 s_magic;             /* Magic signature */
                     80:     __u16 s_state;             /* File system state */
                     81:     __u16 s_errors;            /* Behaviour when detecting errors */
                     82:     __u16 s_pad;
                     83:     __u32 s_lastcheck;         /* time of last check */
                     84:     __u32 s_checkinterval;     /* max. time between checks */
                     85:     __u32 s_creator_os;                /* OS */
                     86:     __u32 s_rev_level;         /* Revision level */
                     87:     __u16 s_def_resuid;                /* Default uid for reserved blocks */
                     88:     __u16 s_def_resgid;                /* Default gid for reserved blocks */
                     89:     __u32 s_reserved[235];     /* Padding to the end of the block */
                     90:   };
                     91: 
                     92: struct ext2_group_desc
                     93:   {
                     94:     __u32 bg_block_bitmap;     /* Blocks bitmap block */
                     95:     __u32 bg_inode_bitmap;     /* Inodes bitmap block */
                     96:     __u32 bg_inode_table;      /* Inodes table block */
                     97:     __u16 bg_free_blocks_count;        /* Free blocks count */
                     98:     __u16 bg_free_inodes_count;        /* Free inodes count */
                     99:     __u16 bg_used_dirs_count;  /* Directories count */
                    100:     __u16 bg_pad;
                    101:     __u32 bg_reserved[3];
                    102:   };
                    103: 
                    104: struct ext2_inode
                    105:   {
                    106:     __u16 i_mode;              /* File mode */
                    107:     __u16 i_uid;               /* Owner Uid */
                    108:     __u32 i_size;              /* 4: Size in bytes */
                    109:     __u32 i_atime;             /* Access time */
                    110:     __u32 i_ctime;             /* 12: Creation time */
                    111:     __u32 i_mtime;             /* Modification time */
                    112:     __u32 i_dtime;             /* 20: Deletion Time */
                    113:     __u16 i_gid;               /* Group Id */
                    114:     __u16 i_links_count;       /* 24: Links count */
                    115:     __u32 i_blocks;            /* Blocks count */
                    116:     __u32 i_flags;             /* 32: File flags */
                    117:     union
                    118:       {
                    119:        struct
                    120:          {
                    121:            __u32 l_i_reserved1;
                    122:          }
                    123:        linux1;
                    124:        struct
                    125:          {
                    126:            __u32 h_i_translator;
                    127:          }
                    128:        hurd1;
                    129:        struct
                    130:          {
                    131:            __u32 m_i_reserved1;
                    132:          }
                    133:        masix1;
                    134:       }
                    135:     osd1;                      /* OS dependent 1 */
                    136:     __u32 i_block[EXT2_N_BLOCKS];      /* 40: Pointers to blocks */
                    137:     __u32 i_version;           /* File version (for NFS) */
                    138:     __u32 i_file_acl;          /* File ACL */
                    139:     __u32 i_dir_acl;           /* Directory ACL */
                    140:     __u32 i_faddr;             /* Fragment address */
                    141:     union
                    142:       {
                    143:        struct
                    144:          {
                    145:            __u8 l_i_frag;      /* Fragment number */
                    146:            __u8 l_i_fsize;     /* Fragment size */
                    147:            __u16 i_pad1;
                    148:            __u32 l_i_reserved2[2];
                    149:          }
                    150:        linux2;
                    151:        struct
                    152:          {
                    153:            __u8 h_i_frag;      /* Fragment number */
                    154:            __u8 h_i_fsize;     /* Fragment size */
                    155:            __u16 h_i_mode_high;
                    156:            __u16 h_i_uid_high;
                    157:            __u16 h_i_gid_high;
                    158:            __u32 h_i_author;
                    159:          }
                    160:        hurd2;
                    161:        struct
                    162:          {
                    163:            __u8 m_i_frag;      /* Fragment number */
                    164:            __u8 m_i_fsize;     /* Fragment size */
                    165:            __u16 m_pad1;
                    166:            __u32 m_i_reserved2[2];
                    167:          }
                    168:        masix2;
                    169:       }
                    170:     osd2;                      /* OS dependent 2 */
                    171:   };
                    172: 
                    173: /* linux/posix_type.h */
                    174: typedef long linux_off_t;
                    175: 
                    176: /* linux/ext2fs.h */
                    177: #define EXT2_NAME_LEN 255
                    178: struct ext2_dir_entry
                    179:   {
                    180:     __u32 inode;               /* Inode number */
                    181:     __u16 rec_len;             /* Directory entry length */
                    182:     __u8 name_len;             /* Name length */
                    183:     __u8 file_type;
                    184:     char name[EXT2_NAME_LEN];  /* File name */
                    185:   };
                    186: 
                    187: /* ext2/super.c */
                    188: #define EXT2_SUPER_MAGIC      0xEF53   /* include/linux/ext2_fs.h */
                    189: #define EXT2_ROOT_INO              2   /* include/linux/ext2_fs.h */
                    190: #define PATH_MAX                1024   /* include/linux/limits.h */
                    191: #define MAX_LINK_COUNT             5   /* number of symbolic links to follow */
                    192: 
                    193: /* made up, these are pointers into FSYS_BUF */
                    194: /* read once, always stays there: */
                    195: #define SUPERBLOCK \
                    196:     ((struct ext2_super_block *)(FSYS_BUF))
                    197: #define GROUP_DESC \
                    198:     ((struct ext2_group_desc *) \
                    199:      ((char *)SUPERBLOCK + sizeof(struct ext2_super_block)))
                    200: #define INODE \
                    201:     ((struct ext2_inode *)((char *)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
                    202: #define DATABLOCK1 \
                    203:     ((char *)((char *)INODE + sizeof(struct ext2_inode)))
                    204: #define DATABLOCK2 \
                    205:     ((char *)((char *)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
                    206: 
                    207: /* linux/ext2_fs.h */
                    208: #define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
                    209: #define EXT2_ADDR_PER_BLOCK_BITS(s)    (log2(EXT2_ADDR_PER_BLOCK(s)))
                    210: 
                    211: /* linux/ext2_fs.h */
                    212: #define EXT2_BLOCK_SIZE_BITS(s)        (__le32_to_cpu((s)->s_log_block_size) + 10)
                    213: /* kind of from ext2/super.c */
                    214: #define EXT2_BLOCK_SIZE(s)     (1 << EXT2_BLOCK_SIZE_BITS(s))
                    215: /* linux/ext2fs.h */
                    216: #define EXT2_DESC_PER_BLOCK(s) \
                    217:      (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
                    218: /* linux/stat.h */
                    219: #define S_IFMT  00170000
                    220: #define S_IFLNK  0120000
                    221: #define S_IFREG  0100000
                    222: #define S_IFDIR  0040000
                    223: #define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
                    224: #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
                    225: #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
                    226: 
                    227: #ifdef E2DEBUG
                    228: void
                    229: dump_super(struct ext2_super_block *s)
                    230: {
                    231:     printf(" superblock 0x%x:\n", s);
                    232:     printf("  inodes=%d\n", __le32_to_cpu(s->s_inodes_count));
                    233:     printf("  blocks=%d\n", __le32_to_cpu(s->s_blocks_count));
                    234:     printf("  reserved=%d\n", __le32_to_cpu(s->s_r_blocks_count));
                    235:     printf("  i_free=%d\n", __le32_to_cpu(s->s_free_inodes_count));
                    236:     printf("  b_free=%d\n", __le32_to_cpu(s->s_free_blocks_count));
                    237:     printf("  first=%d\n", __le32_to_cpu(s->s_first_data_block));
                    238:     printf("  log_b_size=%d, b_size=%d\n", __le32_to_cpu(s->s_log_block_size), EXT2_BLOCK_SIZE(s));
                    239:     printf("  log_f_size=%d\n", __le32_to_cpu(s->s_log_frag_size));
                    240:     printf("  bpg=%d\n", __le32_to_cpu(s->s_blocks_per_group));
                    241:     printf("  fpg=%d\n", __le32_to_cpu(s->s_frags_per_group));
                    242:     printf("  ipg=%d\n", __le32_to_cpu(s->s_inodes_per_group));
                    243: }
                    244: 
                    245: void
                    246: dump_group_desc(struct ext2_group_desc *g)
                    247: {
                    248:     printf(" group_desc 0x%x:\n", g);
                    249:     printf("  b_bmap block=%d\n", __le32_to_cpu(g->bg_block_bitmap));
                    250:     printf("  i_bmap block=%d\n", __le32_to_cpu(g->bg_inode_bitmap));
                    251:     printf("  i_tab block=%d\n", __le32_to_cpu(g->bg_inode_table));
                    252:     printf("  free_blks=%d\n", __le16_to_cpu(g->bg_free_blocks_count));
                    253:     printf("  free_inodes=%d\n", __le16_to_cpu(g->bg_free_inodes_count));
                    254:     printf("  used_dirs=%d\n", __le16_to_cpu(g->bg_used_dirs_count));
                    255: }
                    256: 
                    257: void
                    258: dump_inode(struct ext2_inode *i)
                    259: {
                    260:     printf(" inode 0x%x:\n", i);
                    261:     printf("  mode=%o\n", __le16_to_cpu(i->i_mode));
                    262:     printf("  uid=%d\n", __le16_to_cpu(i->i_uid));
                    263:     printf("  gid=%d\n", __le16_to_cpu(i->i_gid));
                    264:     printf("  size=%d\n", __le32_to_cpu(i->i_size));
                    265:     printf("  atime=%d\n", __le32_to_cpu(i->i_atime));
                    266:     printf("  ctime=%d\n", __le32_to_cpu(i->i_ctime));
                    267:     printf("  mtime=%d\n", __le32_to_cpu(i->i_mtime));
                    268:     printf("  dtime=%d\n", __le32_to_cpu(i->i_dtime));
                    269:     printf("  links=%d\n", __le16_to_cpu(i->i_links_count));
                    270:     printf("  blocks=%d\n", __le32_to_cpu(i->i_blocks));
                    271:     printf("  flags=%d\n", __le32_to_cpu(i->i_flags));
                    272: }
                    273: 
                    274: void
                    275: dump_inode_data(unsigned char *inode, int len)
                    276: {
                    277:   static char hexdigit[] = "0123456789abcdef";
                    278:   unsigned char *i;
                    279:   for (i = inode;
                    280:        i < (inode + len);
                    281:        i++)
                    282:     {
                    283:       printf ("%c", hexdigit[*i >> 4]);
                    284:       printf ("%c", hexdigit[*i % 16]);
                    285:       if (!((i + 1 - inode) % 16))
                    286:        {
                    287:          printf ("\n");
                    288:        }
                    289:       else
                    290:        {
                    291:          printf (" ");
                    292:        }
                    293:     }
                    294: }
                    295: #endif
                    296: 
                    297: /* check filesystem types and read superblock into memory buffer */
                    298: int
                    299: ext2fs_mount (void)
                    300: {
                    301:   int retval = 1;
                    302: 
                    303:   if ((((current_drive & 0x80) || (current_slice != 0))
                    304:        && (current_slice != PC_SLICE_TYPE_EXT2FS)
                    305:        && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
                    306:        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
                    307:        && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
                    308:       || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
                    309:       || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
                    310:                   (char *) SUPERBLOCK)
                    311:       || __le16_to_cpu(SUPERBLOCK->s_magic) != EXT2_SUPER_MAGIC)
                    312:       retval = 0;
                    313: 
                    314:   return retval;
                    315: }
                    316: 
                    317: /* Takes a file system block number and reads it into BUFFER. */
                    318: static int
                    319: ext2_rdfsb (int fsblock, char * buffer)
                    320: {
                    321: #ifdef E2DEBUG
                    322:   printf ("ext2_rdfsb: fsblock %d, devblock %d, size %d\n", fsblock,
                    323:          fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
                    324:          EXT2_BLOCK_SIZE (SUPERBLOCK));
                    325: #endif /* E2DEBUG */
                    326:   return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
                    327:                  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
                    328: }
                    329: 
                    330: /* from
                    331:   ext2/inode.c:ext2_bmap()
                    332: */
                    333: /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
                    334:    a physical block (the location in the file system) via an inode. */
                    335: static int
                    336: ext2fs_block_map (int logical_block)
                    337: {
                    338: 
                    339: #ifdef E2DEBUG
                    340:   printf ("ext2fs_block_map(%d)\n", logical_block);
                    341: #endif /* E2DEBUG */
                    342: 
                    343:   /* if it is directly pointed to by the inode, return that physical addr */
                    344:   if (logical_block < EXT2_NDIR_BLOCKS)
                    345:     {
                    346: #ifdef E2DEBUG
                    347:       printf ("ext2fs_block_map: returning %d\n", __le32_to_cpu(INODE->i_block[logical_block]));
                    348: #endif /* E2DEBUG */
                    349:       return __le32_to_cpu(INODE->i_block[logical_block]);
                    350:     }
                    351:   /* else */
                    352:   logical_block -= EXT2_NDIR_BLOCKS;
                    353:   /* try the indirect block */
                    354:   if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
                    355:     {
                    356:       if (mapblock1 != 1
                    357:          && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_IND_BLOCK]), DATABLOCK1))
                    358:        {
                    359:          errnum = ERR_FSYS_CORRUPT;
                    360:          return -1;
                    361:        }
                    362:       mapblock1 = 1;
                    363:       return __le32_to_cpu(((__u32 *) DATABLOCK1)[logical_block]);
                    364:     }
                    365:   /* else */
                    366:   logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
                    367:   /* now try the double indirect block */
                    368:   if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
                    369:     {
                    370:       int bnum;
                    371:       if (mapblock1 != 2
                    372:          && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_DIND_BLOCK]), DATABLOCK1))
                    373:        {
                    374:          errnum = ERR_FSYS_CORRUPT;
                    375:          return -1;
                    376:        }
                    377:       mapblock1 = 2;
                    378:       if ((bnum = __le32_to_cpu(((__u32 *) DATABLOCK1)
                    379:                   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
                    380:          != mapblock2
                    381:          && !ext2_rdfsb (bnum, DATABLOCK2))
                    382:        {
                    383:          errnum = ERR_FSYS_CORRUPT;
                    384:          return -1;
                    385:        }
                    386:       mapblock2 = bnum;
                    387:       return __le32_to_cpu(((__u32 *) DATABLOCK2)
                    388:        [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
                    389:     }
                    390:   /* else */
                    391:   mapblock2 = -1;
                    392:   logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
                    393:   if (mapblock1 != 3
                    394:       && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1))
                    395:     {
                    396:       errnum = ERR_FSYS_CORRUPT;
                    397:       return -1;
                    398:     }
                    399:   mapblock1 = 3;
                    400:   if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK1)
                    401:                   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
                    402:                                      * 2)]),
                    403:                   DATABLOCK2))
                    404:     {
                    405:       errnum = ERR_FSYS_CORRUPT;
                    406:       return -1;
                    407:     }
                    408:   if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK2)
                    409:                   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
                    410:                    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]),
                    411:                   DATABLOCK2))
                    412:     {
                    413:       errnum = ERR_FSYS_CORRUPT;
                    414:       return -1;
                    415:     }
                    416:   return __le32_to_cpu(((__u32 *) DATABLOCK2)
                    417:     [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
                    418: }
                    419: 
                    420: /* preconditions: all preconds of ext2fs_block_map */
                    421: int
                    422: ext2fs_read (char *buf, int len)
                    423: {
                    424:   int logical_block;
                    425:   int offset;
                    426:   int map;
                    427:   int ret = 0;
                    428:   int size = 0;
                    429: 
                    430: #ifdef E2DEBUG
                    431:   printf("ext2fs_read(0x%x, %d)\n", buf, len);
                    432:   dump_inode(INODE);
                    433:   dump_inode_data((unsigned char *)INODE, sizeof (struct ext2_inode));
                    434: #endif /* E2DEBUG */
                    435:   while (len > 0)
                    436:     {
                    437:       /* find the (logical) block component of our location */
                    438:       logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
                    439:       offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
                    440:       map = ext2fs_block_map (logical_block);
                    441: #ifdef E2DEBUG
                    442:       printf ("map=%d\n", map);
                    443: #endif /* E2DEBUG */
                    444:       if (map < 0)
                    445:        break;
                    446: 
                    447:       size = EXT2_BLOCK_SIZE (SUPERBLOCK);
                    448:       size -= offset;
                    449:       if (size > len)
                    450:        size = len;
                    451: 
                    452:       disk_read_func = disk_read_hook;
                    453: 
                    454:       devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
                    455:               offset, size, buf);
                    456: 
                    457:       disk_read_func = NULL;
                    458: 
                    459:       buf += size;
                    460:       len -= size;
                    461:       filepos += size;
                    462:       ret += size;
                    463:     }
                    464: 
                    465:   if (errnum)
                    466:     ret = 0;
                    467: 
                    468:   return ret;
                    469: }
                    470: 
                    471: 
                    472: /* Based on:
                    473:    def_blk_fops points to
                    474:    blkdev_open, which calls (I think):
                    475:    sys_open()
                    476:    do_open()
                    477:    open_namei()
                    478:    dir_namei() which accesses current->fs->root
                    479:      fs->root was set during original mount:
                    480:      (something)... which calls (I think):
                    481:      ext2_read_super()
                    482:      iget()
                    483:      __iget()
                    484:      read_inode()
                    485:      ext2_read_inode()
                    486:        uses desc_per_block_bits, which is set in ext2_read_super()
                    487:        also uses group descriptors loaded during ext2_read_super()
                    488:    lookup()
                    489:    ext2_lookup()
                    490:    ext2_find_entry()
                    491:    ext2_getblk()
                    492: 
                    493: */
                    494: 
                    495: /* preconditions: ext2fs_mount already executed, therefore supblk in buffer
                    496:  *   known as SUPERBLOCK
                    497:  * returns: 0 if error, nonzero iff we were able to find the file successfully
                    498:  * postconditions: on a nonzero return, buffer known as INODE contains the
                    499:  *   inode of the file we were trying to look up
                    500:  * side effects: messes up GROUP_DESC buffer area
                    501:  */
                    502: int
                    503: ext2fs_dir (char *dirname)
                    504: {
                    505:   int current_ino = EXT2_ROOT_INO;     /* start at the root */
                    506:   int updir_ino = current_ino; /* the parent of the current directory */
                    507:   int group_id;                        /* which group the inode is in */
                    508:   int group_desc;              /* fs pointer to that group */
                    509:   int desc;                    /* index within that group */
                    510:   int ino_blk;                 /* fs pointer of the inode's information */
                    511:   int str_chk = 0;             /* used to hold the results of a string compare */
                    512:   struct ext2_group_desc *gdp;
                    513:   struct ext2_inode *raw_inode;        /* inode info corresponding to current_ino */
                    514: 
                    515:   char linkbuf[PATH_MAX];      /* buffer for following symbolic links */
                    516:   int link_count = 0;
                    517: 
                    518:   char *rest;
                    519:   char ch;                     /* temp char holder */
                    520: 
                    521:   int off;                     /* offset within block of directory entry (off mod blocksize) */
                    522:   int loc;                     /* location within a directory */
                    523:   int blk;                     /* which data blk within dir entry (off div blocksize) */
                    524:   long map;                    /* fs pointer of a particular block from dir entry */
                    525:   struct ext2_dir_entry *dp;   /* pointer to directory entry */
                    526: 
                    527:   /* loop invariants:
                    528:      current_ino = inode to lookup
                    529:      dirname = pointer to filename component we are cur looking up within
                    530:      the directory known pointed to by current_ino (if any)
                    531:    */
                    532: 
                    533: #ifdef E2DEBUG
                    534:   printf("****** ext2fs_dir(%s)\n", dirname);
                    535:   dump_super(SUPERBLOCK);
                    536: #endif /* E2DEBUG */
                    537: 
                    538:   while (1)
                    539:     {
                    540: #ifdef E2DEBUG
                    541:       printf ("ext2fs_dir: inode %d\n", current_ino);
                    542:       printf ("ext2fs_dir: dirname=%s\n", dirname);
                    543: #endif /* E2DEBUG */
                    544: 
                    545:       /* look up an inode */
                    546:       group_id = (current_ino - 1) / __le32_to_cpu(SUPERBLOCK->s_inodes_per_group);
                    547:       group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
                    548:       desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
                    549: #ifdef E2DEBUG
                    550:       printf ("ext2fs_dir: ipg=%d, dpb=%d\n", __le32_to_cpu(SUPERBLOCK->s_inodes_per_group),
                    551:              EXT2_DESC_PER_BLOCK (SUPERBLOCK));
                    552:       printf ("ext2fs_dir: group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);
                    553: #endif /* E2DEBUG */
                    554:       if (!ext2_rdfsb (
                    555:                        (WHICH_SUPER + group_desc + __le32_to_cpu(SUPERBLOCK->s_first_data_block)),
                    556:                        (char*) GROUP_DESC))
                    557:        {
                    558:          return 0;
                    559:        }
                    560: 
                    561: #ifdef E2DEBUG
                    562:       dump_group_desc(GROUP_DESC);
                    563: #endif /* E2DEBUG */
                    564: 
                    565:       gdp = GROUP_DESC;
                    566:       ino_blk = __le32_to_cpu(gdp[desc].bg_inode_table) +
                    567:        (((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group))
                    568:         >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
                    569: #ifdef E2DEBUG
                    570:       printf ("ext2fs_dir: itab_blk=%d, i_in_grp=%d, log2=%d\n",
                    571:         __le32_to_cpu(gdp[desc].bg_inode_table),
                    572:         ((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)),
                    573:         log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
                    574:       printf ("ext2fs_dir: inode table fsblock=%d\n", ino_blk);
                    575: #endif /* E2DEBUG */
                    576:       if (!ext2_rdfsb (ino_blk, (char *)INODE))
                    577:        {
                    578:          return 0;
                    579:        }
                    580: 
                    581:       /* reset indirect blocks! */
                    582:       mapblock2 = mapblock1 = -1;
                    583: 
                    584:       raw_inode = INODE +
                    585:        ((current_ino - 1)
                    586:         & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
                    587: #ifdef E2DEBUG
                    588:       printf ("ext2fs_dir: ipb=%d, sizeof(inode)=%d\n",
                    589:              (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
                    590:              sizeof (struct ext2_inode));
                    591:       printf ("ext2fs_dir: inode=%x, raw_inode=%x\n", INODE, raw_inode);
                    592:       printf ("ext2fs_dir: offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
                    593:       dump_inode(raw_inode);
                    594:       dump_inode_data((unsigned char *)INODE, EXT2_BLOCK_SIZE(SUPERBLOCK));
                    595:       printf ("ext2fs_dir: first word=%x\n", *((int *) raw_inode));
                    596: #endif /* E2DEBUG */
                    597: 
                    598:       /* copy inode to fixed location */
                    599:       memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
                    600: 
                    601: #ifdef E2DEBUG
                    602:       dump_inode(INODE);
                    603:       printf ("ext2fs_dir: first word=%x\n", *((int *) INODE));
                    604: #endif /* E2DEBUG */
                    605: 
                    606:       /* If we've got a symbolic link, then chase it. */
                    607:       if (S_ISLNK (__le16_to_cpu(INODE->i_mode)))
                    608:        {
                    609:          int len;
                    610:          if (++link_count > MAX_LINK_COUNT)
                    611:            {
                    612:              errnum = ERR_SYMLINK_LOOP;
                    613:              return 0;
                    614:            }
                    615: 
                    616:          /* Find out how long our remaining name is. */
                    617:          len = 0;
                    618:          while (dirname[len] && !isspace (dirname[len]))
                    619:            len++;
                    620: 
                    621:          /* Get the symlink size. */
                    622:          filemax = __le32_to_cpu(INODE->i_size);
                    623:          if (filemax + len > sizeof (linkbuf) - 2)
                    624:            {
                    625:              errnum = ERR_FILELENGTH;
                    626:              return 0;
                    627:            }
                    628: 
                    629:          if (len)
                    630:            {
                    631:              /* Copy the remaining name to the end of the symlink data.
                    632:                 Note that DIRNAME and LINKBUF may overlap! */
                    633:              memmove (linkbuf + filemax, dirname, len);
                    634:            }
                    635:          linkbuf[filemax + len] = '\0';
                    636: 
                    637:          /* Read the symlink data. */
                    638:          if (__le32_to_cpu(INODE->i_blocks))
                    639:            {
                    640:              /* Read the necessary blocks, and reset the file pointer. */
                    641:              len = file_read (linkbuf, filemax);
                    642:              filepos = 0;
                    643:              if (!len)
                    644:                return 0;
                    645:            }
                    646:          else
                    647:            {
                    648:              /* Copy the data directly from the inode. */
                    649:              len = filemax;
                    650:              memmove (linkbuf, (char *) INODE->i_block, len);
                    651:            }
                    652: 
                    653: #ifdef E2DEBUG
                    654:          printf ("ext2fs_dir: symlink=%s\n", linkbuf);
                    655: #endif
                    656: 
                    657:          dirname = linkbuf;
                    658:          if (*dirname == '/')
                    659:            {
                    660:              /* It's an absolute link, so look it up in root. */
                    661:              current_ino = EXT2_ROOT_INO;
                    662:              updir_ino = current_ino;
                    663:            }
                    664:          else
                    665:            {
                    666:              /* Relative, so look it up in our parent directory. */
                    667:              current_ino = updir_ino;
                    668:            }
                    669: 
                    670:          /* Try again using the new name. */
                    671:          continue;
                    672:        }
                    673: 
                    674:       /* if end of filename, INODE points to the file's inode */
                    675:       if (!*dirname || isspace (*dirname))
                    676:        {
                    677:          if (!S_ISREG (__le16_to_cpu(INODE->i_mode)))
                    678:            {
                    679:              errnum = ERR_BAD_FILETYPE;
                    680:              return 0;
                    681:            }
                    682: 
                    683:          filemax = __le32_to_cpu(INODE->i_size);
                    684:          return 1;
                    685:        }
                    686: 
                    687:       /* else we have to traverse a directory */
                    688:       updir_ino = current_ino;
                    689: 
                    690:       /* skip over slashes */
                    691:       while (*dirname == '/')
                    692:        dirname++;
                    693: 
                    694:       /* if this isn't a directory of sufficient size to hold our file, abort */
                    695:       if (!(__le32_to_cpu(INODE->i_size)) || !S_ISDIR (__le16_to_cpu(INODE->i_mode)))
                    696:        {
                    697:          errnum = ERR_BAD_FILETYPE;
                    698:          return 0;
                    699:        }
                    700: 
                    701:       /* skip to next slash or end of filename (space) */
                    702:       for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
                    703:           rest++);
                    704: 
                    705:       /* look through this directory and find the next filename component */
                    706:       /* invariant: rest points to slash after the next filename component */
                    707:       *rest = 0;
                    708:       loc = 0;
                    709: 
                    710:       do
                    711:        {
                    712: 
                    713: #ifdef E2DEBUG
                    714:          printf ("ext2fs_dir: dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
                    715: #endif /* E2DEBUG */
                    716: 
                    717:          /* if our location/byte offset into the directory exceeds the size,
                    718:             give up */
                    719:          if (loc >= __le32_to_cpu(INODE->i_size))
                    720:            {
                    721:              if (print_possibilities < 0)
                    722:                {
                    723: # if 0
                    724:                  putchar ('\n');
                    725: # endif
                    726:                }
                    727:              else
                    728:                {
                    729:                  errnum = ERR_FILE_NOT_FOUND;
                    730:                  *rest = ch;
                    731:                }
                    732:              return (print_possibilities < 0);
                    733:            }
                    734: 
                    735:          /* else, find the (logical) block component of our location */
                    736:          blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
                    737: 
                    738:          /* we know which logical block of the directory entry we are looking
                    739:             for, now we have to translate that to the physical (fs) block on
                    740:             the disk */
                    741:          map = ext2fs_block_map (blk);
                    742: #ifdef E2DEBUG
                    743:          printf ("ext2fs_dir: fs block=%d\n", map);
                    744: #endif /* E2DEBUG */
                    745:          mapblock2 = -1;
                    746:          if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
                    747:            {
                    748:              errnum = ERR_FSYS_CORRUPT;
                    749:              *rest = ch;
                    750:              return 0;
                    751:            }
                    752:          off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
                    753:          dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
                    754:          /* advance loc prematurely to next on-disk directory entry  */
                    755:          loc += __le16_to_cpu(dp->rec_len);
                    756: 
                    757:          /* NOTE: ext2fs filenames are NOT null-terminated */
                    758: 
                    759: #ifdef E2DEBUG
                    760:          printf ("ext2fs_dir: directory entry ino=%d\n", __le32_to_cpu(dp->inode));
                    761:          if (__le32_to_cpu(dp->inode))
                    762:            printf ("entry=%s\n", dp->name);
                    763: #endif /* E2DEBUG */
                    764: 
                    765:          if (__le32_to_cpu(dp->inode))
                    766:            {
                    767:              int saved_c = dp->name[dp->name_len];
                    768: 
                    769:              dp->name[dp->name_len] = 0;
                    770:              str_chk = substring (dirname, dp->name);
                    771: 
                    772: # ifndef STAGE1_5
                    773:              if (print_possibilities && ch != '/'
                    774:                  && (!*dirname || str_chk <= 0))
                    775:                {
                    776:                  if (print_possibilities > 0)
                    777:                    print_possibilities = -print_possibilities;
                    778:                  print_a_completion (dp->name);
                    779:                }
                    780: # endif
                    781: 
                    782:              dp->name[dp->name_len] = saved_c;
                    783:            }
                    784: 
                    785:        }
                    786:       while (!__le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/')));
                    787: 
                    788:       current_ino = __le32_to_cpu(dp->inode);
                    789:       *(dirname = rest) = ch;
                    790:     }
                    791:   /* never get here */
                    792: }
                    793: 
                    794: #endif /* FSYS_EXT2_FS */

unix.superglobalmegacorp.com

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