📄 fatlite.c
字号:
}
#endif /* FL_READ_ONLY */
return flOK;
}
#ifndef FL_READ_ONLY
#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.
* Input: vol - Pointer identifying drive
* file->currentPosition - equal to file->fileSize.
* Output: file->fileSize - updated file size.
* Return: flOK or other for fault
*------------------------------------------------------------------------------------------*/
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));
vol.volBuffer.checkPoint = TRUE;
if (file->currentPosition == 0 && i == 0) {
/* Add the mandatory . and .. entries */
tffscpy(directory[0].name,". ",sizeof directory[0].name);
directory[0].attributes = FL_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 += FL_SECTOR_SIZE;
}
/* Update the parent directory by closing the file */
file->flags |= FILE_MODIFIED;
return closeFile(file);
}
#endif /* SUB_DIRECTORY */
#endif /* FL_READ_ONLY */
/*--------------------------------------------------------------------------
* g e t P a t h S e g m e n t
* Provides address of the first character for found path segment as well as
* number of characters in the segment. It also contains code for compatibility
* with the old path type.
* Input: beginSegment - address of the first character in path string from it
* to find a segment
* Output: beginSegment - actual first path segment character
* nextSegment - first character of the next segment
* last - indication of last path segment
* Return: number of characters in path segment, 0 for end of path string,
* -1 for incorrect usage of '\' or '/' in file name.
*---------------------------------------------------------------------------*/
static int getPathSegment( FLWchar **beginSegment, FLWchar **nextSegment, FLBoolean *last)
{
FLWchar *pCurr = *beginSegment;
int length;
int ret;
for (length=0; ((FLByte)*pCurr == '\\') || ((FLByte)*pCurr == '/'); pCurr++, length++);
if (length > 1)
return -1;
/* calculates number of path segment characters between two slashes */
for (length = 0, *beginSegment = pCurr;
!(((FLByte)*pCurr == '\\') || ((FLByte)*pCurr == '/') || ((FLByte)*pCurr == 0));
pCurr++, length++);
*nextSegment = pCurr;
if (((FLByte)*pCurr == '\\') || ((FLByte)*pCurr == '/'))
*last = ((FLByte)*(pCurr + 1))? FALSE: TRUE;
else
*last = TRUE;
ret = length;
return ret;
}
/*-------------------------------------------------------------------------------------------
* v e r i f y L f n M a t c h i n g
* Provides the following information about file name string:
* - if the name is LFN and how many entries it requires (including 8.3 entry)
* - if the name is 8.3 short file name
* - if length and character set but not characters case of the name match 8.3 form
* Input: str - contains pointer to the beginning of name string and number of characters
* Renturn: status - LFN_LONG_NAME, LFN_SHORT_NAME, LFN_UPPERCASE_FOR_SHORT,
* LFN_INVALID_SET
*------------------------------------------------------------------------------------------*/
static LfnStatus verifyLfnMatching( FLPathSegment *str)
{
FLWord i, dots;
FLWord dotIdx = 0;
FLByte charBitsIdx, charBitOffset,charBitMask;
FLBoolean is83set = TRUE;
FLBoolean validCharachter = TRUE;
FLWchar FAR1 *name = str->name;
FLSWord length = str->length;
/* verify if the name contains valid characters and 8.3 length compatability */
for (i=0, dots=0; (i<length) && validCharachter ; i++)
{
if (name[i] > (FLWord)255)
{
is83set = FALSE;
continue;
}
if (name[i] > (FLWord)126)
continue;
if ((FLByte)name[i] == '.')
{
dots++;
dotIdx = i;
continue;
}
/* Calculate the location of the current char in the bit array of*/
/* allowed characters. - instead of IS_INCLUDED */
charBitsIdx = ((FLByte)name[i] - 0x20) >> 3;
charBitOffset = ((FLByte)name[i] - 0x20) & 0x7;
charBitMask = 1 << charBitOffset;
if (SfnAllowedChars[charBitsIdx] & charBitMask)
continue;
if (LfnAllowedChars[charBitsIdx] & charBitMask)
{
is83set = FALSE;
continue;
}
validCharachter = FALSE;
}
if (validCharachter == FALSE)
return LFN_INVALID_SET;
/* Check if name complies with 8.3 format*/
if ((is83set) &&
(dots < 2) &&
(((length <= SHORT_NAME_MAX_LENGTH) && (dots == 0)) ||
((dotIdx <= SHORT_NAME_MAX_LENGTH) && dots == 1)) &&
(((length - dotIdx <= EXTENSION_MAX_LENGTH + 1) && (dots == 1)) || dots == 0))
{
return LFN_SHORT_NAME;
}
return LFN_LONG_NAME;
}
/*-------------------------------------------------------------------------------------
* 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. In the case of LFN (long file name) this
* function finds an entry that contains a short form of the LFN.
* Input: vol - pointer identifying drive
* path - path string to find. Path starts with '/' or '\' and
* its segments are separated by these characters.
* file->flags - FL_FILE_MUST_OPEN = 1, directory will be extended if necessary.
* Output: file->flags - FL_FILE_IS_DIRECTORY, FL_FILE_IS_ROOT_DIR set if true.
* file->fileSize - Set for non-directory files.
* file->currentCluster - Set to 0 (unknown)
* file->ownerDirCluster - Set to 1st cluster of owning directory. If 0 - the
* root directory is owning one.
* file->directorySector - Sector of directory. If 0 entry not found and
* directory is full
* file->directoryIndex - Entry # in directory sector
* file->currentPosition - not set by this routine.
* Return: flOK for success, other for fault
*--------------------------------------------------------------------------------------*/
static FLStatus findDirEntry(Volume *pVol, FLWchar FAR1 *path, File *file)
{
File scanFile; /* Internal file of search */
unsigned dirBackPointer; /* 1st cluster of previous directory */
unsigned offsetInSector;
FLStatus status = flOK; /* root directory exists */
FLWchar *nextSegment, *currSegment;
FLDword reqSpace = 0;
int length;
FLPathSegment pathSegment;
FLLfnSearch lfnSearch, lfnAlloc;
FLBoolean fLastSegment, cont;
LfnStatus lfnStatus;
FLWord segmentCounter;
file->flags |= (FL_FILE_IS_ROOT_DIR | FL_FILE_IS_DIRECTORY);
file->fileSize = (FLSDword) (pVol->sectorsInRootDirectory) << FL_SECTOR_SIZE_BITS;
file->fileVol = pVol;
file->directoryIndex = 0;
file->directorySector = pVol->rootDirectorySectorNo;
dirBackPointer = 0; /* for root directory */
/* while we have another path segment */
currSegment = path;
segmentCounter = 0;
#ifdef SUB_DIRECTORY
for( ; (length = getPathSegment( &currSegment, &nextSegment, &fLastSegment));
currSegment = nextSegment)
#else
if (length = getPathSegment(currSegment, 0, 0)) /* search the root directory */
#endif
{
if (length == -1)
return flInvalidCharSet;
/* check for deep tree */
segmentCounter++;
if( segmentCounter > FL_MAX_TREE_LEVELS )
return flPathTooLong;
/* check for long name */
if( length > PATH_CHARACTERS_MAX_NUM )
return flPathTooLong;
status = flFileNotFound;
if (!(file->flags & FL_FILE_IS_DIRECTORY))
return flPathNotFound; /* if we don't have a directory,
we have no business here */
pathSegment.name = currSegment;
pathSegment.length = length;
pathSegment.get = FALSE;
/* check if the file name is LFN, short name or may be candidate for short name */
lfnStatus = verifyLfnMatching( &pathSegment);
if (lfnStatus == LFN_INVALID_SET)
return flInvalidCharSet;
scanFile = *file; /* the previous file found becomes the scan file */
scanFile.currentPosition = 0;
file->directorySector = 0; /* indicate no entry found yet */
file->flags &= ~(FL_FILE_IS_ROOT_DIR | FL_FILE_IS_DIRECTORY | FL_FILE_READ_ONLY);
file->ownerDirCluster = dirBackPointer;
file->fileSize = 0;
file->currentCluster = 0;
lfnSearch.verifiedChars = lfnAlloc.verifiedChars = 0;
lfnSearch.status = lfnAlloc.status = lfnStatus;
/* Scan directory */
for (cont = TRUE; cont && (scanFile.currentPosition < scanFile.fileSize);
scanFile.currentPosition += FL_SECTOR_SIZE) {
DirectoryEntry FAR0 *dirEntry, *foundEntry;
SectorNo sectorOfDir;
unsigned offsetInSector;
FLStatus readStatus;
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(pVol,sectorOfDir);
if (dirEntry == NULL)
return flSectorNotFound;
if(dirEntry==(const DirectoryEntry FAR0 *)dataErrorToken)
return flDataError;
if( fLastSegment && ( file->flags & FL_FILE_MUST_CREATE ) )
pathSegment.reserved = TRUE; /* always find new space */
else
pathSegment.reserved = FALSE;
foundEntry = findFileName( &pathSegment, dirEntry, &lfnSearch);
if (foundEntry && !(foundEntry->attributes & FL_ATTR_VOL_LABEL)) {
file->directorySector = sectorOfDir;
file->directoryIndex = (FLByte)lfnSearch.idx;
file->fileSize = LE4(foundEntry->fileSize);
if (foundEntry->attributes & FL_ATTR_DIRECTORY) {
file->flags |= FL_FILE_IS_DIRECTORY;
file->fileSize = 0x7fffffffl;
/* Infinite. Directories don't have a recorded size */
}
if (foundEntry->attributes & FL_ATTR_READ_ONLY)
file->flags |= FL_FILE_READ_ONLY;
dirBackPointer = LE2(foundEntry->startingCluster);
status = flOK;
break;
}
else {
if (fLastSegment && (file->flags & FL_FILE_MUST_OPEN) &&
(file->directorySector == 0)) {
if(findSpaceInSector( &pathSegment, dirEntry, &lfnAlloc)) {
/* Found a free entry*/
file->directorySector = sectorOfDir;
file->directoryIndex = (FLByte)lfnAlloc.idx;
}
else {
FLSWord remainedLength;
/* Not enough space for new name is found */
remainedLength = (FLSWord)(pathSegment.length - lfnAlloc.verifiedChars);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -