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

📄 fat32_filelib.c

📁 FAT32代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//					        FAT32 File IO Library
//								    V2.0
// 	  							 Rob Riglar
//						    Copyright 2003 - 2007
//
//   					  Email: rob@robriglar.com
//
//-----------------------------------------------------------------------------
//
// This file is part of FAT32 File IO Library.
//
// FAT32 File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT32 File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT32 File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include "FAT32_Definitions.h"
#include "FAT32_Base.h"
#include "FAT32_Table.h"
#include "FAT32_Access.h"
#include "FAT32_Write.h"
#include "FAT32_Misc.h"
#include "FAT32_Filestring.h"
#include "FAT32_Filelib.h"

//-----------------------------------------------------------------------------
// Locals
//-----------------------------------------------------------------------------
static FL_FILE		Files[MAX_OPEN_FILES];
static int			Filelib_Init = FALSE;

// Macro for checking if file lib is initialised
#define CHECK_FL_INIT()		{ if (Filelib_Init==FALSE) _fl_init(); }

//-----------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
static BOOL				_open_directory(char *path, UINT32 *pathCluster);
static FL_FILE*			_find_spare_file();
static void				_fl_init();
static FL_FILE*			_read_file(char *path);
static BOOL				_write_block(FL_FILE *file, BYTE *data, UINT32 length);
static FL_FILE*			_create_file(char *filename, UINT32 size);

//-----------------------------------------------------------------------------
// _fl_init: Initialise File Library
//-----------------------------------------------------------------------------
static void _fl_init()
{
	int i;
	for (i=0;i<MAX_OPEN_FILES;i++)
		Files[i].inUse = FALSE;

	Filelib_Init = TRUE;
}
//-----------------------------------------------------------------------------
// _find_spare_file: Find a slot in the open files buffer for a new file
//-----------------------------------------------------------------------------
static FL_FILE* _find_spare_file()
{
	int i;
	int freeFile = -1;
	for (i=0;i<MAX_OPEN_FILES;i++)
		if (Files[i].inUse == FALSE)
		{
			freeFile = i;
			break;
		}

	if (freeFile!=-1)
		return &Files[freeFile];
	else
		return NULL;
}
//-----------------------------------------------------------------------------
// _check_file_open: Returns true if the file is already open
//-----------------------------------------------------------------------------
static BOOL _check_file_open(FL_FILE* file)
{
	int i;

	if (file==NULL)
		return FALSE;

	// Compare open files
	for (i=0;i<MAX_OPEN_FILES;i++)
		if ( (Files[i].inUse) && (&Files[i]!=file) )
		{
			// Compare path and name
			if ( (FileString_Compare(Files[i].path,file->path)) && (FileString_Compare(Files[i].filename,file->filename)) )
				return TRUE;
		}

	return FALSE;
}
//-----------------------------------------------------------------------------
// _open_directory: Cycle through path string to find the start cluster
// address of the highest subdir.
//-----------------------------------------------------------------------------
static BOOL _open_directory(char *path, UINT32 *pathCluster)
{
	int levels;
	int sublevel;
	char currentfolder[MAX_LONG_FILENAME];
	FAT32_ShortEntry sfEntry;
	UINT32 startcluster;

	// Set starting cluster to root cluster
	startcluster = FAT32_GetRootCluster();

	// Find number of levels
	levels = FileString_PathTotalLevels(path);

	// Cycle through each level and get the start sector
	for (sublevel=0;sublevel<(levels+1);sublevel++) 
	{
		FileString_GetSubString(path, sublevel, currentfolder);

		// Find clusteraddress for folder (currentfolder) 
		if (FAT32_GetFileEntry(startcluster, currentfolder,&sfEntry))
			startcluster = (((UINT32)sfEntry.FstClusHI)<<16) + sfEntry.FstClusLO;
		else
			return FALSE;
	}

	*pathCluster = startcluster;
	return TRUE;
}

