📄 filesys.c.bak
字号:
/* here we only deal with 8 byte file name length */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include "filesys.h"#define DEBUG#define RevByte(low,high) ((high) << 8 | (low))#define RevWord(lowest,lower,higher,highest) ((highest) << 24 | (higher) << 16 | (lower) << 8 | lowest)struct BootDescriptor_t bdptor;struct Entry *curdir = NULL;int fd;unsigned char fatbuf[0x1200];void ScanBootSector(){ unsigned char buf[SECTOR_SIZE]; /* Attention to type */ int ret,i; if ((ret = read(fd,buf,SECTOR_SIZE)) < 0) perror("read boot sector failed"); for (i = 0; i <= 10; i++) bdptor.Oem_name[i] = buf[i+0x03]; bdptor.Oem_name[i] = '\0'; bdptor.BytesPerSector = RevByte(buf[0x0b],buf[0x0c]); bdptor.SectorsPerCluster= buf[0x0d]; bdptor.ReservedSectors = RevByte(buf[0x0e],buf[0x0f]); bdptor.FATs = buf[0x10]; bdptor.RootDirEntries = RevByte(buf[0x11],buf[0x12]); bdptor.LogicSectors = RevByte(buf[0x13],buf[0x14]); bdptor.MediaType = buf[0x15]; bdptor.SectorsPerFAT = RevByte(buf[0x16],buf[0x17]); bdptor.SectorsPerTrack = RevByte(buf[0x18],buf[0x19]); bdptor.Heads = RevByte(buf[0x1a],buf[0x1b]); bdptor.HiddenSectors = RevByte(buf[0x1c],buf[0x1d]);#ifdef DEBUG printf("Oem_name \t\t%s\n" "BytesPerSecotr \t\t%d\n" "SectorsPerCluster \t%d\n" "ReservedSectors \t%d\n" "FATs \t\t\t%d\n" "RootDirEntries \t\t%d\n" "LogicSectors \t\t%d\n" "MediaType \t\t%x\n" "SectorsPerFAT \t\t%d\n" "SectorsPerTrack \t%d\n" "Heads \t\t\t%d\n" "HiddenSectors \t\t%d\n", bdptor.Oem_name, bdptor.BytesPerSector, bdptor.SectorsPerCluster, bdptor.ReservedSectors, bdptor.FATs, bdptor.RootDirEntries, bdptor.LogicSectors, bdptor.MediaType, bdptor.SectorsPerFAT, bdptor.SectorsPerTrack, bdptor.Heads, bdptor.HiddenSectors);#endif}void findDate(unsigned short *year, unsigned short *month, unsigned short *day, unsigned char info[2]){ int date; date = RevByte(info[0],info[1]); *year = ((date & MASK_YEAR) >> 9) + 1980; *month = (date & MASK_MONTH) >> 5; *day = (date & MASK_DAY);}void findTime(unsigned short *hour, unsigned short *min, unsigned short *sec, unsigned char info[2]){ int time; time = RevByte(info[0],info[1]); // printf("time %x\n",time); *hour = (time & MASK_HOUR) >> 11; *min = (time & MASK_MIN) >> 5; *sec = (time & MASK_SEC) * 2;}/* bug for fix */void FileNameFormat_old(unsigned char *name){ unsigned char *q,*k,filename[12]; q = name; k = name; while (*q != ' ') q++; *q = '\0'; strcpy(filename,k); /* name */ *q = ' '; strcat(filename,"."); while (*q == ' ') q++; k = q; strcat(filename,k); /* extension */ strcpy(name,filename);}void FileNameFormat(unsigned char *name){ unsigned char *p; /* stripp the traling space */ p = name + strlen(name) - 1; while (*p == ' ') p--; p++; *p = '\0';}/* * Function : scan root dir entry */void ScanRootEntry(){ struct Entry entry; int ret,offset; if ((ret = lseek(fd,ROOTDIR_OFFSET,SEEK_SET)) < 0) perror("lseek ROOTDIR_OFFSET failed"); offset = ROOTDIR_OFFSET; while (offset < DATA_OFFSET) { ret = GetEntry(&entry); offset += abs(ret); if (ret > 0) { printf("%12s\t" "%d:%d:%d\t " "%d:%d:%d\t " "%d\t " "%d\t\t " "%s\n", entry.short_name, entry.year, entry.month, entry.day, entry.hour, entry.min, entry.sec, entry.size, entry.FirstCluster, (entry.subdir) ? "dir" : "file"); } }}/* Argument : entry, Type : struct Entry * * Return : offset for success, -count for fail or no entry * Function : get entry from cluster or root dir * Comment : One Entry maybe 32,64,96 Bytes */int GetEntry(struct Entry *pentry){ int ret,i; int count = 0; unsigned char buf[DIR_ENTRY_SIZE],info[2]; /* read 32 Bytes */ if ((ret = read(fd,buf,DIR_ENTRY_SIZE)) < 0) perror("read entry failed"); count += ret; if (buf[0] == 0xe5 || buf[0] == 0x00) /* not used or deleted entry */ return -1*count; else { while (buf[11] == 0x0f) { /* long file name entry, skip it */ if ((ret = read(fd,buf,DIR_ENTRY_SIZE)) < 0) perror("read root dir failed"); count += ret; } /* valid entry */ for (i = 0; i <= 10; i++) pentry->short_name[i] = buf[i]; pentry->short_name[i] = '\0'; FileNameFormat(pentry->short_name); info[0] = buf[22]; info[1] = buf[23]; findTime(&(pentry->hour),&(pentry->min),&(pentry->sec),info); info[0] = buf[24]; info[1] = buf[25]; findDate(&(pentry->year),&(pentry->month),&(pentry->day),info); pentry->FirstCluster = RevByte(buf[26],buf[27]); pentry->size = RevWord(buf[28],buf[29],buf[30],buf[31]); pentry->readonly = (buf[11] & ATTR_READONLY) ? 1 : 0; pentry->hidden = (buf[11] & ATTR_HIDDEN) ? 1 : 0; pentry->system = (buf[11] & ATTR_SYSTEM) ? 1 : 0; pentry->vlabel = (buf[11] & ATTR_VLABEL) ? 1 : 0; pentry->subdir = (buf[11] & ATTR_SUBDIR) ? 1 : 0; pentry->archive = (buf[11] & ATTR_ARCHIVE) ? 1 : 0; return count; }}/* * Function : list current dir contents * Return : 1 for success, -1 for fail */int fd_ls(){ int ret,offset,cluster_addr; struct Entry entry; /* Header */ printf("\tname\tdate\t\t time\t\tsector\tsize\t\tattr\n"); if (curdir == NULL) { /* print root dir */ ScanRootEntry(fd); } else { /* subdir start address,here only read one sector,ignore fat */ cluster_addr = DATA_OFFSET + (curdir->FirstCluster - 2) * SECTOR_SIZE; if ((ret = lseek(fd,cluster_addr,SEEK_SET)) < 0) perror("lseek cluster_addr failed"); offset = cluster_addr; while (offset < cluster_addr + SECTOR_SIZE) { ret = GetEntry(&entry); offset += abs(ret); if (ret > 0) { printf("%12s\t" "%d:%d:%d\t " "%d:%d:%d\t " "%d\t " "%d\t\t" "%s\n", entry.short_name, entry.year, entry.month, entry.day, entry.hour, entry.min, entry.sec, entry.size, entry.FirstCluster, (entry.subdir) ? "dir" : "file"); } } } return 0;}/* Argument : entryname, Type : char * * : pentry, Type : struct Entry* * : mode, Type : int, mode=1 for dir; mode=0 for file * Return : offset( >0 ) if success or -1 if failed * Function : scan current dir for the entry, file or dir */int ScanEntry(char *entryname,struct Entry *pentry,int mode){ int ret,offset,i; int cluster_addr; char uppername[80]; for (i = 0; i < strlen(entryname); i++) uppername[i] = toupper(entryname[i]); uppername[i] = '\0'; if (curdir == NULL) { /* scan in root dir */ if ((ret = lseek(fd,ROOTDIR_OFFSET,SEEK_SET)) < 0) perror("lseek ROOTDIR_OFFSET failed"); offset = ROOTDIR_OFFSET; while (offset < DATA_OFFSET) { ret = GetEntry(pentry); offset += abs(ret); if (pentry->subdir == mode && !strcmp(pentry->short_name,uppername)) return offset; } /* no entry for entryname */ return -1; } else { /* scan in non-root dir , bug cd .. not support */ cluster_addr = DATA_OFFSET + (curdir->FirstCluster - 2) * SECTOR_SIZE; if ((ret = lseek(fd,cluster_addr,SEEK_SET)) < 0) perror("lseek cluster_addr failed"); offset = cluster_addr; while (offset < cluster_addr + SECTOR_SIZE) { ret = GetEntry(pentry); offset += abs(ret); if (pentry->subdir == mode && !strcmp(pentry->short_name,uppername)) return offset; } /* no entry for entryname */ return -1; }}/* Argument : dir, Type char * * Return : 1 if success, or -1 if failed * Function : change dir to parent dir or subdir * e.g "cd .." or "cd subdir", full path not support */int fd_cd(char *dir){ struct Entry *pentry; int ret; if (!strcmp(dir,".")) /* cd . */ return 1; if (!strcmp(dir,"..") && curdir == NULL) return 1; pentry = (struct Entry*)malloc(sizeof(struct Entry)); /* scan current dir for the name of parent dir */ ret = ScanEntry(dir,pentry,1); if (ret < 0) { printf("no such dir\n"); free(pentry); return -1; } free(curdir); curdir = pentry;#ifdef DEBUG/* printf("%12s\t" *//* "%d:%d:%d\t " *//* "%d:%d:%d\t " *//* "%d\t " *//* "%d\t\t " *//* "%s\n", *//* pentry->short_name, *//* pentry->year, pentry->month, pentry->day, *//* pentry->hour, pentry->min, pentry->sec, *//* pentry->size, *//* pentry->FirstCluster, *//* (pentry->subdir) ? "dir" : "file"); */ #endif return 1;}/* Argument : prev, Type unsigned short, previous cluster number * Return : next cluster * Function : get next cluster in fat */unsigned short GetFatCluster(unsigned short prev){ unsigned short next,fatentry; int index; index = prev * 1.5; fatentry = RevByte(fatbuf[index],fatbuf[index+1]); if (prev % 2 == 1) next = fatentry >> 4; else next = fatentry & 0x0fff; return next;}/* Argument : cluster, Type unsigned short, cluster number * Return : void * Function : clear the cluster in fat */void ClearFatCluster(unsigned short cluster){ int index; index = cluster * 1.5; if (cluster % 2 == 1) { fatbuf[index] &= 0x0f; fatbuf[index+1] &= 0x00; } else { fatbuf[index] &= 0x00; fatbuf[index+1] &= 0xf0; }}/* Argument : filename, Type char * * Return : 1 if success, or -1 if failed * Function : remove a file in current dir */int fd_rm(char *filename){ struct Entry *pentry; int ret; unsigned char c; unsigned short seed,next; pentry = (struct Entry*)malloc(sizeof(struct Entry)); /* scan current dir for the name of file */ ret = ScanEntry(filename,pentry,0); if (ret < 0) { printf("no such file\n"); free(pentry); return -1; } /* clear fat entry */ seed = pentry->FirstCluster; while ((next = GetFatCluster(seed)) != 0x0fff) { seed = next; ClearFatCluster(next); } ClearFatCluster(pentry->FirstCluster); /* clear dir entry */ c = 0xe5; if (lseek(fd,ret-0x40,SEEK_SET) < 0) perror("lseek fd_rm failed"); if (write(fd,&c,1) < 0) perror("write failed"); if (lseek(fd,ret-0x20,SEEK_SET) < 0) perror("lseek fd_rm failed"); if (write(fd,&c,1) < 0) perror("write failed"); free(pentry); /* write to fat */ if (WriteFat() < 0) exit(1); return 1;}int WriteFat(){ if (lseek(fd,FAT_ONE_OFFSET,SEEK_SET) < 0) { perror("lseek failed"); return -1; } if (write(fd,fatbuf,0x1200) < 0) { perror("read failed"); return -1; } if (lseek(fd,FAT_TWO_OFFSET,SEEK_SET) < 0) { perror("lseek failed"); return -1; } if (write(fd,fatbuf,0x1200) < 0) { perror("read failed"); return -1; } return 1;}int ReadFat(){ if (lseek(fd,FAT_ONE_OFFSET,SEEK_SET) < 0) { perror("lseek failed"); return -1; } if (read(fd,fatbuf,0x1200) < 0) { perror("read failed"); return -1; } return 1;} int main(){ if ((fd = open(DEVNAME,O_RDWR)) < 0) perror("open failed"); if (ReadFat() < 0) exit(1); /* test zero */ // ScanBootSector(); // ScanRootEntry(); /* test one */ // fd_cd("xxx"); /* test two */ // fd_ls(); /* test three */ //fd_rm("filesys"); close(fd); free(curdir); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -