#include "simplefs.h" #include "disk_io.h" #include "utils.h" // 位图操作工具函数 // 如果位图工具在utils.h中,mkfs.cpp就不再直接需要metadata.h了 #include #include #include #include #include // 字符串操作 #include // stat, fstat #include // open #include // close, ftruncate #include // ceil #include // std::fill #include // std::fill #include // ioctl #include // BLKGETSIZE64 // 默认参数(可通过选项覆盖) const uint32_t DEFAULT_BLOCKS_PER_GROUP = SIMPLEFS_BLOCK_SIZE * 8; // 位图中每位对应一个块 const uint32_t DEFAULT_INODES_PER_GROUP = 1024; // 选定的默认值 // 静态位图辅助函数已移至metadata.cpp void print_usage(const char* prog_name) { std::cerr << "用法: " << prog_name << " <设备文件> [块数量]" << std::endl; std::cerr << " <设备文件>: 磁盘镜像文件或块设备路径" << std::endl; std::cerr << " [块数量]: 可选,新镜像文件的总块数" << std::endl; } // 获取文件大小的函数 off_t get_file_size(int fd) { struct stat st; if (fstat(fd, &st) == -1) { perror("获取文件大小失败"); return -1; } return st.st_size; } int main(int argc, char* argv[]) { if (argc < 2 || argc > 3) { print_usage(argv[0]); return 1; } std::string device_path = argv[1]; uint64_t total_blocks_on_device = 0; uint64_t device_size_bytes = 0; bool create_new_image = false; DeviceFd fd = open(device_path.c_str(), O_RDWR); if (fd == -1) { if (errno == ENOENT && argc == 3) { // 文件不存在,且提供了大小 std::cout << "正在创建新镜像文件: " << device_path << std::endl; fd = open(device_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 0666); if (fd == -1) { perror("创建镜像文件失败"); return 1; } create_new_image = true; try { total_blocks_on_device = std::stoull(argv[2]); if (total_blocks_on_device == 0) { std::cerr << "块数量必须为正数" << std::endl; close(fd); unlink(device_path.c_str()); // 清理已创建的文件 return 1; } device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE; if (ftruncate(fd, device_size_bytes) == -1) { perror("设置镜像大小失败"); close(fd); unlink(device_path.c_str()); // 清理 return 1; } std::cout << "已创建新镜像文件 " << device_path << " (大小: " << total_blocks_on_device << " 块, " << device_size_bytes << " 字节)" << std::endl; } catch (const std::exception& e) { std::cerr << "块数量参数无效: " << e.what() << std::endl; close(fd); unlink(device_path.c_str()); // 清理 return 1; } } else if (errno == ENOENT) { std::cerr << "错误: 镜像文件 '" << device_path << "' 未找到,请提供块数量来创建" << std::endl; perror("打开设备/镜像失败"); return 1; } else { perror("打开设备/镜像失败"); return 1; } } else { bool is_blk_dev = is_block_device(fd); if (is_blk_dev) { std::cout << "检测到块设备" << std::endl; uint64_t size_from_ioctl = 0; if (ioctl(fd, BLKGETSIZE64, &size_from_ioctl) == 0) { std::cout << "通过ioctl获取块设备大小: " << size_from_ioctl << " 字节" << std::endl; if (size_from_ioctl % SIMPLEFS_BLOCK_SIZE != 0) { std::cerr << "警告: 块设备大小不是文件系统块大小的整数倍" << std::endl; } device_size_bytes = size_from_ioctl; total_blocks_on_device = device_size_bytes / SIMPLEFS_BLOCK_SIZE; if (argc == 3) { std::cout << "注意: 忽略[num_blocks]参数,已自动检测设备大小" << std::endl; } } else { perror("ioctl获取设备大小失败"); std::cerr << "无法自动检测块设备大小" << std::endl; if (argc != 3) { std::cerr << "错误: 请手动提供[num_blocks]参数" << std::endl; close(fd); return 1; } try { total_blocks_on_device = std::stoull(argv[2]); if (total_blocks_on_device == 0) { std::cerr << "块数量必须为正数" << std::endl; close(fd); return 1; } device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE; } catch (const std::exception& e) { std::cerr << "块数量参数无效: " << e.what() << std::endl; close(fd); return 1; } } std::cout << "格式化块设备 " << device_path << ",块数: " << total_blocks_on_device << " (" << device_size_bytes << " 字节)" << std::endl; } else { // 这是常规文件,获取其大小 off_t existing_size = get_file_size(fd); if (existing_size == -1) { close(fd); return 1; } if (existing_size == 0) { if (argc == 3) { // 这是空文件但用户要用指定大小格式化 std::cout << "现有文件为空,按新镜像创建处理" << std::endl; create_new_image = true; try { total_blocks_on_device = std::stoull(argv[2]); if (total_blocks_on_device == 0) { std::cerr << "块数量必须为正数" << std::endl; close(fd); return 1; } device_size_bytes = total_blocks_on_device * SIMPLEFS_BLOCK_SIZE; if (ftruncate(fd, device_size_bytes) == -1) { perror("设置镜像大小失败"); close(fd); return 1; } std::cout << "设置镜像 " << device_path << " 大小为 " << total_blocks_on_device << " 块 (" << device_size_bytes << " 字节)" << std::endl; } catch (const std::exception& e) { std::cerr << "块数量参数无效: " << e.what() << std::endl; close(fd); return 1; } } else { std::cerr << "错误: 镜像文件为空" << std::endl; std::cerr << "如需格式化,请提供num_blocks参数" << std::endl; close(fd); return 1; } } else { if (existing_size % SIMPLEFS_BLOCK_SIZE != 0) { std::cerr << "警告: 设备/镜像大小 (" << existing_size << " 字节) 不是块大小 (" << SIMPLEFS_BLOCK_SIZE << " 字节) 的整数倍" << std::endl; } device_size_bytes = existing_size; total_blocks_on_device = device_size_bytes / SIMPLEFS_BLOCK_SIZE; std::cout << "Opened existing image " << device_path << ". Total blocks: " << total_blocks_on_device << " (" << device_size_bytes << " bytes)." << std::endl; if (argc == 3 && !create_new_image) { std::cout << "Note: [num_blocks] argument is ignored when using an existing, non-empty image file." << std::endl; } } } } if (total_blocks_on_device < 64) { std::cerr << "错误: 设备/镜像太小,至少需要64个块" << std::endl; close(fd); if (create_new_image) unlink(device_path.c_str()); return 1; } std::cout << "正在格式化 " << device_path << " 为 SimpleFS..." << std::endl; uint32_t inodes_per_block = SIMPLEFS_BLOCK_SIZE / SIMPLEFS_INODE_SIZE; uint32_t sb_blocks_per_group = DEFAULT_BLOCKS_PER_GROUP; uint32_t sb_inodes_per_group = DEFAULT_INODES_PER_GROUP; if (sb_inodes_per_group > SIMPLEFS_BLOCK_SIZE * 8) { sb_inodes_per_group = SIMPLEFS_BLOCK_SIZE * 8; std::cout << "警告: 请求的每组inode数超过inode位图最大容量,调整为 " << sb_inodes_per_group << std::endl; } uint32_t num_block_groups = static_cast(std::ceil(static_cast(total_blocks_on_device) / sb_blocks_per_group)); if (num_block_groups == 0) num_block_groups = 1; uint64_t total_inodes_fs = static_cast(num_block_groups) * sb_inodes_per_group; if (total_inodes_fs > UINT32_MAX) { total_inodes_fs = UINT32_MAX; } std::cout << "文件系统布局:" << std::endl; std::cout << " 总块数: " << total_blocks_on_device << std::endl; std::cout << " 每组inode数: " << sb_inodes_per_group << std::endl; std::cout << " 块组数: " << num_block_groups << std::endl; std::cout << " 总inode数: " << total_inodes_fs << std::endl; SimpleFS_SuperBlock sb; std::memset(&sb, 0, sizeof(SimpleFS_SuperBlock)); sb.s_magic = SIMPLEFS_MAGIC; sb.s_blocks_count = total_blocks_on_device; sb.s_inodes_count = static_cast(total_inodes_fs); sb.s_log_block_size = static_cast(std::log2(SIMPLEFS_BLOCK_SIZE)) - 10; sb.s_blocks_per_group = sb_blocks_per_group; sb.s_inodes_per_group = sb_inodes_per_group; sb.s_inode_size = SIMPLEFS_INODE_SIZE; sb.s_root_inode = SIMPLEFS_ROOT_INODE_NUM; sb.s_first_ino = 11; sb.s_state = 1; sb.s_errors = 1; sb.s_max_mnt_count = 20; sb.s_mnt_count = 0; sb.s_wtime = time(nullptr); sb.s_block_group_nr = 0; uint32_t gdt_size_bytes = num_block_groups * sizeof(SimpleFS_GroupDesc); uint32_t gdt_blocks = static_cast(std::ceil(static_cast(gdt_size_bytes) / SIMPLEFS_BLOCK_SIZE)); std::cout << " GDT size: " << gdt_size_bytes << " bytes, requiring " << gdt_blocks << " blocks." << std::endl; uint32_t superblock_location_block = 1; uint32_t gdt_start_block = superblock_location_block + 1; std::vector gdt(num_block_groups); std::memset(gdt.data(), 0, gdt_size_bytes); uint32_t running_total_free_blocks = total_blocks_on_device; uint32_t running_total_free_inodes = sb.s_inodes_count; if (superblock_location_block < total_blocks_on_device) running_total_free_blocks--; else { std::cerr << "No space for SB!" << std::endl; return 1; } for(uint32_t i = 0; i < gdt_blocks; ++i) { if ((gdt_start_block + i) < total_blocks_on_device) running_total_free_blocks--; else { std::cerr << "No space for GDT!" << std::endl; return 1; } } uint32_t current_group_meta_start_block = gdt_start_block + gdt_blocks; for (uint32_t i = 0; i < num_block_groups; ++i) { SimpleFS_GroupDesc& current_gd = gdt[i]; uint32_t group_abs_start_block_for_data = i * sb.s_blocks_per_group; uint32_t inode_table_size_blocks = static_cast(std::ceil(static_cast(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE)); bool backup_here = is_backup_group(i); if (i == 0) { current_gd.bg_block_bitmap = current_group_meta_start_block; current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1; current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1; sb.s_first_data_block = current_gd.bg_inode_table + inode_table_size_blocks; } else if (backup_here) { current_gd.bg_block_bitmap = group_abs_start_block_for_data + 1 + gdt_blocks; current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1; current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1; } else { current_gd.bg_block_bitmap = group_abs_start_block_for_data; current_gd.bg_inode_bitmap = current_gd.bg_block_bitmap + 1; current_gd.bg_inode_table = current_gd.bg_inode_bitmap + 1; } uint32_t last_meta_block_for_group = current_gd.bg_inode_table + inode_table_size_blocks -1; if (last_meta_block_for_group >= total_blocks_on_device || current_gd.bg_block_bitmap >= total_blocks_on_device) { std::cerr << "错误: 组 " << i << " 的元数据超出设备限制" << std::endl; close(fd); if(create_new_image) unlink(device_path.c_str()); return 1; } running_total_free_blocks--; // 块位图 running_total_free_blocks--; // inode位图 running_total_free_blocks -= inode_table_size_blocks; // inode表 // 注意:主组(组0)的超级块和GDT已在前面减去,这里不重复减去 if (backup_here && i != 0) { // 只有备份组且不是组0才减去 running_total_free_blocks--; // 备份超级块 running_total_free_blocks -= gdt_blocks; // 备份GDT } uint32_t blocks_in_this_group_range = (i == num_block_groups - 1) ? (total_blocks_on_device - group_abs_start_block_for_data) : sb.s_blocks_per_group; current_gd.bg_free_blocks_count = blocks_in_this_group_range; current_gd.bg_free_blocks_count -= 1; // 块位图 current_gd.bg_free_blocks_count -= 1; // inode位图 current_gd.bg_free_blocks_count -= inode_table_size_blocks; // inode表 if (i == 0) { current_gd.bg_free_blocks_count--; // 超级块 current_gd.bg_free_blocks_count -= gdt_blocks; // GDT } else if (backup_here) { current_gd.bg_free_blocks_count--; // 备份超级块 current_gd.bg_free_blocks_count -= gdt_blocks; // 备份GDT } // 主要SB/GDT的额外空闲块调整已在前面完成 current_gd.bg_free_inodes_count = sb.s_inodes_per_group; current_gd.bg_used_dirs_count = 0; } sb.s_free_blocks_count = running_total_free_blocks; sb.s_free_inodes_count = running_total_free_inodes; if (gdt_start_block + gdt_blocks > gdt[0].bg_block_bitmap) { std::cerr << "严重错误: GDT与组0块位图重叠,设备太小或计算错误" << std::endl; close(fd); if(create_new_image) unlink(device_path.c_str()); return 1; } std::cout << "超级块(根目录前的最终估计值):" << std::endl; std::cout << " 空闲块数: " << sb.s_free_blocks_count << std::endl; std::cout << " 空闲inode数: " << sb.s_free_inodes_count << std::endl; std::cout << " 首个数据块(全局): " << sb.s_first_data_block << std::endl; std::vector fs_block_buffer(SIMPLEFS_BLOCK_SIZE, 0); std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb)); if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) { std::cerr << "超级块写入失败" << std::endl; close(fd); if (create_new_image) unlink(device_path.c_str()); return 1; } std::cout << "超级块已写入块 " << superblock_location_block << std::endl; uint8_t* gdt_write_ptr = reinterpret_cast(gdt.data()); for (uint32_t i = 0; i < gdt_blocks; ++i) { std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0); uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ? (gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE) : SIMPLEFS_BLOCK_SIZE; if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0; std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block); if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) { std::cerr << "GDT块 " << (gdt_start_block + i) << " 写入失败" << std::endl; close(fd); if (create_new_image) unlink(device_path.c_str()); return 1; } } std::cout << "GDT已写入块 " << gdt_start_block << " 到 " << (gdt_start_block + gdt_blocks - 1) << std::endl; std::vector group_block_bitmap_buffer(SIMPLEFS_BLOCK_SIZE, 0); std::vector group_inode_bitmap_buffer(SIMPLEFS_BLOCK_SIZE, 0); for (uint32_t i = 0; i < num_block_groups; ++i) { SimpleFS_GroupDesc& current_gd_ref = gdt[i]; uint32_t group_abs_data_start_block = i * sb.s_blocks_per_group; // 这是该组位图中位0的块号 uint32_t inode_table_size_blocks = static_cast(std::ceil(static_cast(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE)); std::cout << "Processing Group " << i << ":" << std::endl; std::cout << " BB@" << current_gd_ref.bg_block_bitmap << ", IB@" << current_gd_ref.bg_inode_bitmap << ", IT@" << current_gd_ref.bg_inode_table << " (" << inode_table_size_blocks << " blocks)" << std::endl; std::fill(group_block_bitmap_buffer.begin(), group_block_bitmap_buffer.end(), 0); std::fill(group_inode_bitmap_buffer.begin(), group_inode_bitmap_buffer.end(), 0); // 在其块位图中将组自己的元数据块标记为已使用 // 组位图中的位索引相对于该组管理的块起始位置 set_bitmap_bit(group_block_bitmap_buffer, current_gd_ref.bg_block_bitmap - group_abs_data_start_block); set_bitmap_bit(group_block_bitmap_buffer, current_gd_ref.bg_inode_bitmap - group_abs_data_start_block); for (uint32_t j = 0; j < inode_table_size_blocks; ++j) { set_bitmap_bit(group_block_bitmap_buffer, (current_gd_ref.bg_inode_table + j) - group_abs_data_start_block); } bool backup_here = is_backup_group(i); if (backup_here) { uint32_t sb_blk = (i == 0) ? superblock_location_block : group_abs_data_start_block; set_bitmap_bit(group_block_bitmap_buffer, sb_blk - group_abs_data_start_block); for (uint32_t gdt_idx = 0; gdt_idx < gdt_blocks; ++gdt_idx) { uint32_t abs_gdt_block = (i == 0) ? (gdt_start_block + gdt_idx) : (group_abs_data_start_block + 1 + gdt_idx); set_bitmap_bit(group_block_bitmap_buffer, abs_gdt_block - group_abs_data_start_block); } } if (i == 0) { if (!is_bitmap_bit_set(group_block_bitmap_buffer, 0)) { set_bitmap_bit(group_block_bitmap_buffer, 0); bool block0_was_sb = (superblock_location_block == 0); bool block0_was_gdt = false; for(uint32_t gdt_idx=0; gdt_idx < gdt_blocks; ++gdt_idx) if((gdt_start_block + gdt_idx) == 0) block0_was_gdt = true; bool block0_was_group0_bb = (current_gd_ref.bg_block_bitmap == 0); bool block0_was_group0_ib = (current_gd_ref.bg_inode_bitmap == 0); bool block0_was_group0_it = (current_gd_ref.bg_inode_table == 0); if (!block0_was_sb && !block0_was_gdt && !block0_was_group0_bb && !block0_was_group0_ib && !block0_was_group0_it) { if (current_gd_ref.bg_free_blocks_count > 0) current_gd_ref.bg_free_blocks_count--; if (sb.s_free_blocks_count > 0) sb.s_free_blocks_count--; } } set_bitmap_bit(group_inode_bitmap_buffer, 0); set_bitmap_bit(group_inode_bitmap_buffer, 1); if (current_gd_ref.bg_free_inodes_count >= 2) current_gd_ref.bg_free_inodes_count -= 2; else current_gd_ref.bg_free_inodes_count = 0; if (sb.s_free_inodes_count >= 2) sb.s_free_inodes_count -= 2; else sb.s_free_inodes_count = 0; } if (write_block(fd, current_gd_ref.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) { /* error */ return 1; } std::cout << " Written Block Bitmap. Group free blocks: " << current_gd_ref.bg_free_blocks_count << std::endl; if (write_block(fd, current_gd_ref.bg_inode_bitmap, group_inode_bitmap_buffer.data()) != 0) { /* error */ return 1; } std::cout << " Written Inode Bitmap. Group free inodes: " << current_gd_ref.bg_free_inodes_count << std::endl; if (write_zero_blocks(fd, current_gd_ref.bg_inode_table, inode_table_size_blocks) != 0) { /* error */ return 1; } std::cout << " Zeroed Inode Table." << std::endl; } std::cout << "Re-writing Superblock and GDT (final pre-root dir)..." << std::endl; std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb)); if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) { /* error */ return 1;} gdt_write_ptr = reinterpret_cast(gdt.data()); for (uint32_t i = 0; i < gdt_blocks; ++i) { std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0); uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ? (gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE) : SIMPLEFS_BLOCK_SIZE; if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0; std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block); if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) { /* error */ return 1; } } // 将超级块和GDT的备份副本写入指定组 for (uint32_t grp = 1; grp < num_block_groups; ++grp) { if (!is_backup_group(grp)) continue; uint32_t grp_start = grp * sb.s_blocks_per_group; std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb)); if (write_block(fd, grp_start, fs_block_buffer.data()) != 0) { /* error */ return 1; } for (uint32_t i = 0; i < gdt_blocks; ++i) { std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0); uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ? (gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE) : SIMPLEFS_BLOCK_SIZE; if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0; std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block); if (write_block(fd, grp_start + 1 + i, fs_block_buffer.data()) != 0) { /* error */ return 1; } } } std::cout << "Creating root directory..." << std::endl; SimpleFS_GroupDesc& group0_gd = gdt[0]; // 根inode(SIMPLEFS_ROOT_INODE_NUM,通常为2)和inode 1(位0) // 已在inode位图中标记,以及超级块/组描述符 // 在组0的初始设置循环中已减少了空闲inode计数 // 因此,此处不需要再次调用set_bitmap_bit或减少计数 // 只需为组0增加used_dirs_count group0_gd.bg_used_dirs_count++; std::cout << " Root inode " << SIMPLEFS_ROOT_INODE_NUM << " allocation accounted for (marked in bitmap and counts updated earlier)." << std::endl; std::cout << " Incremented used_dirs_count for group 0." << std::endl; // 如果后续决策依赖于最新状态,重新读取inode位图是好习惯 // 但此处不对根inode号本身做分配决策,只分配其数据块,故继续进行 // 如有疑问,可重新读取: // if (read_block(fd, group0_gd.bg_inode_bitmap, group_inode_bitmap_buffer.data()) != 0) { // std::cerr << "根目录数据分配前重新读取组0 inode位图失败" << std::endl; return 1; // } uint32_t root_dir_data_block_num = 0; if (read_block(fd, group0_gd.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) { std::cerr << "组0块位图读取失败,无法分配根目录数据块" << std::endl; return 1; } uint32_t group0_abs_start_block = 0 * sb.s_blocks_per_group; uint32_t search_start_offset_in_group0 = 0; if (sb.s_first_data_block >= group0_abs_start_block && sb.s_first_data_block < (group0_abs_start_block + sb.s_blocks_per_group) ) { search_start_offset_in_group0 = sb.s_first_data_block - group0_abs_start_block; } else if (sb.s_first_data_block < group0_abs_start_block) { search_start_offset_in_group0 = (gdt[0].bg_inode_table + static_cast(std::ceil(static_cast(sb.s_inodes_per_group) * SIMPLEFS_INODE_SIZE / SIMPLEFS_BLOCK_SIZE))) - group0_abs_start_block; } for (uint32_t block_offset_in_group = search_start_offset_in_group0; block_offset_in_group < sb.s_blocks_per_group; ++block_offset_in_group) { if (!is_bitmap_bit_set(group_block_bitmap_buffer, block_offset_in_group)) { root_dir_data_block_num = group0_abs_start_block + block_offset_in_group; set_bitmap_bit(group_block_bitmap_buffer, block_offset_in_group); group0_gd.bg_free_blocks_count--; sb.s_free_blocks_count--; break; } } if (root_dir_data_block_num == 0) { std::cerr << "错误: 组0中找不到根目录的空闲数据块" << std::endl; return 1; } if (write_block(fd, group0_gd.bg_block_bitmap, group_block_bitmap_buffer.data()) != 0) { std::cerr << "组0块位图更新失败" << std::endl; return 1; } std::cout << " 已为根目录分配数据块 " << root_dir_data_block_num << std::endl; std::vector root_dir_data_buffer(SIMPLEFS_BLOCK_SIZE, 0); uint16_t current_offset = 0; SimpleFS_DirEntry dot_entry; dot_entry.inode = SIMPLEFS_ROOT_INODE_NUM; dot_entry.name_len = 1; dot_entry.file_type = S_IFDIR >> 12; std::strncpy(dot_entry.name, ".", 1); dot_entry.rec_len = calculate_dir_entry_len(dot_entry.name_len); std::memcpy(root_dir_data_buffer.data() + current_offset, &dot_entry, (size_t)8 + dot_entry.name_len); current_offset += dot_entry.rec_len; SimpleFS_DirEntry dotdot_entry; dotdot_entry.inode = SIMPLEFS_ROOT_INODE_NUM; dotdot_entry.name_len = 2; dotdot_entry.file_type = S_IFDIR >> 12; std::strncpy(dotdot_entry.name, "..", 2); dotdot_entry.rec_len = SIMPLEFS_BLOCK_SIZE - current_offset; std::memcpy(root_dir_data_buffer.data() + current_offset, &dotdot_entry, (size_t)8 + dotdot_entry.name_len); if (write_block(fd, root_dir_data_block_num, root_dir_data_buffer.data()) != 0) { std::cerr << "根目录数据块写入失败" << std::endl; return 1; } std::cout << " 已向根目录数据块写入'.'和'..'项" << std::endl; SimpleFS_Inode root_inode; std::memset(&root_inode, 0, sizeof(SimpleFS_Inode)); root_inode.i_mode = S_IFDIR | 0777; // 从0755改为0777便于测试 root_inode.i_uid = 0; root_inode.i_gid = 0; root_inode.i_size = SIMPLEFS_BLOCK_SIZE; root_inode.i_links_count = 2; root_inode.i_blocks = SIMPLEFS_BLOCK_SIZE / 512; root_inode.i_atime = root_inode.i_ctime = root_inode.i_mtime = time(nullptr); root_inode.i_block[0] = root_dir_data_block_num; // 基于1的inode编号的修正计算 uint32_t root_inode_idx_in_group = SIMPLEFS_ROOT_INODE_NUM - 1; uint32_t root_inode_block_in_table = group0_gd.bg_inode_table + (root_inode_idx_in_group / inodes_per_block); uint32_t root_inode_offset_in_block = (root_inode_idx_in_group % inodes_per_block) * SIMPLEFS_INODE_SIZE; std::vector inode_table_block_buffer(SIMPLEFS_BLOCK_SIZE); if (read_block(fd, root_inode_block_in_table, inode_table_block_buffer.data()) != 0) { std::cerr << "根inode的inode表块读取失败" << std::endl; return 1; } std::memcpy(inode_table_block_buffer.data() + root_inode_offset_in_block, &root_inode, sizeof(SimpleFS_Inode)); if (write_block(fd, root_inode_block_in_table, inode_table_block_buffer.data()) != 0) { std::cerr << "根inode写入inode表失败" << std::endl; return 1; } std::cout << " Initialized and written root inode (inode " << SIMPLEFS_ROOT_INODE_NUM << ")." << std::endl; std::cout << "Finalizing Superblock and GDT..." << std::endl; std::memcpy(fs_block_buffer.data(), &sb, sizeof(sb)); if (write_block(fd, superblock_location_block, fs_block_buffer.data()) != 0) { /* error */ return 1;} gdt_write_ptr = reinterpret_cast(gdt.data()); for (uint32_t i = 0; i < gdt_blocks; ++i) { std::fill(fs_block_buffer.begin(), fs_block_buffer.end(), 0); uint32_t bytes_to_copy_this_block = (gdt_size_bytes - (i * SIMPLEFS_BLOCK_SIZE) < SIMPLEFS_BLOCK_SIZE) ? (gdt_size_bytes % SIMPLEFS_BLOCK_SIZE == 0 && gdt_size_bytes > 0 ? SIMPLEFS_BLOCK_SIZE : gdt_size_bytes % SIMPLEFS_BLOCK_SIZE) : SIMPLEFS_BLOCK_SIZE; if (gdt_size_bytes == 0 && i==0) bytes_to_copy_this_block = 0; std::memcpy(fs_block_buffer.data(), gdt_write_ptr + (i * SIMPLEFS_BLOCK_SIZE), bytes_to_copy_this_block); if (write_block(fd, gdt_start_block + i, fs_block_buffer.data()) != 0) { /* error */ return 1; } } std::cout << "超级块和GDT已完成" << std::endl; std::cout << "文件系统格式化成功" << std::endl; if (close(fd) == -1) { perror("关闭设备/镜像失败"); } std::cout << "SimpleFS格式化工具完成" << std::endl; return 0; }