#include #include "type-def.h" BOOT_AREA boot; CURR_DIR cwd; FAT_ENTRY *FAT; OPEN_FILE open_file_table[MAX_OPEN_FILES]; extern int verbose; void initFileSystem() { char buf[BLOCK_SIZE]; int i; boot.block_size = BLOCK_SIZE; boot.file_system_size = NUM_BLOCKS; boot.fat_size = (NUM_BLOCKS*sizeof(FAT_ENTRY) + BLOCK_SIZE - 1) / BLOCK_SIZE; boot.first_data_block = boot.fat_size + 1; /* Initialize the FAT table */ /* This is the in-memory version of the FAT table */ FAT = (FAT_ENTRY *)malloc(boot.fat_size * boot.block_size); for(i=boot.first_data_block; i < boot.file_system_size; i++) FAT[i] = FREE_BLOCK_FLAG; for (i=1; i <= boot.fat_size; i++) { dWrite(i, &(FAT[(i-1)*BLOCK_SIZE/sizeof(FAT_ENTRY)])); } /* Initialize the "/", which is empty */ boot.root_dir_block = boot.first_data_block; boot.root_dir_size = 0; FAT[boot.root_dir_block] = END_BLOCK_FLAG; for (i=0; i < boot.block_size; i++) { buf[i] = 0; } dWrite(boot.root_dir_block, buf); /* Initialize the current working directory */ strcpy(cwd.path,"/"); cwd.size = boot.root_dir_size; /* In theory, we need to load the data from the disk */ cwd.nentries = 0; cwd.entries = (FILE_DIR_ENTRY *)NULL; cwd.updated_flag = 0; /* Initialize the open file table */ for (i=0; i < MAX_OPEN_FILES; i++) { open_file_table[i].flag = OPEN_SLOT_FREE; } if (verbose >= 1) { printf("Block size: %d\n", boot.block_size); printf("File system size: %d blocks.\n", boot.file_system_size); printf("FAT table size: %d blocks.\n", boot.fat_size); printf("First data block is %d\n", boot.first_data_block); printf("The root directory is at %d with size %d.\n", boot.root_dir_block, boot.root_dir_size); } return; } int fLs() { /* List all the files and subdirectories under the current working directory */ int i; printf("Files and subdirectories under %s\n",cwd.path); for (i=0; i < cwd.nentries; i++) { printf("\t"); if (cwd.entries[i].attribute & IS_DIR_FLAG) { printf("Directory"); } else { printf("File"); } printf(" %s %d ", cwd.entries[i].fname, cwd.entries[i].size); printf("%s", ctime(&(cwd.entries[i].timestamp))); } return cwd.nentries; } char *Get_Pwd() { return (char *)cwd.path; } void Print_FAT() { int i; printf("The FAT table (excluding the FREE blocks) is given below.\n"); printf("\tBlock 0: reserved for file system descriptor.\n"); printf("\tBlocks 1-%d: used for file allocation table.\n",boot.fat_size); for (i = boot.first_data_block; i < boot.file_system_size; i ++) { if (FAT[i] != FREE_BLOCK_FLAG) { printf("\tBlock %d: ", i); if (FAT[i] == END_BLOCK_FLAG) printf("End of file flag\n"); else printf("%d\n", FAT[i]); } } return; } int fOpen(char *name) { int i, open_slot; int free_block; /* First find an empty slot in the open file table */ for (i=0; i < MAX_OPEN_FILES; i++) { if (open_file_table[i].flag == OPEN_SLOT_FREE) { break; } } if (i >= MAX_OPEN_FILES) { fprintf(stderr,"No open file slot available. "); fprintf(stderr,"Please close some files.\n"); return ERROR; } open_slot = i; /* Now check if the file exists or not */ for (i=0; i < cwd.nentries; i++) { if (strcmp(cwd.entries[i].fname, name)==0) { break; } } if (i >= cwd.nentries) { FILE_DIR_ENTRY afile; struct timeval tp; for (free_block = boot.first_data_block; free_block < boot.file_system_size; free_block ++) { if (FAT[free_block] == FREE_BLOCK_FLAG) { break; } } if (free_block >= boot.file_system_size) { fprintf(stderr,"Cannot find a free block for a new file \"%s\"\n", name); return ERROR; } strcpy(afile.fname,name); afile.attribute = 0; afile.start_block = free_block; FAT[free_block] = END_BLOCK_FLAG; gettimeofday(&tp, (void *)NULL); afile.timestamp = tp.tv_sec; afile.size = 0; i = Add_Entry_ToDir(&cwd, &afile); } open_file_table[open_slot].pos = 0; open_file_table[open_slot].curr_block_pos = 0; open_file_table[open_slot].start_block = cwd.entries[i].start_block; open_file_table[open_slot].curr_block = cwd.entries[i].start_block; open_file_table[open_slot].size = cwd.entries[i].size; open_file_table[open_slot].flag = OPEN_SLOT_USED; /* if the file does not exist, we need to create a file by 1. Find a free block 2. Initialize the FILE_DIR_ENTRY 3. Add to the cwd */ /* At this time, the file should exist and update and initialize the open file slot */ return open_slot; } int fClose(int fileID) { if ( (fileID < 0) || (fileID >= MAX_OPEN_FILES) ) return ERROR; if (open_file_table[fileID].flag != OPEN_SLOT_USED) { return ERROR; } /* This depends on whether you implement buffering or not */ open_file_table[fileID].flag = OPEN_SLOT_FREE; return NO_ERROR; } int fRead(int fileID, char *buffer, int length) { /* Do the error checking first */ /* Use a while loop to read blocks until necessary */ /* Note that buffering can be used to reduce reading from the disk */ /* You also need to update and corresponding attributes */ } /* Note here we assume that position is relative to the beginning of the file */ int fSeek(int fileID, int position) { /* Check the position of the open file and update other fields */ if ( (fileID < 0) || (fileID >= MAX_OPEN_FILES) ) return ERROR; if (position >= open_file_table[fileID].size) { fprintf(stderr,"Cannot go beyond the file limit (%d).\n", open_file_table[fileID].size); return ERROR; } if (position == open_file_table[fileID].pos) { return NO_ERROR; } if (position < 0) return NO_ERROR; /* Otherwise, we need to change the pos and update curr_block and curr_block_pos */ open_file_table[fileID].pos = position; open_file_table[fileID].curr_block_pos = position; open_file_table[fileID].curr_block = open_file_table[fileID].start_block; while (open_file_table[fileID].curr_block_pos >= BLOCK_SIZE) { open_file_table[fileID].curr_block = FAT[open_file_table[fileID].curr_block]; if (open_file_table[fileID].curr_block == END_BLOCK_FLAG) { open_file_table[fileID].pos = 0; open_file_table[fileID].curr_block_pos = 0; open_file_table[fileID].curr_block = open_file_table[fileID].start_block; fprintf(stderr,"Something wrong with the file structure.\n"); return ERROR; } open_file_table[fileID].curr_block_pos -= BLOCK_SIZE; } return NO_ERROR; } int fMkdir(char *name) { /* Add a directory entropy in CWD similar as creating a file */ FILE_DIR_ENTRY afile; int free_block; int i; struct timeval tp; for (free_block = boot.first_data_block; free_block < boot.file_system_size; free_block ++) { if (FAT[free_block] == FREE_BLOCK_FLAG) { break; } } if (free_block >= boot.file_system_size) { fprintf(stderr,"Cannot find a free block for a new directory \"%s\"\n", name); return ERROR; } for (i=0; i < cwd.nentries; i++) { if (strcmp(cwd.entries[i].fname, name)==0) { break; } } if (i < cwd.nentries) { fprintf(stderr,"A file or directory with the same name "); fprintf(stderr,"(\"%s\") has existed already.\n", cwd.entries[i].fname); return ERROR; } strcpy(afile.fname,name); afile.attribute = 0; afile.attribute |= IS_DIR_FLAG; afile.start_block = free_block; FAT[free_block] = END_BLOCK_FLAG; gettimeofday(&tp, (void *)NULL); afile.timestamp = tp.tv_sec; afile.size = 0; Add_Entry_ToDir(&cwd, &afile); return NO_ERROR; } int fWrite(int fileID, char *buffer, int length) { /* Similar to reading but need to update size and write to the virtual disk */ } int fCd(char *name) { } int Add_Entry_ToDir(CURR_DIR *adir, FILE_DIR_ENTRY *anentry) { int i, j; FILE_DIR_ENTRY *tmp; tmp = adir->entries; adir->size += sizeof(FILE_DIR_ENTRY); adir->entries = (FILE_DIR_ENTRY *)malloc(sizeof(FILE_DIR_ENTRY) * (adir->nentries+1)); if (adir->nentries > 0) { for (i=0; i < adir->nentries; i++) { adir->entries[i] = tmp[i]; } free(tmp); } adir->entries[adir->nentries] = *anentry; adir->nentries++; adir->updated_flag = 1; return (int)(adir->nentries-1); }