📄 fatlite.c
字号:
const void FAR0 *mappedSector;#endif buffer.sectorNo = sectorNo; buffer.owner = &vol; if(read) { /* Fixed a bug with no 3rd argument. EAN */ mappedSector = vol.tl.mapSector(vol.tl.rec,sectorNo,NULL); if(mappedSector) tffscpy(buffer.data,mappedSector,SECTOR_SIZE); else return flSectorNotFound; } else tffsset(buffer.data,0,SECTOR_SIZE); } buffer.dirty = TRUE; return flOK;}/*----------------------------------------------------------------------*//* f i r s t S e c t o r O f C l u s t e r *//* *//* Get sector no. corresponding to cluster no. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* cluster : Cluster no. *//* *//* Returns: *//* first sector no. of cluster *//*----------------------------------------------------------------------*/static SectorNo firstSectorOfCluster(Volume vol, unsigned cluster){ return(SectorNo) (cluster - 2) * vol.sectorsPerCluster + vol.firstDataSectorNo;}/*----------------------------------------------------------------------*//* g e t D i r E n t r y *//* *//* Get a read-only copy of a directory entry. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* file : File belonging to directory entry *//* *//* Returns: *//* dirEntry : Pointer to directory entry *//*----------------------------------------------------------------------*/static const DirectoryEntry FAR0 *getDirEntry(File *file){ return(DirectoryEntry FAR0 *) findSector(file->fileVol,file->directorySector) + file->directoryIndex;}/*----------------------------------------------------------------------*//* g e t D i r E n t r y F o r U p d a t e *//* *//* Read a directory sector into the sector buffer and point to an *//* entry, with the intention of modifying it. *//* The buffer will be flushed on operation exit. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* file : File belonging to directory entry *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//* dirEntry : Pointer to directory entry in buffer *//*----------------------------------------------------------------------*/static FLStatus getDirEntryForUpdate(File *file, DirectoryEntry * *dirEntry){ Volume vol = file->fileVol; checkStatus(updateSector(file->fileVol,file->directorySector,TRUE)); *dirEntry = directory + file->directoryIndex; buffer.checkPoint = TRUE; return flOK;}/*----------------------------------------------------------------------*//* s e t C u r r e n t D a t e T i m e *//* *//* Set current time/date in directory entry *//* *//* Parameters: *//* dirEntry : Pointer to directory entry *//* *//*----------------------------------------------------------------------*/static void setCurrentDateTime(DirectoryEntry *dirEntry){ toLE2(dirEntry->updateTime,flCurrentTime()); toLE2(dirEntry->updateDate,flCurrentDate());}/*----------------------------------------------------------------------*//* g e t F A T e n t r y *//* *//* Get an entry from the FAT. The 1st FAT copy is used. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* cluster : Cluster no. of enrty. *//* *//* Returns: *//* Value of FAT entry. *//*----------------------------------------------------------------------*/static unsigned getFATentry(Volume vol, unsigned cluster){ LEushort FAR0 *fat16Sector; unsigned fatSectorNo = vol.firstFATSectorNo;#ifdef FAT_12BIT if(vol.flags & VOLUME_12BIT_FAT) fatSectorNo += (cluster * 3) >> (SECTOR_SIZE_BITS + 1); else#endif fatSectorNo += cluster >> (SECTOR_SIZE_BITS - 1);#ifndef SINGLE_BUFFER if(!buffer.dirty) { /* If the buffer is free, use it to store this FAT sector */ updateSector(&vol,fatSectorNo,TRUE); buffer.dirty = FALSE; }#endif fat16Sector = (LEushort FAR0 *) findSector(&vol,fatSectorNo);#ifdef FAT_12BIT if(vol.flags & VOLUME_12BIT_FAT) { unsigned char FAR0 *fat12Sector = (unsigned char FAR0 *) fat16Sector; unsigned halfByteOffset = (cluster * 3) & (SECTOR_SIZE * 2 - 1); unsigned char firstByte = fat12Sector[halfByteOffset / 2]; halfByteOffset += 2; if(halfByteOffset >= SECTOR_SIZE * 2) { /* Entry continues on the next sector. What a mess */ halfByteOffset -= SECTOR_SIZE * 2; fat12Sector = (unsigned char FAR0 *) findSector(&vol,fatSectorNo + 1); } if(halfByteOffset & 1) return((firstByte & 0xf0) >> 4) + (fat12Sector[halfByteOffset / 2] << 4); else return firstByte + ((fat12Sector[halfByteOffset / 2] & 0xf) << 8); } else#endif return LE2(fat16Sector[cluster & (SECTOR_SIZE / 2 - 1)]);}/*----------------------------------------------------------------------*//* s e t F A T e n t r y *//* *//* Writes a new value to a given FAT cluster entry. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* cluster : Cluster no. of enrty. *//* entry : New value of FAT entry. *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus setFATentry(Volume vol, unsigned cluster, unsigned entry){ LEushort *fat16Sector; unsigned fatSectorNo = vol.firstFATSectorNo;#ifdef FAT_12BIT if(vol.flags & VOLUME_12BIT_FAT) fatSectorNo += (cluster * 3) >> (SECTOR_SIZE_BITS + 1); else#endif fatSectorNo += cluster >> (SECTOR_SIZE_BITS - 1); checkStatus(updateSector(&vol,fatSectorNo,TRUE)); fat16Sector = (LEushort *) buffer.data;#ifdef FAT_12BIT if(vol.flags & VOLUME_12BIT_FAT) { unsigned char *fat12Sector = (unsigned char *) buffer.data; unsigned halfByteOffset = (cluster * 3) & (SECTOR_SIZE * 2 - 1); if(halfByteOffset & 1) { fat12Sector[halfByteOffset / 2] &= 0xf; fat12Sector[halfByteOffset / 2] |= (entry & 0xf) << 4; } else fat12Sector[halfByteOffset / 2] = entry; halfByteOffset += 2; if(halfByteOffset >= SECTOR_SIZE * 2) { /* Entry continues on the next sector. What a mess */ halfByteOffset -= SECTOR_SIZE * 2; fatSectorNo++; checkStatus(updateSector(&vol,fatSectorNo,TRUE)); } if(halfByteOffset & 1) fat12Sector[halfByteOffset / 2] = entry >> 4; else { fat12Sector[halfByteOffset / 2] &= 0xf0; fat12Sector[halfByteOffset / 2] |= (entry & 0x0f00) >> 8; } } else#endif toLE2(fat16Sector[cluster & (SECTOR_SIZE / 2 - 1)],entry); return flOK;}/*----------------------------------------------------------------------*//* a l l o c a t e C l u s t e r *//* *//* Allocates a new cluster for a file and adds it to a FAT chain or *//* marks it in a directory entry. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* file : File to extend. It should be positioned at *//* end-of-file. *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus allocateCluster(File *file){ Volume vol = file->fileVol; unsigned originalRover; if(file->flags & FILE_READ_ONLY) return flNoWriteAccess; /* Look for a free cluster. Start at the allocation rover */ originalRover = vol.allocationRover; do { vol.allocationRover++; if(vol.allocationRover > vol.maxCluster) vol.allocationRover = 2; /* wraparound to start of volume */ if(vol.allocationRover == originalRover) return flNoSpaceInVolume; } while(getFATentry(&vol,vol.allocationRover) != FAT_FREE); /* Found a free cluster. Mark it as an end of chain */ checkStatus(setFATentry(&vol,vol.allocationRover,FAT_LAST_CLUSTER)); /* Mark previous cluster or directory to point to it */ if(file->currentCluster == 0) { DirectoryEntry *dirEntry; checkStatus(getDirEntryForUpdate(file,&dirEntry)); toLE2(dirEntry->startingCluster,vol.allocationRover); setCurrentDateTime(dirEntry); } else checkStatus(setFATentry(&vol,file->currentCluster,vol.allocationRover)); /* Set our new current cluster */ file->currentCluster = vol.allocationRover; return flOK;}/*----------------------------------------------------------------------*//* g e t S e c t o r A n d O f f s e t *//* *//* Based on the current position of a file, gets a sector number and *//* offset in the sector that marks the file's current position. *//* If the position is at the end-of-file, and the file is opened for *//* write, this routine will extend the file by allocating a new cluster.*//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus getSectorAndOffset(File *file, SectorNo *sectorNo, unsigned *offsetInSector){ Volume vol = file->fileVol; unsigned offsetInCluster = (unsigned) file->currentPosition & (vol.bytesPerCluster - 1); if(offsetInCluster == 0) { /* This cluster is finished. Get next */ if(file->flags & FILE_IS_ROOT_DIR) { if(file->currentPosition >= file->fileSize) return flRootDirectoryFull; } else { if(file->currentPosition >= file->fileSize) { checkStatus(allocateCluster(file)); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -