📄 fat32_filelib.c
字号:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 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 + -