📄 apfs_fat32_lib.c
字号:
//-----------------------------------------------------------------------------
// This file is part of AP.FS
// AP.FS is a FAT32 file system face to the embedded system,It's target is to
// support the portable storage device such as SD Card,TF Card or USB Disc 's
// file system.
// please login www.another-prj.com to get more details.
// caiyuqing
// 2008-1-8
//-----------------------------------------------------------------------------
#include "apfs_fat32_definitions.h"
#include "apfs_fat32_lib.h"
#include "apfs_fat32_access.h"
static struct apfs_file Files[MAX_OPEN_FILES];
extern struct fats_internal fats_internal_struct;
//-----------------------------------------------------------------------------
// _fl_init: Initialise File Library
//-----------------------------------------------------------------------------
void apfs_fat32_init_lib()
{
int i;
for (i=0; i < MAX_OPEN_FILES; i++)
{
Files[i].parent_cluster = 0xFFFFFFFF;
Files[i].file_ptr = 0;
Files[i].file_length = 0;
Files[i].start_cluster = 0;
Files[i].current_block = 0xFFFFFFFF;
Files[i].flag = 0;
}
}
//-----------------------------------------------------------------------------
// _find_free_file_slot: Find a slot in the open files buffer for a new file
//-----------------------------------------------------------------------------
static struct apfs_file* _find_free_file_slot()
{
int i;
for(i = 0; i < MAX_OPEN_FILES; i++)
{
if(CHK_FLG(Files[i].flag, IN_USE) == FALSE)
{
SET_FLG(Files[i].flag, IN_USE);
break;
}
}
if(i == MAX_OPEN_FILES)
{
return NULL;
}
else
{
return &Files[i];
}
}
//-----------------------------------------------------------------------------
// _check_file_open: Returns true if the file is already open
//-----------------------------------------------------------------------------
static BOOL _check_file_open(struct apfs_file* fp)
{
int i;
if(fp == NULL)
{
return FALSE;
}
// Compare open files
for(i=0; i<MAX_OPEN_FILES; i++)
{
if((CHK_FLG(Files[i].flag, IN_USE) == TRUE) && (&Files[i] != fp))
{
// Compare path and name
if((apfs_fat32_file_string_compare(Files[i].path, fp->path)) &&
(apfs_fat32_file_string_compare(Files[i].file_name, fp->file_name)))
{
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 *path_cluster)
{
int levels;
int sub_level;
char current_folder[MAX_LONG_FILENAME];
struct fat32_short_entry sf_entry;
UINT32 start_cluster;
// Set starting cluster to root cluster
start_cluster = apfs_fat32_get_root_cluster();
// Find number of levels
levels = apfs_fat32_path_to_levels(path);
// Cycle through each level and get the start sector
for(sub_level = 0; sub_level < (levels + 1); sub_level++)
{
apfs_fat32_get_sub_string(path, sub_level, current_folder);
// Find clusteraddress for folder (currentfolder)
if(apfs_fat32_get_file_entry(start_cluster, current_folder, &sf_entry))
{
start_cluster = (((UINT32)sf_entry.fst_clus_hi)<<16) + sf_entry.fst_clus_lo;
}
else
{
return FALSE;
}
}
*path_cluster = start_cluster;
return TRUE;
}
//-----------------------------------------------------------------------------
// _read_file: Open a file for reading
//-----------------------------------------------------------------------------
static struct apfs_file* _read_file(const char *path)
{
struct apfs_file* fp;
struct fat32_short_entry sf_entry;
fp = _find_free_file_slot();
if(fp == NULL)
{
return NULL;
}
// Check if file already open
if(_check_file_open(fp))
{
CLR_FLG(fp->flag, IN_USE);
return FALSE;
}
// Clear filename
memset(fp->path, 0, sizeof(fp->path));
memset(fp->file_name, 0, sizeof(fp->file_name));
// Split full path into filename and directory path
apfs_fat32_split_path(path, fp->path, fp->file_name);
// If file is in the root dir
if(fp->path[0] == 0)
{
fp->parent_cluster = apfs_fat32_get_root_cluster();
SET_FLG(fp->flag, IN_ROOT);
}
else
{
CLR_FLG(fp->flag, IN_ROOT);
// Find parent directory start cluster
if (!_open_directory(fp->path, &fp->parent_cluster))
{
CLR_FLG(fp->flag, IN_USE);
return NULL;
}
}
// Using dir cluster address search for filename
if(apfs_fat32_get_file_entry(fp->parent_cluster, fp->file_name,&sf_entry))
{
// Initialise file details
memcpy(fp->short_file_name, sf_entry.name, 11);
fp->file_length = sf_entry.file_size;
fp->file_ptr = 0;
fp->start_cluster = (((UINT32)sf_entry.fst_clus_hi)<<16) + sf_entry.fst_clus_lo;
fp->current_block = 0xFFFFFFFF;
apfs_fat32_purge_fat_buffer();
return fp;
}
else
{
CLR_FLG(fp->flag, IN_USE);
return NULL;
}
}
//-----------------------------------------------------------------------------
// _create_file: Create a new file
//-----------------------------------------------------------------------------
static struct apfs_file* _create_file(const char *filename, UINT32 size)
{
struct apfs_file* fp;
fp = _find_free_file_slot();
if(fp == NULL)
{
return NULL;
}
return fp;
}
//-----------------------------------------------------------------------------
// apfs_fat32_fopen: Open or Create a file for reading or writing
//-----------------------------------------------------------------------------
struct apfs_file* apfs_fat32_fopen(const char *path, const char *attr)
{
struct apfs_file* fp = NULL;
UINT32 attr_length;
UINT32 index;
BOOL read = FALSE;
BOOL write = FALSE;
BOOL append = FALSE;
BOOL binary = FALSE;
BOOL create = FALSE;
BOOL erase = FALSE;
attr_length = strlen(attr);
for(index = 0; index < attr_length; index++)
{
switch(tolower(attr[index]))
{
case 'r':
read = TRUE;
break;
case 'w':
write = TRUE;
create = TRUE;
erase = TRUE;
break;
case 'a':
append = TRUE;
write = TRUE;
create = TRUE;
break;
case '+':
if (read)
write = TRUE;
else if (write)
read = TRUE;
else if (append)
read = TRUE;
break;
case 'b':
binary = TRUE;
break;
}
}
// Read
if(read)
{
fp = _read_file(path);
}
/* if ( (fp==NULL) && (create) )
{
fp = _create_file(path, 0);
//the file is exist.
if(fp == NULL)
{
create = FALSE;
}
}
// Write Existing
if ( !create && !read && (write || append) )
fp = _read_file(path);
*/
if(fp != NULL)
{
if(read)
{
SET_FLG(fp->flag, READ);
}
if(write)
{
SET_FLG(fp->flag, WRITE);
}
if(append)
{
SET_FLG(fp->flag, APPEND);
}
if(binary)
{
SET_FLG(fp->flag, BINARY);
}
if(erase)
{
SET_FLG(fp->flag, ERASE);
}
}
return fp;
}
//-----------------------------------------------------------------------------
// apfs_fat32_fclose: Close a file
//-----------------------------------------------------------------------------
void apfs_fat32_fclose(struct apfs_file *fp)
{
if(fp != NULL)
{
fp->file_ptr = 0;
fp->file_length = 0;
fp->start_cluster = 0;
fp->current_block = 0xFFFFFFFF;
fp->flag = 0;
apfs_fat32_purge_fat_buffer();
}
}
//-----------------------------------------------------------------------------
// apfs_fat32_fread: Read data from the file
//-----------------------------------------------------------------------------
int apfs_fat32_fread(BYTE * buffer, UINT32 size, UINT32 count, struct apfs_file *fp)
{
UINT32 currnet_sector;
UINT32 end_sector;
UINT32 offset;
UINT32 sectors;
UINT32 total_size;
UINT32 bytes;
if(buffer == NULL || fp == NULL)
{
return -1;
}
// Check if file open
if(CHK_FLG(fp->flag, IN_USE) == FALSE)
{
return -1;
}
// No read permissions
if(CHK_FLG(fp->flag, READ) == FALSE)
{
return -1;
}
// Check if read starts past end of file
if(fp->file_ptr >= fp->file_length)
{
return -1;
}
// Nothing to be done
if(count == 0 || size == 0)
{
return 0;
}
// Limit to file size
if((fp->file_ptr + (count * size)) >= fp->file_length)
{
total_size = fp->file_length - fp->file_ptr;
}
else
{
total_size = count * size;
}
sectors = (total_size / 512);
if(total_size % 512)
{
sectors++;
}
currnet_sector = fp->file_ptr / 512;
end_sector = currnet_sector + sectors;
bytes = 0;
for(; currnet_sector < end_sector; currnet_sector++ )
{
if(apfs_fat32_sector_reader(fp->start_cluster, currnet_sector))
{
memcpy(fp->file_buf, fats_internal_struct.current_sector, 512);
for(offset = fp->file_ptr % 512; offset < 512 && bytes < total_size;
bytes++, offset++, fp->file_ptr++)
{
buffer[bytes] = fp->file_buf[offset];
}
}
}
return bytes;
}
//-----------------------------------------------------------------------------
// apfs_fat32_fget: read a character from the file
//-----------------------------------------------------------------------------
char apfs_fat32_fgetc(struct apfs_file *fp)
{
UINT32 currnet_sector;
UINT32 offset;
if(fp == NULL)
{
return -1;
}
// Check if file open
if(CHK_FLG(fp->flag, IN_USE) == FALSE)
{
return -1;
}
// No read permissions
if(CHK_FLG(fp->flag, READ) == FALSE)
{
return -1;
}
// Check if read starts past end of file
if(fp->file_ptr >= fp->file_length)
{
return -1;
}
currnet_sector = fp->file_ptr / 512;
offset = fp->file_ptr % 512;
if(fp->current_block != currnet_sector)
{
if(!apfs_fat32_sector_reader(fp->start_cluster, currnet_sector))
{
return -1;
}
else
{
fp->current_block = currnet_sector;
memcpy(fp->file_buf, fats_internal_struct.current_sector, 512);
}
}
fp->file_ptr++;
return fp->file_buf[offset];
}
//-----------------------------------------------------------------------------
// apfs_fat32_fseek: Seek to a specific place in the file
//-----------------------------------------------------------------------------
#define CHECK_FILE_PT if (fp->file_ptr > fp->file_length)\
{fp->file_ptr = fp->file_length;}\
else if(fp->file_ptr < 0)\
{fp->file_ptr = 0;}
int apfs_fat32_fseek(struct apfs_file *fp , UINT32 offset , int origin )
{
if(fp == NULL)
return -1;
// Check if file open
if(CHK_FLG(fp->flag, IN_USE) == FALSE)
return -1;
// Invalidate file buffer
fp->current_block = 0xFFFFFFFF;
if(origin == SEEK_SET)
{
fp->file_ptr = offset;
CHECK_FILE_PT;
return 0;
}
else if(origin == SEEK_CUR)
{
fp->file_ptr += offset;
CHECK_FILE_PT;
return 0;
}
else if(origin == SEEK_END)
{
fp->file_ptr += offset;
CHECK_FILE_PT;
return 0;
}
else
return -1;
}
//-----------------------------------------------------------------------------
// apfs_fat32_feof: Check end of the file
//-----------------------------------------------------------------------------
int apfs_fat32_feof(struct apfs_file *fp)
{
if(fp->file_ptr >= fp->file_length)
{
return 0;
}
else
{
return 1;
}
}
//-----------------------------------------------------------------------------
// apfs_fat32_ftell: Get the position of the file
//-----------------------------------------------------------------------------
int apfs_fat32_ftell(struct apfs_file *fp)
{
return fp->file_ptr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -