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

📄 fatlite.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                                      */
/* 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,&sectorOfDir,&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,&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(&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,&sectorToRead,&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 + -