📄 fatlite.c
字号:
unsigned nextCluster; if(file->currentCluster == 0) nextCluster = LE2(getDirEntry(file)->startingCluster); else nextCluster = getFATentry(&vol,file->currentCluster); if(nextCluster < 2 || nextCluster > vol.maxCluster) /* We have a bad file size, or the FAT is bad */ return flInvalidFATchain; file->currentCluster = nextCluster; } } } *offsetInSector = offsetInCluster & (SECTOR_SIZE - 1); if(file->flags & FILE_IS_ROOT_DIR) *sectorNo = vol.rootDirectorySectorNo + (SectorNo) (file->currentPosition >> SECTOR_SIZE_BITS); else *sectorNo = firstSectorOfCluster(&vol,file->currentCluster) + (SectorNo) (offsetInCluster >> SECTOR_SIZE_BITS); return flOK;}/*----------------------------------------------------------------------*//* c l o s e F i l e *//* *//* Closes an open file, records file size and dates in directory and *//* releases file handle. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* file : File to close. *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus closeFile(File *file){ if((file->flags & FILE_MODIFIED) && !(file->flags & FILE_IS_ROOT_DIR)) { DirectoryEntry *dirEntry; checkStatus(getDirEntryForUpdate(file,&dirEntry)); dirEntry->attributes |= ATTR_ARCHIVE; if(!(file->flags & FILE_IS_DIRECTORY)) toLE4(dirEntry->fileSize,file->fileSize); setCurrentDateTime(dirEntry); } file->flags = 0; /* no longer open */ return flOK;}#ifdef SUB_DIRECTORY/*----------------------------------------------------------------------*//* e x t e n d D i r e c t o r y *//* *//* Extends a directory, writing empty entries and the mandatory '.' and *//* '..' entries. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* file : Directory file to extend. On entry, *//* currentPosition == fileSize. On exit, fileSize*//* is updated. *//* ownerDir : Cluster no. of owner directory *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus extendDirectory(File *file, unsigned ownerDir){ Volume vol = file->fileVol; unsigned i; SectorNo sectorOfDir; unsigned offsetInSector; /* Assuming the current position is at the end-of-file, this will */ /* extend the directory. */ checkStatus(getSectorAndOffset(file,§orOfDir,&offsetInSector)); for(i = 0; i < vol.sectorsPerCluster; i++) { /* Write binary zeroes to indicate never-used entries */ checkStatus(updateSector(&vol,sectorOfDir + i,FALSE)); buffer.checkPoint = TRUE; if(file->currentPosition == 0 && i == 0) { /* Add the mandatory . and .. entries */ tffscpy(directory[0].name,". ",sizeof directory[0].name); directory[0].attributes = ATTR_ARCHIVE | ATTR_DIRECTORY; toLE2(directory[0].startingCluster,file->currentCluster); toLE4(directory[0].fileSize,0); setCurrentDateTime(&directory[0]); tffscpy(&directory[1],&directory[0],sizeof directory[0]); directory[1].name[1] = '.'; /* change . to .. */ toLE2(directory[1].startingCluster,ownerDir); } file->fileSize += SECTOR_SIZE; } /* Update the parent directory by closing the file */ file->flags |= FILE_MODIFIED; return closeFile(file);}#endif /* SUB_DIRECTORY *//*----------------------------------------------------------------------*//* f i n d D i r E n t r y *//* *//* Finds a directory entry by path-name, or finds an available directory*//* entry if the file does not exist. *//* Most fields necessary for opening a file are set by this routine. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* path : path to find *//* file : File in which to record directory information.*//* Specific fields on entry: *//* flags: if FILE_MUST_OPEN = 1, directory *//* will be extended if necessary. *//* on exit: *//* flags: FILE_IS_DIRECTORY and *//* FILE_IS_ROOT_DIR set if true. *//* fileSize: Set for non-directory files. *//* currentCluster: Set to 0 (unknown) *//* ownerDirCluster: Set to 1st cluster of *//* owning directory. *//* directorySector: Sector of directory. If 0 *//* entry not found and directory full*//* directoryEntry: Entry # in directory sector *//* currentPosition: not set by this routine. *//* *//* Returns: *//* FLStatus : 0 on success and file found *//* flFileNotFound on success and file not found *//* otherwise failed. *//*----------------------------------------------------------------------*/static FLStatus findDirEntry(Volume vol, FLSimplePath FAR1 *path, File *file){ File scanFile; /* Internal file of search */ unsigned dirBackPointer = 0; /* 1st cluster of previous directory */ FLStatus status = flOK; /* root directory exists */ file->flags |= (FILE_IS_ROOT_DIR | FILE_IS_DIRECTORY); file->fileSize = (long) (vol.sectorsInRootDirectory) << SECTOR_SIZE_BITS; file->fileVol = &vol;#ifdef SUB_DIRECTORY for(; path->name[0]; path++) /* while we have another path segment */#else if(path->name[0]) /* search the root directory */#endif { status = flFileNotFound; /* not yet */ if(!(file->flags & FILE_IS_DIRECTORY)) return flPathNotFound; /* if we don't have a directory, we have no business here */ scanFile = *file; /* the previous file found becomes the scan file */ scanFile.currentPosition = 0; file->directorySector = 0; /* indicate no entry found yet */ file->flags &= ~(FILE_IS_ROOT_DIR | FILE_IS_DIRECTORY); file->ownerDirCluster = dirBackPointer; file->fileSize = 0; file->currentCluster = 0; /* Scan directory */ while(scanFile.currentPosition < scanFile.fileSize) { int i; DirectoryEntry FAR0 *dirEntry; SectorNo sectorOfDir; unsigned offsetInSector; FLStatus readStatus = getSectorAndOffset(&scanFile,§orOfDir,&offsetInSector); if(readStatus == flInvalidFATchain) { scanFile.fileSize = scanFile.currentPosition; /* now we know */ break; /* we ran into the end of the directory file */ } else if(readStatus != flOK) return readStatus; dirEntry = (DirectoryEntry FAR0 *) findSector(&vol,sectorOfDir); if(dirEntry == NULL) return flSectorNotFound; scanFile.currentPosition += SECTOR_SIZE; for(i = 0; i < DIRECTORY_ENTRIES_PER_SECTOR; i++, dirEntry++) { if(tffscmp(path,dirEntry->name,sizeof dirEntry->name) == 0 && !(dirEntry->attributes & ATTR_VOL_LABEL)) { /* Found a match */ file->directorySector = sectorOfDir; file->directoryIndex = i; file->fileSize = LE4(dirEntry->fileSize); if(dirEntry->attributes & ATTR_DIRECTORY) { file->flags |= FILE_IS_DIRECTORY; file->fileSize = 0x7fffffffl; /* Infinite. Directories don't have a recorded size */ } if(dirEntry->attributes & ATTR_READ_ONLY) file->flags |= FILE_READ_ONLY; dirBackPointer = LE2(dirEntry->startingCluster); status = flOK; goto endOfPathSegment; } else if(dirEntry->name[0] == NEVER_USED_DIR_ENTRY || dirEntry->name[0] == DELETED_DIR_ENTRY) { /* Found a free entry. Remember it in case we don't find a match */ if(file->directorySector == 0) { file->directorySector = sectorOfDir; file->directoryIndex = i; } if(dirEntry->name[0] == NEVER_USED_DIR_ENTRY) /* end of dir */ goto endOfPathSegment; } } } endOfPathSegment: ; } if(status == flFileNotFound && (file->flags & FILE_MUST_OPEN) && file->directorySector == 0) { /* We did not find a place in the directory for this new entry. The */ /* directory should be extended. 'scanFile' refers to the directory */ /* to extend, and the current pointer is at its end */#ifdef SUB_DIRECTORY checkStatus(extendDirectory(&scanFile,(unsigned) file->ownerDirCluster)); file->directorySector = firstSectorOfCluster(&vol,scanFile.currentCluster); file->directoryIndex = 0; /* Has to be. This is a new cluster */#else status = flRootDirectoryFull;#endif } return status;}/*----------------------------------------------------------------------*//* r e a d F i l e *//* *//* Reads from the current position in the file to the user-buffer. *//* Parameters: *//* file : File to read. *//* ioreq->irData : Address of user buffer *//* ioreq->irLength : Number of bytes to read. If the read extends *//* beyond the end-of-file, the read is truncated *//* at the end-of-file. *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//* ioreq->irLength : Actual number of bytes read *//*----------------------------------------------------------------------*/static FLStatus readFile(File *file,IOreq FAR2 *ioreq){ Volume vol = file->fileVol; char FAR1 *userData = (char FAR1 *) ioreq->irData; /* user buffer address */ unsigned long stillToRead = ioreq->irLength; unsigned long remainingInFile = file->fileSize - file->currentPosition; ioreq->irLength = 0; /* read so far */ /* Should we return an end of file status ? */ if(stillToRead > remainingInFile) stillToRead = (unsigned) remainingInFile; while(stillToRead > 0) { SectorNo sectorToRead; unsigned offsetInSector; unsigned readThisTime; const char FAR0 *sector; checkStatus(getSectorAndOffset(file,§orToRead,&offsetInSector)); sector = (const char FAR0 *) findSector(&vol,sectorToRead); readThisTime = SECTOR_SIZE - offsetInSector; if(readThisTime > stillToRead) readThisTime = (unsigned) stillToRead; if(sector) tffscpy(userData,sector + offsetInSector,readThisTime); else return flSectorNotFound; /* Sector does not exist */ stillToRead -= readThisTime; ioreq->irLength += readThisTime; userData += readThisTime; file->currentPosition += readThisTime; } return flOK;}/*----------------------------------------------------------------------*//* f l F i n d N e x t F i l e *//* *//* See the description of 'flFindFirstFile'. *//* *//* Parameters: *//* irHandle : File handle returned by flFindFirstFile. *//* irData : Address of user buffer to receive a *//* DirectoryEntry structure *//* *//* Returns:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -