#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <locale.h>
#include <stdbool.h>
#include <ctype.h>
#define MAX_NAME_LEN 256
#define MAX_CHILDREN 100
#define MAX_USERS 10
#define BLOCK_SIZE 512
#define BLOCK_NUM 1024
#define MAX_CMD_LEN 256
#define MAX_PATH_LEN 4096
#define BITMAP_SIZE (BLOCK_NUM / 8)
typedef enum {
FILE_TYPE,
DIRECTORY_TYPE
} FileType;
typedef struct FileNode FileNode;
typedef struct SystemState SystemState;
struct FileNode {
char name[MAX_NAME_LEN];
FileType type;
FileNode* children[MAX_CHILDREN];
int child_count;
time_t create_time;
unsigned char protect;
int size;
int start_block;
};
typedef struct {
char username[MAX_NAME_LEN];
char password[MAX_NAME_LEN];
FileNode* root;
FileNode* current;
} UserDirectory;
typedef struct {
UserDirectory users[MAX_USERS];
int user_count;
unsigned char bitmap[BITMAP_SIZE];
} MasterFileDirectory;
struct SystemState {
MasterFileDirectory mfd;
char current_user[MAX_NAME_LEN];
FileNode* current_dir;
FILE* disk_fp;
};
/* 前置声明所有函数 */
void init_filesystem(SystemState* state);
void cleanup_filesystem(SystemState* state);
bool login(SystemState* state);
void cd_command(SystemState* state, const char* arg);
void dir_command(SystemState* state, const char* arg);
void mkdir_command(SystemState* state, const char* arg);
void rmdir_command(SystemState* state, const char* arg);
void edit_command(SystemState* state, const char* arg);
void delfile_command(SystemState* state, const char* arg);
void show_help(void);
FileNode* create_node(const char* name, FileType type);
void destroy_node(FileNode* node);
void add_child(FileNode* parent, FileNode* child);
FileNode* find_child(const FileNode* parent, const char* name);
void remove_child(FileNode* parent, const char* name);
int find_free_block(SystemState* state);
/*********************
* 核心功能实现
*********************/
FileNode* create_node(const char* name, FileType type) {
FileNode* node = (FileNode*)malloc(sizeof(FileNode));
if (!node) return NULL;
strncpy(node->name, name, MAX_NAME_LEN - 1);
node->name[MAX_NAME_LEN - 1] = '\0';
node->type = type;
node->child_count = 0;
node->create_time = time(NULL);
node->protect = (type == DIRECTORY_TYPE) ? 0b111 : 0b110;
node->size = 0;
node->start_block = -1;
return node;
}
void destroy_node(FileNode* node) {
if (!node) return;
for (int i = 0; i < node->child_count; i++) {
destroy_node(node->children[i]);
}
free(node);
}
void add_child(FileNode* parent, FileNode* child) {
if (parent && child && parent->child_count < MAX_CHILDREN) {
parent->children[parent->child_count++] = child;
}
}
FileNode* find_child(const FileNode* parent, const char* name) {
if (!parent || !name) return NULL;
for (int i = 0; i < parent->child_count; i++) {
if (strcmp(parent->children[i]->name, name) == 0) {
return parent->children[i];
}
}
return NULL;
}
/*********************
* 系统初始化与清理
*********************/
void init_filesystem(SystemState* state) {
state->disk_fp = fopen("virtual_disk.img", "wb+");
if (!state->disk_fp) {
perror("Failed to open disk file");
exit(EXIT_FAILURE);
}
memset(&state->mfd, 0, sizeof(MasterFileDirectory));
for (int i = 0; i < 2; i++)
state->mfd.bitmap[i / 8] |= (1 << (i % 8));
UserDirectory* user = &state->mfd.users[0];
strncpy(user->username, "jiu", MAX_NAME_LEN);
strncpy(user->password, "123", MAX_NAME_LEN);
user->root = create_node("/", DIRECTORY_TYPE);
user->current = user->root;
state->mfd.user_count = 1;
state->current_dir = user->root;
strncpy(state->current_user, "jiu", MAX_NAME_LEN);
fwrite(&state->mfd, sizeof(MasterFileDirectory), 1, state->disk_fp);
fflush(state->disk_fp);
}
void cleanup_filesystem(SystemState* state) {
if (state) {
for (int i = 0; i < state->mfd.user_count; i++) {
destroy_node(state->mfd.users[i].root);
}
fclose(state->disk_fp);
}
}
/*********************
* 命令实现
*********************/
bool login(SystemState* state) {
char username[MAX_NAME_LEN];
char password[MAX_NAME_LEN];
printf("Username: ");
if (!fgets(username, MAX_NAME_LEN, stdin)) return false;
username[strcspn(username, "\n")] = '\0';
printf("Password: ");
if (!fgets(password, MAX_NAME_LEN, stdin)) return false;
password[strcspn(password, "\n")] = '\0';
for (int i = 0; i < state->mfd.user_count; i++) {
if (strcmp(state->mfd.users[i].username, username) == 0 &&
strcmp(state->mfd.users[i].password, password) == 0) {
state->current_dir = state->mfd.users[i].current;
strncpy(state->current_user, username, MAX_NAME_LEN);
return true;
}
}
return false;
}
int find_free_block(SystemState* state) {
for (int i = 0; i < BLOCK_NUM; i++) {
if (!(state->mfd.bitmap[i / 8] & (1 << (i % 8)))) {
state->mfd.bitmap[i / 8] |= (1 << (i % 8));
return i;
}
}
return -1;
}
void mkdir_command(SystemState* state, const char* dirname) {
if (!dirname || *dirname == '\0') {
printf("Usage: mkdir <directory-name>\n");
return;
}
if (strlen(dirname) >= MAX_NAME_LEN) {
printf("Directory name too long (max %d chars)\n", MAX_NAME_LEN-1);
return;
}
if (find_child(state->current_dir, dirname)) {
printf("Directory already exists: %s\n", dirname);
return;
}
FileNode* new_dir = create_node(dirname, DIRECTORY_TYPE);
if (!new_dir) {
printf("Memory allocation failed\n");
return;
}
add_child(state->current_dir, new_dir);
printf("Created directory: %s\n", dirname);
}
void remove_child(FileNode* parent, const char* name) {
if (!parent || !name) return;
for (int i = 0; i < parent->child_count; i++) {
if (strcmp(parent->children[i]->name, name) == 0) {
destroy_node(parent->children[i]);
for (int j = i; j < parent->child_count - 1; j++) {
parent->children[j] = parent->children[j + 1];
}
parent->child_count--;
return;
}
}
}
void rmdir_command(SystemState* state, const char* dirname) {
if (!dirname || *dirname == '\0') {
printf("Usage: rmdir <directory-name>\n");
return;
}
FileNode* target = find_child(state->current_dir, dirname);
if (!target) {
printf("Directory not found: %s\n", dirname);
return;
}
if (target->type != DIRECTORY_TYPE) {
printf("Not a directory: %s\n", dirname);
return;
}
if (target->child_count > 0) {
printf("Directory not empty: %s\n", dirname);
return;
}
remove_child(state->current_dir, dirname);
printf("Removed directory: %s\n", dirname);
}
void edit_command(SystemState* state, const char* filename) {
if (!filename || *filename == '\0') {
printf("Usage: edit <filename>\n");
return;
}
FileNode* existing = find_child(state->current_dir, filename);
if (existing) {
if (existing->type == DIRECTORY_TYPE) {
printf("Cannot edit directory: %s\n", filename);
return;
}
printf("File already exists. Overwrite? (y/n) ");
int c = getchar();
if (tolower(c) != 'y') {
while ((c = getchar()) != '\n' && c != EOF);
return;
}
remove_child(state->current_dir, filename);
}
int block = find_free_block(state);
if (block == -1) {
printf("No free disk space\n");
return;
}
FileNode* new_file = create_node(filename, FILE_TYPE);
if (!new_file) {
state->mfd.bitmap[block / 8] &= ~(1 << (block % 8));
printf("Memory allocation failed\n");
return;
}
new_file->start_block = block;
new_file->size = BLOCK_SIZE;
add_child(state->current_dir, new_file);
printf("Created file: %s (block %d)\n", filename, block);
}
void delfile_command(SystemState* state, const char* filename) {
if (!filename || *filename == '\0') {
printf("Usage: delfile <filename>\n");
return;
}
FileNode* target = find_child(state->current_dir, filename);
if (!target) {
printf("File not found: %s\n", filename);
return;
}
if (target->type != FILE_TYPE) {
printf("Not a file: %s\n", filename);
return;
}
if (target->start_block != -1) {
state->mfd.bitmap[target->start_block / 8] &= ~(1 << (target->start_block % 8));
}
remove_child(state->current_dir, filename);
printf("Deleted file: %s\n", filename);
}
/*********************
* 主程序
*********************/
int main() {
SystemState state = {0};
init_filesystem(&state);
char input[MAX_CMD_LEN];
char cmd[MAX_NAME_LEN];
char arg[MAX_NAME_LEN];
show_help();
while (true) {
printf("\n%s:%s> ", state.current_user, state.current_dir->name);
if (!fgets(input, MAX_CMD_LEN, stdin)) break;
int args = sscanf(input, "%255s %255s", cmd, arg);
if (args == 0) continue;
if (strcmp(cmd, "login") == 0) {
printf(login(&state) ? "Login successful\n" : "Login failed\n");
}
else if (strcmp(cmd, "cd") == 0) {
cd_command(&state, args >= 2 ? arg : NULL);
}
else if (strcmp(cmd, "dir") == 0) {
dir_command(&state, args >= 2 ? arg : NULL);
}
else if (strcmp(cmd, "mkdir") == 0 && args >= 2) {
mkdir_command(&state, arg);
}
else if (strcmp(cmd, "rmdir") == 0 && args >= 2) {
rmdir_command(&state, arg);
}
else if (strcmp(cmd, "edit") == 0 && args >= 2) {
edit_command(&state, arg);
}
else if (strcmp(cmd, "delfile") == 0 && args >= 2) {
delfile_command(&state, arg);
}
else if (strcmp(cmd, "exit") == 0) {
printf("Exiting system...\n");
break;
}
else {
printf("Unknown command: %s\n", cmd);
show_help();
}
}
cleanup_filesystem(&state);
return 0;
}
void show_help(void) {
printf("\nAvailable commands:\n");
printf("login - User login\n");
printf("cd [path] - Change directory\n");
printf("dir [path] - List directory contents\n");
printf("mkdir <dir> - Create directory\n");
printf("rmdir <dir> - Remove empty directory\n");
printf("edit <file> - Create/edit file\n");
printf("delfile <file> - Delete file\n");
printf("exit - Exit system\n");
}
main函数中调用了cd_command和dir_command,且之前声明过这两个函数,但是没有提供这两个函数的实际实现,帮我实现这两个函数。给出修改后的代码