这个代码讲道理 不是我写的 我是了别人的代码 然后自己借鉴了后重写的 并修了3,4个bug,并且剪短了很多 可以rmdir该目录以及所有下属,可以cd多层目录
三个问题, 1.一个目录文件只删中间一部分,我的写发是这时length不变的,最好修改为read遍历对于free的文件直接跳过(想了想这也不好解决) 2.和老师还讨论了一个问题,如果close了父亲,那么儿子就找不到父亲了,这个可以通过我觉得可以在fcb中加int dirno;int diroff; 3.覆盖写的用处不大,感觉可以修改下write
#include<bits/stdc++.h> using namespace std; #define BLOCKSIZE 1024 #define SIZE 1024000 #define END 65535 #define FREE 0 #define MAXOPENFILE 10 #define MAX_TEXT_SIZE 10000 typedef struct FCB { char filename[8]; char exname[5]; unsigned char attribute; unsigned short time; unsigned short date; unsigned short first; unsigned long length; char free; } fcb; typedef struct FAT{ unsigned short id; } fat; typedef struct USEROPEN { char filename[8]; char exname[5]; unsigned char attribute; unsigned short time; unsigned short date; unsigned short first; unsigned long length; char free; int dirno; int diroff; char dir[80]; int off; char fcbstate; char topenfile; } useropen; typedef struct BLOCK0 { char magic_number[8]; char information[200]; unsigned short root; unsigned char *startblock; } block0; unsigned char *myvhard; useropen openfilelist[MAXOPENFILE]; int currfd; unsigned char *startp; char *FileName = "basasuya.txt"; void setZero(fcb *fcbPtr) { fcbPtr->date = 0; fcbPtr->time = 0; fcbPtr->exname[0] = '\0'; fcbPtr->filename[0] = '\0'; fcbPtr->first = 0; fcbPtr->free = 0; fcbPtr->length = 0; } int getFreeOpenfilelist() { for(int i = 0; i < MAXOPENFILE; ++i) { if(openfilelist[i].topenfile == 0) { openfilelist[i].topenfile = 1; return i; } } return -1; } unsigned short getFreeBLOCK() { fat* fat1 = (fat*)(myvhard + BLOCKSIZE); for(int i = 0; i < (int)(SIZE/BLOCKSIZE); ++i) { if(fat1[i].id == FREE) { return i; } } return END; } int find_father_dir(int fd) { for(int i = 0; i < MAXOPENFILE; ++i) { if(openfilelist[i].first == openfilelist[fd].dirno && openfilelist[i].topenfile == 1) { return i; } } return -1; } void my_format() { block0 *boot = (block0 *)myvhard; strcpy(boot->magic_number,"10101010"); strcpy(boot->information,"0:引导块 1,2:FAT1 3,4:FAT2 数据"); boot->root = 5; boot->startblock = myvhard + BLOCKSIZE*5; fat* fat1 = (fat*)(myvhard + BLOCKSIZE); for(int i = 0; i <= 5; ++i) { fat1[i].id = END; } for(int i = 6; i < 1000; ++i) { fat1[i].id = FREE; } fat* fat2 = (fat*)(myvhard + BLOCKSIZE*3); memcpy(fat2, fat1, BLOCKSIZE); fcb *root = (fcb*)(myvhard + BLOCKSIZE*5); strcpy(root->filename,"."); strcpy(root->exname,"di"); root->attribute = 0; time_t rawTime = time(NULL); struct tm *time = localtime(&rawTime); root->time = time->tm_hour * 2048 + time->tm_min*32 + time->tm_sec/2; root->date = (time->tm_year-100)*512 + (time->tm_mon+1)*32 + (time->tm_mday); root->first = 5; root->free = 1; root->length = 2*sizeof(fcb); fcb* root2 = root+1; memcpy(root2, root, sizeof(fcb)); strcpy(root2->filename, ".."); for(int i = 2; i < int(BLOCKSIZE / sizeof(fcb)); ++i) { // let the whole fcb be zero root2 ++; strcpy(root2->filename, ""); root2->free = 0; } FILE *fp = fopen(FileName, "w"); fwrite(myvhard, SIZE, 1, fp); fclose(fp); } void startSys() { unsigned char buffer[SIZE]; myvhard = (unsigned char *)malloc(SIZE); FILE *file; if((file = fopen(FileName, "r")) != NULL) { fread(buffer, SIZE, 1, file); if(memcmp(buffer, "10101010", 8) != 0) { my_format(); } else memcpy(myvhard, buffer, SIZE); fclose(file); }else { my_format(); } fcb *root; root = (fcb*)(myvhard + 5*BLOCKSIZE); strcpy(openfilelist[0].filename, root->filename); strcpy(openfilelist[0].exname, root->exname); openfilelist[0].attribute = root->attribute; openfilelist[0].time = root->time; openfilelist[0].date = root->date; openfilelist[0].first = root->first; openfilelist[0].length = root->length; openfilelist[0].free = root->free; openfilelist[0].dirno = 5; openfilelist[0].diroff = 0; strcpy(openfilelist[0].dir,"/root/"); openfilelist[0].off = 0; openfilelist[0].fcbstate = 0; openfilelist[0].topenfile = 1; startp = ((block0*)myvhard)->startblock; currfd = 0; return ; } int doread(int fd, int len, char *text) { int lenTmp = len; unsigned char* buf = (unsigned char*)malloc(1024); if(buf == NULL) { printf("do_read申请空间失败\n"); return -1; } int off = openfilelist[fd].off; int blockNum = openfilelist[fd].first; fat* fatPtr = (fat *)(myvhard+BLOCKSIZE) + blockNum; while(off >= BLOCKSIZE) { off -= BLOCKSIZE; blockNum = fatPtr->id; if(blockNum == END) { printf("do_read寻找的块不存在\n"); return -1; } fatPtr = (fat*)(myvhard + BLOCKSIZE) + blockNum; } unsigned char* blockPtr = myvhard +BLOCKSIZE*blockNum; memcpy(buf, blockPtr, BLOCKSIZE); char *textPtr = text; while(len > 0) { if(BLOCKSIZE - off > len) { memcpy(textPtr,buf+off, len); textPtr += len; off += len; openfilelist[fd].off += len; len = 0; }else { memcpy(textPtr, buf+off, BLOCKSIZE-off); textPtr += BLOCKSIZE - off; off = 0; len -= BLOCKSIZE - off; blockNum = fatPtr->id; if(blockNum == END) { printf("len 长度过长,超过文件限制!\n"); break; } fatPtr = (fat*)(myvhard + BLOCKSIZE) + blockNum; blockPtr = myvhard + BLOCKSIZE*blockNum; memcpy(buf, blockPtr, BLOCKSIZE); } } free(buf); return lenTmp - len; } void Read(int fd) { if(fd >= MAXOPENFILE || fd < 0) { printf("文件不存在\n"); return ; } openfilelist[fd].off = 0; char text[MAX_TEXT_SIZE] = "\0"; doread(fd, openfilelist[fd].length, text); printf("%s\n",text); } int dowrite(int fd, char *text, int len, char wstyle) { int blockNum = openfilelist[fd].first; fat *fatPtr = (fat*)(myvhard + BLOCKSIZE) + blockNum; fat* fat1 = (fat*)(myvhard+BLOCKSIZE); if(wstyle == 0) { openfilelist[fd].off = 0; openfilelist[fd].length = 0; }else if(wstyle == 1) { if(openfilelist[fd].attribute == 1 && openfilelist[fd].length != 0 && openfilelist[fd].off != 0) { openfilelist[fd].off --; } }else { if(openfilelist[fd].attribute == 0) { openfilelist[fd].off = openfilelist[fd].length; }else if(openfilelist[fd].attribute == 1 && openfilelist[fd].length != 0) { openfilelist[fd].off = openfilelist[fd].length - 1; } } int off = openfilelist[fd].off; while(off >= BLOCKSIZE) { blockNum = fatPtr->id; if(blockNum == END) { blockNum = getFreeBLOCK(); if(blockNum == END) { printf("盘块不足\n"); return -1; }else { fatPtr->id = blockNum; fatPtr = (fat*)(myvhard + BLOCKSIZE) + blockNum; fatPtr->id = END; } } fatPtr = (fat*)(myvhard + BLOCKSIZE) + blockNum; off -= BLOCKSIZE; } unsigned char *buf = (unsigned char*)malloc(BLOCKSIZE * sizeof(unsigned char)); unsigned char *blockPtr = (unsigned char *)(myvhard + BLOCKSIZE*blockNum); int lenTmp = 0; char *textPtr = text; while(len > lenTmp) { memcpy(buf, blockPtr, BLOCKSIZE); for(; off < BLOCKSIZE; ++off) { *(buf + off) = *textPtr; textPtr ++; lenTmp ++; if(len == lenTmp) { break; } } memcpy(blockPtr, buf, BLOCKSIZE); if(off == BLOCKSIZE && len != lenTmp) { off = 0; blockNum = fatPtr->id; if(blockNum == END) { blockNum = getFreeBLOCK(); if(blockNum == END) { printf("盘块用完\n"); return -1; }else { blockPtr = (unsigned char *)(myvhard + BLOCKSIZE*blockNum); fatPtr->id = blockNum; fatPtr = (fat *)(myvhard + BLOCKSIZE) + blockNum; fatPtr->id = END; } }else { blockPtr = (unsigned char *)(myvhard + BLOCKSIZE * blockNum); fatPtr = (fat *)(myvhard + BLOCKSIZE ) + blockNum; } } } openfilelist[fd].off += len; if(openfilelist[fd].off > openfilelist[fd].length) openfilelist[fd].length = openfilelist[fd].off; free(buf); memcpy((fat*)(myvhard + BLOCKSIZE*3), (fat*)(myvhard + BLOCKSIZE),sizeof(fcb)); return len; } void Write(int fd) { if(fd < 0 || fd >= MAXOPENFILE) { printf("文件不存在\n"); return; } int wstype; printf("输入: 0=截断写, 1=覆盖写, 2=追加写\n"); scanf("%d",&wstype); if(wstype < 0 || wstype > 2) { printf("输入超过限制\n"); return; } char text[MAX_TEXT_SIZE] = "\0"; char textTmp[MAX_TEXT_SIZE] = "\0"; printf("请输入文件系统,以end为文件系统\n"); while(scanf("%s",textTmp)) { if(strcmp(textTmp, "end") == 0) { break; } strcat(text, textTmp); strcat(text, " "); } dowrite(fd,text,strlen(text)+1, wstype); openfilelist[fd].fcbstate = 1; } void Changecurrdlength(char *text) { fcb *fcbPtr = (fcb *)text; fcbPtr->length = openfilelist[currfd].length; openfilelist[currfd].off = 0; dowrite(currfd, (char*)fcbPtr, sizeof(fcb), 1); openfilelist[currfd].fcbstate = 1; } int Close(int fd) { if(fd > MAXOPENFILE || fd < 0) { printf("不存在这个文件\n"); return -1; } int fatherFd = find_father_dir(fd); if(fatherFd == -1) { printf("不存在父目录\n"); return -1; } if(openfilelist[fd].fcbstate == 1) { char buf[MAX_TEXT_SIZE]; doread(fatherFd, openfilelist[fatherFd].length, buf); fcb* fcbPtr = (fcb *)(buf + sizeof(fcb)*openfilelist[fd].diroff); strcpy(fcbPtr->exname, openfilelist[fd].exname); strcpy(fcbPtr->filename, openfilelist[fd].filename); fcbPtr->first = openfilelist[fd].first; fcbPtr->free = openfilelist[fd].free; fcbPtr->length = openfilelist[fd].length; fcbPtr->time = openfilelist[fd].time; fcbPtr->date = openfilelist[fd].date; fcbPtr->attribute = openfilelist[fd].attribute; openfilelist[fatherFd].off = openfilelist[fd].diroff * sizeof(fcb); dowrite(fatherFd, (char *)fcbPtr, sizeof(fcb), 1); } memset(&openfilelist[fd], 0, sizeof(USEROPEN)); currfd = fatherFd; return currfd; } void Remove(char *filename){ char* fname = strtok(filename, "."); char* exname = strtok(NULL, "."); if(!exname){ printf("请输入后缀\n"); return; } if(strcmp(exname,"di") == 0){ printf("不可以输入目录\n"); return ; } char buf[MAX_TEXT_SIZE]; openfilelist[currfd].off = 0; doread(currfd,openfilelist[currfd].length,buf); int i; fcb* fcbPtr = (fcb*)buf; for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); i++, fcbPtr++){ if(strcmp(fcbPtr->filename,fname) == 0 && strcmp(fcbPtr->exname,exname) == 0){ break; } } if( i == int(openfilelist[currfd].length / sizeof(fcb))){ printf("没有这个文件\n"); return; } int blockNum = fcbPtr->first; fat* fat1 = (fat*)(myvhard + BLOCKSIZE); int next = 0; while(1){ next = fat1[blockNum].id; fat1[blockNum].id = FREE; if(next != END){ blockNum = next; } else{ break; } } fat1 = (fat*)(myvhard + BLOCKSIZE); fat* fat2 = (fat*)(myvhard + BLOCKSIZE*3); memcpy(fat2, fat1, sizeof(fat)); setZero(fcbPtr); openfilelist[currfd].off = i * sizeof(fcb); dowrite(currfd,(char*)fcbPtr,sizeof(fcb),1); Changecurrdlength(buf); } void Cd(char *dirname){ if(openfilelist[currfd].attribute == 1){ printf("数据文件不能cd"); return ; }else{ char *buf = (char *)malloc(MAX_TEXT_SIZE); openfilelist[currfd].off = 0; doread(currfd,openfilelist[currfd].length,buf); char tmp[20]; int tot = 0; int fl = 0; for(int i = 0; dirname[i]; ++i) { if(fl) tmp[tot++] = dirname[i]; else if(dirname[i] == '/') { fl = 1; dirname[i] = 0; } } tmp[tot] = 0; int i = 0; fcb* fcbPtr = (fcb*)buf; for(; i < int(openfilelist[currfd].length / sizeof(fcb)); i++,fcbPtr++){ if(strcmp(fcbPtr->filename, dirname) == 0 && fcbPtr->attribute == 0){ break; } } if(strcmp(fcbPtr->exname, "di") != 0){ printf("不含有非数据文件\n"); return; }else { if(strcmp(fcbPtr->filename,".") == 0){ return; } else if(strcmp(fcbPtr->filename, "..") == 0){ if(currfd == 0){ return; }else{ currfd = Close(currfd); return; } } else{ int fd = getFreeOpenfilelist(); if(fd == -1){ return; } else{ openfilelist[fd].attribute = fcbPtr->attribute; openfilelist[fd].off = 0; openfilelist[fd].date = fcbPtr->date; openfilelist[fd].time = fcbPtr->time; strcpy(openfilelist[fd].filename, fcbPtr->filename); strcpy(openfilelist[fd].exname,fcbPtr->exname); openfilelist[fd].first = fcbPtr->first; openfilelist[fd].free = fcbPtr->free; openfilelist[fd].fcbstate = 0; openfilelist[fd].length = fcbPtr->length; strcpy(openfilelist[fd].dir, (char*)(string(openfilelist[currfd].dir) + string(dirname) + string("/")).c_str()); openfilelist[fd].topenfile = 1; openfilelist[fd].dirno = openfilelist[currfd].first; openfilelist[fd].diroff = i; currfd = fd; } if(tot) Cd(tmp); } } } } void Mkdir(char *dirname) { char* fname = strtok(dirname, "."); char* exname = strtok(NULL, "."); if(exname) { printf("不允许输入后缀名\n"); return; } char text[MAX_TEXT_SIZE]; openfilelist[currfd].off = 0; int fileLen = doread(currfd, openfilelist[currfd].length, text); fcb *fcbPtr = (fcb*)text; for(int i = 0; i < (int)(fileLen/sizeof(fcb)); ++i) { if(strcmp(dirname, fcbPtr[i].filename) == 0 && fcbPtr->attribute == 0) { printf("目录名已经存在!\n"); return; } } int fd = getFreeOpenfilelist(); if(fd == -1) { printf("打开文件表已经被占用\n"); return; } unsigned short int blockNum = getFreeBLOCK(); if(blockNum == END) { printf("盘块应经被用完\n"); openfilelist[fd].topenfile = 0; return; } fat *fat1 = (fat *)(myvhard + BLOCKSIZE); fat *fat2 = (fat *)(myvhard + BLOCKSIZE*3); fat1[blockNum].id = END; fat2[blockNum].id = END; int i; for(i=0;i < (int)(fileLen/sizeof(fcb)); ++i) { if(fcbPtr[i].free == 0) break; } openfilelist[currfd].off = i*sizeof(fcb); openfilelist[currfd].fcbstate = 1; fcb* fcbtmp = new fcb; fcbtmp->attribute = 0; time_t rawtime = time(NULL); struct tm* time = localtime(&rawtime); fcbtmp->date = (time->tm_year-100)*512 + (time->tm_mon+1)*32 + (time->tm_mday); fcbtmp->time = (time->tm_hour)*2048 + (time->tm_min)*32 + (time->tm_sec) / 2; strcpy(fcbtmp->filename , dirname); strcpy(fcbtmp->exname, "di"); fcbtmp->first = blockNum; fcbtmp->length = 2 * sizeof(fcb); fcbtmp->free = 1; dowrite(currfd,(char *)fcbtmp,sizeof(fcb),1); openfilelist[fd].attribute = 0; openfilelist[fd].off = 0; openfilelist[fd].date = fcbtmp->date; openfilelist[fd].time = fcbtmp->time; openfilelist[fd].dirno = openfilelist[currfd].first; openfilelist[fd].diroff = i; strcpy(openfilelist[fd].exname,"di"); strcpy(openfilelist[fd].filename,dirname); openfilelist[fd].fcbstate = 0; openfilelist[fd].first = fcbtmp->first; openfilelist[fd].free = fcbtmp->free; openfilelist[fd].length = fcbtmp->length; openfilelist[fd].topenfile = 1; strcpy(openfilelist[fd].dir, (char*)(string(openfilelist[currfd].dir) + string(dirname) + string("/")).c_str()); strcpy(fcbtmp->filename, "."); strcpy(fcbtmp->exname, "di"); fcbtmp->first = blockNum; fcbtmp->length = 2 * sizeof(fcb); dowrite(fd,(char*)fcbtmp,sizeof(fcb),1); fcb *fcbtmp2 = new fcb; memcpy(fcbtmp2,fcbtmp,sizeof(fcb)); strcpy(fcbtmp2->filename,".."); fcbtmp2->first = openfilelist[currfd].first; fcbtmp2->length = openfilelist[currfd].length; fcbtmp2->date = openfilelist[currfd].date; fcbtmp2->time = openfilelist[currfd].time; dowrite(fd,(char*)fcbtmp2,sizeof(fcb),1); Changecurrdlength(text); Close(fd); } void Rmdir(char *dirname) { char* fname = strtok(dirname, "."); char* exname = strtok(NULL, "."); if(strcmp(dirname, ".") == 0 || strcmp(dirname, "..") == 0) { printf("不能删除特殊目录项\n"); return ; } if(exname) { printf("删除目录文件 没有后缀名\n"); return; } char buf[MAX_TEXT_SIZE]; openfilelist[currfd].off = 0; doread(currfd,openfilelist[currfd].length,buf); int i; fcb* fcbPtr = (fcb*)buf; for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); i++, fcbPtr++){ if(strcmp(fcbPtr->filename,fname) == 0 && fcbPtr->attribute == 0){ break; } } if( i == int(openfilelist[currfd].length / sizeof(fcb))){ printf("没有这个文件\n"); return; } Cd(dirname); openfilelist[currfd].off = 0; doread(currfd,openfilelist[currfd].length,buf); fcbPtr = (fcb*)buf; for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); i++, fcbPtr++); for(fcbPtr--,i--; i >= 0; --i, fcbPtr--){ if(fcbPtr->attribute == 1){ char *tmp = fcbPtr->filename; strcat(tmp, "."); strcat(tmp, fcbPtr->exname); Remove(tmp); }else if(strcmp(fcbPtr->filename,".") == 0 || strcmp(fcbPtr->filename,"..") == 0) continue; else { char *tmp = fcbPtr->filename; Rmdir(tmp); } } Cd(".."); openfilelist[currfd].off = 0; doread(currfd,openfilelist[currfd].length,buf); fcbPtr = (fcb*)buf; for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); i++, fcbPtr++){ if(strcmp(fcbPtr->filename,fname) == 0 && fcbPtr->attribute == 0){ break; } } int blockNum = fcbPtr->first; fat* fat1 = (fat*)(myvhard + BLOCKSIZE); int next = 0; while(1) { next = fat1[blockNum].id; fat1[blockNum].id = FREE; if(next != END) { blockNum = next; }else break; } fat1 = (fat*)(myvhard + BLOCKSIZE); fat* fat2 = (fat*)(myvhard + BLOCKSIZE*3); memcpy(fat2, fat1, sizeof(fat)); setZero(fcbPtr); openfilelist[currfd].off = i * sizeof(fcb); dowrite(currfd,(char*)fcbPtr,sizeof(fcb),1); Changecurrdlength(buf); } void Touch(char *filename) { char* fname = strtok(filename, "."); char* exname = strtok(NULL,"."); if(strcmp(fname,"") == 0) { printf("请输入文件名\n"); return ; } if(!exname) { printf("请输入后缀名\n"); return; } if(openfilelist[currfd].attribute == 1) { printf("数据文件下不允许使用create\n"); return; } openfilelist[currfd].off = 0; char buf[MAX_TEXT_SIZE]; doread(currfd, openfilelist[currfd].length, buf); int i; fcb* fcbPtr = (fcb*)(buf); for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); ++i,++fcbPtr) { if(strcmp(fcbPtr->filename,filename)==0 && strcmp(fcbPtr->exname,exname)==0){ printf("文件已存在\n"); return; } } fcbPtr = (fcb*)(buf); for(i=0; i < int(openfilelist[currfd].length / sizeof(fcb)); ++i,++fcbPtr) { if(fcbPtr->free == 0) break; } int blockNum = getFreeBLOCK(); if(blockNum == -1){ printf("没有空闲的盘块号\n"); return ; } fat* fat1 = (fat*)(myvhard + BLOCKSIZE); fat1[blockNum].id = END; fat* fat2 = (fat*)(myvhard + BLOCKSIZE * 3); memcmp(fat2, fat1, BLOCKSIZE*2); strcpy(fcbPtr->filename,filename); strcpy(fcbPtr->exname,exname); time_t rawtime = time(NULL); struct tm* time = localtime(&rawtime); fcbPtr->date = (time->tm_year-100)*512 + (time->tm_mon+1)*32 + (time->tm_mday); fcbPtr->time = (time->tm_hour)*2048 + (time->tm_min)*32 + (time->tm_sec) / 2; fcbPtr->first = blockNum; fcbPtr->free = 1; fcbPtr->length = 0; fcbPtr->attribute = 1; openfilelist[currfd].off = i * sizeof(fcb); dowrite(currfd,(char *)fcbPtr,sizeof(fcb),1); Changecurrdlength(buf); } void Ls(){ if(openfilelist[currfd].attribute == 1){ printf("数据文件不能用ls\n"); return; } char buf[MAX_TEXT_SIZE]; openfilelist[currfd].off = 0; doread(currfd, openfilelist[currfd].length, buf); fcb* fcbPtr = (fcb*)buf; for(int i=0; i < (int)(openfilelist[currfd].length / sizeof(fcb)); i++){ if(fcbPtr->free == 1){ if(fcbPtr->attribute == 0){ printf("%s\\\t<DIR>\t%d/%d/%d\t%d:%d:%d\n", fcbPtr->filename, (fcbPtr->date>>9)+2000, (fcbPtr->date>>5)&0x000f, (fcbPtr->date)&0x001f, (fcbPtr->time>>11), (fcbPtr->time>>5)&0x003f, (fcbPtr->time)&0x001f * 2); } else{ unsigned int length = fcbPtr->length; if(length != 0) length -= 2; printf("%s.%s\t