//-----------------------------------------------------------------------------
//								External API
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// fl_shutdown: Call before shutting down system
//-----------------------------------------------------------------------------
void fl_shutdown()
{
	// If first call to library, initialise
	CHECK_FL_INIT();

	FAT32_PurgeFATBuffer();
}
//-----------------------------------------------------------------------------
// fopen: Open or Create a file for reading or writing
//-----------------------------------------------------------------------------
FL_FILE* fl_fopen(char *path, char *mode)
{
	int modlen, i;
	FL_FILE* file; 

	BOOL read = FALSE;
	BOOL write = FALSE;
	BOOL append = FALSE;
	BOOL binary = FALSE;
	BOOL create = FALSE;
	BOOL erase = FALSE;

	// If first call to library, initialise
	CHECK_FL_INIT();

	if ((path==NULL) || (mode==NULL))
		return NULL;

	modlen = (int)strlen(mode);

	// Supported Modes:
	// "r" Open a file for reading. The file must exist. 
	// "w" Create an empty file for writing. If a file with the same name already exists its content is erased and the file is treated as a new empty file.  
	// "a" Append to a file. Writing operations append data at the end of the file. The file is created if it does not exist. 
	// "r+" Open a file for update both reading and writing. The file must exist. 
	// "w+" Create an empty file for both reading and writing. If a file with the same name already exists its content is erased and the file is treated as a new empty file. 
	// "a+" Open a file for reading and appending. All writing operations are performed at the end of the file, protecting the previous content to be overwritten. You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations will move it back to the end of file. The file is created if it does not exist. 

	for (i=0;i<modlen;i++)
	{
		switch (tolower(mode[i]))
		{
		case 'r':
			read = TRUE;
			break;
		case 'w':
			write = TRUE;
			erase = TRUE;
			create = TRUE;
			break;
		case 'a':
			write = TRUE;
			append = TRUE;
			create = TRUE;
			break;
		case '+':
			if (read)
				write = TRUE;
			else if (write)
			{
				read = TRUE;
				erase = TRUE;
				create = TRUE;
			}
			else if (append)
			{
				read = TRUE;
				write = TRUE;
				append = TRUE;
				create = TRUE;
			}
			break;
		case 'b':
			binary = TRUE;
			break;
		}
	}
	
	file = NULL;

	// Read
	if (read)
		file = _read_file(path);

	// Create New
#ifdef INCLUDE_WRITE_SUPPORT
	if ( (file==NULL) && (create) )
		file = _create_file(path, 0);
#else
	create = FALSE;
	write = FALSE;
	append = FALSE;
#endif

	// Write Existing
	if ( !create && !read && (write || append) )
		file = _read_file(path);

	if (file!=NULL)
	{
		file->Read = read;
		file->Write = write;
		file->Append = append;
		file->Binary = binary;
		file->Erase = erase;
	}

	return file;	
}
//-----------------------------------------------------------------------------
// _read_file: Open a file for reading
//-----------------------------------------------------------------------------
static FL_FILE* _read_file(char *path)
{
	FL_FILE* file; 
	FAT32_ShortEntry sfEntry;

	// If first call to library, initialise
	CHECK_FL_INIT();

	file = _find_spare_file();
	if (file==NULL)
		return NULL;

	// Clear filename
	memset(file->path, '\n', sizeof(file->path));
	memset(file->filename, '\n', sizeof(file->filename));

	// Split full path into filename and directory path
	FileString_SplitPath(path, file->path, file->filename);

	// Check if file already open
	if (_check_file_open(file))
		return FALSE;

	// If file is in the root dir
	if (file->path[0]==0)
	{
		file->parentcluster = FAT32_GetRootCluster();
		file->inRoot = TRUE;
	}
	else
	{
		file->inRoot = FALSE;

		// Find parent directory start cluster
		if (!_open_directory(file->path, &file->parentcluster))
			return NULL;
	}

	// Using dir cluster address search for filename
	if (FAT32_GetFileEntry(file->parentcluster, file->filename,&sfEntry))
	{
		// Initialise file details
		memcpy(file->shortfilename, sfEntry.Name, 11);
		file->filelength = sfEntry.FileSize;
		file->bytenum = 0;
		file->startcluster = (((UINT32)sfEntry.FstClusHI)<<16) + sfEntry.FstClusLO;
		file->currentBlock = 0xFFFFFFFF;
		file->inUse = TRUE;

		FAT32_PurgeFATBuffer();

		return file;
	}

	return NULL;
}
//-----------------------------------------------------------------------------
// fl_fclose: Close an open file
//-----------------------------------------------------------------------------
void fl_fclose(FL_FILE *file)
{
	// If first call to library, initialise
	CHECK_FL_INIT();

	if (file!=NULL)
	{
		file->bytenum = 0;
		file->filelength = 0;
		file->startcluster = 0;
		file->currentBlock = 0xFFFFFFFF;
		file->inUse = FALSE;

		FAT32_PurgeFATBuffer();
	}
}
//-----------------------------------------------------------------------------
// fl_fgetc: Get a character in the stream
//-----------------------------------------------------------------------------
int fl_fgetc(FL_FILE *file)
{
	UINT32 sector;
	UINT32 offset;	
	BYTE returnchar=0;

	// If first call to library, initialise
	CHECK_FL_INIT();

	if (file==NULL)
		return -1;

	// Check if file open
	if (file->inUse==FALSE)
		return -1;

	// No read permissions
	if (file->Read==FALSE)
		return -1;

	// Check if read past end of file
	if (file->bytenum>=file->filelength)
		return -1;

	// Calculations for file position
	sector = file->bytenum / 512;
	offset = file->bytenum - (sector*512);

	// If file block not already loaded
	if (file->currentBlock!=sector)
	{
		// Read the appropriate sector
		if (!FAT32_SectorReader(file->startcluster, sector)) 
			return -1;

		// Copy to file's buffer
        memcpy(file->filebuf, FATFS_Internal.currentsector, 512);
		file->currentBlock=sector;
	}

	// Get the data block
	returnchar = file->filebuf[offset];

	// Increase next read position
	file->bytenum++;

	// Return character read
	return returnchar;
}
//-----------------------------------------------------------------------------
// fl_fread: Read a block of data from the file
//-----------------------------------------------------------------------------
int fl_fread (FL_FILE *file, BYTE * buffer, UINT32 count)
{
	UINT32 sector;
	UINT32 offset;
	UINT32 totalSectors;
	UINT32 bytesRead;
	UINT32 thisReadCount;
	UINT32 i;

	// If first call to library, initialise
	CHECK_FL_INIT();

	if (buffer==NULL || file==NULL)
		return -1;

	// Check if file open
	if (file->inUse==FALSE)
		return -1;

	// No read permissions
	if (file->Read==FALSE)
		return -1;

	// Nothing to be done
	if (count==0)
		return 0;

	// Check if read starts past end of file
	if (file->bytenum>=file->filelength)
		return -1;

	// Limit to file size
	if ( (file->bytenum + count) > file->filelength )
		count = file->filelength - file->bytenum;

	// Calculations for file position
	sector = file->bytenum / 512;
	offset = file->bytenum - (sector*512);

	// Calculate how many sectors this is
	totalSectors = (count+offset) / 512;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -