Initial commit
This commit is contained in:
52
src/disk_io.cpp
Normal file
52
src/disk_io.cpp
Normal 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
1618
src/fuse_ops.cpp
Normal file
File diff suppressed because it is too large
Load Diff
113
src/main.cpp
Normal file
113
src/main.cpp
Normal 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; // 超级块在块1,GDT从块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
1022
src/metadata.cpp
Normal file
File diff suppressed because it is too large
Load Diff
100
src/utils.cpp
Normal file
100
src/utils.cpp
Normal 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user