分析Ext2文件系统结构。

时间:2023-03-09 00:21:53
分析Ext2文件系统结构。

1. 目的

分析Ext2文件系统结构。

使用 debugfs 应该跟容易分析 Ext2文件系统结构

了解ext2的hole的

2. 准备工作

预习文件系统基本知识:

http://www.doc88.com/p-66910733083.html

预习ext2的基本知识:

简直不要太硬了!一文带你彻底理解文件系统

http://www.360doc.com/content/11/0628/15/7204565_130135577.shtml

ext2的工具

http://www.360doc.com/content/11/0628/15/7204565_130135913.shtml

加载一个磁盘,格式化为ext2,并mount到mnt,创建一个topa目录和 suba,subb,subc子目录。

在suba子目录中创建一个带有hole的文件(没有实现)。
加载一个磁盘

我们采用 linux loop设备作为虚拟磁盘。

http://www.cnblogs.com/linuxcat/archive/2012/08/12/2634424.html

$ dd if=/dev/zero of=~/file.img bs=1M count=40

$ sudo losetup --find --show ~/file.img

/dev/loop0

格式化磁盘为ext2

$ sudo mkfs -t ext2 /dev/loop0

mke2fs 1.42.8 (20-Jun-2013)
Discarding device blocks: done                            
Filesystem label=
OS type: Linux
Block size=1024 (log=0)                   #  每个1KB的块位描述符描述8K个数据块,即8MB,每个group是8M
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
10240 inodes, 40960 blocks
2048 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=41943040
5 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
    8193, 24577     # 第1,3个块组有Superblock备份。

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

mount到mnt

$ sudo mount /dev/loop0 /mnt

$ ls /mnt

lost+found

创建目录

$ cd /mnt

$ sudo mkdir topa

$ cd topa

$ sudo mkdir suba subb subc

获得 ext2的信息

$ sudo dumpe2fs /dev/loop0

or

$ dumpe2fs ~/file.img

dumpe2fs 1.42.8 (20-Jun-2013)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          04f20704-8cd4-4122-9e02-e447de76e5d3
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      ext_attr resize_inode dir_index filetype sparse_super
Filesystem flags:         signed_directory_hash
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:             
Block count:             
Reserved block count:    
Free blocks:              39172
Free inodes:              10229
First block:              1
Block size:               1024
Fragment size:            1024
Reserved GDT blocks:      159
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         2048
Inode blocks per group:   256
Filesystem created:       Sun Aug  3 16:53:57 2014
Last mount time:          n/a
Last write time:          Sun Aug  3 16:53:57 2014
Mount count:              0
Maximum mount count:      -1
Last checked:             Sun Aug  3 16:53:57 2014
Check interval:           0 (<none>)
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:              128
Default directory hash:   half_md4
Directory Hash Seed:      45294dd9-663b-42f7-b6a6-7de9468ea58b

Group 0: (Blocks 1-8192)
  Primary superblock at 1, Group descriptors at 2-2
  Reserved GDT blocks at 3-161
  Block bitmap at 162 (+161), Inode bitmap at 163 (+162)
  Inode table at 164-419 (+163)
  7759 free blocks, 2037 free inodes, 2 directories
  Free blocks: 434-8192
  Free inodes: 12-2048
Group 1: (Blocks 8193-16384)
  Backup superblock at 8193, Group descriptors at 8194-8194
  Reserved GDT blocks at 8195-8353
  Block bitmap at 8354 (+161), Inode bitmap at 8355 (+162)
  Inode table at 8356-8611 (+163)
  7773 free blocks, 2048 free inodes, 0 directories
  Free blocks: 8612-16384
  Free inodes: 2049-4096
Group 2: (Blocks 16385-24576)
  Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
  Inode table at 16387-16642 (+2)
  7934 free blocks, 2048 free inodes, 0 directories
  Free blocks: 16643-24576
  Free inodes: 4097-6144
Group 3: (Blocks 24577-32768)
  Backup superblock at 24577, Group descriptors at 24578-24578
  Reserved GDT blocks at 24579-24737
  Block bitmap at 24738 (+161), Inode bitmap at 24739 (+162)
  Inode table at 24740-24995 (+163)
  7773 free blocks, 2048 free inodes, 0 directories
  Free blocks: 24996-32768
  Free inodes: 6145-8192
Group 4: (Blocks 32769-40959)
  Block bitmap at 32769 (+0), Inode bitmap at 32770 (+1)
  Inode table at 32771-33026 (+2)
  7933 free blocks, 2048 free inodes, 0 directories
  Free blocks: 33027-40959
  Free inodes: 8193-10240

创建hole的文件

#  sudo echo -n "hello world" | dd of=./hole bs=1024 seek=1

分析磁盘

大蓝图

分析Ext2文件系统结构。

分析超级块

$ sudo hexdump -s 1024 -n 1024 /dev/loop0

or
$ sudo dd if=/dev/loop0 bs=1 count=1024 skip=1024 | od -t x1 -Ax
000000 00 28 00 00 00 a0 00 00 00 08 00 00 04 99 00 00      # s_inodes_count
000010 f5 27 00 00 01 00 00 00 00 00 00 00 00 00 00 00       # s_free_inodes_count
000020 00 20 00 00 00 20 00 00 00 08 00 00 54 fa dd 53       # s_blocks_per_group
000030 54 fa dd 53 01 00 ff ff 53 ef 00 00 01 00 00 00            # s_wtime
000040 a5 f8 dd 53 00 00 00 00 00 00 00 00 01 00 00 00       # s_lastcheck
000050 00 00 00 00 0b 00 00 00 80 00 00 00 38 00 00 00      # s_def_resuid
000060 02 00 00 00 01 00 00 00 04 f2 07 04 8c d4 41 22       #  s_feature_incompat
000070 9e 02 e4 47 de 76 e5 d3 00 00 00 00 00 00 00 00
000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9f 00
0000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000e0 00 00 00 00 00 00 00 00 00 00 00 00 45 29 4d d9
0000f0 66 3b 42 f7 b6 a6 7d e9 46 8e a5 8b 01 00 00 00
000100 0c 00 00 00 00 00 00 00 a5 f8 dd 53 00 00 00 00
000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000160 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.00181353 s, 565 kB/s
000400

以上数据是little edidan

内核源代码中fs/ext2/ext2.h 文件:

struct ext2_super_block {
    __le32    s_inodes_count;        /* Inodes count */         // 00 28 00 00 =  10240
    __le32    s_blocks_count;        /* Blocks count */         //  00 a0 00 00 =  40960
    __le32    s_r_blocks_count;    /* Reserved blocks count */   // 00 08 00 00 = 2048
    __le32    s_free_blocks_count;    /* Free blocks count */      // 04 99 00 00 = 39172
    __le32    s_free_inodes_count;    /* Free inodes count */    // f5 27 00 00 = 10299
    __le32    s_first_data_block;    /* First Data Block */          //  01 00 00 00 =  1
    __le32    s_log_block_size;    /* Block size */                     //  00 00 00 00 = 0 ,  2^0 * 1024 = 1
    __le32    s_log_frag_size;    /* Fragment size */                //  00 00 00 00 = 0 ,  2^0 * 1024 = 1
    __le32    s_blocks_per_group;    /* # Blocks per group */       // 00 20 00 00 =  8192
    __le32    s_frags_per_group;    /* # Fragments per group */    // 00 20 00 00 = 8192
    __le32    s_inodes_per_group;    /* # Inodes per group */       // 00 08 00 00 =  2048
    __le32    s_mtime;        /* Mount time */                                   //  54 fa dd 53  =  1407056468,   '2014-08-03, 17:01:08'
    __le32    s_wtime;        /* Write time */                                     //  54 fa dd 53 = 1407056468,    '2014-08-03, 17:01:08'
    __le16    s_mnt_count;        /* Mount count */                         //   01 00 = 1
    __le16    s_max_mnt_count;    /* Maximal mount count */       //   ff ff,   -1
    __le16    s_magic;        /* Magic signature */                                // 53 ef
    __le16    s_state;        /* File system state */                                //  00 00
    __le16    s_errors;        /* Behaviour when detecting errors */      // 01 00
    __le16    s_minor_rev_level;     /* minor revision level */               // 00 00
    __le32    s_lastcheck;        /* time of last check */
    __le32    s_checkinterval;    /* max. time between checks */
    __le32    s_creator_os;        /* OS */
    __le32    s_rev_level;        /* Revision level */                                 // 01 00 00 00
    __le16    s_def_resuid;        /* Default uid for reserved blocks */
    __le16    s_def_resgid;        /* Default gid for reserved blocks */
    __le32    s_first_ino;         /* First non-reserved inode */
    __le16   s_inode_size;         /* size of inode structure */                 //  80 00 = 128
    __le16    s_block_group_nr;     /* block group # of this superblock */
    __le32    s_feature_compat;     /* compatible feature set */
    __le32    s_feature_incompat;     /* incompatible feature set */
    __le32    s_feature_ro_compat;     /* readonly-compatible feature set */
    __u8    s_uuid[16];        /* 128-bit uuid for volume */
    char    s_volume_name[16];     /* volume name */
    char    s_last_mounted[64];     /* directory where last mounted */
    __le32    s_algorithm_usage_bitmap; /* For compression */
    __u8    s_prealloc_blocks;    /* Nr of blocks to try to preallocate*/
    __u8    s_prealloc_dir_blocks;    /* Nr to preallocate for dirs */
    __u16    s_padding1;
    /*
     * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
     */
    __u8    s_journal_uuid[16];    /* uuid of journal superblock */
    __u32    s_journal_inum;        /* inode number of journal file */
    __u32    s_journal_dev;        /* device number of journal file */
    __u32    s_last_orphan;        /* start of list of inodes to delete */
    __u32    s_hash_seed[4];        /* HTREE hash seed */
    __u8    s_def_hash_version;    /* Default hash version to use */
    __u8    s_reserved_char_pad;
    __u16    s_reserved_word_pad;
    __le32    s_default_mount_opts;
     __le32    s_first_meta_bg;     /* First metablock block group */
    __u32    s_reserved[190];    /* Padding to the end of the block */
};

分析组描述符(GDT

每32个自己位一个GDT。磁盘大小是40M, 每个group是8M, 一共5个group

$ sudo dd if=/dev/loop0 bs=1 count=1024 skip=2048 | od -t x1 -Ax
000000 a2 00 00 00 a3 00 00 00 a4 00 00 00 4f 1e f5 07
000010 02 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00        # 块组0的组描述符
000020 a2 20 00 00 a3 20 00 00 a4 20 00 00 5d 1e 00 08
000030 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00       # 块组1的组描述符
000040 01 40 00 00 02 40 00 00 03 40 00 00 f9 1e fc 07
000050 04 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00       # 块组2的组描述符
000060 a2 60 00 00 a3 60 00 00 a4 60 00 00 5d 1e 00 08
000070 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00       # 块组3的组描述符
000080 01 80 00 00 02 80 00 00 03 80 00 00 fd 1e 00 08
000090 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00       # 块组4的组描述符
0000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.00123069 s, 832 kB/s
000400

内核源代码中fs/ext2/ext2.h 文件:

第0个组描述符的信息。

struct ext2_group_desc
{                                                   
        __le32  bg_block_bitmap;                /* Blocks bitmap block */      // a2 00 00 00 = 162,  0b10100010, 00000000, 00000000, 00000000
        __le32  bg_inode_bitmap;                /* Inodes bitmap block */     // a3 00 00 00 = 163,  0b10100011, 00000000, 00000000, 00000000
        __le32  bg_inode_table;         /* Inodes table block */                 // a4 00 00 00 =  164,  0b10100100, 00000000, 00000000, 00000000
        __le16  bg_free_blocks_count;   /* Free blocks count */             // 4f 1e =  7759
        __le16  bg_free_inodes_count;   /* Free inodes count */            // f5 07 =  2037
        __le16  bg_used_dirs_count;     /* Directories count */               // 02 00 = 2, 有个2个目录,2个inode, 在组块2有4个目录。
        __le16  bg_pad;                                                                          // 04 00 = 4
        __le32  bg_reserved[3];
};

分析索引节点表

$ ll -ia
total 19
   2 drwxr-xr-x.  4 root root  1024 Aug  3 17:14 .
   2 drwxr-xr-x. 19 root root  4096 Aug  1 17:49 ..
  11 drwx------.  2 root root 12288 Aug  3 16:53 lost+found
4097 drwxr-xr-x.  5 root root  1024 Aug  3 17:15 topa

首先分析,第0个组块中的inode, 第2个 根目录 inode的偏移量 164K + 128

$ sudo dd if=~/file.img bs=1 count=1024 skip=164K | od -t x1 -Ax
000000 00 00 00 00 00 00 00 00 a5 f8 dd 53 a5 f8 dd 53
000010 a5 f8 dd 53 00 00 00 00 00 00 00 00 00 00 00 00
000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*                                                                                                        # inode 2
000080 ed 41 00 00 00 04 00 00 82 fd dd 53 80 fd dd 53               # i_mode
000090 80 fd dd 53 00 00 00 00 00 00 04 00 02 00 00 00              # i_mtime
0000a0 00 00 00 00 01 00 00 00 a4 01 00 00 00 00 00 00             # i_flags
0000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000300 80 81 00 00 00 30 04 04 a5 f8 dd 53 a5 f8 dd 53
1024+0 records in
1024+0 records out
1024 bytes (1.0 kB) copied, 0.002057 s, 498 kB/s
000310 a5 f8 dd 53 00 00 00 00 00 00 01 00 bc 03 00 00
000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000350 00 00 00 00 00 00 00 00 00 00 00 00 b1 01 00 00
000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000400

内核源代码中fs/ext2/ext2.h 文件:

struct ext2_inode {
    __le16    i_mode;        /* File mode */                                       # ed 41
    __le16    i_uid;        /* Low 16 bits of Owner Uid */
    __le32    i_size;        /* Size in bytes */
    __le32    i_atime;    /* Access time */
    __le32    i_ctime;    /* Creation time */                                     # 
    __le32    i_mtime;    /* Modification time */                               # 80 fd dd 53
    __le32    i_dtime;    /* Deletion Time */
    __le16    i_gid;        /* Low 16 bits of Group Id */
    __le16    i_links_count;    /* Links count */
    __le32    i_blocks;    /* Blocks count */
    __le32    i_flags;    /* File flags */
    union {
        struct {
            __le32  l_i_reserved1;
        } linux1;
        struct {
            __le32  h_i_translator;
        } hurd1;
        struct {
            __le32  m_i_reserved1;
        } masix1;
    } osd1;                /* OS dependent 1 */
    __le32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */            // a4 01 00 00 = 420
    __le32    i_generation;    /* File version (for NFS) */
    __le32    i_file_acl;    /* File ACL */
    __le32    i_dir_acl;    /* Directory ACL */
    __le32    i_faddr;    /* Fragment address */
    union {
        struct {
            __u8    l_i_frag;    /* Fragment number */
            __u8    l_i_fsize;    /* Fragment size */
            __u16    i_pad1;
            __le16    l_i_uid_high;    /* these 2 fields    */
            __le16    l_i_gid_high;    /* were reserved2[0] */
            __u32    l_i_reserved2;
        } linux2;
        struct {
            __u8    h_i_frag;    /* Fragment number */
            __u8    h_i_fsize;    /* Fragment size */
            __le16    h_i_mode_high;
            __le16    h_i_uid_high;
            __le16    h_i_gid_high;
            __le32    h_i_author;
        } hurd2;
        struct {
            __u8    m_i_frag;    /* Fragment number */
            __u8    m_i_fsize;    /* Fragment size */
            __u16    m_pad1;
            __u32    m_i_reserved2[2];
        } masix2;
    } osd2;                /* OS dependent 2 */
};

有关 EXT2_N_BLOCKS 定义,请参考: http://blog.****.net/xiakan008/article/details/5913749

 /*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)

分析Ext2文件系统结构。

第2个组块中的inode信息。

$ sudo dd if=~/file.img bs=1 count=1024 skip=16387K | od -t x1 -Ax
000000 ed 41 00 00 00 04 00 00 95 fd dd 53 94 fd dd 53
000010 94 fd dd 53 00 00 00 00 00 00 05 00 04 00 00 00
000020 00 00 00 00 04 00 00 00 04 41 00 00 00 00 00 00                 #  block = 16644, topa 目录
000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000060 00 00 00 00 6f db 63 e9 03 41 00 00 00 00 00 00
000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1024+0 records in
1024+0 records out
000080 ed 41 00 00 00 04 00 00 94 fd dd 53 94 fd dd 53
1024 bytes (1.0 kB) copied

000090 94 fd dd 53 00 00 00 00 00 00 02 00 04 00 00 00
0000a0 00 00 00 00 01 00 00 00 05 41 00 00 00 00 00 00              #  block = 16645, suba 目录
, 0.00127417 s, 804 kB/s
0000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000e0 00 00 00 00 70 db 63 e9 03 41 00 00 00 00 00 00
0000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000100 ed 41 00 00 00 04 00 00 94 fd dd 53 94 fd dd 53
000110 94 fd dd 53 00 00 00 00 00 00 02 00 04 00 00 00
000120 00 00 00 00 01 00 00 00 06 41 00 00 00 00 00 00
000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000160 00 00 00 00 71 db 63 e9 03 41 00 00 00 00 00 00
000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000180 ed 41 00 00 00 04 00 00 94 fd dd 53 94 fd dd 53
000190 94 fd dd 53 00 00 00 00 00 00 02 00 04 00 00 00
0001a0 00 00 00 00 01 00 00 00 07 41 00 00 00 00 00 00
0001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0001e0 00 00 00 00 72 db 63 e9 03 41 00 00 00 00 00 00
0001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
000400

分析目录

$ sudo dd if=~/file.img bs=1024 count=1 skip=420 | hexdump -C
1+0 records in
1+0 records out
00000000  02 00 00 00 0c 00 01 02  2e 00 00 00 02 00 00 00  |................|
1024 bytes (1.0 kB) copied00000010  0c 00 02 02 2e 2e 00 00  0b 00 00 00 14 00 0a 02  |................|
, 8.4743e-05 s, 12.1 MB/s
00000020  6c 6f 73 74 2b 66 6f 75  6e 64 00 00 01 10 00 00  |lost+found......|
00000030  d4 03 04 02 74 6f 70 61  00 00 00 00 00 00 00 00  |....topa........|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

$ sudo dd if=~/file.img bs=1024 count=1 skip=16644 | hexdump -C
1+0 records in
1+0 records out
00000000  01 10 00 00 0c 00   2e 00 00 00 02 00 00 00  |................|               # inode = 4097, topa,  inode = 2, 根目录
00000010  0c 00 2e 2e 00 00  02 10 00 00 0c 00 04 02  |................|
00000020  73 75 62 61 03 10 00 00  0c 00 04 02 73 75 62 62  |suba........subb|
00000030  04 10 00 00 d0 03 04 02  73 75 62 63 00 00 00 00  |........subc....|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

当前目录:

内核源代码中fs/ext2/ext2.h 文件:

struct ext2_dir_entry_2 {
        __le32  inode;                  /* Inode number */                     # 01 10 00 00 = 4097
        __le16  rec_len;                /* Directory entry length */        # 0c 00 = 12
        __u8    name_len;               /* Name length */                    # = 1
        __u8    file_type;                                                               # , 目录
        char    name[];                 /* File name, up to EXT2_NAME_LEN */
};

$ ll -ia topa/
total 9
4097 drwxr-xr-x. 5 root root 1024 Aug  3 17:15 .
   2 drwxr-xr-x. 4 root root 1024 Aug  3 17:14 ..
4098 drwxr-xr-x. 2 root root 1024 Aug  3 17:15 suba
4099 drwxr-xr-x. 2 root root 1024 Aug  3 17:15 subb
4100 drwxr-xr-x. 2 root root 1024 Aug  3 17:15 subc

分析文件:

之前还没有创建文件,现在创建一个hole文件。

#  sudo echo -n "hello world" | dd of=./hole bs=1024 seek=1

途中,有6个block是hole。 本例子中只有一个block是hole。

分析Ext2文件系统结构。

$ sudo dd if=~/file.img bs=1 count=1024 skip=16387K | od -t x1 -Ax

# 偏移量在 128 * 200 的位置。

000200 a4 81 00 00 0b 04 00 00 56 5d de 53 56 5d de 53
000210 56 5d de 53 00 00 00 00 00 00 01 00 04 00 00 00
000220 00 00 00 00 01 00 00 00 00 00 00 00 01 42 00 00      // 00 00 00 00 为hole, 00 00 00 01 为hello world
000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

$ sudo dd if=~/file.img bs=1024 count=1 skip=16897 | hexdump -C

