Initial commit

This commit is contained in:
2025-11-06 10:49:44 +08:00
commit 2d16528ac4
20 changed files with 4653 additions and 0 deletions

52
src/disk_io.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include "disk_io.h"
#include "simplefs.h"
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <vector>
// 读取磁盘块
int read_block(DeviceFd fd, uint32_t block_num, void* buffer) {
off_t offset = static_cast<off_t>(block_num) * SIMPLEFS_BLOCK_SIZE;
ssize_t bytes_read = pread(fd, buffer, SIMPLEFS_BLOCK_SIZE, offset);
if (bytes_read == -1) {
perror("磁盘读取失败");
return -1;
}
if (bytes_read < SIMPLEFS_BLOCK_SIZE) {
return -1;
}
return 0;
}
// 写入磁盘块
int write_block(DeviceFd fd, uint32_t block_num, const void* buffer) {
off_t offset = static_cast<off_t>(block_num) * SIMPLEFS_BLOCK_SIZE;
ssize_t bytes_written = pwrite(fd, buffer, SIMPLEFS_BLOCK_SIZE, offset);
if (bytes_written == -1) {
perror("磁盘写入失败");
return -1;
}
if (bytes_written < SIMPLEFS_BLOCK_SIZE) {
return -1;
}
return 0;
}
// 批量写入零块
int write_zero_blocks(DeviceFd fd, uint32_t start_block_num, uint32_t count) {
if (count == 0) return 0;
std::vector<uint8_t> zero_buffer(SIMPLEFS_BLOCK_SIZE, 0);
for (uint32_t i = 0; i < count; ++i) {
if (write_block(fd, start_block_num + i, zero_buffer.data()) != 0) {
return -1;
}
}
return 0;
}

1618
src/fuse_ops.cpp Normal file

File diff suppressed because it is too large Load Diff

113
src/main.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include <fuse.h>
#include "fuse_ops.h" // init_fuse_operations和SimpleFS_Context
#include "disk_io.h" // read_block等
#include "simplefs.h" // 结构体
#include "utils.h" // is_block_device
#include <iostream>
#include <vector>
#include <string>
#include <cstring> // memset, strerror
#include <cerrno> // errno
#include <fcntl.h> // open
#include <unistd.h> // close
#include <cmath> // ceil
static SimpleFS_Context fs_context; // 全局文件系统上下文
int main(int argc, char *argv[]) {
if (argc < 3) {
std::cerr << "用法: " << argv[0] << " <设备文件> <挂载点> [FUSE选项...]" << std::endl;
return 1;
}
// 设备镜像路径是argv[1]
// 挂载点是argv[2]
// FUSE选项从argv[2]开始,如果我们移位的话,或者手动处理
// 保持简单FUSE选项在挂载点之后传递
std::string device_path = argv[1];
fs_context.device_fd = open(device_path.c_str(), O_RDWR);
if (fs_context.device_fd < 0) {
perror("无法打开设备文件");
return 1;
}
// 读取超级块
std::vector<uint8_t> sb_buffer(SIMPLEFS_BLOCK_SIZE);
if (read_block(fs_context.device_fd, 1, sb_buffer.data()) != 0) { // 超级块在块1
std::cerr << "无法读取超级块" << std::endl;
close(fs_context.device_fd);
return 1;
}
std::memcpy(&fs_context.sb, sb_buffer.data(), sizeof(SimpleFS_SuperBlock));
// 验证超级块魔数
if (fs_context.sb.s_magic != SIMPLEFS_MAGIC) {
std::cerr << "魔数不匹配不是有效的SimpleFS文件系统" << std::endl;
close(fs_context.device_fd);
return 1;
}
std::cout << "SimpleFS已加载 - 块总数: " << fs_context.sb.s_blocks_count
<< ", 空闲块: " << fs_context.sb.s_free_blocks_count << std::endl;
// 读取组描述符表(GDT)
uint32_t num_block_groups = static_cast<uint32_t>(std::ceil(static_cast<double>(fs_context.sb.s_blocks_count) / fs_context.sb.s_blocks_per_group));
if (num_block_groups == 0 && fs_context.sb.s_blocks_count > 0) num_block_groups = 1;
uint32_t gdt_size_bytes = num_block_groups * sizeof(SimpleFS_GroupDesc);
uint32_t gdt_blocks_count = static_cast<uint32_t>(std::ceil(static_cast<double>(gdt_size_bytes) / SIMPLEFS_BLOCK_SIZE));
fs_context.gdt.resize(num_block_groups);
std::vector<uint8_t> gdt_buffer_raw(gdt_blocks_count * SIMPLEFS_BLOCK_SIZE);
uint32_t gdt_start_block = 1 + 1; // 超级块在块1GDT从块2开始
for (uint32_t i = 0; i < gdt_blocks_count; ++i) {
if (read_block(fs_context.device_fd, gdt_start_block + i, gdt_buffer_raw.data() + (i * SIMPLEFS_BLOCK_SIZE)) != 0) {
std::cerr << "无法读取组描述符表" << std::endl;
close(fs_context.device_fd);
return 1;
}
}
std::memcpy(fs_context.gdt.data(), gdt_buffer_raw.data(), gdt_size_bytes);
// 准备FUSE参数
bool is_blk_dev = is_block_device(fs_context.device_fd);
bool allow_other_found = false;
for (int i = 0; i < argc; ++i) {
if (std::string(argv[i]) == "-o" && (i + 1 < argc) && std::string(argv[i+1]).find("allow_other") != std::string::npos) {
allow_other_found = true;
break;
}
if (std::string(argv[i]).find("-oallow_other") != std::string::npos) {
allow_other_found = true;
break;
}
}
std::vector<char*> fuse_argv_vec;
fuse_argv_vec.push_back(argv[0]); // 程序名
// 添加原始参数,除了设备路径
for (int i = 2; i < argc; ++i) {
fuse_argv_vec.push_back(argv[i]);
}
if (!allow_other_found) {
fuse_argv_vec.push_back(const_cast<char*>("-o"));
fuse_argv_vec.push_back(const_cast<char*>("allow_other"));
}
struct fuse_operations simplefs_ops;
init_fuse_operations(&simplefs_ops);
// 传递上下文给FUSE
int ret = fuse_main(fuse_argv_vec.size(), fuse_argv_vec.data(), &simplefs_ops, &fs_context);
close(fs_context.device_fd);
return ret;
}

1022
src/metadata.cpp Normal file

File diff suppressed because it is too large Load Diff

100
src/utils.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include "utils.h"
#include <iostream>
#include <cstring>
void set_bitmap_bit(std::vector<uint8_t>& bitmap_data, uint32_t bit_index) {
uint32_t byte_index = bit_index / 8;
uint8_t bit_offset = bit_index % 8;
if (bit_index < bitmap_data.size() * 8) {
bitmap_data[byte_index] |= (1 << bit_offset);
}
}
void clear_bitmap_bit(std::vector<uint8_t>& bitmap_data, uint32_t bit_index) {
uint32_t byte_index = bit_index / 8;
uint8_t bit_offset = bit_index % 8;
if (bit_index < bitmap_data.size() * 8) {
bitmap_data[byte_index] &= ~(1 << bit_offset);
}
}
bool is_bitmap_bit_set(const std::vector<uint8_t>& bitmap_data, uint32_t bit_index) {
uint32_t byte_index = bit_index / 8;
uint8_t bit_offset = bit_index % 8;
if (bit_index < bitmap_data.size() * 8) {
return (bitmap_data[byte_index] & (1 << bit_offset)) != 0;
}
return true;
}
void parse_path(const std::string& path, std::string& dirname, std::string& basename) {
if (path.empty()) {
dirname = ".";
basename = "";
return;
}
// 规范化路径
std::string p_normalized;
p_normalized.reserve(path.length());
if (path[0] == '/') {
p_normalized += '/';
}
for (size_t i = 0; i < path.length(); ++i) {
if (path[i] == '/') {
if (!p_normalized.empty() && p_normalized.back() != '/') {
p_normalized += '/';
}
} else {
p_normalized += path[i];
}
}
// 移除尾部斜杠,除非是根路径
if (p_normalized.length() > 1 && p_normalized.back() == '/') {
p_normalized.pop_back();
}
if (p_normalized.empty() && path[0] == '/') {
p_normalized = "/";
}
if (p_normalized == "/") {
dirname = "/";
basename = "/";
return;
}
size_t last_slash = p_normalized.find_last_of('/');
if (last_slash == std::string::npos) {
dirname = ".";
basename = p_normalized;
} else {
basename = p_normalized.substr(last_slash + 1);
if (last_slash == 0) {
dirname = "/";
} else {
dirname = p_normalized.substr(0, last_slash);
}
}
}
#include <sys/stat.h>
bool is_block_device(int fd) {
struct stat st;
if (fstat(fd, &st) == -1) {
return false;
}
return S_ISBLK(st.st_mode);
}
bool is_backup_group(uint32_t group_index) {
if (group_index == 0 || group_index == 1) return true;
uint32_t n = group_index;
while (n % 3 == 0) n /= 3;
while (n % 5 == 0) n /= 5;
while (n % 7 == 0) n /= 7;
return n == 1;
}