📄 fat.c
字号:
return 0;}static int update_short_entry( struct fat_file* file, int size, int attr ){ unsigned char buf[SECTOR_SIZE]; int sector = file->direntry / DIR_ENTRIES_PER_SECTOR; unsigned char* entry = buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR); unsigned int* sizeptr; unsigned short* clusptr; struct fat_file dir; int rc; LDEBUGF("update_file_size(cluster:%x entry:%d size:%d)\n", file->firstcluster, file->direntry, size); /* create a temporary file handle for the dir holding this file */ rc = fat_open(file->dircluster, &dir, NULL); if (rc < 0) return rc * 10 - 1; rc = fat_seek( &dir, sector ); if (rc<0) return rc * 10 - 2; rc = fat_readwrite(&dir, 1, buf, false); if (rc < 1) return rc * 10 - 3; if (!entry[0] || entry[0] == 0xe5) panicf("Updating size on empty dir entry %d\n", file->direntry); entry[FATDIR_ATTR] = attr & 0xFF; clusptr = (short*)(entry + FATDIR_FSTCLUSHI); *clusptr = SWAB16(file->firstcluster >> 16); clusptr = (short*)(entry + FATDIR_FSTCLUSLO); *clusptr = SWAB16(file->firstcluster & 0xffff); sizeptr = (int*)(entry + FATDIR_FILESIZE); *sizeptr = SWAB32(size); {#ifdef HAVE_RTC unsigned short time = 0; unsigned short date = 0;#else /* get old time to increment from */ unsigned short time = SWAB16(*(unsigned short*)(entry + FATDIR_WRTTIME)); unsigned short date = SWAB16(*(unsigned short*)(entry + FATDIR_WRTDATE));#endif fat_time(&date, &time, NULL); *(unsigned short*)(entry + FATDIR_WRTTIME) = SWAB16(time); *(unsigned short*)(entry + FATDIR_WRTDATE) = SWAB16(date); *(unsigned short*)(entry + FATDIR_LSTACCDATE) = SWAB16(date); } rc = fat_seek( &dir, sector ); if (rc < 0) return rc * 10 - 4; rc = fat_readwrite(&dir, 1, buf, true); if (rc < 1) return rc * 10 - 5; return 0;}static int parse_direntry(struct fat_direntry *de, unsigned char *buf){ int i=0,j=0; memset(de, 0, sizeof(struct fat_direntry)); de->attr = buf[FATDIR_ATTR]; de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; de->crtdate = BYTES2INT16(buf,FATDIR_CRTDATE); de->crttime = BYTES2INT16(buf,FATDIR_CRTTIME); de->wrtdate = BYTES2INT16(buf,FATDIR_WRTDATE); de->wrttime = BYTES2INT16(buf,FATDIR_WRTTIME); de->filesize = BYTES2INT32(buf,FATDIR_FILESIZE); de->firstcluster = BYTES2INT16(buf,FATDIR_FSTCLUSLO) | (BYTES2INT16(buf,FATDIR_FSTCLUSHI) << 16); /* fix the name */ for (i=0; (i<8) && (buf[FATDIR_NAME+i] != ' '); i++) de->name[j++] = buf[FATDIR_NAME+i]; if ( buf[FATDIR_NAME+8] != ' ' ) { de->name[j++] = '.'; for (i=8; (i<11) && (buf[FATDIR_NAME+i] != ' '); i++) de->name[j++] = buf[FATDIR_NAME+i]; } return 1;}int fat_open(unsigned int startcluster, struct fat_file *file, struct fat_dir* dir){ file->firstcluster = startcluster; file->lastcluster = startcluster; file->lastsector = 0; file->clusternum = 0; file->sectornum = 0; file->eof = false; /* remember where the file's dir entry is located */ if ( dir ) { file->direntry = dir->entry - 1; file->direntries = dir->entrycount; file->dircluster = dir->file.firstcluster; } LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); return 0;}int fat_create_file(char* name, struct fat_file* file, struct fat_dir* dir){ int rc; LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir); rc = add_dir_entry(dir, file, name, false, false); if (!rc) { file->firstcluster = 0; file->lastcluster = 0; file->lastsector = 0; file->clusternum = 0; file->sectornum = 0; file->eof = false; } return rc;}int fat_create_dir(char* name, struct fat_dir* newdir, struct fat_dir* dir){ unsigned char buf[SECTOR_SIZE]; int i; int sector; int rc; struct fat_file dummyfile; LDEBUGF("fat_create_dir(\"%s\",%x,%x)\n",name,newdir,dir); memset(newdir, 0, sizeof(struct fat_dir)); memset(&dummyfile, 0, sizeof(struct fat_file)); /* First, add the entry in the parent directory */ rc = add_dir_entry(dir, &newdir->file, name, true, false); if (rc < 0) return rc * 10 - 1; /* Allocate a new cluster for the directory */ newdir->file.firstcluster = find_free_cluster(fat_bpb.fsinfo.nextfree); if(newdir->file.firstcluster == 0) return -1; update_fat_entry(newdir->file.firstcluster, FAT_EOF_MARK); /* Clear the entire cluster */ memset(buf, 0, sizeof buf); sector = cluster2sec(newdir->file.firstcluster); for(i = 0;i < (int)fat_bpb.bpb_secperclus;i++) { rc = transfer( sector + fat_bpb.startsector + i, 1, buf, true ); if (rc < 0) return rc * 10 - 2; } /* Then add the "." entry */ rc = add_dir_entry(newdir, &dummyfile, ".", true, true); if (rc < 0) return rc * 10 - 3; dummyfile.firstcluster = newdir->file.firstcluster; update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY); /* and the ".." entry */ rc = add_dir_entry(newdir, &dummyfile, "..", true, true); if (rc < 0) return rc * 10 - 4; /* The root cluster is cluster 0 in the ".." entry */ if(dir->file.firstcluster == fat_bpb.bpb_rootclus) dummyfile.firstcluster = 0; else dummyfile.firstcluster = dir->file.firstcluster; update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY); /* Set the firstcluster field in the direntry */ update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY); rc = flush_fat(); if (rc < 0) return rc * 10 - 5; return rc;}int fat_truncate(struct fat_file *file){ /* truncate trailing clusters */ int next; int last = file->lastcluster; LDEBUGF("fat_truncate(%x, %x)\n", file->firstcluster, last); for ( last = get_next_cluster(last); last; last = next ) { next = get_next_cluster(last); update_fat_entry(last,0); } if (file->lastcluster) update_fat_entry(file->lastcluster,FAT_EOF_MARK); return 0;}int fat_closewrite(struct fat_file *file, int size, int attr){ int rc; LDEBUGF("fat_closewrite(size=%d)\n",size); if (!size) { /* empty file */ if ( file->firstcluster ) { update_fat_entry(file->firstcluster, 0); file->firstcluster = 0; } } if (file->dircluster) { rc = update_short_entry(file, size, attr); if (rc < 0) return rc * 10 - 1; } flush_fat();#ifdef TEST_FAT if ( file->firstcluster ) { /* debug */ int count = 0; int len; int next; for ( next = file->firstcluster; next; next = get_next_cluster(next) ) LDEBUGF("cluster %d: %x\n", count++, next); len = count * fat_bpb.bpb_secperclus * SECTOR_SIZE; LDEBUGF("File is %d clusters (chainlen=%d, size=%d)\n", count, len, size ); if ( len > size + fat_bpb.bpb_secperclus * SECTOR_SIZE) panicf("Cluster chain is too long\n"); if ( len < size ) panicf("Cluster chain is too short\n"); }#endif return 0;}static int free_direntries(int dircluster, int startentry, int numentries){ unsigned char buf[SECTOR_SIZE]; struct fat_file dir; unsigned int entry = startentry - numentries + 1; unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; int i; int rc; /* create a temporary file handle for the dir holding this file */ rc = fat_open(dircluster, &dir, NULL); if (rc < 0) return rc * 10 - 1; rc = fat_seek( &dir, sector ); if (rc < 0) return rc * 10 - 2; rc = fat_readwrite(&dir, 1, buf, false); if (rc < 1) return rc * 10 - 3; for (i=0; i < numentries; i++) { LDEBUGF("Clearing dir entry %d (%d/%d)\n", entry, i+1, numentries); buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; entry++; if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { /* flush this sector */ rc = fat_seek(&dir, sector); if (rc < 0) return rc * 10 - 4; rc = fat_readwrite(&dir, 1, buf, true); if (rc < 1) return rc * 10 - 5; if ( i+1 < numentries ) { /* read next sector */ rc = fat_readwrite(&dir, 1, buf, false); if (rc < 1) return rc * 10 - 6; } sector++; } } if ( entry % DIR_ENTRIES_PER_SECTOR ) { /* flush this sector */ rc = fat_seek(&dir, sector); if (rc < 0) return rc * 10 - 7; rc = fat_readwrite(&dir, 1, buf, true); if (rc < 1) return rc * 10 - 8; } return 0;}int fat_remove(struct fat_file* file){ int next, last = file->firstcluster; int rc; LDEBUGF("fat_remove(%x)\n",last); while ( last ) { next = get_next_cluster(last); update_fat_entry(last,0); last = next; } if ( file->dircluster ) { rc = free_direntries(file->dircluster, file->direntry, file->direntries); if (rc < 0) return rc * 10 - 1; } file->firstcluster = 0; file->dircluster = 0; return 0;}int fat_rename(struct fat_file* file, unsigned char* newname, int size, int attr){ int rc; struct fat_dir dir; struct fat_file newfile = *file; if ( !file->dircluster ) { DEBUGF("File has no dir cluster!\n"); return -1; } /* create a temporary file handle */ rc = fat_opendir(&dir, file->dircluster); if (rc < 0) return rc * 10 - 2; /* create new name */ rc = add_dir_entry(&dir, &newfile, newname, false, false); if (rc < 0) return rc * 10 - 3; /* write size and cluster link */ rc = update_short_entry(&newfile, size, attr); if (rc < 0) return rc * 10 - 4; /* remove old name */ rc = free_direntries(file->dircluster, file->direntry, file->direntries); if (rc < 0) return rc * 10 - 5; rc = flush_fat(); if (rc < 0) return rc * 10 - 6; return 0;}static int next_write_cluster(struct fat_file* file, int oldcluster, int* newsector){ int cluster = 0; int sector;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -