【操作系統】C語言編寫的FAT16文件系統

這是上學期操作系統的期末課程設計作業之一,主要功能是在物理內存中虛擬出一個1M大小的FAT16的文件系統,然後把它讀入內存中,進行具體的文件操作,具體的實用性不大,主要目的是爲了練習C語言,幫助理解文件系統的特點,代碼如下:

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <time.h>

#define BLOCKSIZE 1024  // 磁盤塊大小
#define SIZE 1024000  // 虛擬磁盤空間大小
#define END 65535  // FAT中的文件結束標誌
#define FREE 0  // FAT中盤塊空閒標誌
#define ROOTBLOCKNUM 2  // 根目錄區所佔盤塊數
#define MAXOPENFILE 10  // 最多同時打開文件個數t
#define MAXTEXT 10000

/* 文件控制塊 */
typedef struct FCB
{
    char filename[8];  // 文件名
    char exname[3];  // 文件擴展名
    unsigned char attribute;  // 文件屬性字段,值爲0時表示目錄文件,值爲1時表示數據文件
    unsigned short time;  // 文件創建時間
    unsigned short date;  // 文件創建日期
    unsigned short first;  // 文件起始盤塊號
    unsigned long length;  // 文件長度
    char free;  // 表示目錄項是否爲空,若值爲0,表示空,值爲1,表示已分配
}fcb;

/* 文件分配表 */
typedef struct FAT
{
    unsigned short id;  // 磁盤塊的狀態(空閒的,最後的,下一個)
}fat;
/* 用戶打開文件表 */
typedef struct USEROPEN
{
    char filename[8];  // 文件名
    char exname[3];  // 文件擴展名
    unsigned char attribute;  // 文件屬性字段,值爲0時表示目錄文件,值爲1時表示數據文件
    unsigned short time;  // 文件創建時間
    unsigned short date;  // 文件創建日期
    unsigned short first;  // 文件起始盤塊號
    unsigned long length;  // 文件長度(對數據文件是字節數,對目錄文件可以是目錄項個數)
    char free;  // 表示目錄項是否爲空,若值爲0,表示空,值爲1,表示已分配

	unsigned short dirno;  // 相應打開文件的目錄項在父目錄文件中的盤塊號
    int diroff;  // 相應打開文件的目錄項在父目錄文件的dirno盤塊中的目錄項序號
    char dir[80];  // 相應打開文件所在的目錄名,這樣方便快速檢查出指定文件是否已經打開
    int father;  // 父目錄在打開文件表項的位置
	int count;  // 讀寫指針在文件中的位置,文件的總字符數
    char fcbstate;  // 是否修改了文件的FCB的內容,如果修改了置爲1,否則爲0
	char topenfile;  // 表示該用戶打開表項是否爲空,若值爲0,表示爲空,否則表示已被某打開文件佔據
}useropen;

/* 引導塊 */
typedef struct BLOCK0
{
    char magic[10];  // 文件系統魔數
	char information[200];  // 存儲一些描述信息,如磁盤塊大小、磁盤塊數量、最多打開文件數等
    unsigned short root;  // 根目錄文件的起始盤塊號
	unsigned char *startblock;  // 虛擬磁盤上數據區開始位置
}block0;
unsigned char *myvhard;  // 指向虛擬磁盤的起始地址
useropen openfilelist[MAXOPENFILE];  // 用戶打開文件表數組
int curdir;  // 用戶打開文件表中的當前目錄所在打開文件表項的位置
char currentdir[80];  // 記錄當前目錄的目錄名(包括目錄的路徑)
unsigned char* startp;  // 記錄虛擬磁盤上數據區開始位置
char myfilename[] = "myfilesys";//文件系統的文件名

void startsys();  // 進入文件系統
void my_format();  // 磁盤格式化
void my_cd(char *dirname);  // 更改當前目錄
void my_mkdir(char *dirname);  // 創建子目錄
void my_rmdir(char *dirname);  // 刪除子目錄
void my_ls();  // 顯示目錄
void my_create (char *filename);  // 創建文件
void my_rm(char *filename);  // 刪除文件
int my_open(char *filename);  // 打開文件
int my_close(int fd);  // 關閉文件
int my_write(int fd);  // 寫文件
int do_write(int fd, char *text, int len, char wstyle);  // 實際寫文件
int my_read (int fd, int len);  // 讀文件
int do_read (int fd, int len,char *text);  // 實際讀文件
void my_exitsys();  // 退出文件系統
unsigned short findblock();  // 尋找空閒盤塊
int findopenfile();  // 尋找空閒文件表項
void startsys()
{
    FILE *fp;
    unsigned char buf[SIZE];
    fcb *root;
	int i;
	myvhard = (unsigned char *)malloc(SIZE);//申請虛擬磁盤空間
	memset(myvhard, 0, SIZE);//將myvhard中前SIZE個字節用 0 替換並返回 myvhard
	if((fp = fopen(myfilename, "r")) != NULL)
	{
	    fread(buf, SIZE, 1, fp);//將二進制文件讀取到緩衝區
	    fclose(fp);//關閉打開的文件,緩衝區數據寫入文件,釋放系統提供文件資源
	    if(strcmp(((block0 *)buf)->magic, "10101010"))//判斷開始的8個字節內容是否爲文件系統魔數
	    {
	        printf("myfilesys is not exist,begin to creat the file...\n");
	        my_format();
	    }
	    else
	    {
	        for(i = 0; i < SIZE; i++)
                myvhard[i] = buf[i];
	    }
	}
	else
	{
	    printf("myfilesys is not exist,begin to creat the file...\n");
	    my_format();
	}
	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].father = 0;
	openfilelist[0].count = 0;
	openfilelist[0].fcbstate = 0;
	openfilelist[0].topenfile = 1;
	for(i = 1; i < MAXOPENFILE; i++)
        openfilelist[i].topenfile = 0;
	curdir = 0;
	strcpy(currentdir, "\\root\\");
	startp = ((block0 *)myvhard)->startblock;
}
void my_format()
{
    FILE *fp;
	fat *fat1, *fat2;
	block0 *blk0;
	time_t now;
	struct tm *nowtime;
	fcb *root;
	int i;
	blk0 = (block0 *)myvhard;
	fat1 = (fat *)(myvhard + BLOCKSIZE);
	fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
	root = (fcb *)(myvhard + 5 * BLOCKSIZE);
	strcpy(blk0->magic, "10101010");
	strcpy(blk0->information, "My FileSystem Ver 1.0 \n Blocksize=1KB Whole size=1000KB Blocknum=1000 RootBlocknum=2\n");
	blk0->root = 5;
	blk0->startblock = (unsigned char *)root;
	for(i = 0; i < 5; i++)
    {
        fat1->id = END;
        fat2->id = END;
        fat1++;
        fat2++;
    }
    fat1->id = 6;
    fat2->id = 6;
    fat1++;
    fat2++;
    fat1->id = END;
    fat2->id = END;
    fat1++;
    fat2++;
	for(i = 7; i < SIZE / BLOCKSIZE; i++)
    {
        fat1->id = FREE;
        fat2->id = FREE;
        fat1++;
        fat2++;
    }
    now = time(NULL);
    nowtime = localtime(&now);
    strcpy(root->filename, ".");
    strcpy(root->exname, "");
    root->attribute = 0x28;
    root->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	root->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	root->first = 5;
	root->length = 2 * sizeof(fcb);
	root->free = 1;
	root++;
	now = time(NULL);
    nowtime = localtime(&now);
	strcpy(root->filename, "..");
    strcpy(root->exname, "");
    root->attribute = 0x28;
    root->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	root->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	root->first = 5;
	root->length = 2 * sizeof(fcb);
	root->free = 1;
    fp = fopen(myfilename, "w");
    fwrite(myvhard, SIZE, 1, fp);
    fclose(fp);
}
void my_cd(char *dirname)
{
    char *dir;
	int fd;
	dir = strtok(dirname, "\\");//分解字符串爲一組字符串。dirname爲要分解的字符串,"\\"爲分隔符字符串
	if(strcmp(dir, ".") == 0)
        return;
    else if(strcmp(dir, "..") == 0)
    {
        if(curdir)
            curdir = my_close(curdir);
        return;
    }
    else if(strcmp(dir, "root") == 0)
    {
        while(curdir)
            curdir = my_close(curdir);
        dir = strtok(NULL, "\\");
    }
    while(dir)
    {
        fd = my_open(dir);
        if(fd != -1)
            curdir = fd;
        else
            return;
        dir = strtok(NULL, "\\");
    }
}
void my_mkdir(char *dirname)
{
    fcb *fcbptr;
    fat *fat1, *fat2;
    time_t now;
	struct tm *nowtime;
    char text[MAXTEXT];
    unsigned short blkno;
    int rbn, fd, i;
    fat1 = (fat *)(myvhard + BLOCKSIZE);
    fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
    openfilelist[curdir].count = 0;
    rbn = do_read(curdir, openfilelist[curdir].length, text);
    fcbptr = (fcb *)text;
    for(i = 0; i < rbn / sizeof(fcb); i++)//在當前目錄下找,是否有重名目錄
    {
        if(strcmp(fcbptr->filename, dirname) == 0 && strcmp(fcbptr->exname, "") == 0)
        {
            printf("Error,the dirname is already exist!\n");
            return;
        }
        fcbptr++;
    }
    fcbptr = (fcb *)text;
    for(i = 0; i < rbn / sizeof(fcb); i++)
    {
        if(fcbptr->free == 0)
            break;
        fcbptr++;
    }
    blkno = findblock();//尋找空閒盤塊
    if(blkno == -1)
        return;
    (fat1 + blkno)->id = END;
    (fat2 + blkno)->id = END;
	now = time(NULL);
    nowtime = localtime(&now);
    strcpy(fcbptr->filename, dirname);
    strcpy(fcbptr->exname, "");
    fcbptr->attribute = 0x30;
    fcbptr->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	fcbptr->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	fcbptr->first = blkno;
	fcbptr->length = 2 * sizeof(fcb);
	fcbptr->free = 1;
	openfilelist[curdir].count = i * sizeof(fcb);
	do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);

	fd = my_open(dirname);//建立新目錄的'.','..'目錄
	if(fd == -1)
        return;
	fcbptr = (fcb *)malloc(sizeof(fcb));
    now = time(NULL);
    nowtime = localtime(&now);
	strcpy(fcbptr->filename, ".");
	strcpy(fcbptr->exname, "");
	fcbptr->attribute = 0x28;
	fcbptr->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	fcbptr->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	fcbptr->first = blkno;
	fcbptr->length = 2 * sizeof(fcb);
	fcbptr->free = 1;
	do_write(fd, (char *)fcbptr, sizeof(fcb), 2);
	now = time(NULL);
    nowtime = localtime(&now);
	strcpy(fcbptr->filename, "..");
	strcpy(fcbptr->exname, "");
	fcbptr->attribute = 0x28;
	fcbptr->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	fcbptr->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	fcbptr->first = blkno;
	fcbptr->length = 2 * sizeof(fcb);
	fcbptr->free = 1;
	do_write(fd, (char *)fcbptr, sizeof(fcb), 2);
	free(fcbptr);
	my_close(fd);

	fcbptr = (fcb *)text;
	fcbptr->length = openfilelist[curdir].length;
	openfilelist[curdir].count = 0;
	do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);
    openfilelist[curdir].fcbstate = 1;
}

void my_rmdir(char *dirname)
{
    fcb *fcbptr,*fcbptr2;
    fat *fat1, *fat2, *fatptr1, *fatptr2;
	char text[MAXTEXT], text2[MAXTEXT];
	unsigned short blkno;
	int rbn, rbn2, fd, i, j;
	fat1 = (fat *)(myvhard + BLOCKSIZE);
    fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
	if(strcmp(dirname, ".") == 0 || strcmp(dirname, "..") == 0)
	{
	    printf("Error,can't remove this directory.\n");
	    return;
	}
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)//查找要刪除的目錄
	{
	    if(strcmp(fcbptr->filename, dirname) == 0 && strcmp(fcbptr->exname, "") == 0)
            break;
	    fcbptr++;
	}
	if(i == rbn / sizeof(fcb))
	{
	    printf("Error,the directory is not exist.\n");
        return;
	}
	fd = my_open(dirname);
	rbn2 = do_read(fd, openfilelist[fd].length, text2);
	fcbptr2 = (fcb *)text2;
	for(j = 0; j < rbn2 / sizeof(fcb); j++)//判斷要刪除目錄是否爲空
	{
	    if(strcmp(fcbptr2->filename, ".") && strcmp(fcbptr2->filename, "..") && strcmp(fcbptr2->filename, ""))
	    {
	        my_close(fd);
	        printf("Error,the directory is not empty.\n");
			return;
	    }
	    fcbptr2++;
	}
    blkno = openfilelist[fd].first;
    while(blkno != END)
    {
        fatptr1 = fat1 + blkno;
        fatptr2 = fat2 + blkno;
        blkno = fatptr1->id;
        fatptr1->id = FREE;
        fatptr2->id = FREE;
    }
	my_close(fd);
    strcpy(fcbptr->filename, "");
    fcbptr->free = 0;
    openfilelist[curdir].count = i * sizeof(fcb);
    do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);
    openfilelist[curdir].fcbstate = 1;
}
void my_ls()
{
    fcb *fcbptr;
	char text[MAXTEXT];
	int rbn, i;
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
    {
        if(fcbptr->free)
        {
            if(fcbptr->attribute & 0x20)
				printf("%s\\\t\t<DIR>\t\t%d/%d/%d\t%02d:%02d:%02d\n", fcbptr->filename, (fcbptr->date >> 9) + 1980, (fcbptr->date >> 5) & 0x000f, fcbptr->date & 0x001f, fcbptr->time >> 11, (fcbptr->time >> 5) & 0x003f, fcbptr->time & 0x001f * 2);
			else
                printf("%s.%s\t\t%dB\t\t%d/%d/%d\t%02d:%02d:%02d\t\n", fcbptr->filename, fcbptr->exname, (int)(fcbptr->length), (fcbptr->date >> 9) + 1980, (fcbptr->date >> 5) & 0x000f, fcbptr->date & 0x1f, fcbptr->time >> 11, (fcbptr->time >> 5) & 0x3f, fcbptr->time & 0x1f * 2);
        }
        fcbptr++;
    }
}
void my_create(char *filename)
{
    fcb *fcbptr;
    fat *fat1, *fat2;
    char *fname, *exname, text[MAXTEXT];
    unsigned short blkno;
	int rbn, i;
	time_t now;
	struct tm *nowtime;
	fat1 = (fat *)(myvhard + BLOCKSIZE);
	fat2 = (fat *)(myvhard + BLOCKSIZE);
	fname = strtok(filename, ".");
	exname = strtok(NULL, ".");
	if(strcmp(fname, "") == 0)
	{
	    printf("Error,creating file must have a right name.\n");
		return;
	}
	if(!exname)
	{
	    printf("Error,creating file must have a extern name.\n");
		return;
	}
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
	{
	    if(strcmp(fcbptr->filename, fname) == 0 && strcmp(fcbptr->exname, exname) == 0)
	    {
	        printf("Error,the filename is already exist!\n");
			return;
	    }
	    fcbptr++;
	}
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
	{
	    if(fcbptr->free == 0)
            break;
        fcbptr++;
	}
	blkno = findblock();
	if(blkno == -1)
        return;
    (fat1 + blkno)->id = END;
    (fat2 + blkno)->id = END;

    now = time(NULL);
    nowtime = localtime(&now);
    strcpy(fcbptr->filename, fname);
    strcpy(fcbptr->exname, exname);
    fcbptr->attribute = 0x00;
    fcbptr->time = nowtime->tm_hour * 2048 + nowtime->tm_min * 32 + nowtime->tm_sec / 2;
	fcbptr->date = (nowtime->tm_year - 80) * 512 + (nowtime->tm_mon + 1) * 32 + nowtime->tm_mday;
	fcbptr->first = blkno;
	fcbptr->length = 0;
	fcbptr->free = 1;
	openfilelist[curdir].count = i * sizeof(fcb);
	do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);
    fcbptr = (fcb *)text;
    fcbptr->length = openfilelist[curdir].length;
    openfilelist[curdir].count = 0;
    do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);
    openfilelist[curdir].fcbstate = 1;
}
void my_rm(char *filename)
{
    fcb *fcbptr;
    fat *fat1, *fat2, *fatptr1, *fatptr2;
    char *fname, *exname, text[MAXTEXT];
	unsigned short blkno;
	int rbn, i;
	fat1 = (fat *)(myvhard + BLOCKSIZE);
	fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
	fname = strtok(filename, ".");
	exname = strtok(NULL, ".");
	if(strcmp(fname, "") == 0)
	{
	    printf("Error,removing file must have a right name.\n");
		return;
	}
	if(!exname)
	{
	    printf("Error,removing file must have a extern name.\n");
		return;
	}
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
	{
	    if(strcmp(fcbptr->filename, fname) == 0 && strcmp(fcbptr->exname, exname) == 0)
            break;
        fcbptr++;
	}
	if(i == rbn / sizeof(fcb))
	{
	    printf("Error,the file is not exist.\n");
	    return;
	}
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
	{
	    if(strcmp(fcbptr->filename, fname) == 0 && strcmp(fcbptr->exname, exname) == 0)
            break;
        fcbptr++;
	}
	if(i == rbn / sizeof(fcb))
	{
	    printf("Error,the file is not exist.\n");
	    return;
	}
	blkno = fcbptr->first;
	while(blkno != END)
	{
	    fatptr1 = fat1 + blkno;
	    fatptr2 = fat2 + blkno;
	    blkno = fatptr1->id;
	    fatptr1->id = FREE;
	    fatptr2->id = FREE;
	}
	strcpy(fcbptr->filename, "");
	fcbptr->free = 0;
	openfilelist[curdir].count = i * sizeof(fcb);
	do_write(curdir, (char *)fcbptr, sizeof(fcb), 2);
	openfilelist[curdir].fcbstate = 1;
}
int my_open(char *filename)
{
    fcb *fcbptr;
	char *fname, exname[3], *str, text[MAXTEXT];
	int rbn, fd, i;
	fname = strtok(filename, ".");
	str = strtok(NULL, ".");
	if(str)
        strcpy(exname, str);
    else
        strcpy(exname, "");
	for(i = 0; i < MAXOPENFILE; i++)
	{
	    if(strcmp(openfilelist[i].filename, fname) == 0 && strcmp(openfilelist[i].exname, exname) == 0 && i != curdir)
	    {
	        printf("Error,the file is already open.\n");
	        return -1;
	    }
	}
	openfilelist[curdir].count = 0;
	rbn = do_read(curdir, openfilelist[curdir].length, text);
	fcbptr = (fcb *)text;
	for(i = 0; i < rbn / sizeof(fcb); i++)
	{
	    if(strcmp(fcbptr->filename, fname) == 0 && strcmp(fcbptr->exname, exname) == 0)
            break;
        fcbptr++;
	}
	if(i == rbn / sizeof(fcb))
    {
        printf("Error,the file is not exist.\n");
        return -1;
    }
	fd = findopenfile();
    if(fd == -1)
        return -1;
    strcpy(openfilelist[fd].filename, fcbptr->filename);
	strcpy(openfilelist[fd].exname, fcbptr->exname);
	openfilelist[fd].attribute = fcbptr->attribute;
	openfilelist[fd].time = fcbptr->time;
	openfilelist[fd].date = fcbptr->date;
	openfilelist[fd].first = fcbptr->first;
	openfilelist[fd].length = fcbptr->length;
	openfilelist[fd].free = fcbptr->free;
	openfilelist[fd].dirno = openfilelist[curdir].first;
	openfilelist[fd].diroff = i;
	strcpy(openfilelist[fd].dir, openfilelist[curdir].dir);
	strcat(openfilelist[fd].dir, filename);
	if(fcbptr->attribute & 0x20)
        strcat(openfilelist[fd].dir, "\\");
	openfilelist[fd].father = curdir;
	openfilelist[fd].count = 0;
	openfilelist[fd].fcbstate = 0;
	openfilelist[fd].topenfile = 1;
	return fd;
}
int my_close(int fd)
{
    fcb *fcbptr;
	int father;
	if(fd < 0 || fd >= MAXOPENFILE)
	{
	    printf("Error,the file is not exist.\n");
	    return -1;
	}
	if(openfilelist[fd].fcbstate)
	{
	    fcbptr = (fcb *)malloc(sizeof(fcb));
	    strcpy(fcbptr->filename, openfilelist[fd].filename);
	    strcpy(fcbptr->exname, openfilelist[fd].exname);
        fcbptr->attribute = openfilelist[fd].attribute;
        fcbptr->time = openfilelist[fd].time;
        fcbptr->date = openfilelist[fd].date;
        fcbptr->first = openfilelist[fd].first;
        fcbptr->length = openfilelist[fd].length;
        fcbptr->free = openfilelist[fd].free;
        father = openfilelist[fd].father;
        openfilelist[father].count = openfilelist[fd].diroff * sizeof(fcb);
        do_write(father, (char *)fcbptr, sizeof(fcb), 2);
        free(fcbptr);
        openfilelist[fd].fcbstate = 0;
	}
	strcpy(openfilelist[fd].filename, "");
	strcpy(openfilelist[fd].exname, "");
	openfilelist[fd].topenfile = 0;
	return father;
}
int my_write(int fd)
{
    fat *fat1, *fat2, *fatptr1, *fatptr2;
    int wstyle, len, ll, tmp;
    char text[MAXTEXT];
    unsigned short blkno;
    fat1 = (fat *)(myvhard + BLOCKSIZE);
    fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
    if(fd < 0 || fd >= MAXOPENFILE)
    {
        printf("The file is not exist!\n");
		return -1;
    }
    while(1)
    {
        printf("Please enter the number of write style:\n1.cut write\t2.cover write\t3.add write\n");
		scanf("%d", &wstyle);
		if(wstyle > 0 && wstyle < 4)
            break;
		printf("Input Error!");
    }
    getchar();
	switch(wstyle)
    {
        case 1:
            blkno = openfilelist[fd].first;
            fatptr1 = fat1 + blkno;
            fatptr2 = fat2 + blkno;
            blkno = fatptr1->id;
            fatptr1->id = END;
            fatptr2->id = END;
            while(blkno != END)
            {
                fatptr1 = fat1 + blkno;
                fatptr2 = fat2 + blkno;
                blkno = fatptr1->id;
                fatptr1->id = FREE;
                fatptr2->id = FREE;
            }
            openfilelist[fd].count = 0;
            openfilelist[fd].length = 0;
            break;
        case 2:
            openfilelist[fd].count = 0;
            break;
        case 3:
            openfilelist[fd].count = openfilelist[fd].length;
            break;
        default:
            break;
    }
	ll = 0;
    printf("please input write data(end with Ctrl+Z):\n");
    while(gets(text))
    {
        len = strlen(text);
        text[len++] = '\n';
        text[len] = '\0';
        tmp = do_write(fd, text, len, wstyle);
        if(tmp != -1)
            ll += tmp;
        if(tmp < len)
        {
            printf("Wirte Error!");
            break;
        }
    }
    return ll;
}

int do_write(int fd, char *text, int len, char wstyle)
{
    fat *fat1, *fat2, *fatptr1, *fatptr2;
    unsigned char *buf, *blkptr;
    unsigned short blkno, blkoff;
    int i, ll;
    fat1 = (fat *)(myvhard + BLOCKSIZE);
    fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
    buf = (unsigned char *)malloc(BLOCKSIZE);
    if(buf == NULL)
    {
        printf("malloc failed!\n");
        return -1;
    }
	blkno = openfilelist[fd].first;
    blkoff = openfilelist[fd].count;
    fatptr1 = fat1 + blkno;
    fatptr2 = fat2 + blkno;
    while(blkoff >= BLOCKSIZE)
    {
        blkno = fatptr1->id;
        if(blkno == END)
        {
            blkno = findblock();
            if(blkno == -1)
            {
                free(buf);
                return -1;
            }
            fatptr1->id = blkno;
            fatptr2->id = blkno;
            fatptr1 = fat1 + blkno;
            fatptr2 = fat2 + blkno;
            fatptr1->id = END;
            fatptr2->id = END;
        }
        else
        {
            fatptr1 = fat1 + blkno;
            fatptr2 = fat2 + blkno;
        }
        blkoff = blkoff - BLOCKSIZE;
    }

    ll = 0;
	while(ll < len)
    {
        blkptr = (unsigned char *)(myvhard + blkno * BLOCKSIZE);
        for(i = 0; i < BLOCKSIZE; i++)
            buf[i] = blkptr[i];
        for(;blkoff < BLOCKSIZE; blkoff++)
        {
            buf[blkoff] = text[ll++];
            openfilelist[fd].count++;
            if(ll == len)
                break;
        }
        for(i = 0; i < BLOCKSIZE; i++)
            blkptr[i] = buf[i];
        if(ll < len)
        {
            blkno = fatptr1->id;
            if(blkno == END)
            {
                blkno = findblock();
                if(blkno == -1)
                    break;
                fatptr1->id = blkno;
                fatptr2->id = blkno;
                fatptr1 = fat1 + blkno;
                fatptr2 = fat2 + blkno;
                fatptr1->id = END;
                fatptr2->id = END;
            }
            else
            {
                fatptr1 = fat1 + blkno;
                fatptr2 = fat2 + blkno;
            }
            blkoff = 0;
			}
    }
	if(openfilelist[fd].count > openfilelist[fd].length)
        openfilelist[fd].length = openfilelist[fd].count;
    openfilelist[fd].fcbstate = 1;
    free(buf);
    return ll;
}
int my_read(int fd, int len)
{
    char text[MAXTEXT];
    int ll;
    if(fd < 0 || fd >= MAXOPENFILE)
    {
        printf("The File is not exist!\n");
        return -1;
    }
    openfilelist[fd].count = 0;
    ll = do_read(fd, len, text);
    if(ll != -1)
        printf("%s", text);
    else
        printf("Read Error!\n");
    return ll;
}
int do_read(int fd, int len, char *text)
{
    fat *fat1, *fatptr;
    unsigned char *buf, *blkptr;
    unsigned short blkno, blkoff;
    int i, ll;
    fat1 = (fat *)(myvhard + BLOCKSIZE);
    buf = (unsigned char *)malloc(BLOCKSIZE);
    if(buf == NULL)
    {
        printf("malloc failed!\n");
        return -1;
    }
    blkno = openfilelist[fd].first;
    blkoff = openfilelist[fd].count;
    if(blkoff >= openfilelist[fd].length)
    {
        puts("Read out of range!");
        free(buf);
        return -1;
    }
    fatptr = fat1 + blkno;
    while(blkoff >= BLOCKSIZE)
    {
        blkno = fatptr->id;
        blkoff = blkoff - BLOCKSIZE;
        fatptr = fat1 + blkno;
    }
	ll = 0;
    while(ll < len)
    {
        blkptr = (unsigned char *)(myvhard + blkno * BLOCKSIZE);
        for(i = 0; i < BLOCKSIZE; i++)
            buf[i] = blkptr[i];
        for(; blkoff < BLOCKSIZE; blkoff++)
        {
            text[ll++] = buf[blkoff];
            openfilelist[fd].count++;
            if(ll == len || openfilelist[fd].count == openfilelist[fd].length)
                break;
        }
        if(ll < len && openfilelist[fd].count != openfilelist[fd].length)
        {
            blkno = fatptr->id;
            if(blkno == END)
                break;
            blkoff = 0;
            fatptr = fat1 + blkno;
        }
    }
    text[ll] = '\0';
    free(buf);
    return ll;
}
void my_exitsys()
{
    FILE *fp;
    while(curdir)
        curdir = my_close(curdir);
    fp = fopen(myfilename, "w");
    fwrite(myvhard, SIZE, 1, fp);
    fclose(fp);
    free(myvhard);
}
unsigned short findblock()
{
    unsigned short i;
	fat *fat1, *fatptr;
	fat1 = (fat *)(myvhard + BLOCKSIZE);
	for(i = 7; i < SIZE / BLOCKSIZE; i++)
	{
		fatptr = fat1 + i;
		if(fatptr->id == FREE)
			return i;
	}
	printf("Error,Can't find free block!\n");
	return -1;
}

int findopenfile()
{
    int i;
    for(i = 0; i < MAXTEXT; i++)
    {
        if(openfilelist[i].topenfile == 0)
            return i;
    }
    printf("Error,open too many files!\n");
    return -1;
}
int main()
{
    char cmd[15][10] = {"cd", "mkdir", "rmdir", "ls", "create", "rm", "open", "close", "write", "read", "exit"};
	char s[30], *sp;
	int cmdn, flag = 1, i;
	startsys();
	printf("*********************File System V1.0*******************************\n\n");
	printf("命令名\t\t命令參數\t\t命令說明\n\n");
	printf("cd\t\t目錄名(路徑名)\t\t切換當前目錄到指定目錄\n");
	printf("mkdir\t\t目錄名\t\t\t在當前目錄創建新目錄\n");
	printf("rmdir\t\t目錄名\t\t\t在當前目錄刪除指定目錄\n");
	printf("ls\t\t無\t\t\t顯示當前目錄下的目錄和文件\n");
	printf("create\t\t文件名\t\t\t在當前目錄下創建指定文件\n");
	printf("rm\t\t文件名\t\t\t在當前目錄下刪除指定文件\n");
	printf("open\t\t文件名\t\t\t在當前目錄下打開指定文件\n");
	printf("write\t\t無\t\t\t在打開文件狀態下,寫該文件\n");
	printf("read\t\t無\t\t\t在打開文件狀態下,讀取該文件\n");
	printf("close\t\t無\t\t\t在打開文件狀態下,讀取該文件\n");
	printf("exit\t\t無\t\t\t退出系統\n\n");
	printf("*********************************************************************\n\n");
	while(flag)
	{
		printf("%s>", openfilelist[curdir].dir);
		gets(s);
		cmdn = -1;
		if(strcmp(s, ""))
		{
			sp=strtok(s, " ");
			for(i = 0; i < 15; i++)
			{
				if(strcmp(sp, cmd[i]) == 0)
				{
					cmdn = i;
					break;
				}
			}
//			printf("%d\n", cmdn);
			switch(cmdn)
			{
                case 0:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                        my_cd(sp);
                    else
                        printf("Please input the right command.\n");
                    break;
                case 1:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                        my_mkdir(sp);
                    else
                        printf("Please input the right command.\n");
                    break;
					case 2:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                        my_rmdir(sp);
                    else
                        printf("Please input the right command.\n");
                    break;
                case 3:
                    if(openfilelist[curdir].attribute & 0x20)
                        my_ls();
                    else
                        printf("Please input the right command.\n");
                    break;
                case 4:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                        my_create(sp);
                    else
                        printf("Please input the right command.\n");
                    break;
                case 5:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                        my_rm(sp);
                    else
                        printf("Please input the right command.\n");
                    break;
					case 6:
                    sp = strtok(NULL, " ");
                    if(sp && (openfilelist[curdir].attribute & 0x20))
                    {
                        if(strchr(sp, '.'))//查找sp中'.'首次出現的位置
                            curdir = my_open(sp);
                        else
                            printf("the openfile should have exname.\n");
                    }
                    else
                        printf("Please input the right command.\n");
                    break;
                case 7:
                    if(!(openfilelist[curdir].attribute & 0x20))
                        curdir = my_close(curdir);
                    else
                        printf("No files opened.\n");
                    break;
                case 8:
                    if(!(openfilelist[curdir].attribute & 0x20))
                        my_write(curdir);
                    else
                        printf("No files opened.\n");
                    break;
                case 9:
                    if(!(openfilelist[curdir].attribute & 0x20))
                        my_read(curdir, openfilelist[curdir].length);
                    else
                        printf("No files opened.\n");
                    break;
					case 10:
                    if(openfilelist[curdir].attribute & 0x20)
                    {
                        my_exitsys();
                        flag = 0;
                    }
                    else
                        printf("Please input the right command.\n");
                    break;
                default:
                    printf("Please input the right command.\n");
                    break;
			}
		}
	}
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章