#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
//要正常运行应该把所有出现路径的地方修改为自己的当前文件目录
#define SHOWSIZE 15
#define BLOCKSIZE 1024
#define SIZE 1024000
#define END 65535 //2^16 -> FAT16
#define FREE 0
#define ROOTBLOCKNUM 2
#define MAXOPENFILE 10
#define DISKFSADD "/home/oz/FileSys"
#define MAXFCBNUM (int)1024/sizeof(fcb)
#define CURDIR_DES (DE*)((((DE*)(openfilelist[curdir].DE_open+basis))->file_fcb).first * BLOCKSIZE+my_v_disk)
typedef struct FCB{
char filename[20];
char exname[3];
unsigned char attribute; //0 dir 1 data
unsigned short time;
unsigned short date;
unsigned short first; //starting disk-block
unsigned long length;
char free; //0 empty 1 allocated
}fcb;
typedef struct DE{
struct DE* p;
int valid;
fcb file_fcb;
char dir[80];
unsigned short last_modify_time;
long next; //point to sibling directories
long child;//point to child directories
long parent;
}DE;
unsigned char* basis;
typedef struct FAT{ // [present-block] : next-block
unsigned short id[SIZE/BLOCKSIZE];
}fat;
fcb file_fcb;
typedef struct USEROPEN{
fcb open_file_fcb;
long DE_open;
char dir[80]; //file address
int count; //
char fcbstate; // fcb changed? if so, write back to update
char topenfile; //notify if this item has been taken
}useropen;
typedef struct BLOCK0{
char information[200];
unsigned short root;
unsigned char* startblock;
}block0;
DE CurDirDEarray[SHOWSIZE];
char currentdir[80];
char dir_new[80];
unsigned char *data_start_p;
unsigned char *my_v_disk;
useropen openfilelist[MAXOPENFILE];
int curdir = -1;
//from textbook
unsigned char *guideBlock, *dataBlock;
DE* rootBlock; // *** All directories are DE pointer
int *fat1, *fat2;
void fcbcpy(fcb* dst, fcb* src){
strcpy(dst->filename, src->filename);
strcpy(dst->exname, src->exname);
dst->attribute = src->attribute;
dst->time = src->time;
dst->date = src->date;
dst->first = src->first;
dst->length = src->length;
dst->free = src->free;
}
DE rootDE = {.file_fcb = { .attribute = 0, .first = 5, .length = 0, .free = 1}, .valid = 1, };
void showCURDIR_DES(DE* CurDirDEarray){
for (int i =0; i<SHOWSIZE; i++) {
CurDirDEarray[i] = *(CURDIR_DES+i);
CurDirDEarray[i].p = CURDIR_DES+i;
}
}
//全局变量一级连接局部变量可以保存,二级链接的会被回收
void my_format(void);
//
void startsys(void){
my_v_disk = (unsigned char*)malloc(sizeof(char) * SIZE);FILE* fs_on_disk; //saved_fs
basis = my_v_disk;
guideBlock = my_v_disk;
fat1 = (int*)my_v_disk + sizeof(char)*BLOCKSIZE*1;
fat2 = (int*)my_v_disk + sizeof(char)*BLOCKSIZE*3;
rootBlock = (DE*)(my_v_disk + sizeof(char)*BLOCKSIZE*5);
dataBlock = (unsigned char*)(my_v_disk + sizeof(char)*BLOCKSIZE*7);
rootDE.next = (unsigned char*)&rootDE-basis;
if( (fs_on_disk = fopen("/home/oz/FileSys/myfilesys", "rb")) == NULL){
printf("FS has not been created, creating now....\n");
my_format();
}
else{
if(fread(my_v_disk,sizeof(char), SIZE, fs_on_disk) == 0){
printf("Read FS_on_disk error!\n");
return;
}
}
//printf("DESIZE:%d\n", sizeof(DE));
memset(openfilelist , 0 ,sizeof(useropen)*MAXOPENFILE);
strcpy( openfilelist[0].dir, "");
//every time the v-disk starts, fs should make these basic pointers point to right place.
openfilelist[0].count = 0;openfilelist[0].fcbstate = 0;openfilelist[0].topenfile = 1;
openfilelist[0].DE_open = ( guideBlock + sizeof(block0) - basis );
curdir = 0;
guideBlock = my_v_disk;
showCURDIR_DES(CurDirDEarray);
printf("FS Intials successfully!\n");
}
void my_format(void){
strcpy( rootDE.file_fcb.filename, "");strcpy( rootDE.file_fcb.exname, ""); strcpy( rootDE.dir, "");
rootDE.child = (unsigned char*)rootBlock-basis;
//set all-0
memset(my_v_disk, 0, sizeof(char)*SIZE);
//initial block0
block0 block_guide = {.information = "disk_size:1024\ndisk_num:1000\n", .root = 5, .startblock = my_v_disk + sizeof(char)*BLOCKSIZE*7};
*(block0*)guideBlock = block_guide;
DE* rootDE_pointer = (DE*)(guideBlock+sizeof(block0));
*rootDE_pointer = rootDE;
//initial fat/root/data address
fat1[0] = -1; fat1[1] = 2; fat1[2] = -1; fat1[3] = 2; fat1[4] = -1; fat1[5] = 6; fat1[6] = -1;
fat2[0] = -1; fat2[1] = 2; fat2[2] = -1; fat2[3] = 2; fat2[4] = -1; fat2[5] = 6; fat2[6] = -1;
DE dotDE = {.file_fcb = {.attribute = 0, .first = 5}, .valid = 1};strcpy( dotDE.file_fcb.filename, "."); strcpy( dotDE.dir, ""); strcpy( dotDE.file_fcb.exname, "");
DE dotdotDE = {.file_fcb = { .attribute = 0,.first = 5}, .next = (unsigned char*)rootBlock-basis,.valid = 1};strcpy( dotdotDE.file_fcb.filename, "..");strcpy( dotdotDE.file_fcb.exname, "");strcpy( dotdotDE.dir, "");
dotDE.next = (unsigned char*)(rootBlock+1)-basis;
rootDE_pointer->file_fcb.length += sizeof(DE);
rootDE_pointer->file_fcb.length += sizeof(DE);
openfilelist[0].open_file_fcb.length += 2*sizeof(DE);
*rootBlock = dotDE;
*(rootBlock+1) = dotdotDE;
return;
}
DE* same_name_fileORdir(char* filename, int type){
if(strcmp(filename, "..") == 0){
return (DE*)(((DE*)(openfilelist[curdir].DE_open+basis))->parent + basis);
}
//printf("in sname_name\n");
DE* move, *first;
DE* move_pre = NULL;
move = first = (DE*)(((DE*)(openfilelist[curdir].DE_open+basis))->child+basis);
do{
if( move->file_fcb.attribute != type || strcmp(move->file_fcb.filename, filename) != 0){
move_pre = move;
move = (DE*)(move->next+basis);
continue;
}
else{
return move;
}
}while(move != first);
//printf("out same_name!\n");
return NULL;
}
void my_mkdir(char* dirname){
//default every dir-data(child_file FCB) take 1 block
DE* file_point = CURDIR_DES;
DE* new_file_DE_point;
new_file_DE_point = file_point;
DE* new_dir_point; //new dir in disk, it initially contains . and ..
if(same_name_fileORdir(dirname, 0) != NULL){
printf("Directory %s exists!\n", dirname);
return;
}
//able to create directory
//look-up in fat to allocate block to new-dir
int block_free = 0;
while( fat1[block_free] != FREE){
block_free++;
}
fat1[block_free] = -1; // sign it as NOT_FREE
new_dir_point = (DE*)( my_v_disk + block_free*sizeof(char)*BLOCKSIZE);
//add new-DE to curdir-data
while((*new_file_DE_point).valid == 1){
new_file_DE_point++;
}
DE* cur_child = (DE*)(((DE*)(openfilelist[curdir].DE_open+basis))->child+basis);
DE new_file_DE = {.file_fcb = { .attribute = 0, .first = block_free, .length = 0, .free = 1},.valid = 1, .next = (((DE*)(openfilelist[curdir].DE_open+basis))->child), .parent = (openfilelist[curdir].DE_open)};
strcpy(new_file_DE.file_fcb.filename, dirname);
DE* tmp = (DE*)(cur_child->next+basis);
while((DE*)(tmp->next+basis) != cur_child ){
tmp = (DE*)(tmp->next+basis);
}
tmp->next = (unsigned char*)new_file_DE_point - basis;
( (DE*)(openfilelist[curdir].DE_open+basis))->child = (unsigned char*)new_file_DE_point - basis;
//get new path
strcpy(dir_new, openfilelist[curdir].dir);
strcat(dir_new, "/");
strcat(dir_new, dirname);
strcpy(new_file_DE.dir, dir_new);
openfilelist[curdir].open_file_fcb.length += sizeof(DE)/sizeof(char);
openfilelist[curdir].fcbstate = 1;
//add 2 special dir-item . and ..
//assume that . and .. have no child
DE dotDE = {.file_fcb= { .attribute = 0, .first = block_free}, .valid = 1};
DE dotdotDE = {.file_fcb = { .attribute = 0, .first = ((DE*)(openfilelist[curdir].DE_open+basis))->file_fcb.first }, .next = (unsigned char*)new_dir_point-basis, .valid = 1};
dotDE.next = (unsigned char*)(new_dir_point+1) - basis ;
strcpy( dotDE.file_fcb.filename, ".");
strcpy( dotDE.file_fcb.exname, "");
strcpy( dotDE.dir, new_file_DE.dir);
strcpy( dotdotDE.file_fcb.filename, "..");
strcpy( dotdotDE.file_fcb.exname, "");
strcpy( dotdotDE.dir, openfilelist[curdir].dir);
//it doesn't matter new_dir_point changes, because through first we can find the file entry in disk.
*new_dir_point++ = dotDE;
*new_dir_point = dotdotDE;
//set child-entry
new_file_DE.child = (unsigned char*)new_dir_point -basis;
*new_file_DE_point = new_file_DE;
//printf("My_mkdir success!\n");
return;
}
void my_creat(char* filename){
showCURDIR_DES(CurDirDEarray);
if(filename[0] == '3'){
;
}
//default every dir-data(child_file FCB) take 1 block
DE* file_point = CURDIR_DES;
DE* new_file_DE_point = file_point;
DE* new_dir_point; //new file in disk
if(same_name_fileORdir(filename, 1) != NULL){
printf("Directory %s exists!\n", filename);
}
//able to create directorychar dir[80];
//look-up in fat to allocate block to new-dir
int block_free = 0;
while(fat1[block_free] != FREE){
block_free++;
}
fat1[block_free] = -1; // sign it as NOT_FREE
new_dir_point = (DE*)(my_v_disk + block_free*sizeof(char)*BLOCKSIZE);
//add new-DE to curdir-data
while(new_file_DE_point->valid == 1){
new_file_DE_point++;
}
DE* cur_child = (DE*)(((DE*)((DE*)(openfilelist[curdir].DE_open+ basis)))->child+basis);
DE new_file_DE = {.file_fcb = { .attribute = 1, .first = block_free, .length = 0, .free = 1},.valid = 1, .next = (unsigned char*)cur_child -basis, .child = 0, .parent = openfilelist[curdir].DE_open };
strcpy(new_file_DE.file_fcb.filename, filename );//printf("filename in creat:%s\n", filename);
DE* tmp = (DE*)(cur_child->next +basis);
while(tmp->next != (unsigned char*)cur_child -basis){
tmp = (DE*)(tmp->next +basis);
}
tmp->next = (unsigned char*)new_file_DE_point -basis;
((DE*)(openfilelist[curdir].DE_open+basis))->child = (unsigned char*)new_file_DE_point - basis;
//get new path
strcpy(dir_new, openfilelist[curdir].dir);
strcat(dir_new, "/");
strcat(dir_new, filename);
strcpy(new_file_DE.dir, dir_new);
openfilelist[curdir].open_file_fcb.length += sizeof(DE)/sizeof(char);
openfilelist[curdir].fcbstate = 1;
*new_file_DE_point = new_file_DE;
return;
}
void my_rmdir(char* dirname){
DE* move, *first;
DE* move_pre = NULL;
move = first = (DE*)(((DE*)(openfilelist[curdir].DE_open+basis))->child+basis);
DE* find_pre = first;
do{
find_pre = (DE*)(find_pre->next+basis);
}while((DE*)(find_pre->next+basis) != first);
move_pre = find_pre;
do{
if( move->file_fcb.attribute != 0 || strcmp(move->file_fcb.filename, dirname) != 0){
move = (DE*)(move->next+basis);
move_pre = move;
continue;
}
else{
//check if it's emptyfcb file_fcb;
if(move->file_fcb.length != 0){
printf("File %s is not empty!\n", dirname);
return;
}
//remove it!
fat1[move->file_fcb.first] = 0;
move->file_fcb.free = 0;move->valid = 0;
openfilelist[curdir].open_file_fcb.length -= sizeof(DE)/sizeof(char);
openfilelist[curdir].fcbstate = 1;
move_pre->next = move->next;
((DE*)(openfilelist[curdir].DE_open+basis))->child = (unsigned char*)move_pre-basis; // in case child-point invalid
return;
}
}while(move != first);
printf("Directory %s not found!\n", dirname);
return;
}
void my_rm(char* filename){
DE* move, *first;
DE* move_pre = NULL;
move = first = (DE*)(((DE*)(openfilelist[curdir].DE_open+basis))->child+basis);
DE* find_pre = first;
do{
find_pre = (DE*)(find_pre->next+basis);
}while((DE*)(find_pre->next+basis) != first);
move_pre = find_pre;
do{
if( move->file_fcb.attribute != 1){ //filename is a dir
if( strcmp(move->file_fcb.filename, filename) == 0){
printf("%s is a Directory!\n", filename);
return;
}
move = (DE*)(move->next+basis);
move_pre = move;
continue;
}
else{
//remove it!
fat1[move->file_fcb.first] = 0;
move->file_fcb.free = 0;move->valid = 0;
openfilelist[curdir].open_file_fcb.length -= sizeof(DE)/sizeof(char);
openfilelist[curdir].fcbstate = 1;
move_pre->next = move->next;
((DE*)(openfilelist[curdir].DE_open+basis))->child = (unsigned char*)move_pre-basis; // in case child-point invalid
return;
}
}while(move != first);
printf("Dir %s not found!\n", filename);
return;
}
int my_open(char* filename, int type){
//DE tmp = *openfilelist[0].DE_open;
DE* open_file;
int fd = 0;
int full = 1;
//if opened or full
if( strcmp(filename, "..") == 0 && ((DE*)(openfilelist[curdir].DE_open+basis))->parent == openfilelist[0].DE_open){
return 0;
}
for(int i = 1; i<MAXOPENFILE; i++){
if( openfilelist[i].topenfile != 0 && strcmp(((DE*)(openfilelist[i].DE_open+basis))->file_fcb.filename, filename)==0 ) {
printf("File has been opened already!\n");
return -1;
}
if(full && openfilelist[i].topenfile == 0){
full = 0;
fd = i;
}
}
if(full){
printf("OPENFILELIST has been fulled!\n");
return 0;
}
//if exist
if( (open_file = same_name_fileORdir(filename, type)) == NULL ){
if(type == 0){
printf("Directory %s doesn't exists!\n", filename);
}
else printf("File %s doesn't exists!\n", filename);
return 0;
}
//open it
openfilelist[fd].DE_open = (unsigned char*)open_file-basis;
strcpy(openfilelist[fd].dir, open_file->dir);
openfilelist[fd].count = 0;
openfilelist[fd].fcbstate = 0;
openfilelist[fd].topenfile = 1;
fcbcpy(&openfilelist[fd].open_file_fcb, &open_file->file_fcb);
if(type == 1){
printf("Successfully opened file %s with returned fd: %d\n", filename, fd);
}
else{
printf("Successfully opened directory %s with returned fd: %d\n", filename, fd);
}
return fd;
}
void my_close(int fd, int type){
//find it -> delete in OPENFILELIST
if(openfilelist[fd].topenfile == 0){
printf("Invalid fd:%d\n", fd);
return;
}
if(openfilelist[fd].fcbstate == 1){
fcbcpy(&((DE*)(openfilelist[fd].DE_open+basis))->file_fcb, &openfilelist[fd].open_file_fcb);
}
//delete in OFL
openfilelist[fd].topenfile = 0;
if(type == 1){
printf("Successfully closed file %s with given fd: %d\n", openfilelist[fd].open_file_fcb.filename, fd);
}
else{
printf("Successfully closed directory %s with given fd: %d\n", openfilelist[fd].open_file_fcb.filename, fd);
}
return;
}
void my_cd(char* dirname){
int open_ret;
if( strcmp(dirname, "..") == 0 && curdir == 0){
return;
}
if(same_name_fileORdir(dirname, 0) == NULL){
printf("No such name directory!\n");
return;
}
if(strcmp(dirname, ".") == 0){
return;
}
if(curdir != 0){
my_close(curdir, 0);
}
if((open_ret = my_open(dirname, 0)) != -1){
curdir = open_ret;
}
strcpy(currentdir, ((DE*)(openfilelist[curdir].DE_open+basis))->dir);
return;
}
void my_list(void){
showCURDIR_DES(CurDirDEarray);
DE* move = (DE*)((((DE*)(openfilelist[curdir].DE_open+basis))->child)+basis);
//DE tmp = *move;
DE* first = move;
do{
// if ( strcmp(move->file_fcb.filename , ".") != 0 && strcmp(move->file_fcb.filename , "..") != 0) {
printf("%s ", (move->file_fcb).filename);
// }
move = (DE*)(move->next +basis);
}while(move != first);
printf("\n");
}
char buffer[BLOCKSIZE];
char read_buffer[BLOCKSIZE];
int write_bytes = 0;
void do_write(int fd, char* text, int len, char mod){
int block_num, offset;
int first = ((DE*)(openfilelist[fd].DE_open+basis))->file_fcb.first;
int write_block = first;
block_num = openfilelist[fd].count/BLOCKSIZE;
offset = openfilelist[fd].count%BLOCKSIZE;
for(int i =0 ; i<block_num; i++){
write_block = fat1[first];
first = write_block;
}
unsigned char* start_write = write_block*BLOCKSIZE + my_v_disk+ offset;
while(len>0){
//if current_block is full
if(offset >= BLOCKSIZE){
int free_block=0;
//allpy for more disk
while(fat1[free_block] != 0){
free_block++;
}
fat1[free_block] = -1;
fat1[write_block] = free_block;
write_block = free_block;
offset = 0;
start_write = write_block*BLOCKSIZE + my_v_disk+ offset;
}
// write into disk
*start_write = *text;
len--; offset++; start_write++; text++;
((DE*)(openfilelist[fd].DE_open+basis))->file_fcb.length++;
}
return;
}
void my_write(int fd){
if(openfilelist[fd].topenfile == 0){
printf("Invalid fd value!\n");
return;
}
char text;
char mode;
printf("Enter write mode [r/c/a]:");
scanf(" %c ",&mode);
if(mode == 'a'){
openfilelist[fd].count = (int)((DE*)(openfilelist[fd].DE_open+basis))->file_fcb.length;
}
else if(mode == 'c'){
openfilelist[fd].count = openfilelist[fd].count;
}
else if(mode == 'r'){
openfilelist[fd].count = 0;
}
else{
printf("No such write-mode!\n");
return;
}
while((text = getchar()) != '\n'){
if(write_bytes == BLOCKSIZE){
do_write(fd, buffer, BLOCKSIZE, mode);
write_bytes= 0;
}
buffer[write_bytes] = text;
write_bytes++;
}
if(write_bytes != 0){
do_write(fd, buffer, write_bytes, mode);
write_bytes= 0;
}
openfilelist[fd].fcbstate = 1;
//DE tmp = *openfilelist[curdir].DE_open;
return;
}
int do_read(int fd, int len, char* text){
int read_block = ((DE*)(openfilelist[fd].DE_open+basis))->file_fcb.first;
int offset, block_num;
block_num = openfilelist[fd].count/BLOCKSIZE;
offset = openfilelist[fd].count%BLOCKSIZE;
while(block_num > 0){
read_block = fat1[read_block];
block_num--;
}
unsigned char* start_read = read_block*BLOCKSIZE + my_v_disk + offset;
int read_bytes = 0;
while(len > 0){
// if buffer's full, read into usr space
if(read_bytes == BLOCKSIZE){
for(int i = 0; i<BLOCKSIZE; i++){
*text = *(read_buffer+i);
text++;
}
read_bytes= 0;
}
if(offset >= BLOCKSIZE){
read_block = fat1[read_block];
offset = 0;
start_read = read_block*BLOCKSIZE + my_v_disk + offset;
}
read_buffer[read_bytes] = *start_read;
len--; start_read++; read_bytes++; offset++;
}
if(read_bytes != 0){
for(int i = 0; i<read_bytes; i++){
*text = *(read_buffer+i);
text++;
}
read_bytes= 0;
}
return len;
}
int my_read(int fd, int len){
if(openfilelist[fd].topenfile == 0){
printf("File not open yet\n");
return 0;
}
openfilelist[fd].count = 0;
char text[5*BLOCKSIZE];
do_read(fd, len, text);
printf("%s\n", text);
return len;
}
void my_exitsys(void){
my_close(0, 0);
FILE* v_disk = fopen("/home/oz/FileSys/myfilesys", "w");
if(fwrite(my_v_disk, sizeof(char), SIZE, v_disk) == 0){
printf("Write FS into disk Error!\n");
}
else{
printf("FileSystem successfully saved in real disk!\n");
}
free(my_v_disk);
return;
}
int main(void){
char* cmd[5];
int cmd_num, len;
for(int i = 0; i<5; i++){
cmd[i] = malloc(sizeof(char)*20);
}
printf("*******************Welcome to Myshell*****************************\n");
startsys();
while(1){
printf("Myshell %s > ", currentdir);
scanf("%s", cmd[0]);
if(strcmp(cmd[0], "my_cd") == 0){
scanf("%s", cmd[1]);
my_cd(cmd[1]);
}
else if(strcmp(cmd[0], "my_mkdir") == 0){
scanf("%s", cmd[1]);
my_mkdir(cmd[1]);
}
else if(strcmp(cmd[0], "my_rmdir") == 0){
scanf("%s", cmd[1]);
my_rmdir(cmd[1]);
}
else if(strcmp(cmd[0], "my_ls") == 0){
my_list();
}
else if(strcmp(cmd[0], "my_touch") == 0){
scanf("%s", cmd[1]);
my_creat(cmd[1]);
}
else if(strcmp(cmd[0], "my_rm") == 0){
scanf("%s", cmd[1]);
my_rm(cmd[1]);
}
else if(strcmp(cmd[0], "my_open") == 0){
scanf("%s", cmd[1]);
my_open(cmd[1], 1);
}
else if(strcmp(cmd[0], "my_close") == 0){
scanf("%d",&cmd_num );
if(cmd_num == 0){
printf("Root directory can't be closed!\n");
continue;
}
my_close(cmd_num, 1);
}
else if(strcmp(cmd[0], "my_write") == 0){
if(scanf("%d", &cmd_num) == 1){
my_write(cmd_num);
}
else{
printf("Enter the right fd value!\n");
}
}
else if(strcmp(cmd[0], "my_read") == 0){
scanf("%d", &cmd_num);
scanf("%d", &len);
my_read(cmd_num, len);
}
else if(strcmp(cmd[0], "exit") == 0){
my_exitsys();
break;
}
else{
printf("Invalid Command!\n");
}
fflush(stdin);
}
printf("****************************Bye!**********************************\n");
return 0;
}
杭电操作系统实验5-简单文件系统的实现
于 2024-01-01 02:52:29 首次发布