Changeset ad34feb in mainline


Ignore:
Timestamp:
2011-02-23T23:07:28Z (13 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
102d400
Parents:
a54af66
Message:

Implement reading of blocks from inode in libext2

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/ext2info/ext2info.c

    ra54af66 rad34feb  
    5656static void print_block_groups(ext2_filesystem_t *);
    5757static void print_block_group(ext2_block_group_t *);
    58 static void print_inode_by_number(ext2_filesystem_t *, uint32_t);
     58static void print_inode_by_number(ext2_filesystem_t *, uint32_t, bool, uint32_t);
    5959static void print_inode(ext2_filesystem_t *, ext2_inode_t *);
     60static void print_inode_data(ext2_filesystem_t *, ext2_inode_t *, uint32_t);
    6061
    6162#define ARG_SUPERBLOCK 1
     
    6364#define ARG_INODE 4
    6465#define ARG_STRICT_CHECK 8
     66#define ARG_INODE_DATA 16
    6567#define ARG_COMMON (ARG_SUPERBLOCK | ARG_BLOCK_GROUPS)
    6668#define ARG_ALL (ARG_COMMON | ARG_INODE)
     
    7779        int arg_flags;
    7880        uint32_t inode = 0;
     81        uint32_t inode_data = 0;
    7982       
    8083        arg_flags = 0;
     
    120123                arg_flags |= ARG_INODE;
    121124                --argc; ++argv;
     125               
     126                if (str_cmp(*argv, "--inode-data") == 0) {
     127                        --argc; ++argv;
     128                        if (argc == 0) {
     129                                printf(NAME ": Argument expected for --inode-data\n");
     130                                return 2;
     131                        }
     132                       
     133                        inode_data = strtol(*argv, &endptr, 10);
     134                        if (*endptr != '\0') {
     135                                printf(NAME ": Error, invalid argument for --inode-data.\n");
     136                                syntax_print();
     137                                return 1;
     138                        }
     139                       
     140                        arg_flags |= ARG_INODE_DATA;
     141                        --argc; ++argv;
     142                }
    122143        }
    123144
     
    164185       
    165186        if (arg_flags & ARG_INODE) {
    166                 print_inode_by_number(&filesystem, inode);
     187                print_inode_by_number(&filesystem, inode, arg_flags & ARG_INODE_DATA,
     188                    inode_data);
    167189        }
    168190
     
    175197static void syntax_print(void)
    176198{
    177         printf("syntax: ext2info --strict-check --superblock --block-groups --inode <i-number> <device_name>\n");
     199        printf("syntax: ext2info [--strict-check] [--superblock] [--block-groups] "
     200            "[--inode <i-number> [--inode-data <block-number>]] <device_name>\n");
    178201}
    179202
     
    322345}
    323346
    324 void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode)
     347void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode,
     348    bool print_data, uint32_t data)
    325349{
    326350        int rc;
     
    336360       
    337361        print_inode(fs, inode_ref->inode);
     362        if (print_data) {
     363                print_inode_data(fs, inode_ref->inode, data);
     364        }
    338365       
    339366        rc = ext2_filesystem_put_inode_ref(inode_ref);
     
    355382        const char *type;
    356383        uint32_t block;
     384        uint32_t total_blocks;
    357385        int i;
    358386        bool all_blocks = false;
     
    365393        usage_count = ext2_inode_get_usage_count(inode);
    366394        flags = ext2_inode_get_flags(inode);
     395        total_blocks = ext2_inode_get_reserved_blocks(fs->superblock, inode);
    367396       
    368397        type = "Unknown";
     
    390419       
    391420        access = mode & EXT2_INODE_MODE_ACCESS_MASK;
     421       
    392422       
    393423        printf("  Mode: %08x (Type: %s, Access bits: %04ho)\n", mode, type, access);
     
    397427        printf("  Usage (link) count: %u\n", usage_count);
    398428        printf("  Flags: %u\n", flags);
     429        printf("  Total allocated blocks: %u\n", total_blocks);
    399430        printf("  Block list: ");
    400431        for (i = 0; i < 12; i++) {
     
    406437                printf("%u ", block);
    407438        }
     439        all_blocks = all_blocks || ext2_inode_get_indirect_block(inode, 0) == 0;
    408440        if (!all_blocks) {
    409441                printf(" and more...");
    410442        }
    411443        printf("\n");
     444}
     445
     446void print_inode_data(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t data)
     447{
     448        int rc;
     449        uint32_t data_block_index;
     450        block_t *block;
     451        size_t i;
     452        unsigned char c;
     453       
     454        rc = ext2_filesystem_get_inode_data_block_index(fs, inode, data,
     455            &data_block_index);
     456       
     457        if (rc != EOK) {
     458                printf("Failed getting data block #%u\n", data);
     459                return;
     460        }
     461       
     462        printf("Data for inode contents block #%u is located in filesystem "
     463            "block %u\n", data, data_block_index);
     464       
     465        printf("Data preview (only printable characters):\n");
     466       
     467        rc = block_get(&block, fs->device, data_block_index, 0);
     468        if (rc != EOK) {
     469                printf("Failed reading filesystem block %u\n", data_block_index);
     470                return;
     471        }
     472       
     473        for (i = 0; i < block->size; i++) {
     474                c = ((unsigned char *)block->data)[i];
     475                if (c >= 32 && c < 127) {
     476                        putchar(c);
     477                }
     478                else {
     479                        putchar('.');
     480                }
     481        }
     482       
     483        printf("\n");   
     484       
     485        rc = block_put(block);
     486        if (rc != EOK) {
     487                printf("Failed putting filesystem block\n");
     488        }
     489       
    412490}
    413491
  • uspace/lib/ext2/libext2_filesystem.c

    ra54af66 rad34feb  
    4141#include <libblock.h>
    4242#include <malloc.h>
     43#include <assert.h>
    4344
    4445/**
     
    255256
    256257/**
     258 * Find a filesystem block number where iblock-th data block
     259 * of the given inode is located.
     260 *
     261 * @return              EOK on success or negative error code on failure
     262 */
     263int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *fs, ext2_inode_t* inode,
     264    aoff64_t iblock, uint32_t* fblock)
     265{
     266        int rc;
     267        aoff64_t limits[4];
     268        uint32_t block_ids_per_block;
     269        aoff64_t blocks_per_level[4];
     270        uint32_t offset_in_block;
     271        uint32_t current_block;
     272        aoff64_t block_offset_in_level;
     273        int i;
     274        int level;
     275        block_t *block;
     276       
     277        if (iblock < EXT2_INODE_DIRECT_BLOCKS) {
     278                current_block = ext2_inode_get_direct_block(inode, (uint32_t)iblock);
     279                if (current_block == 0) {
     280                        return EIO;
     281                }
     282                *fblock = current_block;
     283                return EOK;
     284        }
     285       
     286        // Compute limits for indirect block levels
     287        // TODO: compute this once when loading filesystem and store in ext2_filesystem_t
     288        block_ids_per_block = ext2_superblock_get_block_size(fs->superblock) / sizeof(uint32_t);
     289        limits[0] = EXT2_INODE_DIRECT_BLOCKS;
     290        blocks_per_level[0] = 1;
     291        for (i = 1; i < 4; i++) {
     292                blocks_per_level[i]  = blocks_per_level[i-1] *
     293                    block_ids_per_block;
     294                limits[i] = limits[i-1] + blocks_per_level[i];
     295        }
     296       
     297        // Determine the indirection level needed to get the desired block
     298        level = -1;
     299        for (i = 1; i < 4; i++) {
     300                if (iblock < limits[i]) {
     301                        level = i;
     302                        break;
     303                }
     304        }
     305       
     306        if (level == -1) {
     307                return EIO;
     308        }
     309       
     310        block_offset_in_level = iblock - limits[level-1];
     311        current_block = ext2_inode_get_indirect_block(inode, level-1);
     312        offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     313       
     314        while (level > 0) {
     315                rc = block_get(&block, fs->device, current_block, 0);
     316                if (rc != EOK) {
     317                        return rc;
     318                }
     319               
     320                assert(offset_in_block < block_ids_per_block);
     321                current_block = ((uint32_t*)block->data)[offset_in_block];
     322               
     323                rc = block_put(block);
     324                if (rc != EOK) {
     325                        return rc;
     326                }
     327               
     328                if (current_block == 0) {
     329                        return EIO;
     330                }
     331               
     332                level -= 1;
     333               
     334                if (level == 0) {
     335                        break;
     336                }
     337               
     338                offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     339                block_offset_in_level %= blocks_per_level[level-1];
     340        }
     341       
     342        *fblock = current_block;
     343       
     344        return EOK;
     345}
     346
     347/**
    257348 * Finalize an instance of filesystem
    258349 *
  • uspace/lib/ext2/libext2_filesystem.h

    ra54af66 rad34feb  
    6060    ext2_inode_ref_t **);
    6161extern int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *);
     62extern int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *, ext2_inode_t*,
     63    aoff64_t, uint32_t*);
    6264extern void ext2_filesystem_fini(ext2_filesystem_t *);
    6365
  • uspace/lib/ext2/libext2_inode.c

    ra54af66 rad34feb  
    3838#include "libext2_superblock.h"
    3939#include <byteorder.h>
     40#include <assert.h>
    4041
    4142/**
     
    142143
    143144/**
     145 * Get number of blocks allocated for contents of the file
     146 * represented by this inode.
     147 *
     148 * @param inode pointer to inode
     149 */
     150inline uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *sb,
     151    ext2_inode_t *inode)
     152{
     153        return ext2_inode_get_reserved_512_blocks(inode) /
     154            (ext2_superblock_get_block_size(sb) / 512);
     155}
     156
     157/**
    144158 * Get inode flags
    145159 *
     
    158172inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *inode, uint8_t idx)
    159173{
     174        assert(idx < EXT2_INODE_DIRECT_BLOCKS);
    160175        return uint32_t_le2host(inode->direct_blocks[idx]);
    161176}
     
    165180 *
    166181 * @param inode pointer to inode
     182 * @param idx Indirection level. Valid values are 0 <= idx < 3, where 0 is
     183 *            singly-indirect block and 2 is triply-indirect-block
    167184 */
    168 inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *inode)
     185inline uint32_t ext2_inode_get_indirect_block(ext2_inode_t *inode, uint8_t idx)
    169186{
    170         return uint32_t_le2host(inode->single_indirect_block);
     187        assert(idx < 3);
     188        return uint32_t_le2host(inode->indirect_blocks[idx]);
    171189}
    172 
    173 /**
    174  * Get double indirect block ID
    175  *
    176  * @param inode pointer to inode
    177  */
    178 inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *inode)
    179 {
    180         return uint32_t_le2host(inode->double_indirect_block);
    181 }
    182 
    183 /**
    184  * Get triple indirect block ID
    185  *
    186  * @param inode pointer to inode
    187  */
    188 inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *inode)
    189 {
    190         return uint32_t_le2host(inode->triple_indirect_block);
    191 }
    192 
    193 
    194190
    195191/** @}
  • uspace/lib/ext2/libext2_inode.h

    ra54af66 rad34feb  
    5151        uint8_t unused2[4];
    5252        uint32_t direct_blocks[12]; // Direct block ids stored in this inode
    53         uint32_t single_indirect_block;
    54         uint32_t double_indirect_block;
    55         uint32_t triple_indirect_block;
     53        uint32_t indirect_blocks[3];
    5654        uint32_t version;
    5755        uint32_t file_acl;
     
    7573#define EXT2_INODE_MODE_ACCESS_MASK     0x0FFF
    7674#define EXT2_INODE_MODE_TYPE_MASK       0xF000
     75#define EXT2_INODE_DIRECT_BLOCKS        12
    7776
    7877typedef struct ext2_inode_ref {
     
    8887inline uint16_t ext2_inode_get_usage_count(ext2_inode_t *);
    8988inline uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *);
     89inline uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *,
     90    ext2_inode_t *);
    9091inline uint32_t ext2_inode_get_flags(ext2_inode_t *);
    9192inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *, uint8_t);
    92 inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *);
    93 inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *);
    94 inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *);
     93inline uint32_t ext2_inode_get_indirect_block(ext2_inode_t *, uint8_t level);
    9594
    9695
Note: See TracChangeset for help on using the changeset viewer.