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

📄 apfs_fat32_lib.c

📁 一个可以在开发板上运行的fat文件系统,是在windows平台下开发的,是学习文件系统的好帮手
💻 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 + -