⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatlite.c

📁 M-System DOC(Disk on a Chip) Flash芯片映像读写工具, 可以进行二片Flash芯片的内容互相拷贝, 提高烧录程序的效率.
💻 C
📖 第 1 页 / 共 5 页
字号:
  }
#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,&sectorOfDir,&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,&sectorOfDir,&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 + -