1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 00 00 00 00 00  |hello world.....|
, 5.7942e-05 s, 17.7 MB/s
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

测试文件开头增删字符block的变化:

$ dd if=/dev/zero of=~/file.img bs=512 count=1000

$ LOOFDEV=`sudo losetup --find --show ~/file.img`

$ mkdir file.image.loop -p

$ sudo mkfs -t ext2 $LOOFDEV

$ dumpe2fs ~/file.img

dumpe2fs 1.44.1 (24-Mar-2018)
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem UUID: 4e7d8a8c-a652-4f16-beb7-b320c0c4a6f3
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 64
Block count: 500
Reserved block count: 25
Free blocks: 472
Free inodes: 53
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 1
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 64
Inode blocks per group: 8
Filesystem created: Sun May 10 12:48:17 2020
Last mount time: n/a
Last write time: Sun May 10 12:48:17 2020
Mount count: 0
Maximum mount count: -1
Last checked: Sun May 10 12:48:17 2020
Check interval: 0 (<none>)
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Default directory hash: half_md4
Directory Hash Seed: bd26ae4a-c652-4e4e-89e1-2c296429320b Group 0: (Blocks 1-499)
Primary superblock at 1, Group descriptors at 2-2
Reserved GDT blocks at 3-3
Block bitmap at 4 (+3)
Inode bitmap at 5 (+4)
Inode table at 6-13 (+5)
472 free blocks, 53 free inodes, 2 directories
Free blocks: 28-499
Free inodes: 12-64

$ sudo hexdump -c -n 1024*2 -s 1024*40  $LOOFDEV

$ sudo mount  $LOOFDEV file.image.loop

$ # vim a.txt

$ # printf "%0.sa" {1..1024};printf "%0.sb" {1..1024}

$ COUNT=1024

$ # printf '%0.sa' $(seq 1 $COUNT)

$ python -c "print('a' * $COUNT + 'b' * $COUNT + 'c' * $COUNT)" |sudo tee  a.txt

写入1024个字母“a”(HEX 61,DEX97 )

写入10024个字母“b”(HEX 62,DEX98 )

写入10024个字母“b”(HEX 63,DEX99 )

$ cat a.txt |wc -c

$ sudo cp  a.txt file.image.loop/

$ cd file.image.loop/

$ ls -lia

$ sudo debugfs $LOOFDEV

debugfs: stat a.txt

blocks a.txt

$ sudo dd if=$LOOFDEV bs=1024 count=4 skip= | od -t x1 -Ax$ sudo umount $LOOFDEV

sed -r '1s/.{4}//' file

$ cat a.txt |wc -c

$ sudo debugfs $LOOFDEV

debugfs: stat a.txt

blocks a.txt

$ sudo sed -i '1i\aaaa' a.txt

$ sudo debugfs $LOOFDEV

debugfs: stat a.txt

blocks a.txt

$ cat a.txt |wc -c

$ sudo lsof $LOOFDEV

$ sudo umount  $LOOFDEV

$ sudo losetup -d $LOOFDEV

参考:

发现很多人做过类似的分析过程:

http://blog.chinaunix.net/uid-24774106-id-3266816.html

http://www.360doc.com/content/11/0628/15/7204565_130136729.shtml

使用 sed 命令替换/删除 文本字符的 20 个例子