📄 fatlite.c
字号:
/* */
/* 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: */
/* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -