📄 fat.c
字号:
LDEBUGF("next_write_cluster(%x,%x)\n",file->firstcluster, oldcluster); if (oldcluster) cluster = get_next_cluster(oldcluster); if (!cluster) { if (oldcluster) cluster = find_free_cluster(oldcluster+1); else cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); if (cluster) { if (oldcluster) update_fat_entry(oldcluster, cluster); else file->firstcluster = cluster; update_fat_entry(cluster, FAT_EOF_MARK); } else {#ifdef TEST_FAT if (fat_bpb.fsinfo.freecount>0) panicf("There is free space, but find_free_cluster() " "didn't find it!\n");#endif DEBUGF("next_write_cluster(): Disk full!\n"); return 0; } } sector = cluster2sec(cluster); if (sector<0) return 0; *newsector = sector; return cluster;}static int transfer( unsigned int start, int count, char* buf, bool write ){ int rc; LDEBUGF("transfer(s=%x, c=%x, %s)\n",start, count, write?"write":"read"); if (write) { if (start < fat_bpb.firstdatasector) panicf("Writing before data\n"); rc = ata_write_sectors(start, count, buf); } else rc = ata_read_sectors(start, count, buf); if (rc < 0) { DEBUGF( "transfer() - Couldn't %s sector %x" " (error code %d)\n", write ? "write":"read", start, rc); return rc; } return 0;}int fat_readwrite( struct fat_file *file, int sectorcount, void* buf, bool write ){ int cluster = file->lastcluster; int sector = file->lastsector; int clusternum = file->clusternum; int numsec = file->sectornum; bool eof = file->eof; int first=0, last=0; int i; int rc; LDEBUGF( "fat_readwrite(file:%x,count:0x%x,buf:%x,%s)\n", file->firstcluster,sectorcount,buf,write?"write":"read"); LDEBUGF( "fat_readwrite: sec=%x numsec=%d eof=%d\n", sector,numsec, eof?1:0); if ( eof && !write) return 0; /* find sequential sectors and write them all at once */ for (i=0; (i < sectorcount) && (sector > -1); i++ ) { numsec++; if ( numsec > (int)fat_bpb.bpb_secperclus || !cluster ) { int oldcluster = cluster; if (write) cluster = next_write_cluster(file, cluster, §or); else { cluster = get_next_cluster(cluster); sector = cluster2sec(cluster); } clusternum++; numsec=1; if (!cluster) { eof = true; if ( write ) { /* remember last cluster, in case we want to append to the file */ cluster = oldcluster; clusternum--; i = -1; /* Error code */ break; } } else eof = false; } else { if (sector) sector++; else { /* look up first sector of file */ sector = cluster2sec(file->firstcluster); numsec=1; } } if (!first) first = sector; if ( ((sector != first) && (sector != last+1)) || /* not sequential */ (last-first+1 == 256) ) { /* max 256 sectors per ata request */ int count = last - first + 1; rc = transfer( first + fat_bpb.startsector, count, buf, write ); if (rc < 0) return rc * 10 - 1; ((char*)buf) += count * SECTOR_SIZE; first = sector; } if ((i == sectorcount-1) && /* last sector requested */ (!eof)) { int count = sector - first + 1; rc = transfer( first + fat_bpb.startsector, count, buf, write ); if (rc < 0) return rc * 10 - 2; } last = sector; } file->lastcluster = cluster; file->lastsector = sector; file->clusternum = clusternum; file->sectornum = numsec; file->eof = eof; /* if eof, don't report last block as read/written */ if (eof) i--; DEBUGF("Sectors written: %d\n", i); return i;}int fat_seek(struct fat_file *file, unsigned int seeksector ){ int clusternum=0, numclusters=0, sectornum=0, sector=0; int cluster = file->firstcluster; int i; file->eof = false; if (seeksector) { /* we need to find the sector BEFORE the requested, since the file struct stores the last accessed sector */ seeksector--; numclusters = clusternum = seeksector / fat_bpb.bpb_secperclus; sectornum = seeksector % fat_bpb.bpb_secperclus; if (file->clusternum && clusternum >= file->clusternum) { cluster = file->lastcluster; numclusters -= file->clusternum; } for (i=0; i<numclusters; i++) { cluster = get_next_cluster(cluster); if (!cluster) { DEBUGF("Seeking beyond the end of the file! " "(sector %d, cluster %d)\n", seeksector, i); return -1; } } sector = cluster2sec(cluster) + sectornum; } else { sectornum = -1; } LDEBUGF("fat_seek(%x, %x) == %x, %x, %x\n", file->firstcluster, seeksector, cluster, sector, sectornum); file->lastcluster = cluster; file->lastsector = sector; file->clusternum = clusternum; file->sectornum = sectornum + 1; return 0;}int fat_opendir(struct fat_dir *dir, unsigned int startcluster){ int rc; if (startcluster == 0) startcluster = sec2cluster(fat_bpb.rootdirsector); rc = fat_open(startcluster, &dir->file, NULL); if(rc) { DEBUGF( "fat_opendir() - Couldn't open dir" " (error code %d)\n", rc); return rc * 10 - 1; } dir->entry = 0; dir->sector = 0; return 0;}/* convert from unicode to a single-byte charset */static void unicode2iso(unsigned char* unicode, unsigned char* iso, int count ){ int i; for (i=0; i<count; i++) { int x = i*2; switch (unicode[x+1]) { case 0x01: /* latin extended. convert to ISO 8859-2 */ case 0x02: iso[i] = unicode2iso8859_2[unicode[x]]; break; case 0x03: /* greek, convert to ISO 8859-7 */ iso[i] = unicode[x] + 0x30; break; /* Sergei says most russians use Win1251, so we will too. Win1251 differs from ISO 8859-5 by an offset of 0x10. */ case 0x04: /* cyrillic, convert to Win1251 */ switch (unicode[x]) { case 1: iso[i] = 168; break; case 81: iso[i] = 184; break; default: iso[i] = unicode[x] + 0xb0; /* 0xa0 for ISO 8859-5 */ break; } break; case 0x05: /* hebrew, convert to ISO 8859-8 */ iso[i] = unicode[x] + 0x10; break; case 0x06: /* arabic, convert to ISO 8859-6 */ case 0x0e: /* thai, convert to ISO 8859-11 */ iso[i] = unicode[x] + 0xa0; break; default: iso[i] = unicode[x]; break; } }}int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry){ bool done = false; int i; int rc; unsigned char firstbyte; int longarray[20]; int longs=0; int sectoridx=0; unsigned char* cached_buf = dir->sectorcache[0]; dir->entrycount = 0; while(!done) { if ( !(dir->entry % DIR_ENTRIES_PER_SECTOR) || !dir->sector ) { rc = fat_readwrite(&dir->file, 1, cached_buf, false); if (rc == 0) { /* eof */ entry->name[0] = 0; break; } if (rc < 0) { DEBUGF( "fat_getnext() - Couldn't read dir" " (error code %d)\n", rc); return rc * 10 - 1; } dir->sector = dir->file.lastsector; } for (i = dir->entry % DIR_ENTRIES_PER_SECTOR; i < DIR_ENTRIES_PER_SECTOR; i++) { unsigned int entrypos = i * DIR_ENTRY_SIZE; firstbyte = cached_buf[entrypos]; dir->entry++; if (firstbyte == 0xe5) { /* free entry */ sectoridx = 0; dir->entrycount = 0; continue; } if (firstbyte == 0) { /* last entry */ entry->name[0] = 0; dir->entrycount = 0; return 0; } dir->entrycount++; /* longname entry? */ if ( ( cached_buf[entrypos + FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { longarray[longs++] = entrypos + sectoridx; } else { if ( parse_direntry(entry, &cached_buf[entrypos]) ) { /* don't return volume id entry */ if ( entry->attr == FAT_ATTR_VOLUME_ID ) continue; /* replace shortname with longname? */ if ( longs ) { int j,l=0; /* iterate backwards through the dir entries */ for (j=longs-1; j>=0; j--) { unsigned char* ptr = cached_buf; int index = longarray[j]; /* current or cached sector? */ if ( sectoridx >= SECTOR_SIZE ) { if ( sectoridx >= SECTOR_SIZE*2 ) { if ( ( index >= SECTOR_SIZE ) && ( index < SECTOR_SIZE*2 )) ptr = dir->sectorcache[1]; else ptr = dir->sectorcache[2]; } else { if ( index < SECTOR_SIZE ) ptr = dir->sectorcache[1]; } index &= SECTOR_SIZE-1; } /* names are stored in unicode, but we only grab the low byte (iso8859-1). */ unicode2iso(ptr + index + 1, entry->name + l, 5); l+= 5; unicode2iso(ptr + index + 14, entry->name + l, 6); l+= 6; unicode2iso(ptr + index + 28, entry->name + l, 2); l+= 2; } entry->name[l]=0; } done = true; sectoridx = 0; i++; break; } } } /* save this sector, for longname use */ if ( sectoridx ) memcpy( dir->sectorcache[2], dir->sectorcache[0], SECTOR_SIZE ); else memcpy( dir->sectorcache[1], dir->sectorcache[0], SECTOR_SIZE ); sectoridx += SECTOR_SIZE; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -