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