Annotation of qemu/roms/openbios/fs/ext2/ext2_utils.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *
                      3:  * (c) 2008-2009 Laurent Vivier <[email protected]>
                      4:  *
                      5:  * This file has been copied from EMILE, http://emile.sf.net
                      6:  *
                      7:  */
                      8: 
                      9: #include "libext2.h"
                     10: #include "ext2_utils.h"
                     11: #include "libopenbios/bindings.h"
                     12: #include "libc/diskio.h"
                     13: #include "libc/byteorder.h"
                     14: 
                     15: int ext2_probe(int fd, long long offset)
                     16: {
                     17:        struct ext2_super_block *super;
                     18: 
                     19:        super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block));
                     20:        seek_io(fd, 2 * 512 + offset);
                     21:        read_io(fd, super, sizeof (*super));
                     22: 
                     23:        if (__le16_to_cpu(super->s_magic) != EXT2_SUPER_MAGIC) {
                     24:                free(super);
                     25:                return 0;
                     26:        }
                     27: 
                     28:        free(super);
                     29:        return -1;
                     30: }
                     31: 
                     32: void ext2_get_super(int fd, struct ext2_super_block *super)
                     33: {
                     34:        seek_io(fd, 2 * 512);
                     35:        read_io(fd, super, sizeof (*super));
                     36: 
                     37:        super->s_inodes_count = __le32_to_cpu(super->s_inodes_count);
                     38:        super->s_blocks_count = __le32_to_cpu(super->s_blocks_count);
                     39:        super->s_r_blocks_count = __le32_to_cpu(super->s_r_blocks_count);
                     40:        super->s_free_blocks_count = __le32_to_cpu(super->s_free_blocks_count);
                     41:        super->s_free_inodes_count = __le32_to_cpu(super->s_free_inodes_count);
                     42:        super->s_first_data_block = __le32_to_cpu(super->s_first_data_block);
                     43:        super->s_log_block_size = __le32_to_cpu(super->s_log_block_size);
                     44:        super->s_log_frag_size = __le32_to_cpu(super->s_log_frag_size);
                     45:        super->s_blocks_per_group = __le32_to_cpu(super->s_blocks_per_group);
                     46:        super->s_frags_per_group = __le32_to_cpu(super->s_frags_per_group);
                     47:        super->s_inodes_per_group = __le32_to_cpu(super->s_inodes_per_group);
                     48:        super->s_mtime = __le32_to_cpu(super->s_mtime);
                     49:        super->s_wtime = __le32_to_cpu(super->s_wtime);
                     50:        super->s_mnt_count = __le16_to_cpu(super->s_mnt_count);
                     51:        super->s_max_mnt_count = __le16_to_cpu(super->s_max_mnt_count);
                     52:        super->s_magic = __le16_to_cpu(super->s_magic);
                     53:        super->s_state = __le16_to_cpu(super->s_state);
                     54:        super->s_errors = __le16_to_cpu(super->s_errors);
                     55:        super->s_minor_rev_level = __le16_to_cpu(super->s_minor_rev_level);
                     56:        super->s_lastcheck = __le32_to_cpu(super->s_lastcheck);
                     57:        super->s_checkinterval = __le32_to_cpu(super->s_checkinterval);
                     58:        super->s_creator_os = __le32_to_cpu(super->s_creator_os);
                     59:        super->s_rev_level = __le32_to_cpu(super->s_rev_level);
                     60:        super->s_def_resuid = __le16_to_cpu(super->s_def_resuid);
                     61:        super->s_def_resgid = __le16_to_cpu(super->s_def_resgid);
                     62:        super->s_first_ino = __le32_to_cpu(super->s_first_ino);
                     63:        super->s_inode_size = __le16_to_cpu(super->s_inode_size);
                     64:        super->s_block_group_nr = __le16_to_cpu(super->s_block_group_nr);
                     65:        super->s_feature_compat = __le32_to_cpu(super->s_feature_compat);
                     66:        super->s_feature_incompat = __le32_to_cpu(super->s_feature_incompat);
                     67:        super->s_feature_ro_compat = __le32_to_cpu(super->s_feature_ro_compat);
                     68:        super->s_algorithm_usage_bitmap =
                     69:                                __le32_to_cpu(super->s_algorithm_usage_bitmap);
                     70:        super->s_journal_inum = __le32_to_cpu(super->s_journal_inum);
                     71:        super->s_journal_dev = __le32_to_cpu(super->s_journal_dev);
                     72:        super->s_last_orphan = __le32_to_cpu(super->s_last_orphan);
                     73:        super->s_hash_seed[0] = __le32_to_cpu(super->s_hash_seed[0]);
                     74:        super->s_hash_seed[1] = __le32_to_cpu(super->s_hash_seed[1]);
                     75:        super->s_hash_seed[2] = __le32_to_cpu(super->s_hash_seed[2]);
                     76:        super->s_hash_seed[3] = __le32_to_cpu(super->s_hash_seed[3]);
                     77:        super->s_default_mount_opts =
                     78:                                __le32_to_cpu(super->s_default_mount_opts);
                     79:        super->s_first_meta_bg = __le32_to_cpu(super->s_first_meta_bg);
                     80: }
                     81: 
                     82: void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock)
                     83: {
                     84:        long long offset;
                     85: 
                     86:        if (fsblock == volume->current)
                     87:                return;
                     88: 
                     89:        volume->current = fsblock;
                     90:        offset = fsblock * EXT2_BLOCK_SIZE(volume->super);
                     91: 
                     92:        seek_io(volume->fd, offset);
                     93:        read_io(volume->fd, volume->buffer, EXT2_BLOCK_SIZE(volume->super));
                     94: }
                     95: 
                     96: void ext2_get_group_desc(ext2_VOLUME* volume,
                     97:                   int group_id, struct ext2_group_desc *gdp)
                     98: {
                     99:        unsigned int block, offset;
                    100:        struct ext2_group_desc *le_gdp;
                    101: 
                    102:        block = 1 + volume->super->s_first_data_block;
                    103:        block += group_id / EXT2_DESC_PER_BLOCK(volume->super);
                    104:        ext2_read_block(volume,  block);
                    105: 
                    106:        offset = group_id % EXT2_DESC_PER_BLOCK(volume->super);
                    107:        offset *= sizeof(*gdp);
                    108: 
                    109:        le_gdp = (struct ext2_group_desc *)(volume->buffer + offset);
                    110: 
                    111:        gdp->bg_block_bitmap = __le32_to_cpu(le_gdp->bg_block_bitmap);
                    112:        gdp->bg_inode_bitmap = __le32_to_cpu(le_gdp->bg_inode_bitmap);
                    113:        gdp->bg_inode_table = __le32_to_cpu(le_gdp->bg_inode_table);
                    114:        gdp->bg_free_blocks_count = __le16_to_cpu(le_gdp->bg_free_blocks_count);
                    115:        gdp->bg_free_inodes_count = __le16_to_cpu(le_gdp->bg_free_inodes_count);
                    116:        gdp->bg_used_dirs_count = __le16_to_cpu(le_gdp->bg_used_dirs_count);
                    117: }
                    118: 
                    119: int ext2_get_inode(ext2_VOLUME* volume,
                    120:                    unsigned int ino, struct ext2_inode *inode)
                    121: {
                    122:        struct ext2_group_desc desc;
                    123:        unsigned int block;
                    124:        unsigned int group_id;
                    125:        unsigned int offset;
                    126:        struct ext2_inode *le_inode;
                    127:        int i;
                    128: 
                    129:        ino--;
                    130: 
                    131:        group_id = ino / EXT2_INODES_PER_GROUP(volume->super);
                    132:        ext2_get_group_desc(volume, group_id, &desc);
                    133: 
                    134:        ino %= EXT2_INODES_PER_GROUP(volume->super);
                    135: 
                    136:        block = desc.bg_inode_table;
                    137:        block += ino / (EXT2_BLOCK_SIZE(volume->super) /
                    138:                        EXT2_INODE_SIZE(volume->super));
                    139:        ext2_read_block(volume, block);
                    140: 
                    141:        offset = ino % (EXT2_BLOCK_SIZE(volume->super) /
                    142:                        EXT2_INODE_SIZE(volume->super));
                    143:        offset *= EXT2_INODE_SIZE(volume->super);
                    144: 
                    145:        le_inode = (struct ext2_inode *)(volume->buffer + offset);
                    146: 
                    147:        inode->i_mode = __le16_to_cpu(le_inode->i_mode);
                    148:        inode->i_uid = __le16_to_cpu(le_inode->i_uid);
                    149:        inode->i_size = __le32_to_cpu(le_inode->i_size);
                    150:        inode->i_atime = __le32_to_cpu(le_inode->i_atime);
                    151:        inode->i_ctime = __le32_to_cpu(le_inode->i_ctime);
                    152:        inode->i_mtime = __le32_to_cpu(le_inode->i_mtime);
                    153:        inode->i_dtime = __le32_to_cpu(le_inode->i_dtime);
                    154:        inode->i_gid = __le16_to_cpu(le_inode->i_gid);
                    155:        inode->i_links_count = __le16_to_cpu(le_inode->i_links_count);
                    156:        inode->i_blocks = __le32_to_cpu(le_inode->i_blocks);
                    157:        inode->i_flags = __le32_to_cpu(le_inode->i_flags);
                    158:        if (S_ISLNK(inode->i_mode)) {
                    159:                memcpy(inode->i_block, le_inode->i_block, EXT2_N_BLOCKS * 4);
                    160:        } else {
                    161:                for (i = 0; i < EXT2_N_BLOCKS; i++)
                    162:                        inode->i_block[i] = __le32_to_cpu(le_inode->i_block[i]);
                    163:         }
                    164:        inode->i_generation = __le32_to_cpu(le_inode->i_generation);
                    165:        inode->i_file_acl = __le32_to_cpu(le_inode->i_file_acl);
                    166:        inode->i_dir_acl = __le32_to_cpu(le_inode->i_dir_acl);
                    167:        inode->i_faddr = __le32_to_cpu(le_inode->i_faddr);
                    168:        inode->osd2.linux2.l_i_frag = le_inode->osd2.linux2.l_i_frag;
                    169:        inode->osd2.linux2.l_i_fsize = le_inode->osd2.linux2.l_i_fsize;
                    170:        inode->osd2.linux2.l_i_uid_high =
                    171:                        __le16_to_cpu(le_inode->osd2.linux2.l_i_uid_high);
                    172:        inode->osd2.linux2.l_i_gid_high =
                    173:                        __le16_to_cpu(le_inode->osd2.linux2.l_i_gid_high);
                    174:        return 0;
                    175: }
                    176: 
                    177: unsigned int ext2_get_block_addr(ext2_VOLUME* volume, struct ext2_inode *inode,
                    178:                                 unsigned int logical)
                    179: {
                    180:        unsigned int physical;
                    181:        unsigned int addr_per_block;
                    182: 
                    183:        /* direct */
                    184: 
                    185:        if (logical < EXT2_NDIR_BLOCKS) {
                    186:                physical = inode->i_block[logical];
                    187:                return physical;
                    188:        }
                    189: 
                    190:        /* indirect */
                    191: 
                    192:        logical -= EXT2_NDIR_BLOCKS;
                    193: 
                    194:        addr_per_block = EXT2_ADDR_PER_BLOCK (volume->super);
                    195:        if (logical < addr_per_block) {
                    196:                ext2_read_block(volume, inode->i_block[EXT2_IND_BLOCK]);
                    197:                physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical]);
                    198:                return physical;
                    199:        }
                    200: 
                    201:        /* double indirect */
                    202: 
                    203:        logical -=  addr_per_block;
                    204: 
                    205:        if (logical < addr_per_block * addr_per_block) {
                    206:                ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
                    207:                physical = __le32_to_cpu(((unsigned int *)volume->buffer)
                    208:                                                [logical / addr_per_block]);
                    209:                ext2_read_block(volume, physical);
                    210:                physical = __le32_to_cpu(((unsigned int *)volume->buffer)
                    211:                                                [logical % addr_per_block]);
                    212:                return physical;
                    213:        }
                    214: 
                    215:        /* triple indirect */
                    216: 
                    217:        logical -= addr_per_block * addr_per_block;
                    218:        ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
                    219:        physical = __le32_to_cpu(((unsigned int *)volume->buffer)
                    220:                                [logical / (addr_per_block * addr_per_block)]);
                    221:        ext2_read_block(volume, physical);
                    222:        logical = logical % (addr_per_block * addr_per_block);
                    223:        physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical / addr_per_block]);
                    224:        ext2_read_block(volume, physical);
                    225:        physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical % addr_per_block]);
                    226:        return physical;
                    227: }
                    228: 
                    229: int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode,
                    230:                   off_t offset, char *buffer, size_t length)
                    231: {
                    232:        unsigned int logical, physical;
                    233:        int blocksize = EXT2_BLOCK_SIZE(volume->super);
                    234:        int shift;
                    235:        size_t read;
                    236: 
                    237:        if (offset >= inode->i_size)
                    238:                return -1;
                    239: 
                    240:        if (offset + length >= inode->i_size)
                    241:                length = inode->i_size - offset;
                    242: 
                    243:        read = 0;
                    244:        logical = offset / blocksize;
                    245:        shift = offset % blocksize;
                    246: 
                    247:        if (shift) {
                    248:                physical = ext2_get_block_addr(volume, inode, logical);
                    249:                ext2_read_block(volume, physical);
                    250: 
                    251:                if (length < blocksize - shift) {
                    252:                        memcpy(buffer, volume->buffer + shift, length);
                    253:                        return length;
                    254:                }
                    255:                read += blocksize - shift;
                    256:                memcpy(buffer, volume->buffer + shift, read);
                    257: 
                    258:                buffer += read;
                    259:                length -= read;
                    260:                logical++;
                    261:        }
                    262: 
                    263:        while (length) {
                    264:                physical = ext2_get_block_addr(volume, inode, logical);
                    265:                ext2_read_block(volume, physical);
                    266: 
                    267:                if (length < blocksize) {
                    268:                        memcpy(buffer, volume->buffer, length);
                    269:                        read += length;
                    270:                        return read;
                    271:                }
                    272:                memcpy(buffer, volume->buffer, blocksize);
                    273: 
                    274:                buffer += blocksize;
                    275:                length -= blocksize;
                    276:                read += blocksize;
                    277:                logical++;
                    278:        }
                    279: 
                    280:        return read;
                    281: }
                    282: 
                    283: off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode,
                    284:                     off_t index, struct ext2_dir_entry_2 *entry)
                    285: {
                    286:        int ret;
                    287: 
                    288:        ret = ext2_read_data(volume, inode, index,
                    289:                             (char*)entry, sizeof(*entry));
                    290:        if (ret == -1)
                    291:                return -1;
                    292: 
                    293:         entry->inode = __le32_to_cpu(entry->inode);
                    294:         entry->rec_len = __le16_to_cpu(entry->rec_len);
                    295:        return index + entry->rec_len;
                    296: }
                    297: 
                    298: unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name)
                    299: {
                    300:        struct ext2_inode inode;
                    301:        int ret;
                    302:        unsigned int ino;
                    303:        off_t index;
                    304:        struct ext2_dir_entry_2 entry;
                    305: 
                    306:        ino = EXT2_ROOT_INO;
                    307:        while(1) {
                    308:                while (*name == '\\')
                    309:                        name++;
                    310:                if (!*name)
                    311:                    break;
                    312:                ret = ext2_get_inode(volume, ino, &inode);
                    313:                if (ret == -1)
                    314:                        return 0;
                    315:                index = 0;
                    316:                while (1) {
                    317:                        index = ext2_dir_entry(volume, &inode, index, &entry);
                    318:                        if (index == -1)
                    319:                                return 0;
                    320:                        ret = strncmp(name, entry.name, entry.name_len);
                    321:                        if (ret == 0  &&
                    322:                            (name[entry.name_len] == 0 ||
                    323:                             name[entry.name_len] == '\\')) {
                    324:                                ino = entry.inode;
                    325:                                break;
                    326:                        }
                    327:                }
                    328:                name += entry.name_len;
                    329:        }
                    330: 
                    331:        return ino;
                    332: }

unix.superglobalmegacorp.com

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