From 9ff98bdbaeb97a99f79d5afaf9d00bf233aadcff Mon Sep 17 00:00:00 2001 From: Sanya239 Date: Thu, 15 May 2025 15:27:11 +0300 Subject: [PATCH 1/4] some progress was achieved --- cleanup.sh | 5 + ext2_types.h | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 192 ++++++++++++++++++++++++++++- test.sh | 34 ++++++ util.c | 188 +++++++++++++++++++++++++++++ 5 files changed, 749 insertions(+), 2 deletions(-) create mode 100644 cleanup.sh create mode 100644 ext2_types.h create mode 100644 test.sh create mode 100644 util.c diff --git a/cleanup.sh b/cleanup.sh new file mode 100644 index 0000000..048228b --- /dev/null +++ b/cleanup.sh @@ -0,0 +1,5 @@ +umount ext2 +sudo rm -rf ext2.img +sudo rm -rf ext2 +sudo rm stats.txt + diff --git a/ext2_types.h b/ext2_types.h new file mode 100644 index 0000000..abae2b4 --- /dev/null +++ b/ext2_types.h @@ -0,0 +1,332 @@ +/* + * linux/include/linux/ext2_fs.h + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/include/linux/minix_fs.h + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * EXT2_*_*() convienience macros added by Andrew Clausen + * Copyright (C) 2000, 2009-2014, 2019-2023 Free Software Foundation, Inc. + */ + +#ifndef _EXT2_FS_H +#define _EXT2_FS_H + +#include +#include + +/* + * The second extended file system constants/structures + */ + +#define EXT2_SUPER_MAGIC_CONST 0xEF53 +#define EXT2_MIN_BLOCK_SIZE 1024 +#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) +#define EXT2_VALID_FS 0x0001 +#define EXT2_ERROR_FS 0x0002 +#define EXT2_RESERVED_INODE_COUNT 11 + +/* + * Codes for operating systems + */ +#define EXT2_OS_LINUX 0 +#define EXT2_OS_HURD 1 +#define EXT2_OS_MASIX 2 +#define EXT2_OS_FREEBSD 3 +#define EXT2_OS_LITES 4 + +/* + * Feature set definitions + */ +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2_FEATURE_COMPAT_HAS_DIR_INDEX 0x0020 + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 + +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 + +/* + * Special inodes numbers + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_ACL_IDX_INO 3 /* ACL inode */ +#define EXT2_ACL_DATA_INO 4 /* ACL inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ + +/* + * Ext2 directory file types. Only the low 3 bits are used. The + * other bits are reserved for now. + */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +/* + * Behaviour when detecting errors + */ +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ +#define EXT2_ERRORS_PANIC 3 /* Panic */ +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE + +struct ext2_dir_entry_2 +{ + uint32_t inode; + uint16_t rec_len; + uint8_t name_len; + uint8_t file_type; + char name[255]; +}; + +struct ext2_group_desc +{ + uint32_t bg_block_bitmap; + uint32_t bg_inode_bitmap; + uint32_t bg_inode_table; + uint16_t bg_free_blocks_count; + uint16_t bg_free_inodes_count; + uint16_t bg_used_dirs_count; + uint16_t bg_pad; + uint32_t bg_reserved[3]; +}; + +struct ext2_inode +{ + uint16_t i_mode; /* File mode */ + uint16_t i_uid; /* Owner Uid */ + uint32_t i_size; /* Size in bytes */ + uint32_t i_atime; /* Access time */ + uint32_t i_ctime; /* Creation time */ + uint32_t i_mtime; /* Modification time */ + uint32_t i_dtime; /* Deletion Time */ + uint16_t i_gid; /* Group Id */ + uint16_t i_links_count; /* Links count */ + uint32_t i_blocks; /* Blocks count */ + uint32_t i_flags; /* File flags */ + union { + struct { + uint32_t l_i_reserved1; + } linux1; + struct { + uint32_t h_i_translator; + } hurd1; + struct { + uint32_t m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + uint32_t i_generation; /* File version (for NFS) */ + uint32_t i_file_acl; /* File ACL */ + uint32_t i_dir_acl; /* Directory ACL */ + uint32_t i_faddr; /* Fragment address */ + union { + struct { + uint8_t l_i_frag; /* Fragment number */ + uint8_t l_i_fsize; /* Fragment size */ + uint16_t i_pad1; + uint32_t l_i_reserved2[2]; + } linux2; + struct { + uint8_t h_i_frag; /* Fragment number */ + uint8_t h_i_fsize; /* Fragment size */ + uint16_t h_i_mode_high; + uint16_t h_i_uid_high; + uint16_t h_i_gid_high; + uint32_t h_i_author; + } hurd2; + struct { + uint8_t m_i_frag; /* Fragment number */ + uint8_t m_i_fsize; /* Fragment size */ + uint16_t m_pad1; + uint32_t m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ +}; + +#define i_size_high i_dir_acl + +struct __attribute__ ((packed)) ext2_super_block +{ + uint32_t s_inodes_count; /* Inodes count */ + uint32_t s_blocks_count; /* Blocks count */ + uint32_t s_r_blocks_count; /* Reserved blocks count */ + uint32_t s_free_blocks_count; /* Free blocks count */ + uint32_t s_free_inodes_count; /* Free inodes count */ + uint32_t s_first_data_block; /* First Data Block */ + uint32_t s_log_block_size; /* Block size */ + int32_t s_log_frag_size; /* Fragment size */ + uint32_t s_blocks_per_group; /* # Blocks per group */ + uint32_t s_frags_per_group; /* # Fragments per group */ + uint32_t s_inodes_per_group; /* # Inodes per group */ + uint32_t s_mtime; /* Mount time */ + uint32_t s_wtime; /* Write time */ + uint16_t s_mnt_count; /* Mount count */ + int16_t s_max_mnt_count; /* Maximal mount count */ + uint16_t s_magic; /* Magic signature */ + uint16_t s_state; /* File system state */ + uint16_t s_errors; /* Behaviour when detecting errors */ + uint16_t s_minor_rev_level; /* minor revision level */ + uint32_t s_lastcheck; /* time of last check */ + uint32_t s_checkinterval; /* max. time between checks */ + uint32_t s_creator_os; /* OS */ + uint32_t s_rev_level; /* Revision level */ + uint16_t s_def_resuid; /* Default uid for reserved blocks */ + uint16_t s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the file system. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + uint32_t s_first_ino; /* First non-reserved inode */ + uint16_t s_inode_size; /* size of inode structure */ + uint16_t s_block_group_nr; /* block group # of this superblock */ + uint32_t s_feature_compat; /* compatible feature set */ + uint32_t s_feature_incompat; /* incompatible feature set */ + uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ + uint8_t s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + uint32_t s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + uint16_t s_padding1; + /* + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. + */ + uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ + uint32_t s_journal_inum; /* inode number of journal file */ + uint32_t s_journal_dev; /* device number of journal file */ + uint32_t s_last_orphan; /* start of list of inodes to delete */ + + uint32_t s_reserved[197]; /* Padding to the end of the block */ +}; + +#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s).s_log_block_size) + + +#define EXT2_DIRENT_INODE(dir_ent) (le32toh((dir_ent).inode)) +#define EXT2_DIRENT_REC_LEN(dir_ent) (le16toh((dir_ent).rec_len)) +#define EXT2_DIRENT_NAME_LEN(dir_ent) ((dir_ent).name_len) +#define EXT2_DIRENT_FILE_TYPE(dir_ent) ((dir_ent).file_type) + +#define EXT2_GROUP_BLOCK_BITMAP(gd) (le32toh((gd).bg_block_bitmap)) +#define EXT2_GROUP_INODE_BITMAP(gd) (le32toh((gd).bg_inode_bitmap)) +#define EXT2_GROUP_INODE_TABLE(gd) (le32toh((gd).bg_inode_table)) +#define EXT2_GROUP_FREE_BLOCKS_COUNT(gd) \ + (le16toh((gd).bg_free_blocks_count)) +#define EXT2_GROUP_FREE_INODES_COUNT(gd) \ + (le16toh((gd).bg_free_inodes_count)) +#define EXT2_GROUP_USED_DIRS_COUNT(gd) \ + (le16toh((gd).bg_used_dirs_count)) + +#define EXT2_INODE_MODE(inode) (le16toh((inode).i_mode)) +#define EXT2_INODE_UID(inode) (le16toh((inode).i_uid)) +#define EXT2_INODE_SIZE(inode) \ + ((uint64_t) le32toh((inode).i_size) \ + + ((uint64_t) le32toh((inode).i_size_high) << 32)) +#define EXT2_INODE_ATIME(inode) (le32toh((inode).i_atime)) +#define EXT2_INODE_CTIME(inode) (le32toh((inode).i_ctime)) +#define EXT2_INODE_MTIME(inode) (le32toh((inode).i_mtime)) +#define EXT2_INODE_DTIME(inode) (le32toh((inode).i_dtime)) +#define EXT2_INODE_GID(inode) (le16toh((inode).i_gid)) +#define EXT2_INODE_LINKS_COUNT(inode) (le16toh((inode).i_links_count)) +#define EXT2_INODE_BLOCKS(inode) (le32toh((inode).i_blocks)) +#define EXT2_INODE_FLAGS(inode) (le32toh((inode).i_flags)) +#define EXT2_INODE_TRANSLATOR(inode) (le32toh((inode).osd1.hurd1.h_i_translator)) +#define EXT2_INODE_BLOCK(inode, blk) (le32toh((inode).i_block[blk])) + +#define EXT2_SUPER_INODES_COUNT(sb) (le32toh((sb).s_inodes_count)) +#define EXT2_SUPER_BLOCKS_COUNT(sb) (le32toh((sb).s_blocks_count)) +#define EXT2_SUPER_R_BLOCKS_COUNT(sb) (le32toh((sb).s_r_blocks_count)) +#define EXT2_SUPER_FREE_BLOCKS_COUNT(sb) \ + (le32toh((sb).s_free_blocks_count)) +#define EXT2_SUPER_FREE_INODES_COUNT(sb) \ + (le32toh((sb).s_free_inodes_count)) +#define EXT2_SUPER_FIRST_DATA_BLOCK(sb) \ + (le32toh((sb).s_first_data_block)) +#define EXT2_SUPER_LOG_BLOCK_SIZE(sb) (le32toh((sb).s_log_block_size)) +#define EXT2_SUPER_LOG_FRAG_SIZE(sb) \ + ((int32_t) le32toh((sb).s_log_frag_size)) +#define EXT2_SUPER_BLOCKS_PER_GROUP(sb) \ + (le32toh((sb).s_blocks_per_group)) +#define EXT2_SUPER_FRAGS_PER_GROUP(sb) \ + (le32toh((sb).s_frags_per_group)) +#define EXT2_SUPER_INODES_PER_GROUP(sb) \ + (le32toh((sb).s_inodes_per_group)) +#define EXT2_SUPER_MTIME(sb) (le32toh((sb).s_mtime)) +#define EXT2_SUPER_WTIME(sb) (le32toh((sb).s_wtime)) +#define EXT2_SUPER_MNT_COUNT(sb) (le16toh((sb).s_mnt_count)) +#define EXT2_SUPER_MAX_MNT_COUNT(sb) \ + ((int16_t) le16toh((sb).s_max_mnt_count)) +#define EXT2_SUPER_MAGIC(sb) (le16toh((sb).s_magic)) +#define EXT2_SUPER_STATE(sb) (le16toh((sb).s_state)) +#define EXT2_SUPER_ERRORS(sb) (le16toh((sb).s_errors)) +#define EXT2_SUPER_MINOR_REV_LEVEL(sb) \ + (le16toh((sb).s_minor_rev_level)) +#define EXT2_SUPER_LASTCHECK(sb) (le32toh((sb).s_lastcheck)) +#define EXT2_SUPER_CHECKINTERVAL(sb) (le32toh((sb).s_checkinterval)) +#define EXT2_SUPER_CREATOR_OS(sb) (le32toh((sb).s_creator_os)) +#define EXT2_SUPER_REV_LEVEL(sb) (le32toh((sb).s_rev_level)) +#define EXT2_SUPER_DEF_RESUID(sb) (le16toh((sb).s_def_resuid)) +#define EXT2_SUPER_DEF_RESGID(sb) (le16toh((sb).s_def_resgid)) + +#define EXT2_SUPER_FIRST_INO(sb) (le32toh((sb).s_first_ino)) +#define EXT2_SUPER_INODE_SIZE(sb) (le16toh((sb).s_inode_size)) +#define EXT2_SUPER_BLOCK_GROUP_NR(sb) (le16toh((sb).s_block_group_nr)) +#define EXT2_SUPER_FEATURE_COMPAT(sb) (le32toh((sb).s_feature_compat)) +#define EXT2_SUPER_FEATURE_INCOMPAT(sb) \ + (le32toh((sb).s_feature_incompat)) +#define EXT2_SUPER_FEATURE_RO_COMPAT(sb) \ + (le32toh((sb).s_feature_ro_compat)) +#define EXT2_SUPER_UUID(sb) ((sb).s_uuid) +#define EXT2_SUPER_VOLUME_NAME(sb) ((sb).s_volume_name) +#define EXT2_SUPER_LAST_MOUNTED(sb) ((sb).s_last_mounted) +#define EXT2_SUPER_ALGORITHM_USAGE_BITMAP(sb) \ + (le32toh((sb).s_algorithm_usage_bitmap)) + +#define EXT2_SUPER_JOURNAL_UUID(sb) ((sb).s_journal_uuid) +#define EXT2_SUPER_JOURNAL_INUM(sb) (le32toh((sb).s_journal_inum)) +#define EXT2_SUPER_JOURNAL_DEV(sb) (le32toh((sb).s_journal_dev)) +#define EXT2_SUPER_LAST_ORPHAN(sb) (le32toh((sb).s_last_orphan)) + +#endif diff --git a/main.c b/main.c index 63f8805..588b610 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,194 @@ #include +#include +#include -int main(void) { - printf("Hello, World!\n"); +#include "ext2_types.h" + +struct ext2_super_block superblock; +struct ext2_group_desc *group_descriptor_table; +struct ext2_inode inode; + + +#define SUPERBLOCK_OFFSET 1024 +#define SUPERBLOCK_SIZE 1024 + +int read_superblock(FILE *fp) { + if (fseek(fp, SUPERBLOCK_OFFSET, SEEK_SET) != 0) { + perror("fseek"); + return -1; + } + + if (fread(&superblock, sizeof(struct ext2_super_block), 1, fp) != 1) { + perror("fread superblock"); + return -1; + } + + return 0; +} + + +int read_group_descriptors(FILE *fp) { + const uint32_t gd_table_offset = (EXT2_BLOCK_SIZE(superblock) == SUPERBLOCK_SIZE) + ? SUPERBLOCK_SIZE + SUPERBLOCK_OFFSET + : EXT2_BLOCK_SIZE(superblock); + + if (fseek(fp, gd_table_offset, SEEK_SET) != 0) { + perror("fseek to group descriptor table"); + return -1; + } + + uint32_t num_groups = (EXT2_SUPER_BLOCKS_COUNT(superblock) + EXT2_SUPER_BLOCKS_PER_GROUP(superblock) - 1) / + EXT2_SUPER_BLOCKS_PER_GROUP(superblock); + group_descriptor_table = malloc(num_groups * sizeof(struct ext2_group_desc)); + if (fread(group_descriptor_table, sizeof(struct ext2_group_desc), num_groups, fp) != 1) { + perror("fread group descriptor table"); + return -1; + } + + return 0; +} + +// Чтение inode по его номеру +int read_inode_by_number(FILE *fp, uint32_t inode_num) { + if (inode_num == 0 || inode_num > EXT2_SUPER_INODES_COUNT(superblock)) { + fprintf(stderr, "Invalid inode number: %u\n", inode_num); + return -1; + } + + uint32_t inodes_per_group = EXT2_SUPER_INODES_PER_GROUP(superblock); + const uint32_t group = (inode_num - 1) / inodes_per_group; + const uint32_t index_in_group = (inode_num - 1) % inodes_per_group; + + uint32_t inode_table_block = EXT2_GROUP_INODE_TABLE(group_descriptor_table[group]); + + // Размер inode + const uint32_t inode_size = EXT2_SUPER_INODE_SIZE(superblock); + + // Смещение до нужного inode (в байтах) + long int inode_offset = (inode_table_block * EXT2_BLOCK_SIZE(superblock)) + (index_in_group * inode_size); + + // Чтение inode + if (fseek(fp, inode_offset, SEEK_SET) != 0) { + perror("fseek to inode"); + return -1; + } + + if (fread(&inode, sizeof(struct ext2_inode), 1, fp) != 1) { + perror("fread inode"); + return -1; + } + + return 0; +} + +int print_inode_blocks(FILE *device, uint32_t block_size) { + printf("File size: %u bytes\n", inode.i_size); + + // Вывод прямых блоков + for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { + if (inode.i_block[i]) + printf("Direct block %d: %u\n", i, inode.i_block[i]); + } + return 0; + // Вывод из одинарно косвенного блока + if (inode.i_block[EXT2_IND_BLOCK]) { + printf("Indirect block: %u\n", inode.i_block[EXT2_IND_BLOCK]); + + uint32_t count = block_size / sizeof(uint32_t); + uint32_t blocks[count]; + fseek(device, inode.i_block[EXT2_IND_BLOCK] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, device); + + for (uint32_t i = 0; i < count; i++) { + if (blocks[i]) + printf(" Indirect -> %u\n", blocks[i]); + } + } + + // Вывод из двойного косвенного блока + if (inode.i_block[EXT2_DIND_BLOCK]) { + printf("Double indirect block: %u\n", inode.i_block[EXT2_DIND_BLOCK]); + + uint32_t count = block_size / sizeof(uint32_t); + uint32_t indirect_blocks[count]; + fseek(device, inode.i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); + fread(indirect_blocks, sizeof(uint32_t), count, device); + + for (uint32_t i = 0; i < count; i++) { + if (indirect_blocks[i]) { + printf(" Double indirect -> Indirect block: %u\n", indirect_blocks[i]); + + uint32_t blocks[count]; + fseek(device, indirect_blocks[i] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, device); + + for (uint32_t j = 0; j < count; j++) { + if (blocks[j]) + printf(" -> %u\n", blocks[j]); + } + } + } + } + + // Вывод из тройного косвенного блока + if (inode.i_block[EXT2_TIND_BLOCK]) { + printf("Triple indirect block: %u\n", inode.i_block[EXT2_TIND_BLOCK]); + + uint32_t count = block_size / sizeof(uint32_t); + uint32_t dind_blocks[count]; + fseek(device, inode.i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); + fread(dind_blocks, sizeof(uint32_t), count, device); + + for (uint32_t i = 0; i < count; i++) { + if (dind_blocks[i]) { + printf(" Triple indirect -> Double indirect block: %u\n", dind_blocks[i]); + + uint32_t indirect_blocks[count]; + fseek(device, dind_blocks[i] * block_size, SEEK_SET); + fread(indirect_blocks, sizeof(uint32_t), count, device); + + for (uint32_t j = 0; j < count; j++) { + if (indirect_blocks[j]) { + printf(" -> Indirect block: %u\n", indirect_blocks[j]); + + uint32_t blocks[count]; + fseek(device, indirect_blocks[j] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, device); + + for (uint32_t k = 0; k < count; k++) { + if (blocks[k]) + printf(" -> %u\n", blocks[k]); + } + } + } + } + } + } +} + + +int main(int argc, char *argv[]) { + if (argc != 3) { + printf("Usage: \n"); + exit(-1); + } + char *filename = argv[1]; + FILE *fp = fopen(filename, "rb"); + if (fp == NULL) { + perror("fopen"); + } + + if (read_superblock(fp) == -1) { + return -1; + } + if (read_group_descriptors(fp) == -1) { + return -1; + } + if (read_inode_by_number(fp, strtol(argv[2], 0, 10)) == -1) { + return -1; + } + if (print_inode_blocks(0, 0) == -1) { + return -1; + } return 0; } diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..0d1a4ad --- /dev/null +++ b/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +truncate --size 1M ext2.img +mkfs.ext2 ext2.img +mkdir ext2 +sudo mount -t ext2 ext2.img ext2 +cd ext2 + +# Создание вложенной структуры папок +mkdir -p project/section1/subsectionA +mkdir -p project/section1/subsectionB +mkdir -p project/section2/subsectionC + +# Создание файлов и запись текста +echo "Это файл A1" > project/section1/subsectionA/fileA1.txt +truncate -s 10K project/section1/subsectionA/fileA1.txt +echo "Это файл A2" > project/section1/subsectionA/fileA2.txt +echo "Это файл B1, в котором написан текст побольше, чем в файле А2 или А1" > project/section1/subsectionB/fileB1.txt +echo "C1" > project/section2/subsectionC/fileC1.txt +echo "Это файл C2, в котором написан ну просто огромный и содержательный текст. А потом этот файл ещё и ресайзнут до невероятных масштабов. Короче говоря файл-гигант!" > project/section2/subsectionC/fileC2.txt +truncate -s 100K project/section2/subsectionC/fileC1.txt + +cd .. + + +shopt -s globstar # Включаем поддержку ** +for file in ext2/project/**/**; do + if [ -f "$file" ]; then + inode=$(stat -c '%i' "$file") + md5=$(md5sum "$file" | awk '{print $1}') + echo "Файл: $file | inode: $inode | md5: $md5" >> stats.txt + fi +done + diff --git a/util.c b/util.c new file mode 100644 index 0000000..3e804c1 --- /dev/null +++ b/util.c @@ -0,0 +1,188 @@ +// // найти адреса блоков данных (прямые и непрямые), извлечь их и вывести в stdout. +// +// #include +// #include +// #include +// +// const size_t start = 0; +// const size_t superblock_start = 1024; +// size_t block_group_descriptor_table_start = -1; +// +// uint32_t big_endian(uint32_t n) { +// union { +// uint32_t u32; +// uint8_t u8[4]; +// } be; +// +// for (size_t i = 0; i < 4; i++) { +// size_t shift = (4 - 1 - i) * 8; +// be.u8[i] = (n >> shift) & 0xFFu; +// } +// return be.u32; +// } +// +// typedef struct superblock { +// int32_t block_size; +// int32_t blocks_per_group; +// int32_t inodes_per_group; +// int32_t inode_size; +// } superblock_t; +// +// typedef struct block_group_descriptor { +// size_t inode_table_starting_block; +// } block_group_descriptor_t; +// +// typedef struct inode { +// size_t size; +// size_t direct_blocks[12]; +// size_t indirect1; +// size_t indirect2; +// size_t indirect3; +// } inode_t; +// +// superblock_t read_superblock(FILE *f) { +// superblock_t sb; +// fseek(f, superblock_start, start); +// fseek(f, 24, 0); +// fread(&sb.block_size, sizeof(sb.block_size), 1, f); +// sb.block_size = 1024 << sb.block_size; +// fseek(f, 32, 0); +// fread(&sb.blocks_per_group, sizeof(sb.blocks_per_group), 1, f); +// fseek(f, 40, 0); +// fread(&sb.inodes_per_group, sizeof(sb.inodes_per_group), 1, f); +// +// char tmp[2]; +// fseek(f, 62, 0); +// fread(tmp, sizeof(char), 2, f); +// if (tmp[0] == 0 && tmp[1] == 0) { +// sb.inode_size = 128; +// } else { +// sb.inode_size = 256; +// } +// +// if (sb.block_size>1024) { +// block_group_descriptor_table_start = 1; +// } +// else { +// block_group_descriptor_table_start = 2; +// } +// return sb; +// } +// +// block_group_descriptor_t read_block_group_descriptor(FILE *f, superblock_t sb) { +// block_group_descriptor_t bd; +// fseek(f, block_group_descriptor_table_start*sb.block_size+8, SEEK_SET); +// fread(&bd.inode_table_starting_block, sizeof(bd.inode_table_starting_block), 1, f); +// return bd; +// } +// +// inode_t read_inode(FILE *f, int inode_number) { +// inode_t data; +// superblock_t sb = read_superblock(f); +// +// int group_number = (inode_number - 1) / sb.blocks_per_group; +// int index = (inode_number - 1) % sb.inodes_per_group; +// int offset = index * sb.inode_size / sb.block_size; +// +// block_group_descriptor_t bd = read_block_group_descriptor(f, sb); +// fseek(f, (offset+bd.inode_table_starting_block)*sb.block_size + index*sb.inode_size, SEEK_SET); +// +// } +// +// +// // Пример: считать блоки из файловой системы ext2 +// void print_inode_blocks(struct ext2_inode *inode, FILE *device, uint32_t block_size) { +// printf("File size: %u bytes\n", inode->i_size); +// +// // Вывод прямых блоков +// for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { +// if (inode->i_block[i]) +// printf("Direct block %d: %u\n", i, inode->i_block[i]); +// } +// +// // Вывод из одинарно косвенного блока +// if (inode->i_block[EXT2_IND_BLOCK]) { +// printf("Indirect block: %u\n", inode->i_block[EXT2_IND_BLOCK]); +// +// uint32_t count = block_size / sizeof(uint32_t); +// uint32_t blocks[count]; +// fseek(device, inode->i_block[EXT2_IND_BLOCK] * block_size, SEEK_SET); +// fread(blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t i = 0; i < count; i++) { +// if (blocks[i]) +// printf(" Indirect -> %u\n", blocks[i]); +// } +// } +// +// // Вывод из двойного косвенного блока +// if (inode->i_block[EXT2_DIND_BLOCK]) { +// printf("Double indirect block: %u\n", inode->i_block[EXT2_DIND_BLOCK]); +// +// uint32_t count = block_size / sizeof(uint32_t); +// uint32_t indirect_blocks[count]; +// fseek(device, inode->i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); +// fread(indirect_blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t i = 0; i < count; i++) { +// if (indirect_blocks[i]) { +// printf(" Double indirect -> Indirect block: %u\n", indirect_blocks[i]); +// +// uint32_t blocks[count]; +// fseek(device, indirect_blocks[i] * block_size, SEEK_SET); +// fread(blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t j = 0; j < count; j++) { +// if (blocks[j]) +// printf(" -> %u\n", blocks[j]); +// } +// } +// } +// } +// +// // Вывод из тройного косвенного блока +// if (inode->i_block[EXT2_TIND_BLOCK]) { +// printf("Triple indirect block: %u\n", inode->i_block[EXT2_TIND_BLOCK]); +// +// uint32_t count = block_size / sizeof(uint32_t); +// uint32_t dind_blocks[count]; +// fseek(device, inode->i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); +// fread(dind_blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t i = 0; i < count; i++) { +// if (dind_blocks[i]) { +// printf(" Triple indirect -> Double indirect block: %u\n", dind_blocks[i]); +// +// uint32_t indirect_blocks[count]; +// fseek(device, dind_blocks[i] * block_size, SEEK_SET); +// fread(indirect_blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t j = 0; j < count; j++) { +// if (indirect_blocks[j]) { +// printf(" -> Indirect block: %u\n", indirect_blocks[j]); +// +// uint32_t blocks[count]; +// fseek(device, indirect_blocks[j] * block_size, SEEK_SET); +// fread(blocks, sizeof(uint32_t), count, device); +// +// for (uint32_t k = 0; k < count; k++) { +// if (blocks[k]) +// printf(" -> %u\n", blocks[k]); +// } +// } +// } +// } +// } +// } +// } +// +// int main(int argc, char *argv[]) { +// if (argc != 2) { +// printf("Usage: %s \n", argv[0]); +// } +// char *filename = argv[1]; +// FILE *f = fopen(filename, "rb"); +// if (f == NULL) { +// perror("fopen"); +// } +// } From 8cff4902b63b2cfcdbedeb9f867add0e3c0ee8a6 Mon Sep 17 00:00:00 2001 From: Sanya239 Date: Sat, 17 May 2025 04:06:24 +0300 Subject: [PATCH 2/4] =?UTF-8?q?sudo=20sh=20test.sh=20#=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=83=D1=81=D0=BA=D0=B0=D0=B5=D1=82=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82.=20=D0=A0=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=20=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B5=20stats.txt=20?= =?UTF-8?q?(=D0=BF=D1=80=D0=B8=D0=BA=D1=80=D0=B5=D0=BF=D0=BB=D1=91=D0=BD?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=D0=B0)=20sudo=20sh=20cleanup.sh=20#=20=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=B0=D0=B5=D1=82=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=D0=BE=D0=B9=20=D1=81=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cleanup.sh | 2 - main.c | 173 ++++++++++++++++++++++++++++++++++++++---------- test.sh | 23 +++++-- util.c | 188 ----------------------------------------------------- 4 files changed, 156 insertions(+), 230 deletions(-) delete mode 100644 util.c diff --git a/cleanup.sh b/cleanup.sh index 048228b..9510c07 100644 --- a/cleanup.sh +++ b/cleanup.sh @@ -1,5 +1,3 @@ -umount ext2 sudo rm -rf ext2.img sudo rm -rf ext2 -sudo rm stats.txt diff --git a/main.c b/main.c index 588b610..481232b 100644 --- a/main.c +++ b/main.c @@ -54,7 +54,6 @@ int read_inode_by_number(FILE *fp, uint32_t inode_num) { fprintf(stderr, "Invalid inode number: %u\n", inode_num); return -1; } - uint32_t inodes_per_group = EXT2_SUPER_INODES_PER_GROUP(superblock); const uint32_t group = (inode_num - 1) / inodes_per_group; const uint32_t index_in_group = (inode_num - 1) % inodes_per_group; @@ -81,50 +80,137 @@ int read_inode_by_number(FILE *fp, uint32_t inode_num) { return 0; } -int print_inode_blocks(FILE *device, uint32_t block_size) { - printf("File size: %u bytes\n", inode.i_size); + +// Печатает содержимое блока ext2 как текст +void print_block_contents(FILE *fp, uint32_t block_num, uint64_t size) { + uint8_t *buffer = malloc(size); + if (!buffer) { + perror("malloc"); + return; + } + + // Смещение в байтах = номер блока * размер блока + uint64_t offset = (uint64_t) block_num * EXT2_BLOCK_SIZE(superblock); + + if (fseek(fp, offset, SEEK_SET) != 0) { + perror("fseek to block"); + free(buffer); + return; + } + + if (fread(buffer, size, 1, fp) != 1) { + perror("fread block"); + free(buffer); + return; + } + fwrite(buffer, size, 1, stdout); + + free(buffer); +} + +int print_inode_blocks(FILE *fp) { + uint32_t block_size = EXT2_BLOCK_SIZE(superblock); + uint64_t filesize = EXT2_INODE_SIZE(inode); // Вывод прямых блоков + + int32_t zeroes[block_size]; + for (uint32_t i = 0; i < block_size; i++) { + zeroes[i] = 0; + } + for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { - if (inode.i_block[i]) - printf("Direct block %d: %u\n", i, inode.i_block[i]); + if (inode.i_block[i]) { + if (filesize >= block_size) { + print_block_contents(fp, inode.i_block[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, inode.i_block[i], filesize); + return 0; + } + } else { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } + } } - return 0; // Вывод из одинарно косвенного блока - if (inode.i_block[EXT2_IND_BLOCK]) { - printf("Indirect block: %u\n", inode.i_block[EXT2_IND_BLOCK]); - uint32_t count = block_size / sizeof(uint32_t); + uint32_t count = block_size / sizeof(uint32_t); + + if (inode.i_block[EXT2_IND_BLOCK]) { uint32_t blocks[count]; - fseek(device, inode.i_block[EXT2_IND_BLOCK] * block_size, SEEK_SET); - fread(blocks, sizeof(uint32_t), count, device); + fseek(fp, (inode.i_block[EXT2_IND_BLOCK]) * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, fp); for (uint32_t i = 0; i < count; i++) { - if (blocks[i]) - printf(" Indirect -> %u\n", blocks[i]); + if (blocks[i]) { + if (filesize >= block_size) { + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, blocks[i], filesize); + return 0; + } + } else { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } + } + } + } else { + for (uint32_t i = 0; i < count; i++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } } } // Вывод из двойного косвенного блока if (inode.i_block[EXT2_DIND_BLOCK]) { - printf("Double indirect block: %u\n", inode.i_block[EXT2_DIND_BLOCK]); - - uint32_t count = block_size / sizeof(uint32_t); uint32_t indirect_blocks[count]; - fseek(device, inode.i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); - fread(indirect_blocks, sizeof(uint32_t), count, device); + fseek(fp, inode.i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); + fread(indirect_blocks, sizeof(uint32_t), count, fp); for (uint32_t i = 0; i < count; i++) { if (indirect_blocks[i]) { - printf(" Double indirect -> Indirect block: %u\n", indirect_blocks[i]); - uint32_t blocks[count]; - fseek(device, indirect_blocks[i] * block_size, SEEK_SET); - fread(blocks, sizeof(uint32_t), count, device); + fseek(fp, indirect_blocks[i] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, fp); for (uint32_t j = 0; j < count; j++) { if (blocks[j]) - printf(" -> %u\n", blocks[j]); + if (filesize >= block_size) { + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, blocks[i], filesize); + return 0; + } + } + } + } + } else { + for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < count; j++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; } } } @@ -134,35 +220,50 @@ int print_inode_blocks(FILE *device, uint32_t block_size) { if (inode.i_block[EXT2_TIND_BLOCK]) { printf("Triple indirect block: %u\n", inode.i_block[EXT2_TIND_BLOCK]); - uint32_t count = block_size / sizeof(uint32_t); uint32_t dind_blocks[count]; - fseek(device, inode.i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); - fread(dind_blocks, sizeof(uint32_t), count, device); + fseek(fp, inode.i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); + fread(dind_blocks, sizeof(uint32_t), count, fp); for (uint32_t i = 0; i < count; i++) { if (dind_blocks[i]) { - printf(" Triple indirect -> Double indirect block: %u\n", dind_blocks[i]); - uint32_t indirect_blocks[count]; - fseek(device, dind_blocks[i] * block_size, SEEK_SET); - fread(indirect_blocks, sizeof(uint32_t), count, device); + fseek(fp, dind_blocks[i] * block_size, SEEK_SET); + fread(indirect_blocks, sizeof(uint32_t), count, fp); for (uint32_t j = 0; j < count; j++) { if (indirect_blocks[j]) { - printf(" -> Indirect block: %u\n", indirect_blocks[j]); - uint32_t blocks[count]; - fseek(device, indirect_blocks[j] * block_size, SEEK_SET); - fread(blocks, sizeof(uint32_t), count, device); + fseek(fp, indirect_blocks[j] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, fp); for (uint32_t k = 0; k < count; k++) { if (blocks[k]) - printf(" -> %u\n", blocks[k]); + if (filesize >= block_size) { + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, blocks[i], filesize); + return 0; + } } } } } } + } else { + for (uint32_t q = 0; q < count; q++) { + for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < count; j++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } + } + } + } } } @@ -187,7 +288,7 @@ int main(int argc, char *argv[]) { if (read_inode_by_number(fp, strtol(argv[2], 0, 10)) == -1) { return -1; } - if (print_inode_blocks(0, 0) == -1) { + if (print_inode_blocks(fp) == -1) { return -1; } return 0; diff --git a/test.sh b/test.sh index 0d1a4ad..615f3a9 100644 --- a/test.sh +++ b/test.sh @@ -17,18 +17,33 @@ truncate -s 10K project/section1/subsectionA/fileA1.txt echo "Это файл A2" > project/section1/subsectionA/fileA2.txt echo "Это файл B1, в котором написан текст побольше, чем в файле А2 или А1" > project/section1/subsectionB/fileB1.txt echo "C1" > project/section2/subsectionC/fileC1.txt -echo "Это файл C2, в котором написан ну просто огромный и содержательный текст. А потом этот файл ещё и ресайзнут до невероятных масштабов. Короче говоря файл-гигант!" > project/section2/subsectionC/fileC2.txt -truncate -s 100K project/section2/subsectionC/fileC1.txt +echo "Это файл C2, в котором написан ну просто огромный и содержательный текст(нет). Короче говоря файл-гигант!" > project/section2/subsectionC/fileC2.txt +head -c 40K /dev/urandom >> project/section2/subsectionC/fileC2.txt +truncate -s 1000K project/section2/subsectionC/fileC2.txt cd .. shopt -s globstar # Включаем поддержку ** + +inode_numbers=() +test_array=() +echo "${test_array[@]}" +echo "Реальные данные" > stats.txt for file in ext2/project/**/**; do if [ -f "$file" ]; then inode=$(stat -c '%i' "$file") - md5=$(md5sum "$file" | awk '{print $1}') - echo "Файл: $file | inode: $inode | md5: $md5" >> stats.txt + inode_numbers+=("$inode") + sha512=$(sha512sum "$file" | awk '{print $1}') + echo "Файл: $file | inode: $inode | sha512: $sha512" >> stats.txt fi done +umount ext2 +echo "Файлы сгенерированы" +echo "Вывод утилиты" >> stats.txt +for inode in ${inode_numbers[@]}; do + echo "$inode" + sha512=$(./main "ext2.img" "$inode" | sha512sum | awk '{print $1}') + echo "Файл2: $file | inode: $inode | sha512: $sha512" >> stats.txt +done diff --git a/util.c b/util.c deleted file mode 100644 index 3e804c1..0000000 --- a/util.c +++ /dev/null @@ -1,188 +0,0 @@ -// // найти адреса блоков данных (прямые и непрямые), извлечь их и вывести в stdout. -// -// #include -// #include -// #include -// -// const size_t start = 0; -// const size_t superblock_start = 1024; -// size_t block_group_descriptor_table_start = -1; -// -// uint32_t big_endian(uint32_t n) { -// union { -// uint32_t u32; -// uint8_t u8[4]; -// } be; -// -// for (size_t i = 0; i < 4; i++) { -// size_t shift = (4 - 1 - i) * 8; -// be.u8[i] = (n >> shift) & 0xFFu; -// } -// return be.u32; -// } -// -// typedef struct superblock { -// int32_t block_size; -// int32_t blocks_per_group; -// int32_t inodes_per_group; -// int32_t inode_size; -// } superblock_t; -// -// typedef struct block_group_descriptor { -// size_t inode_table_starting_block; -// } block_group_descriptor_t; -// -// typedef struct inode { -// size_t size; -// size_t direct_blocks[12]; -// size_t indirect1; -// size_t indirect2; -// size_t indirect3; -// } inode_t; -// -// superblock_t read_superblock(FILE *f) { -// superblock_t sb; -// fseek(f, superblock_start, start); -// fseek(f, 24, 0); -// fread(&sb.block_size, sizeof(sb.block_size), 1, f); -// sb.block_size = 1024 << sb.block_size; -// fseek(f, 32, 0); -// fread(&sb.blocks_per_group, sizeof(sb.blocks_per_group), 1, f); -// fseek(f, 40, 0); -// fread(&sb.inodes_per_group, sizeof(sb.inodes_per_group), 1, f); -// -// char tmp[2]; -// fseek(f, 62, 0); -// fread(tmp, sizeof(char), 2, f); -// if (tmp[0] == 0 && tmp[1] == 0) { -// sb.inode_size = 128; -// } else { -// sb.inode_size = 256; -// } -// -// if (sb.block_size>1024) { -// block_group_descriptor_table_start = 1; -// } -// else { -// block_group_descriptor_table_start = 2; -// } -// return sb; -// } -// -// block_group_descriptor_t read_block_group_descriptor(FILE *f, superblock_t sb) { -// block_group_descriptor_t bd; -// fseek(f, block_group_descriptor_table_start*sb.block_size+8, SEEK_SET); -// fread(&bd.inode_table_starting_block, sizeof(bd.inode_table_starting_block), 1, f); -// return bd; -// } -// -// inode_t read_inode(FILE *f, int inode_number) { -// inode_t data; -// superblock_t sb = read_superblock(f); -// -// int group_number = (inode_number - 1) / sb.blocks_per_group; -// int index = (inode_number - 1) % sb.inodes_per_group; -// int offset = index * sb.inode_size / sb.block_size; -// -// block_group_descriptor_t bd = read_block_group_descriptor(f, sb); -// fseek(f, (offset+bd.inode_table_starting_block)*sb.block_size + index*sb.inode_size, SEEK_SET); -// -// } -// -// -// // Пример: считать блоки из файловой системы ext2 -// void print_inode_blocks(struct ext2_inode *inode, FILE *device, uint32_t block_size) { -// printf("File size: %u bytes\n", inode->i_size); -// -// // Вывод прямых блоков -// for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { -// if (inode->i_block[i]) -// printf("Direct block %d: %u\n", i, inode->i_block[i]); -// } -// -// // Вывод из одинарно косвенного блока -// if (inode->i_block[EXT2_IND_BLOCK]) { -// printf("Indirect block: %u\n", inode->i_block[EXT2_IND_BLOCK]); -// -// uint32_t count = block_size / sizeof(uint32_t); -// uint32_t blocks[count]; -// fseek(device, inode->i_block[EXT2_IND_BLOCK] * block_size, SEEK_SET); -// fread(blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t i = 0; i < count; i++) { -// if (blocks[i]) -// printf(" Indirect -> %u\n", blocks[i]); -// } -// } -// -// // Вывод из двойного косвенного блока -// if (inode->i_block[EXT2_DIND_BLOCK]) { -// printf("Double indirect block: %u\n", inode->i_block[EXT2_DIND_BLOCK]); -// -// uint32_t count = block_size / sizeof(uint32_t); -// uint32_t indirect_blocks[count]; -// fseek(device, inode->i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); -// fread(indirect_blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t i = 0; i < count; i++) { -// if (indirect_blocks[i]) { -// printf(" Double indirect -> Indirect block: %u\n", indirect_blocks[i]); -// -// uint32_t blocks[count]; -// fseek(device, indirect_blocks[i] * block_size, SEEK_SET); -// fread(blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t j = 0; j < count; j++) { -// if (blocks[j]) -// printf(" -> %u\n", blocks[j]); -// } -// } -// } -// } -// -// // Вывод из тройного косвенного блока -// if (inode->i_block[EXT2_TIND_BLOCK]) { -// printf("Triple indirect block: %u\n", inode->i_block[EXT2_TIND_BLOCK]); -// -// uint32_t count = block_size / sizeof(uint32_t); -// uint32_t dind_blocks[count]; -// fseek(device, inode->i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); -// fread(dind_blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t i = 0; i < count; i++) { -// if (dind_blocks[i]) { -// printf(" Triple indirect -> Double indirect block: %u\n", dind_blocks[i]); -// -// uint32_t indirect_blocks[count]; -// fseek(device, dind_blocks[i] * block_size, SEEK_SET); -// fread(indirect_blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t j = 0; j < count; j++) { -// if (indirect_blocks[j]) { -// printf(" -> Indirect block: %u\n", indirect_blocks[j]); -// -// uint32_t blocks[count]; -// fseek(device, indirect_blocks[j] * block_size, SEEK_SET); -// fread(blocks, sizeof(uint32_t), count, device); -// -// for (uint32_t k = 0; k < count; k++) { -// if (blocks[k]) -// printf(" -> %u\n", blocks[k]); -// } -// } -// } -// } -// } -// } -// } -// -// int main(int argc, char *argv[]) { -// if (argc != 2) { -// printf("Usage: %s \n", argv[0]); -// } -// char *filename = argv[1]; -// FILE *f = fopen(filename, "rb"); -// if (f == NULL) { -// perror("fopen"); -// } -// } From c63f25db53fb4e6812d063a081706bd66438ab4d Mon Sep 17 00:00:00 2001 From: Sanya239 Date: Sat, 17 May 2025 12:03:54 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=97=D0=B0=D0=B1=D1=8B=D0=BB,=20=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D0=BF=D0=BC=D0=BF=D0=B8=D0=BB=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test.sh b/test.sh index 615f3a9..6f8fc8b 100644 --- a/test.sh +++ b/test.sh @@ -40,6 +40,8 @@ for file in ext2/project/**/**; do done umount ext2 echo "Файлы сгенерированы" + +gcc -o main main.c echo "Вывод утилиты" >> stats.txt for inode in ${inode_numbers[@]}; do echo "$inode" From 577f9fa7a8eb5f9f74cf101a6751ef4e8bdfc532 Mon Sep 17 00:00:00 2001 From: Sanya239 Date: Sat, 24 May 2025 23:18:24 +0300 Subject: [PATCH 4/4] some fix --- main.c | 467 +++++++++++++++++++++++++++++--------------------------- test.sh | 22 +-- 2 files changed, 249 insertions(+), 240 deletions(-) diff --git a/main.c b/main.c index 481232b..41b18c6 100644 --- a/main.c +++ b/main.c @@ -13,283 +13,292 @@ struct ext2_inode inode; #define SUPERBLOCK_SIZE 1024 int read_superblock(FILE *fp) { - if (fseek(fp, SUPERBLOCK_OFFSET, SEEK_SET) != 0) { - perror("fseek"); - return -1; - } + if (fseek(fp, SUPERBLOCK_OFFSET, SEEK_SET) != 0) { + perror("fseek"); + return -1; + } - if (fread(&superblock, sizeof(struct ext2_super_block), 1, fp) != 1) { - perror("fread superblock"); - return -1; - } + if (fread(&superblock, sizeof(struct ext2_super_block), 1, fp) != 1) { + perror("fread superblock"); + return -1; + } - return 0; + return 0; } int read_group_descriptors(FILE *fp) { - const uint32_t gd_table_offset = (EXT2_BLOCK_SIZE(superblock) == SUPERBLOCK_SIZE) - ? SUPERBLOCK_SIZE + SUPERBLOCK_OFFSET - : EXT2_BLOCK_SIZE(superblock); - - if (fseek(fp, gd_table_offset, SEEK_SET) != 0) { - perror("fseek to group descriptor table"); - return -1; - } - - uint32_t num_groups = (EXT2_SUPER_BLOCKS_COUNT(superblock) + EXT2_SUPER_BLOCKS_PER_GROUP(superblock) - 1) / - EXT2_SUPER_BLOCKS_PER_GROUP(superblock); - group_descriptor_table = malloc(num_groups * sizeof(struct ext2_group_desc)); - if (fread(group_descriptor_table, sizeof(struct ext2_group_desc), num_groups, fp) != 1) { - perror("fread group descriptor table"); - return -1; - } - - return 0; + const uint32_t gd_table_offset = (EXT2_BLOCK_SIZE(superblock) == SUPERBLOCK_SIZE) + ? SUPERBLOCK_SIZE + SUPERBLOCK_OFFSET + : EXT2_BLOCK_SIZE(superblock); + + if (fseek(fp, gd_table_offset, SEEK_SET) != 0) { + perror("fseek to group descriptor table"); + return -1; + } + + uint32_t num_groups = (EXT2_SUPER_BLOCKS_COUNT(superblock) + EXT2_SUPER_BLOCKS_PER_GROUP(superblock) - 1) / + EXT2_SUPER_BLOCKS_PER_GROUP(superblock); + group_descriptor_table = malloc(num_groups * sizeof(struct ext2_group_desc)); + if (fread(group_descriptor_table, sizeof(struct ext2_group_desc), num_groups, fp) != 1) { + perror("fread group descriptor table"); + return -1; + } + + return 0; } // Чтение inode по его номеру int read_inode_by_number(FILE *fp, uint32_t inode_num) { - if (inode_num == 0 || inode_num > EXT2_SUPER_INODES_COUNT(superblock)) { - fprintf(stderr, "Invalid inode number: %u\n", inode_num); - return -1; - } - uint32_t inodes_per_group = EXT2_SUPER_INODES_PER_GROUP(superblock); - const uint32_t group = (inode_num - 1) / inodes_per_group; - const uint32_t index_in_group = (inode_num - 1) % inodes_per_group; - - uint32_t inode_table_block = EXT2_GROUP_INODE_TABLE(group_descriptor_table[group]); - - // Размер inode - const uint32_t inode_size = EXT2_SUPER_INODE_SIZE(superblock); - - // Смещение до нужного inode (в байтах) - long int inode_offset = (inode_table_block * EXT2_BLOCK_SIZE(superblock)) + (index_in_group * inode_size); - - // Чтение inode - if (fseek(fp, inode_offset, SEEK_SET) != 0) { - perror("fseek to inode"); - return -1; - } - - if (fread(&inode, sizeof(struct ext2_inode), 1, fp) != 1) { - perror("fread inode"); - return -1; - } - - return 0; + if (inode_num == 0 || inode_num > EXT2_SUPER_INODES_COUNT(superblock)) { + fprintf(stderr, "Invalid inode number: %u\n", inode_num); + return -1; + } + uint32_t inodes_per_group = EXT2_SUPER_INODES_PER_GROUP(superblock); + const uint32_t group = (inode_num - 1) / inodes_per_group; + const uint32_t index_in_group = (inode_num - 1) % inodes_per_group; + + uint32_t inode_table_block = EXT2_GROUP_INODE_TABLE(group_descriptor_table[group]); + + // Размер inode + const uint32_t inode_size = EXT2_SUPER_INODE_SIZE(superblock); + + // Смещение до нужного inode (в байтах) + long int inode_offset = (inode_table_block * EXT2_BLOCK_SIZE(superblock)) + (index_in_group * inode_size); + + // Чтение inode + if (fseek(fp, inode_offset, SEEK_SET) != 0) { + perror("fseek to inode"); + return -1; + } + + if (fread(&inode, sizeof(struct ext2_inode), 1, fp) != 1) { + perror("fread inode"); + return -1; + } + + return 0; } // Печатает содержимое блока ext2 как текст void print_block_contents(FILE *fp, uint32_t block_num, uint64_t size) { - uint8_t *buffer = malloc(size); - if (!buffer) { - perror("malloc"); - return; - } + uint8_t *buffer = malloc(size); + if (!buffer) { + perror("malloc"); + return; + } - // Смещение в байтах = номер блока * размер блока - uint64_t offset = (uint64_t) block_num * EXT2_BLOCK_SIZE(superblock); - - if (fseek(fp, offset, SEEK_SET) != 0) { - perror("fseek to block"); - free(buffer); - return; - } - - if (fread(buffer, size, 1, fp) != 1) { - perror("fread block"); - free(buffer); - return; - } - fwrite(buffer, size, 1, stdout); + // Смещение в байтах = номер блока * размер блока + uint64_t offset = (uint64_t) block_num * EXT2_BLOCK_SIZE(superblock); + if (fseek(fp, offset, SEEK_SET) != 0) { + perror("fseek to block"); free(buffer); -} + return; + } -int print_inode_blocks(FILE *fp) { - uint32_t block_size = EXT2_BLOCK_SIZE(superblock); - uint64_t filesize = EXT2_INODE_SIZE(inode); + if (fread(buffer, size, 1, fp) != 1) { + perror("fread block"); + free(buffer); + return; + } + fwrite(buffer, size, 1, stdout); - // Вывод прямых блоков + free(buffer); +} - int32_t zeroes[block_size]; - for (uint32_t i = 0; i < block_size; i++) { - zeroes[i] = 0; +void print_inode_blocks(FILE *fp) { + uint32_t block_size = EXT2_BLOCK_SIZE(superblock); + uint64_t filesize = EXT2_INODE_SIZE(inode); + + // Вывод прямых блоков + + int32_t zeroes[block_size]; + for (uint32_t i = 0; i < block_size; i++) { + zeroes[i] = 0; + } + + for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { + if (inode.i_block[i]) { + if (filesize >= block_size) { + print_block_contents(fp, inode.i_block[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, inode.i_block[i], filesize); + return 0; + } + } else { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } } - - for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { - if (inode.i_block[i]) { - if (filesize >= block_size) { - print_block_contents(fp, inode.i_block[i], block_size); - filesize -= block_size; - } else if (filesize > 0) { - print_block_contents(fp, inode.i_block[i], filesize); - return 0; - } - } else { - if (filesize >= block_size) { - fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); - filesize -= block_size; - } else if (filesize > 0) { - fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); - return 0; - } + } + // Вывод из одинарно косвенного блока + + uint32_t count = block_size / sizeof(uint32_t); + + if (inode.i_block[EXT2_IND_BLOCK]) { + uint32_t blocks[count]; + fseek(fp, (inode.i_block[EXT2_IND_BLOCK]) * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, fp); + + for (uint32_t i = 0; i < count; i++) { + if (blocks[i]) { + if (filesize >= block_size) { + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; + } else if (filesize > 0) { + print_block_contents(fp, blocks[i], filesize); + return 0; } + } else { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } + } + } + } else { + for (uint32_t i = 0; i < count; i++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } } - // Вывод из одинарно косвенного блока + } - uint32_t count = block_size / sizeof(uint32_t); + // Вывод из двойного косвенного блока + if (inode.i_block[EXT2_DIND_BLOCK]) { + uint32_t indirect_blocks[count]; + fseek(fp, inode.i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); + fread(indirect_blocks, sizeof(uint32_t), count, fp); - if (inode.i_block[EXT2_IND_BLOCK]) { + for (uint32_t i = 0; i < count; i++) { + if (indirect_blocks[i]) { uint32_t blocks[count]; - fseek(fp, (inode.i_block[EXT2_IND_BLOCK]) * block_size, SEEK_SET); + fseek(fp, indirect_blocks[i] * block_size, SEEK_SET); fread(blocks, sizeof(uint32_t), count, fp); - for (uint32_t i = 0; i < count; i++) { - if (blocks[i]) { - if (filesize >= block_size) { - print_block_contents(fp, blocks[i], block_size); - filesize -= block_size; - } else if (filesize > 0) { - print_block_contents(fp, blocks[i], filesize); - return 0; - } - } else { - if (filesize >= block_size) { - fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); - filesize -= block_size; - } else if (filesize > 0) { - fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); - return 0; - } - } - } - } else { - for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < count; j++) { + if (blocks[j]) { if (filesize >= block_size) { - fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); - filesize -= block_size; + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; } else if (filesize > 0) { - fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); - return 0; + print_block_contents(fp, blocks[i], filesize); + return 0; } + } } + } } + } else { + for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < count; j++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } + } + } + } + + // Вывод из тройного косвенного блока + if (inode.i_block[EXT2_TIND_BLOCK]) { + printf("Triple indirect block: %u\n", inode.i_block[EXT2_TIND_BLOCK]); + + uint32_t dind_blocks[count]; + fseek(fp, inode.i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); + fread(dind_blocks, sizeof(uint32_t), count, fp); - // Вывод из двойного косвенного блока - if (inode.i_block[EXT2_DIND_BLOCK]) { + for (uint32_t i = 0; i < count; i++) { + if (dind_blocks[i]) { uint32_t indirect_blocks[count]; - fseek(fp, inode.i_block[EXT2_DIND_BLOCK] * block_size, SEEK_SET); + fseek(fp, dind_blocks[i] * block_size, SEEK_SET); fread(indirect_blocks, sizeof(uint32_t), count, fp); - for (uint32_t i = 0; i < count; i++) { - if (indirect_blocks[i]) { - uint32_t blocks[count]; - fseek(fp, indirect_blocks[i] * block_size, SEEK_SET); - fread(blocks, sizeof(uint32_t), count, fp); - - for (uint32_t j = 0; j < count; j++) { - if (blocks[j]) - if (filesize >= block_size) { - print_block_contents(fp, blocks[i], block_size); - filesize -= block_size; - } else if (filesize > 0) { - print_block_contents(fp, blocks[i], filesize); - return 0; - } - } - } - } - } else { - for (uint32_t i = 0; i < count; i++) { - for (uint32_t j = 0; j < count; j++) { + for (uint32_t j = 0; j < count; j++) { + if (indirect_blocks[j]) { + uint32_t blocks[count]; + fseek(fp, indirect_blocks[j] * block_size, SEEK_SET); + fread(blocks, sizeof(uint32_t), count, fp); + + for (uint32_t k = 0; k < count; k++) { + if (blocks[k]) { if (filesize >= block_size) { - fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); - filesize -= block_size; + print_block_contents(fp, blocks[i], block_size); + filesize -= block_size; } else if (filesize > 0) { - fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); - return 0; + print_block_contents(fp, blocks[i], filesize); + return 0; } + } } + } } + } } - - // Вывод из тройного косвенного блока - if (inode.i_block[EXT2_TIND_BLOCK]) { - printf("Triple indirect block: %u\n", inode.i_block[EXT2_TIND_BLOCK]); - - uint32_t dind_blocks[count]; - fseek(fp, inode.i_block[EXT2_TIND_BLOCK] * block_size, SEEK_SET); - fread(dind_blocks, sizeof(uint32_t), count, fp); - - for (uint32_t i = 0; i < count; i++) { - if (dind_blocks[i]) { - uint32_t indirect_blocks[count]; - fseek(fp, dind_blocks[i] * block_size, SEEK_SET); - fread(indirect_blocks, sizeof(uint32_t), count, fp); - - for (uint32_t j = 0; j < count; j++) { - if (indirect_blocks[j]) { - uint32_t blocks[count]; - fseek(fp, indirect_blocks[j] * block_size, SEEK_SET); - fread(blocks, sizeof(uint32_t), count, fp); - - for (uint32_t k = 0; k < count; k++) { - if (blocks[k]) - if (filesize >= block_size) { - print_block_contents(fp, blocks[i], block_size); - filesize -= block_size; - } else if (filesize > 0) { - print_block_contents(fp, blocks[i], filesize); - return 0; - } - } - } - } - } - } - } else { - for (uint32_t q = 0; q < count; q++) { - for (uint32_t i = 0; i < count; i++) { - for (uint32_t j = 0; j < count; j++) { - if (filesize >= block_size) { - fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); - filesize -= block_size; - } else if (filesize > 0) { - fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); - return 0; - } - } - } + } else { + for (uint32_t q = 0; q < count; q++) { + for (uint32_t i = 0; i < count; i++) { + for (uint32_t j = 0; j < count; j++) { + if (filesize >= block_size) { + fwrite(zeroes, sizeof(int32_t), block_size / sizeof(int32_t), stdout); + filesize -= block_size; + } else if (filesize > 0) { + fwrite(zeroes, sizeof(int32_t), filesize / sizeof(int32_t), stdout); + return 0; + } } + } } + } } +FILE *fp -int main(int argc, char *argv[]) { - if (argc != 3) { - printf("Usage: \n"); - exit(-1); - } - char *filename = argv[1]; - FILE *fp = fopen(filename, "rb"); - if (fp == NULL) { - perror("fopen"); - } +void end() { + close(fp); + free(group_descriptor_table); + exit(-1); +} - if (read_superblock(fp) == -1) { - return -1; - } - if (read_group_descriptors(fp) == -1) { - return -1; - } - if (read_inode_by_number(fp, strtol(argv[2], 0, 10)) == -1) { - return -1; - } - if (print_inode_blocks(fp) == -1) { - return -1; - } - return 0; +int main(int argc, char *argv[]) { + if (argc != 3) { + printf("Usage: \n"); + exit(-1); + } + char *filename = argv[1]; + fp = fopen(filename, "rb"); + if (fp == NULL) { + perror("fopen"); + } + + if (read_superblock(fp) == -1) { + return -1; + } + if (read_group_descriptors(fp) == -1) { + return -1; + } + if (read_inode_by_number(fp, strtol(argv[2], 0, 10)) == -1) { + return -1; + } + if (print_inode_blocks(fp) == -1) { + return -1; + } + return 0; } diff --git a/test.sh b/test.sh index 6f8fc8b..4221db1 100644 --- a/test.sh +++ b/test.sh @@ -7,19 +7,19 @@ sudo mount -t ext2 ext2.img ext2 cd ext2 # Создание вложенной структуры папок -mkdir -p project/section1/subsectionA -mkdir -p project/section1/subsectionB -mkdir -p project/section2/subsectionC +sudo mkdir -p project/section1/subsectionA +sudo mkdir -p project/section1/subsectionB +sudo mkdir -p project/section2/subsectionC # Создание файлов и запись текста -echo "Это файл A1" > project/section1/subsectionA/fileA1.txt -truncate -s 10K project/section1/subsectionA/fileA1.txt -echo "Это файл A2" > project/section1/subsectionA/fileA2.txt -echo "Это файл B1, в котором написан текст побольше, чем в файле А2 или А1" > project/section1/subsectionB/fileB1.txt -echo "C1" > project/section2/subsectionC/fileC1.txt -echo "Это файл C2, в котором написан ну просто огромный и содержательный текст(нет). Короче говоря файл-гигант!" > project/section2/subsectionC/fileC2.txt -head -c 40K /dev/urandom >> project/section2/subsectionC/fileC2.txt -truncate -s 1000K project/section2/subsectionC/fileC2.txt +sudo echo "Это файл A1" > project/section1/subsectionA/fileA1.txt +sudo truncate -s 10K project/section1/subsectionA/fileA1.txt +sudo echo "Это файл A2" > project/section1/subsectionA/fileA2.txt +sudo echo "Это файл B1, в котором написан текст побольше, чем в файле А2 или А1" > project/section1/subsectionB/fileB1.txt +sudo echo "C1" > project/section2/subsectionC/fileC1.txt +sudo echo "Это файл C2, в котором написан ну просто огромный и содержательный текст(нет). Короче говоря файл-гигант!" > project/section2/subsectionC/fileC2.txt +sudo head -c 40K /dev/urandom >> project/section2/subsectionC/fileC2.txt +sudo truncate -s 1000K project/section2/subsectionC/fileC2.txt cd ..