📄 fatlite.c
字号:
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: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus findNextFile(File *file, IOreq FAR2 *ioreq){ DirectoryEntry FAR1 *irDirEntry = (DirectoryEntry FAR1 *) ioreq->irData; /* Do we have a directory ? */ if (!(file->flags & FILE_IS_DIRECTORY)) return flNotADirectory; ioreq->irLength = DIRECTORY_ENTRY_SIZE; do { readFile(file,ioreq); if (ioreq->irLength != DIRECTORY_ENTRY_SIZE || irDirEntry->name[0] == NEVER_USED_DIR_ENTRY) { checkStatus(closeFile(file)); return flNoMoreFiles; } } while (irDirEntry->name[0] == DELETED_DIR_ENTRY || (irDirEntry->attributes & ATTR_VOL_LABEL)); return flOK;}/*----------------------------------------------------------------------*//* d e l e t e F i l e *//* *//* Deletes a file or directory. *//* *//* Parameters: *//* ioreq->irPath : path of file to delete *//* isDirectory : 0 = delete file, other = delete directory *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//*----------------------------------------------------------------------*/static FLStatus deleteFile(Volume vol, IOreq FAR2 *ioreq, FLBoolean isDirectory){ File file; /* Our private file */ DirectoryEntry *dirEntry; file.flags = 0; checkStatus(findDirEntry(&vol,ioreq->irPath,&file)); if (file.flags & FILE_READ_ONLY) return flNoWriteAccess; if (isDirectory) { DirectoryEntry fileFindInfo; ioreq->irData = &fileFindInfo; if (!(file.flags & FILE_IS_DIRECTORY)) return flNotADirectory; /* Verify that directory is empty */ file.currentPosition = 0; for (;;) { FLStatus status = findNextFile(&file,ioreq); if (status == flNoMoreFiles) break; if (status != flOK) return status; if (!((fileFindInfo.attributes & ATTR_DIRECTORY) && (tffscmp(fileFindInfo.name,". ",sizeof fileFindInfo.name) == 0 || tffscmp(fileFindInfo.name,".. ",sizeof fileFindInfo.name) == 0))) return flDirectoryNotEmpty; } } else { /* Did we find a directory ? */ if (file.flags & FILE_IS_DIRECTORY) return flFileIsADirectory; } /* Mark directory entry deleted */ checkStatus(getDirEntryForUpdate(&file,&dirEntry)); dirEntry->name[0] = DELETED_DIR_ENTRY; /* Delete FAT entries */ file.currentPosition = 0; file.currentCluster = LE2(dirEntry->startingCluster); while (file.currentPosition < file.fileSize) { unsigned nextCluster; if (file.currentCluster < 2 || file.currentCluster > vol.maxCluster) /* We have a bad file size, or the FAT is bad */ return isDirectory ? flOK : flInvalidFATchain; nextCluster = getFATentry(&vol,file.currentCluster); /* mark FAT free */ checkStatus(setFATentry(&vol,file.currentCluster,FAT_FREE)); buffer.checkPoint = TRUE; /* mark sectors free */ checkStatus(vol.tl.deleteSector(vol.tl.rec, firstSectorOfCluster(&vol,file.currentCluster), vol.sectorsPerCluster)); file.currentPosition += vol.bytesPerCluster; file.currentCluster = nextCluster; } return flOK;}/*----------------------------------------------------------------------*//* s e t N a m e I n D i r E n t r y *//* *//* Sets the file name in a directory entry from a path name *//* *//* Parameters: *//* dirEntry : directory entry *//* path : path the last segment of which is the name *//* *//*----------------------------------------------------------------------*/static void setNameInDirEntry(DirectoryEntry *dirEntry, FLSimplePath FAR1 *path){ FLSimplePath FAR1 *lastSegment; for (lastSegment = pat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -