#include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h>
#define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b))
#define MAX_LENGTH 2048 #define BLOCK_SIZE 1024 #define DISK_SIZE 1024000 #define END -1 #define ROOT_BLOCK_NUM (sizeof(FCB)-1)/BLOCK_SIZE+1 #define FAT_BLOCK_NUM (sizeof(FAT)-1)/BLOCK_SIZE+1 #define BITMAP_BLOCK_NUM (sizeof(Bitmap)-1)/BLOCK_SIZE+1 #define MAX_OPEN_FILE 10 #define SAVE_DISK_DIR "./disk.sv"
#define INSTRUCTION_OPEN "open" #define INSTRUCTION_CLOSE "close" #define INSTRUCTION_LS "ls" #define INSTRUCTION_LSOF "lsof" #define INSTRUCTION_CD "cd" #define INSTRUCTION_MKDIR "mkdir" #define INSTRUCTION_RMDIR "rmdir" #define INSTRUCTION_FORMAT "format" #define INSTRUCTION_EXITSYS "exit" #define INSTRUCTION_SEEK "seek" #define INSTRUCTION_WRITE "write" #define INSTRUCTION_READ "read" #define INSTRUCTION_CREATE "create" #define INSTRUCTION_RM "rm"
typedef struct FCB { char filename[256]; char exname[8]; unsigned char attribute; short block_num; int len; short first; char free; int permission; int item_num; int save_place; } FCB;
typedef struct UserOpen { char dir[2048]; FCB *fcb; short openCount; int ptr; int fd; int permission; struct UserOpen *next; } UserOpen;
typedef struct Bitmap { int map[DISK_SIZE / BLOCK_SIZE / 32 + 1]; int free_num; } Bitmap;
typedef struct FAT { short next[DISK_SIZE / BLOCK_SIZE]; } FAT;
FAT fat; Bitmap bitmap; UserOpen *user_open = NULL; int opening_num; short free_fd[MAX_OPEN_FILE] = {0}; char current_dir[2048]; FCB *current_fcb; FCB *current_menu; int current_fd; FCB root_fcb; FCB *root_menu; char *disk;
int init(char *disk_dir, int new);
int free_block(short block);
short *get_block(int num);
int block_write(short block, char *text, int start, int len);
int block_read(short block, char *text, int start, int len);
int file_read(FCB fcb, char *text, int start, int len);
int file_write(FCB *fcb, char *text, int start, int len);
int file_get_block(FCB *fcb, int num);
int file_clear(FCB *fcb);
int read_menu(FCB menu_fcb, FCB **menu_item);
int file_open(char *dir, int *fd, int permission);
int file_close(int fd);
int file_find(char *dir, FCB **fcb, FCB *menu_fcb);
int file_create(char *filename, FCB *menu_fcb, int attribute, int permission);
int file_delete(int target, FCB *menu_fcb, char *full_dir);
int file_find_menu(char *filename, FCB *menu_fcb, int *where);
void do_ls();
void do_lsof();
int do_cd(char *dir);
int save_root();
int update_fcb(FCB *fcb);
int save_bitmap();
int save_fat();
int save_disk(char *dir);
int load_disk(char *dir);
int load_fat();
int load_bitmap();
int load_root();
void root_init();
void bitmap_init();
void fat_init();
int my_open(char *dir);
void my_close(int fd);
void my_create(char *dir);
void my_rm(char *dir);
void my_ls();
void my_lsof();
void my_cd(char *dir);
void my_mkdir(char *dir);
void my_rmdir(char *dir);
void my_format();
void startsys();
void my_exitsys();
int do_seek(int fd, int where);
void my_seek(int fd);
int do_write(int fd, char *text, int len, char wstyle);
int do_read(int fd, char *text, int len);
void my_write(int fd);
void my_read(int fd);
void shell();
void shell() { char line[MAX_LENGTH]; while(1) { printf("%s >", current_dir); char section[MAX_LENGTH]; char *param1; int section_ptr = 0, part = 0; int instruction = -1; int flag = 0; fgets(line, MAX_LENGTH, stdin); while(strlen(line) < 2) fgets(line, MAX_LENGTH, stdin); for(int i = 0; i < strlen(line); i++) { if(flag) break; if(line[i] == ' ' || i == strlen(line) - 1) { char *buffer = (char*) malloc(sizeof(char) * (section_ptr + 1)); memcpy(buffer, section, section_ptr); buffer[section_ptr] = '\0'; section_ptr = 0; if(part == 0) { if(!strcmp(buffer, INSTRUCTION_CD)) instruction = 0; if(!strcmp(buffer, INSTRUCTION_CLOSE)) instruction = 1; if(!strcmp(buffer, INSTRUCTION_EXITSYS)) { instruction = 2; my_exitsys(); flag = 1; } if(!strcmp(buffer, INSTRUCTION_FORMAT)) { instruction = 3; my_format(); flag = 1; } if(!strcmp(buffer, INSTRUCTION_LS)) { instruction = 4; my_ls(); flag = 1; } if(!strcmp(buffer, INSTRUCTION_LSOF)) { instruction = 5; my_lsof(); flag = 1; } if(!strcmp(buffer, INSTRUCTION_MKDIR)) instruction = 6; if(!strcmp(buffer, INSTRUCTION_OPEN)) instruction = 7; if(!strcmp(buffer, INSTRUCTION_READ)) instruction = 8; if(!strcmp(buffer, INSTRUCTION_RMDIR)) instruction = 9; if(!strcmp(buffer, INSTRUCTION_SEEK)) instruction = 10; if(!strcmp(buffer, INSTRUCTION_WRITE)) instruction = 11; if(!strcmp(buffer, INSTRUCTION_CREATE)) instruction = 12; if(!strcmp(buffer, INSTRUCTION_RM)) instruction = 13; if(!(~instruction)) { printf("instruction %s not find\n", buffer); flag = 1; } part = 1; free(buffer); continue; } if(part == 1) { if(instruction == 0) { my_cd(buffer); flag = 1; } if(instruction == 1) { int fd = 0, doing = 1; for(int j = 0; j < strlen(buffer); j++) { if(buffer[j] < '0' || buffer[j] > '9') { printf("invalid param: %s\n", buffer); doing = 0; break; } fd = fd * 10 + buffer[j] - '0'; } if(doing) my_close(fd); flag = 1; } if(instruction == 6) { my_mkdir(buffer); flag = 1; } if(instruction == 7) { my_open(buffer); flag = 1; } if(instruction == 8) { int fd = 0, doing = 1; for(int j = 0; j < strlen(buffer); j++) { if(buffer[j] < '0' || buffer[j] > '9') { printf("invalid param: %s\n", buffer); doing = 0; break; } fd = fd * 10 + buffer[j] - '0'; } if(doing) my_read(fd); flag = 1; } if(instruction == 9) { my_rmdir(buffer); flag = 1; } if(instruction == 10) { int fd = 0, doing = 1; for(int j = 0; j < strlen(buffer); j++) { if(buffer[j] < '0' || buffer[j] > '9') { printf("invalid param: %s\n", buffer); doing = 0; break; } fd = fd * 10 + buffer[j] - '0'; } if(doing) my_seek(fd); flag = 1; } if(instruction == 11) { int fd = 0, doing = 1; for(int j = 0; j < strlen(buffer); j++) { if(buffer[j] < '0' || buffer[j] > '9') { printf("invalid param: %s\n", buffer); doing = 0; break; } fd = fd * 10 + buffer[j] - '0'; } if(doing) my_write(fd); flag = 1; } if(instruction == 12) { my_create(buffer); flag = 1; } if(instruction == 13) { my_rm(buffer); flag = 1; } part = 2; free(buffer); continue; } } section[section_ptr++] = line[i]; } } }
void my_read(int fd) { int len; printf("请输入读取长度:"); scanf("%d", &len); char *text = (char*) malloc(sizeof(char) * len); if(do_read(fd, text, len)) return; printf("读取内容:\n"); for(int i = 0; i < len; i++) putchar(text[i]); printf("\n"); }
int do_read(int fd, char *text, int len) { FCB *fcb; UserOpen *uo; if(fd < 0 || fd >= MAX_OPEN_FILE || !free_fd[fd]) { printf("invalid fd\n"); return 1; } for(UserOpen *i = user_open; i; i = i->next) { if(i->fd == fd) { fcb = i->fcb; uo = i; if(!(uo->permission & 1)) { printf("this file is not readable\n"); return 1; } if(uo->ptr + len >= fcb->len) { printf("read area(%d, %d) out of file space\n", uo->ptr, uo->ptr + len); return 1; } break; } } if(file_read(*fcb, text, uo->ptr, len)) { printf("read failed\n"); } return 0; }
void my_write(int fd) { int size = BLOCK_SIZE; int len = 0; char c; char *text = (char*) malloc(sizeof(char) * BLOCK_SIZE); printf("请输入数据(输入ctrl+d或ctrl+z以结束输入):\n"); while(~(c = getchar())) { if(len == size) { size += BLOCK_SIZE; text = (char*) realloc(text, sizeof(char) * size); } text[len++] = c; } clearerr(stdin); printf("请输入写入方式(a 追加 | c 覆盖 | w 截断):"); c = getchar(); do_write(fd, text, len, c); free(text); }
int do_write(int fd, char *text, int len, char wstyle) { FCB *fcb; UserOpen *uo; if(fd < 0 || fd >= MAX_OPEN_FILE || !free_fd[fd]) { printf("invalid fd\n"); return 1; } for(UserOpen *i = user_open; i; i = i->next) { if(i->fd == fd) { fcb = i->fcb; uo = i; if(!(uo->permission & 2)) { printf("this file is not writeable\n"); return 1; } break; } } int start = 0; if(wstyle == 'a') { start = fcb->len; } else if(wstyle == 'w') { file_clear(fcb); start = 0; } else if(wstyle == 'c') { start = uo->ptr; } else { printf("invalid wstyle\n"); return 1; } if(file_write(fcb, text, start, len) || update_fcb(fcb)) { printf("write failed\n"); return 1; } return 0; }
void my_seek(int fd) { int where; printf("请输入指针位置:"); scanf("%d", &where); if(do_seek(fd, where)) return; }
int do_seek(int fd, int where) { if(fd < 0 || fd >= MAX_OPEN_FILE || !free_fd[fd]) { printf("invali fd\n"); return 1; } for(UserOpen *i = user_open; i; i = i->next) { if(i->fd == fd) { if(where < 0) { printf("invali pointer\n"); return 1; } i->ptr = where; return 0; } } return 1; }
void my_exitsys() { if(save_disk(SAVE_DISK_DIR)) printf("disk saving failed"); free(disk); exit(0); }
void startsys() { if(init(SAVE_DISK_DIR, 0)) if(init(NULL, 1)) printf("can't start file system\n"); printf("file system start\n"); }
void my_format() { free(disk); if(init(NULL, 1)) printf("format failed\n"); printf("format sucessed\n"); }
void my_rmdir(char *dir) { FCB *menu_fcb; int target, ptr = strlen(dir) - 1; while(ptr >= 0 && dir[ptr] != '/') ptr--; if(ptr < 0 || ptr == strlen(dir) - 1) { printf("failed due to a wrong dir\n"); return; } char full_dir[2048]; if(dir[0] == '.') { if(strcmp(current_dir, "/")) { strcpy(full_dir, current_dir); strcat(full_dir, dir + 1); } else { strcpy(full_dir, dir + 1); } } else { strcpy(full_dir, dir); } char *menu_dir = (char*) malloc(sizeof(char) * ptr + 1); memcpy(menu_dir, dir, ptr); menu_dir[ptr] = '\0'; char *filename = (char*) malloc(sizeof(char) * (strlen(dir) - ptr)); memcpy(filename, dir + ptr + 1, strlen(dir) - ptr - 1); filename[strlen(dir) - ptr - 1] = '\0'; if(ptr == 0) { menu_fcb = &root_fcb; } else if(ptr == 1 && menu_dir[0] == '.') { menu_fcb = current_fcb; } else { if(file_find(menu_dir, &menu_fcb, NULL)) { printf("failed due to a wrong dir\n"); free(menu_dir); free(filename); return; } } free(menu_dir); if(file_find_menu(filename, menu_fcb, &target) || !~target) { printf("failed due to a wrong dir\n"); free(filename); return; }
FCB *menu; if(read_menu(*menu_fcb, &menu)) { printf("failed due to a wrong dir\n"); free(filename); return; }
if(!(menu + target)->attribute) { printf("please use rmdir to remove a file\n"); free(filename); return; } if(file_delete(target, menu_fcb, full_dir)) { printf("failed to rm the file %s\n", dir); free(filename); return; } free(filename); }
void my_mkdir(char *dir) { if(dir[strlen(dir) - 1] == '/') { printf("failed due to a wrong dir\n"); return; } int ptr = 0, fnptr = 0; FCB *fcb, *menu; if(dir[ptr] == '.' && dir[ptr + 1] == '/') { fcb = current_fcb; menu = current_menu; ptr += 2; } else if(dir[ptr] == '/') { fcb = &root_fcb; menu = root_menu; ptr++; } else { printf("failed due to a wrong dir\n"); return; } char filename[256]; int permission = 3; int attribute = 1; while(ptr <= strlen(dir)) { if(dir[ptr] == '/' || ptr == strlen(dir)) { if(!fnptr) { printf("failed due to a wrong dir\n"); return; } int where; char *buffer = (char*) malloc(sizeof(char) * fnptr + sizeof(char)); memcpy(buffer, filename, fnptr); buffer[fnptr] = '\0'; if(file_find_menu(buffer, fcb, &where)) { printf("file : %s failed to create\n", dir); free(buffer); return; } if(~where && ptr == strlen(dir)) { { printf("file : %s has existed\n", dir); free(buffer); return; } } if(!~where) { if(file_create(buffer, fcb, ptr == strlen(dir) ? attribute : 1, 3)) { printf("file : %s failed to create\n", dir); free(buffer); return; } if(read_menu(*fcb, &menu)) { printf("file : %s failed to create\n", dir); free(buffer); return; } where = fcb->item_num - 1; } free(buffer); if(ptr == strlen(dir)) return; fcb = menu + where; if(read_menu(*fcb, &menu)) { printf("file : %s failed to create\n", dir); return; } ptr++; fnptr = 0; continue; } filename[fnptr++] = dir[ptr++]; } }
void my_cd(char *dir) { if(do_cd(dir)) printf("failed to move to %s\n", dir); }
void my_ls() { do_ls(); }
void my_lsof() { do_lsof(); }
void my_rm(char *dir) { FCB *menu_fcb; int target, ptr = strlen(dir) - 1; while(ptr >= 0 && dir[ptr] != '/') ptr--; if(ptr < 0 || ptr == strlen(dir) - 1) { printf("failed due to a wrong dir\n"); return; } char full_dir[2048]; if(dir[0] == '.') { if(strcmp(current_dir, "/")) { strcpy(full_dir, current_dir); strcat(full_dir, dir + 1); } else { strcpy(full_dir, dir + 1); } } else { strcpy(full_dir, dir); } char *menu_dir = (char*) malloc(sizeof(char) * ptr + 1); memcpy(menu_dir, dir, ptr); menu_dir[ptr] = '\0'; char *filename = (char*) malloc(sizeof(char) * (strlen(dir) - ptr)); memcpy(filename, dir + ptr + 1, strlen(dir) - ptr - 1); filename[strlen(dir) - ptr - 1] = '\0'; if(ptr == 0) { menu_fcb = &root_fcb; } else if(ptr == 1 && menu_dir[0] == '.') { menu_fcb = current_fcb; } else { if(file_find(menu_dir, &menu_fcb, NULL)) { printf("failed due to a wrong dir\n"); free(menu_dir); free(filename); return; } } free(menu_dir); if(file_find_menu(filename, menu_fcb, &target) || !~target) { printf("failed due to a wrong dir\n"); free(filename); return; }
FCB *menu; if(read_menu(*menu_fcb, &menu)) { printf("failed due to a wrong dir\n"); free(filename); return; }
if((menu + target)->attribute) { printf("please use rmdir to remove a menu\n"); free(filename); return; } if(file_delete(target, menu_fcb, full_dir)) { printf("failed to rm the file %s\n", dir); free(filename); return; } free(filename); }
void my_create(char *dir) { if(dir[strlen(dir) - 1] == '/') { printf("failed due to a wrong dir\n"); return; } int ptr = 0, fnptr = 0; FCB *fcb, *menu; if(dir[ptr] == '.' && dir[ptr + 1] == '/') { fcb = current_fcb; menu = current_menu; ptr += 2; } else if(dir[ptr] == '/') { fcb = &root_fcb; menu = root_menu; ptr++; } else { printf("failed due to a wrong dir\n"); return; } char filename[256]; int permission = 3; int attribute = 0; while(ptr <= strlen(dir)) { if(dir[ptr] == '/' || ptr == strlen(dir)) { if(!fnptr) { printf("failed due to a wrong dir\n"); return; } int where; char *buffer = (char*) malloc(sizeof(char) * fnptr + sizeof(char)); memcpy(buffer, filename, fnptr); buffer[fnptr] = '\0'; if(file_find_menu(buffer, fcb, &where)) { printf("file : %s failed to create\n", dir); free(buffer); return; } if(~where && ptr == strlen(dir)) { { printf("file : %s has existed\n", dir); free(buffer); return; } } if(!~where) { if(file_create(buffer, fcb, ptr == strlen(dir) ? attribute : 1, 3)) { printf("file : %s failed to create\n", dir); free(buffer); return; } if(read_menu(*fcb, &menu)) { printf("file : %s failed to create\n", dir); free(buffer); return; } where = fcb->item_num - 1; } free(buffer); if(ptr == strlen(dir)) return; fcb = menu + where; if(read_menu(*fcb, &menu)) { printf("file : %s failed to create\n", dir); return; } ptr++; fnptr = 0; continue; } filename[fnptr++] = dir[ptr++]; } }
void my_close(int fd) { for(UserOpen *i = user_open; i; i = i->next) { if(i->fd == fd) { if(!strcmp(i->dir, current_dir)) { printf("can't close current menu\n"); return; } } } if(file_close(fd)) { printf("failed to close\n"); } }
int my_open(char *dir) { int permission; printf("请输入开启方式(十进制数字,其二进制位第一位表示可读,第二位表示可写):"); scanf("%d", &permission); int fd; if(file_open(dir, &fd, permission)) { printf("file : %s failed to open\n", dir); return -1; } printf("file : %s open sucessed. fd is %d\n", dir, fd); return fd; }
int load_bitmap() { Bitmap *buffer = (Bitmap*) malloc(sizeof(Bitmap)); memcpy(buffer, disk + (ROOT_BLOCK_NUM + FAT_BLOCK_NUM) * BLOCK_SIZE, sizeof(Bitmap)); bitmap = *buffer; return 0; }
int load_fat() { FAT *buffer = (FAT*) malloc(sizeof(FAT)); memcpy(buffer, disk + ROOT_BLOCK_NUM * BLOCK_SIZE, sizeof(FAT)); fat = *buffer; return 0; }
int load_root() { FCB *fcb = (FCB*) malloc(sizeof(FCB)); memcpy(fcb, disk, sizeof(FCB)); root_fcb = *fcb; return 0; }
int load_disk(char *dir) { FILE *file = fopen(dir, "rb"); if(file == NULL) return 1; fread(disk, sizeof(char), sizeof(char) * DISK_SIZE, file);
fclose(file); printf("load from %s\n", dir); if(load_fat()) return 1; if(load_root()) return 1; if(load_bitmap()) return 1; if(read_menu(root_fcb, &root_menu)) return 1; return 0; }
int save_disk(char *dir) { if(save_fat()) return 1; if(save_root()) return 1; if(save_bitmap()) return 1; FILE *file = fopen(dir, "wb"); if (file == NULL) { return 1; } fwrite(disk, sizeof(char),sizeof(char) * DISK_SIZE, file);
fclose(file); printf("saved to %s\n", dir); return 0; }
int save_fat() { char *buffer = (char*) &fat; memcpy(disk + ROOT_BLOCK_NUM * BLOCK_SIZE, buffer, sizeof(FAT)); return 0; }
int save_bitmap() { char *buffer = (char*) &bitmap; memcpy(disk + (ROOT_BLOCK_NUM + FAT_BLOCK_NUM) * BLOCK_SIZE, buffer, sizeof(Bitmap)); return 0; }
int save_root() { char *buffer = (char*) &root_fcb; memcpy(disk, buffer, sizeof(FCB)); return 0; }
int update_fcb(FCB *fcb) { int fcb_size = sizeof(FCB); short block = fcb->save_place / BLOCK_SIZE; int start = fcb->save_place % BLOCK_SIZE; int rest_byte = fcb_size; while(rest_byte) { if(rest_byte + start <= BLOCK_SIZE) { if(block_write(block, ((char*) fcb) + fcb_size - rest_byte, start, rest_byte)) return 1; rest_byte = 0; } else { if(block_write(block, ((char*) fcb) + fcb_size - rest_byte, start, BLOCK_SIZE - start)) return 1; rest_byte -= BLOCK_SIZE - start; start = 0; block = fat.next[block]; } } return 0; }
int do_cd(char *dir) { FCB *fcb; if((file_find(dir, &fcb, NULL) || !fcb->attribute) && strcmp(dir, "/")) return 1; if(current_fd != -1) { if(file_close(current_fd)) return 1; } if(!strcmp(dir, "/")) { current_fcb = &root_fcb; current_menu = root_menu; strcpy(current_dir, "/"); current_fd = -1; return 0; }
char full_dir[2048]; if(dir[0] == '.') { if(strcmp(current_dir, "/")) { strcpy(full_dir, current_dir); strcat(full_dir, dir + 1); } else { strcpy(full_dir, dir + 1); } } else { strcpy(full_dir, dir); }
if(file_open(dir, ¤t_fd, 0)) return 1; FCB *menu; if(read_menu(*fcb, &menu)) return 1; strcpy(current_dir, full_dir); current_fcb = fcb; current_menu = menu; return 0; }
void do_lsof() { for(UserOpen *i = user_open; i; i = i->next) { printf("文件描述符:%d\t路径:%s\t读写指针:%d\n", i->fd, i->dir, i->ptr); } }
void do_ls() { for(int i = 0; i < current_fcb->item_num; i++) { printf("文件名: %s\t文件类型: %s\t 文件长度(B):%d\n", (current_menu + i)->filename, (current_menu + i)->attribute ? "目录": "文件", (current_menu + i)->len); } }
int file_find_menu(char *filename, FCB *menu_fcb, int *where) { FCB *menu; if(read_menu(*menu_fcb, &menu)) return 1; for(int i = 0; i < menu_fcb->item_num; i++) { if(!strcmp((menu + i)->filename, filename)) { *where = i; return 0; } } *where = -1; return 0; }
int file_delete(int target, FCB *menu_fcb, char *full_dir) { if(!(menu_fcb->permission & 2)) { printf("can't remove the menu %s\n", menu_fcb->filename); return 0; } FCB *menu; if(read_menu(*menu_fcb, &menu)) return 1; if(!((menu + target) -> permission & 2)) { printf("can't remove the file %s\n", (menu + target)->filename); return 1; } for(UserOpen *i = user_open; i; i = i->next) { if(!strcmp(full_dir, i->dir)) { printf("the file %s is opening\n", (menu + target)->filename); return 1; } } FCB target_fcb = menu[target]; if(target_fcb.attribute == 1) { FCB *target_menu; if(read_menu(target_fcb, &target_menu)) return 1; for(int i = target_fcb.item_num - 1; i >=0; i--) { char buffer[2048]; strcpy(buffer, full_dir); strcat(buffer, "/"); strcat(buffer, (target_menu + i)->filename); if(file_delete(i, &target_fcb, buffer)) return 1; } } for(int i = menu_fcb->item_num - 1; i > target; i--) menu[i].save_place = menu[i - 1].save_place; for(int i = target; i < menu_fcb->item_num - 1; i++) { menu[i] = menu[i + 1]; } char *buffer = (char*) menu; if(file_clear(menu_fcb)) return 1; if(file_write(menu_fcb, buffer, 0, (menu_fcb->item_num - 1) * sizeof(FCB))) { menu_fcb->item_num = 0; return 1; } menu_fcb->item_num--; if(update_fcb(menu_fcb)) return 1; if(read_menu(root_fcb, &root_menu)) return 1; if(read_menu(*current_fcb, ¤t_menu)) return 1; return 0; }
int file_create(char *filename, FCB *menu_fcb, int attribute, int permission) { if(!menu_fcb->attribute) return 1; FCB *menu; if(read_menu(*menu_fcb, &menu)) return 1; for(int i = 0; i < menu_fcb->item_num; i++) if(!strcmp(filename, (menu + i)->filename)) return 1; FCB new_fcb; new_fcb.attribute = attribute; strcpy(new_fcb.filename, filename); int dotptr = 0; while(filename[dotptr] != '.' && dotptr < strlen(filename)) dotptr++; if(filename[dotptr] == strlen(filename)) { strcpy(new_fcb.exname, filename + dotptr + 1); } new_fcb.first = -1; new_fcb.free = 1; new_fcb.len = 0; new_fcb.item_num = 0; new_fcb.block_num = 0; new_fcb.permission = permission; new_fcb.save_place = 0; char *buffer = (char*) &new_fcb; if(file_write(menu_fcb, buffer, menu_fcb->len, sizeof(FCB))) return 1; menu_fcb->item_num += 1; short block = menu_fcb->first, t=0; while(t < (menu_fcb->len - sizeof(FCB)) / BLOCK_SIZE) { t++; block = fat.next[block]; } new_fcb.save_place = block * BLOCK_SIZE + (menu_fcb->len - sizeof(FCB)) % BLOCK_SIZE; if(file_write(menu_fcb, buffer, menu_fcb->len - sizeof(FCB), sizeof(FCB))) return 1; if(update_fcb(menu_fcb)) return 1; if(read_menu(root_fcb, &root_menu)) return 1; if(read_menu(*current_fcb, ¤t_menu)) return 1; return 0; }
int file_find(char *dir, FCB **fcb, FCB *menu_fcb) { char filename[256]; int filename_ptr = 0; FCB *menu = root_menu; int menu_num = root_fcb.item_num; int i = 0; if(dir[i] == '.') { if(menu_fcb == NULL) { menu = current_menu; menu_num = current_fcb->item_num; } else { if(read_menu(*menu_fcb, &menu)) return 1; menu_num = menu_fcb->item_num; } i++; } if(dir[i] != '/') { return 1; } while(i < strlen(dir)) { if(dir[i + 1] == '/') { i++; int find = 0; for(int j = 0; j < menu_num; j++) { if(!strcmp(filename, (menu + j)->filename)) { if(!(menu + j)->attribute) return 1; menu_num = (menu + j)->item_num; if(read_menu(*(menu + j), &menu)) { if(menu != root_menu && menu != current_menu) free(menu); return 1; } find = 1; } } if(!find) return 1; filename_ptr = 0; } filename[filename_ptr++] = dir[++i]; } if(!filename_ptr) return 1; for(int i = 0; i < menu_num; i++) { if(!strcmp(filename, (menu + i)->filename)) { *fcb = (menu + i); return 0; } } return 1; }
int file_close(int fd) { if(!(free_fd[fd])) return 1; UserOpen *prev; for(UserOpen *i = user_open; i; prev = i, i = i->next) { if(i->fd == fd) { if(!--(i->openCount)) { free_fd[fd] = 0; opening_num--; if(i == user_open) user_open = i->next; else prev->next = i->next; free(i); } return 0; } } return 1; }
int file_open(char *dir, int *fd, int permission) { FCB *fcb; if(file_find(dir, &fcb, NULL)) return 1; if(fcb->attribute) permission = 0; if(((fcb->permission) | permission) > fcb->permission) return 1; char full_dir[2048]; if(dir[0] == '.') { if(strcmp(current_dir, "/")) { strcpy(full_dir, current_dir); strcat(full_dir, dir + 1); } else { strcpy(full_dir, dir + 1); } } else { strcpy(full_dir, dir); } for(UserOpen *i = user_open; i; i = i->next) { if(!strcmp(full_dir, i->dir)) { i->openCount++; i->permission |= permission; *fd = i->fd; return 0; } } if(opening_num == MAX_OPEN_FILE) return 1; opening_num++; UserOpen *new_user_open = (UserOpen*) malloc(sizeof(UserOpen)); strcpy(new_user_open->dir, full_dir); for(int i = 0; i < MAX_OPEN_FILE; i++) { if(!free_fd[i]) { free_fd[i] = 1; new_user_open->fd = i; *fd = i; break; } } new_user_open->permission = permission; new_user_open->openCount = 1; new_user_open->ptr = 0; new_user_open->fcb = fcb; new_user_open->next = user_open; user_open = new_user_open; return 0; }
int read_menu(FCB menu_fcb, FCB **menu_item) { if(!menu_fcb.attribute) return 1; char *buffer = (char*) malloc(sizeof(char) * menu_fcb.len); if(file_read(menu_fcb, buffer, 0, menu_fcb.len)) { free(buffer); return 1; } *menu_item = (FCB*) buffer; return 0; }
void fat_init() { memset(fat.next, -1, sizeof(fat.next)); }
void bitmap_init() { memset(bitmap.map, 0, sizeof(bitmap.map)); bitmap.free_num = DISK_SIZE / BLOCK_SIZE; }
void root_init() { strcpy(root_fcb.filename, "root"); root_fcb.attribute = 1; root_fcb.block_num = 0; root_fcb.first = -1; root_fcb.free = 1; root_fcb.item_num = 0; root_fcb.len = 0; root_fcb.permission = 3; root_fcb.save_place = 0; }
int file_clear(FCB *fcb) { short next; for(short i = fcb->first; i != -1; i = next) { next = fat.next[i]; if(free_block(i)) return 1; fat.next[i] = -1; } fcb->free = 1; fcb->len = 0; fcb->first = -1; fcb->block_num = 0; return 0; }
int file_get_block(FCB *fcb, int num) { short *blocks = get_block(num); if(!blocks) return 1; int t = 0; if(!~(fcb->first)) { fcb->first = blocks[t]; } while(t < num - 1) { fat.next[blocks[t]] = blocks[t + 1]; t++; } fcb->free = 0; fcb->block_num += num; free(blocks); return 0; }
int file_write(FCB *fcb, char *text, int start, int len) { if(start + len > fcb->len) { fcb->len = start + len; } if((start + len) / BLOCK_SIZE + 1 > fcb->block_num) { if(file_get_block(fcb, (start + len) / BLOCK_SIZE + 1 - fcb->block_num)) return 1; } char buffer[BLOCK_SIZE]; for(short i = fcb->first, t = 0; i != -1; i = fat.next[i], t++) { if(t == start / BLOCK_SIZE) { memcpy(buffer, text, min(len, BLOCK_SIZE - start % BLOCK_SIZE)); if(block_write(i, buffer, start % BLOCK_SIZE, min(len, BLOCK_SIZE - start % BLOCK_SIZE))) return 1; if(start / BLOCK_SIZE == (start + len) / BLOCK_SIZE) break; } if(t > start / BLOCK_SIZE && t < (start + len) / BLOCK_SIZE) { memcpy(buffer, text - start % BLOCK_SIZE + BLOCK_SIZE * (t - start / BLOCK_SIZE), BLOCK_SIZE); if(block_write(i, buffer, 0, BLOCK_SIZE)) return 1; } if(t == (start + len) / BLOCK_SIZE) { memcpy(buffer, text - start % BLOCK_SIZE + BLOCK_SIZE * (t - start / BLOCK_SIZE), (start + len - 1) % BLOCK_SIZE + 1); if(block_write(i, buffer, 0, (start + len - 1) % BLOCK_SIZE + 1)) return 1; break; } } return 0; }
int file_read(FCB fcb, char *text, int start, int len) { if(start + len > fcb.len) return 1; for(short i = fcb.first, t = 0; i != -1; i = fat.next[i], t++) { if(t == start / BLOCK_SIZE) { if(block_read(i, text, start % BLOCK_SIZE, min(len, BLOCK_SIZE - start % BLOCK_SIZE))) return 1; if(start / BLOCK_SIZE == (start + len) / BLOCK_SIZE) break; } if(t > start / BLOCK_SIZE && t < (start + len) / BLOCK_SIZE) { if(block_read(i, text - start % BLOCK_SIZE + BLOCK_SIZE * (t - start / BLOCK_SIZE), 0, BLOCK_SIZE)) return 1; } if(t == (start + len) / BLOCK_SIZE) { if(block_read(i, text - start % BLOCK_SIZE + BLOCK_SIZE * (t - start / BLOCK_SIZE), 0, (start + len - 1) % BLOCK_SIZE + 1)) return 1; break; } } return 0; }
int block_read(short block, char *text, int start, int len) { if(block < 0 || block >= DISK_SIZE / BLOCK_SIZE || start <0 || len < 0 || start + len > BLOCK_SIZE) return 1; memcpy(text, disk + block * BLOCK_SIZE + start, len); return 0; }
int block_write(short block, char *text, int start, int len) { if(block < 0 || block >= DISK_SIZE / BLOCK_SIZE || start <0 || len < 0 || start + len > BLOCK_SIZE) return 1; memcpy(disk + block * BLOCK_SIZE + start, text, len); return 0; }
short *get_block(int num) { short *free_block = (short*) malloc(num * sizeof(short)); int n = num; if(num > bitmap.free_num || num <= 0) { free(free_block); return free_block; } bitmap.free_num -= n; for(short i = 0; i < DISK_SIZE / BLOCK_SIZE / 32 + 1; i++) { for(short j = 0; j < 32; j++) { if(i * 32 + j + 1 > DISK_SIZE / BLOCK_SIZE || !n) { break; } if(!((bitmap.map[i] >> j) & 1)) { bitmap.map[i] |= (1 << j); free_block[num - n--] = i * 32 + j; } } if(!n) { break; } } return free_block; }
int free_block(short block) { if(block < 0 || block >= DISK_SIZE / BLOCK_SIZE) return 1; bitmap.free_num += (bitmap.map[(block >> 5)] >> (block & 31)) & 1; bitmap.map[(block >> 5)] &= ~(1 << (block & 31)); return 0; }
int init(char *disk_dir, int new) { disk = (char*) malloc(DISK_SIZE * sizeof(char)); if(new) { bitmap_init(); fat_init(); root_init(); get_block(ROOT_BLOCK_NUM + FAT_BLOCK_NUM + BITMAP_BLOCK_NUM); save_root(); } else { if(load_disk(disk_dir)) return 1; } current_fcb = &root_fcb; current_menu = root_menu; current_fd = -1; strcpy(current_dir, "/"); opening_num = 0; user_open = NULL; memset(free_fd, 0, sizeof(free_fd));
return 0; }
int main() { startsys(); shell(); return 0; }
|