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