基于FATFS底层实现的虚拟文件系统VFS接口(用于裸机移植sqlite3)

sqlite3移植所需的文件系统支持,采用的VFS接口,只实现了一些基本接口,对于属性与权限接口则未实现具体功能,由于FATFS文件系统没有权限管理,VFS主要是linux上面使用的,这里还是有区别,而且裸机情况下也不需要什么权限管理。
需要用户堆支持。

 

ff_vfs.c

/*************************************************************************************************************
 * 文件名		:	ff_vfs.c
 * 功能			:	VFS虚拟文件系统支持
 * 作者			:	cp1300@139.com
 * 创建时间		:	2020-09-29
 * 最后修改时间	:	2020-09-29
 * 详细			:	兼容linux的vfs文件系统API支持,需要先初始化fatfs
*************************************************************************************************************/
#include "system.h"
#include "ff.h"
#include "ff_vfs.h"
#include <stdlib.h>
#include "errno-base.h"


//内存申请接口
static void* (*vfs_malloc)(size_t size) = malloc;		//默认的内存申请接口
static void (*vfs_free)(void *ptr) = free;				//默认的内存释放接口

/*************************************************************************************************************************
* 函数			:	int ff_vfs_init(void)
* 功能			:	初始化VFS系统
* 参数			:	无
* 返回			:	0:执行成功;负数:执行错误,返回错误代码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	底层文件系统初始化由FATFS初始化完成
*************************************************************************************************************************/
int ff_vfs_init(void)
{
	return 0;
}


/*************************************************************************************************************************
* 函数			:	int ff_vfs_error(FRESULT Status)
* 功能			:	FATFS错误转义
* 参数			:	Status:FATFS错误代码
* 返回			:	VFS错误代码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	用于兼容linux中VFS文件系统错误代码
*************************************************************************************************************************/
int ff_vfs_error(FRESULT Status)
{
	switch(Status)
	{
		case FR_OK:					return 0;			//(0) 无错误
		case FR_DISK_ERR:			return -EIO;		//(1) 低级磁盘I / O层发生硬错误
		case FR_INT_ERR:			return -EPIPE;		//(2) 断言失败
		case FR_NOT_READY:			return -EIO;		//(3) 物理驱动器无法工作
		case FR_NO_FILE:			return -ENOENT;		//(4) 找不到文件
		case FR_NO_PATH:			return -ENOENT;		//(5) 找不到路径
		case FR_INVALID_NAME:		return -ENOEXEC;	//(6) 路径名格式无效
		case FR_DENIED:				return -ENOSPC;		//(7) 由于访问被禁止或目录已满而拒绝访问
		case FR_EXIST:				return -EACCES;		//(8) 由于禁止访问而拒绝访问 
		case FR_INVALID_OBJECT:		return -ENXIO;		//(9) 文件/目录对象无效
		case FR_WRITE_PROTECTED:	return -EROFS;		//(10) 物理驱动器受写保护
		case FR_INVALID_DRIVE:		return -ENXIO;		//(11) 逻辑驱动器号无效
		case FR_NOT_ENABLED:		return -ENXIO;		//(12) 该卷没有工作区
		case FR_NO_FILESYSTEM:		return -EPERM;		//(13) 没有有效的FAT卷
		case FR_MKFS_ABORTED:		return -EPERM;		//(14) 由于任何问题f_mkfs()中止
		case FR_TIMEOUT:			return -EBUSY;		//(15) 无法在限定时间内获得访问卷的授权
		case FR_LOCKED:				return -EACCES;		//(16) 根据文件共享策略拒绝该操作
		case FR_NOT_ENOUGH_CORE:	return -ENOMEM;		//(17) 无法分配LFN工作缓冲区
		case FR_TOO_MANY_OPEN_FILES:return -EMFILE;		//(18) 打开文件数> FF_FS_LOCK
		case FR_INVALID_PARAMETER:	return -EINVAL;		//(19) 给定参数无效
		default:return -EPERM;
	}
}


/*************************************************************************************************************************
* 函数			:	int ff_open(const char *path, int flags, int mode)
* 功能			:	打开path所描述的文件或者设备,打开成功时返回系统分配的文件描述符fd,错误时返回对应的错误码
* 参数			:	path:文件路径;flags:打开文件的参数(打开文件时参数flags必须要包含O_RDONLY, O_WRONLY, O_RDWR三者之一)
					mode:相关权限,忽略
* 返回			:	正数:文件描述符(实际上是个指针);负数:执行错误,返回错误代码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	O_RDONLY	以只读方式打开文件
					O_WRONLY	以只写方式打开
					O_RDWR		以可读可写方式打开
					O_CREAT		文件不存在时创建文件
					O_EXCL		在打开文件时,如果文件存在而且同时指定的标志位O_CREAT,则返回-EEXIST;如果文件不存在,则创建文件
					O_TRUNC		打开文件时,如果文件的长度不为0,则将文件的长度截短为0,下次写入文件时,从文件开始出写入数据
					O_APPEND	打开文件后,将文件的写入点设置为文件末尾,下次写入文件时,新写入的数据会追加到文件末尾
*************************************************************************************************************************/
int ff_open(const char *path, int flags, int mode)
{
	u8 OpenMode = 0;
	FIL *pFile;
	FRESULT Status;
	
	pFile = (FIL *)vfs_malloc(sizeof(FIL));		//申请内存
	if(pFile == NULL)							//申请内存失败
	{
		DEBUG("ff_open 内存不足!\r\n");
		return -ENOMEM; 
	}
	//打开文件的参数定义
	if(flags & O_WRONLY)					//只写
	{
		OpenMode |= FA_WRITE;
	}
	if(flags & O_RDWR)						//读写方式
	{
		OpenMode |= FA_WRITE | FA_READ;
	}
	if((OpenMode & (FA_WRITE | FA_READ)) == 0)//如果没有规定读写,默认是只读
	{
		OpenMode |= FA_READ;
	}
	if((flags & O_CREAT) && (flags & O_EXCL))			//如果文件存在而且同时指定的标志位O_CREAT,则返回-EEXIST;如果文件不存在,则创建文件
	{
		OpenMode |= FA_CREATE_NEW;
	}
	else if(flags & O_CREAT)				//不存在则创建,存在则打开
	{
		OpenMode |= FA_OPEN_ALWAYS;
	}
	if(flags & O_TRUNC)						//截断,相当于每次新建
	{
		OpenMode |= FA_CREATE_ALWAYS;	
	}
	if(flags & O_APPEND)						//追加方式
	{
		OpenMode |= FA_OPEN_APPEND;	
	}

	Status = f_open (pFile, path, OpenMode);	
	if(Status != FR_OK)	//打开失败
	{
		DEBUG("ff_open %s, ERROR=%d\r\n",path, Status);
		vfs_free(pFile);							//释放内存
		pFile = NULL;
		
		if((flags & O_CREAT) && (flags & O_EXCL) && (Status ==FR_EXIST))	 //如果文件存在而且同时指定的标志位O_CREAT,则返回-EEXIST;
		{
			return -EEXIST;
		}	
		return ff_vfs_error(Status);				//错误代码转义
	}
	
	return (int)pFile;
}

/*************************************************************************************************************************
* 函数			:	int ff_close(int fd)
* 功能			:	关闭已打开的文件描述符fd(该描述符fd后续会被打开其他文件时复用)
* 参数			:	fd:关闭文件的描述符
* 返回			:	0:成功;负数:执行错误,返回错误代码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	会释放申请的内存
*************************************************************************************************************************/
int ff_close(int fd)
{
	FRESULT Status;
	
	if(fd <= 0) return -ENXIO;						//文件指针为空,直接返回
	Status = f_close((FIL*)fd);						//关闭文件
	if(Status == FR_OK) 
	{
		vfs_free((void *)fd);						//释放内存
	}
	
	return ff_vfs_error(Status);					//错误代码转义
}


/*************************************************************************************************************************
* 函数			:	int ff_read(int fd, void *buf, size_t nbytes)
* 功能			:	从打开的文件中读取若干字节到buffer
* 参数			:	fd:文件的描述符;buf:文件读取的数据缓存;nbytes:要读取的字节数
* 返回			:	读取成功,返回读取到的字节个数;如果读取时文件偏移已经到达文件末尾,则返回0。其他错误情况,返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	如果文件支持seek,那么aos_read()将从文件当前偏移(offset)处开始读取,读取成功后将文件的偏移向后增加成功读取到的字节数。
*************************************************************************************************************************/
int ff_read(int fd, void *buf, size_t nbytes)
{
	FRESULT Status;
	UINT cnt;
	
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	Status = f_read ((FIL*)fd, buf, nbytes, (UINT *)&cnt);	
	if(Status != FR_OK) 
	{
		DEBUG("ff_read ERROR=%d\r\n", Status);
		return ff_vfs_error(Status);	//错误代码转义
	}
	return cnt;
}

/*************************************************************************************************************************
* 函数			:	int ff_write(int fd, const void *buf, size_t nbytes)
* 功能			:	将buffer开始出的nbytes字节数据写入到已经打开的文件
* 参数			:	fd:文件的描述符;buf:要写入文件的数据缓存;nbytes:文件写入的长度
* 返回			:	写入成功时,返回写入到文件的字节个数,实际写入的字节数有可能小于nbytes(文件空间不足);写入失败时返回错误码(负数)
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	如果文件支持seek,那么aos_write()将从文件当前偏移(offset)处开始写入,写入成功后将文件的偏移向后增加成功写入的字节数。
*************************************************************************************************************************/
int ff_write(int fd, const void *buf, size_t nbytes)
{
	FRESULT Status;
	UINT cnt;
	
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	Status = f_write ((FIL*)fd, buf, nbytes, (UINT *)&cnt);	
	if(Status != FR_OK) 
	{
		DEBUG("ff_write ERROR=%d\r\n", Status);
		return ff_vfs_error(Status);					//错误代码转义
	}
	return cnt;
}

/*************************************************************************************************************************
* 函数			:	off_t ff_lseek(int fd, off_t offset, int whence)
* 功能			:	重新设置已打开文件的偏移
* 参数			:	fd:文件的描述符;offset:相对于第三个参数whence的偏移值;whence:相对位置设置
* 返回			:	非负数:成功,返回相对于文件开始处的偏移字节数;负数:失败,返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	VFS_SEEK_SET: 文件偏移设置为从文件开始处offset字节处。 
					VFS_SEEK_CUR:文件偏移设置为相对于当前文件位置的offset字节处。 
					VFS_SEEK_END:文件偏移摄者为文件末尾的offset字节处。
*************************************************************************************************************************/
off_t ff_lseek(int fd, off_t offset, int whence)
{
	FRESULT Status;
	long long temp;
	
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	
	switch(whence)
	{
		case VFS_SEEK_SET:	//文件偏移设置为从文件开始处offset字节处
		{
			Status = f_lseek((FIL*)fd, offset);
			if(Status == FR_OK)
			{
				return (off_t)((FIL*)fd)->fptr;
			}
			return ff_vfs_error(Status);				//错误代码转义
		}
		case VFS_SEEK_CUR:	//文件偏移设置为相对于当前文件位置的offset字节处
		{
			temp = (off_t)((FIL*)fd)->fptr;
			temp += offset;
			if(temp >= U32_MAX) temp = U32_MAX-1;
			Status = f_lseek((FIL*)fd, temp);
			if(Status == FR_OK)
			{
				return (off_t)((FIL*)fd)->fptr;
			}
			return ff_vfs_error(Status);				//错误代码转义
		}
		case VFS_SEEK_END:	//文件偏移摄者为文件末尾的offset字节处
		{
			temp = (off_t)((FIL*)fd)->obj.objsize;		//获取文件大小
			temp -= offset;
			if(temp <= 0) temp = 0;
			Status = f_lseek((FIL*)fd, temp);
			if(Status == FR_OK)
			{
				return (off_t)((FIL*)fd)->fptr;
			}
			return ff_vfs_error(Status);				//错误代码转义
		}
		default : return -EINVAL;	//参数错误
	}
}

/*************************************************************************************************************************
* 函数			:	int ff_sync(int fd)
* 功能			:	更新缓存到存储器中
* 参数			:	fd:文件的描述符;
* 返回			:	0:成功;负数:数据同步失败,返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_sync(int fd)
{
	FRESULT Status;

	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	Status = f_sync ((FIL*)fd);							//存储文件
	return ff_vfs_error(Status);						//错误代码转义
}

/*************************************************************************************************************************
* 函数			:	int ff_stat(const char *path, struct stat *st)
* 功能			:	读取文件的属性信息,如文件大小、文件模式等信息
* 参数			:	path:文件路径;st:文件状态信息结构体指针
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_stat(const char *path, struct stat *st)
{
	FRESULT Status;
	FILINFO *pInfo;	
	
	if(path == NULL || st == NULL)
	{
		return -EINVAL;
	}
	pInfo = vfs_malloc(sizeof(FILINFO));	//申请内存
	if(pInfo == NULL)
	{
		return -ENOMEM;
	}
	Status = f_stat (path, pInfo);
	if(Status == FR_OK)			 //获取成功
	{
		st->st_size = pInfo->fsize;		//文件大小
		st->st_mode = pInfo->fattrib;	//文件属性
		st->st_actime = 0;  			//最后访问时间
		st->st_modtime = 0; 			//最后修改时间
		//WORD	fdate;			/* Modified date */
		//WORD	ftime;			/* Modified time */
	}
	vfs_free(pInfo);					//释放申请的内存
	return ff_vfs_error(Status);		//错误代码转义
}

/*************************************************************************************************************************
* 函数			:	int ff_fstat(int fd, struct stat *st)
* 功能			:	读取文件的属性信息,如文件大小、文件模式等信息
* 参数			:	fd:文件描述符;st:文件状态信息结构体指针
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_fstat(int fd, struct stat *st)
{
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	if(st == NULL) return -EINVAL;
	
	st->st_size = ((FIL*)fd)->obj.objsize;				//文件大小
	st->st_mode = 0777;				//文件属性
	st->st_actime = 0;  			//最后访问时间
	st->st_modtime = 0; 			//最后修改时间
	
	return 0;
}

/*************************************************************************************************************************
* 函数			:	int ff_access(const char *path, int amode)
* 功能			:	检查当前程序是否可以访问path文件
* 参数			:	fd:文件描述符;amode:指定访问权限
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	amode指定访问权限,它的值可以是F_OK,或者R_OK、W_OK和X_OK的或“|”组合。F_OK用于测试文件是否存在,R_OK、W_OK和X_OK分别测试文件是否具有读、写、执行权限
*************************************************************************************************************************/
int ff_access(const char *path, int amode)
{
	struct stat st;
	
	return ff_stat(path, &st);
}

/*************************************************************************************************************************
* 函数			:	char *ff_getcwd(char *buf, size_t size)
* 功能			:	返回当当前程序的绝对工作目录字符串指针,同时如果buf参数不为空,也将当前工作目录字符串复制到buf中
* 参数			:	buf:路径存储区;size:路径缓冲区大小
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
char *ff_getcwd(char *buf, size_t size)
{
	FRESULT Status;
	
	if(buf == NULL || size == 0)
	{
		return NULL;
	}
	
	Status = f_getcwd (buf, size);
	if(Status == FR_OK)	//获取成功
	{
		return buf;
	}
	else
	{
		DEBUG("ff_getcwd ERROR=%d\r\n", Status);
	}
	
	return NULL;
}

/*************************************************************************************************************************
* 函数			:	int ff_ftruncate(int fd, off_t  length)
* 功能			:	指定文件大小
* 参数			:	fd:已经打开的文件描述符,必须由写入权限;length:指定的文件大小
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_ftruncate(int fd, off_t  length)
{
	FRESULT Status;
	UINT cnt;
	u32 PackCnt;	//整数包数量
	u16 EndPackSize;//最后一包数据量
	u8 *pBuff;
	u32 i;
	
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	if(length <= ((FIL*)fd)->obj.objsize)				//比文件小,直接截断即可
	{
		Status = f_lseek ((FIL*)fd, length);			//移动文件读写指针
		if(Status == FR_OK)
		{
			Status = f_truncate((FIL*)fd);				//截断文件
			if(Status == FR_OK)
			{
				return 0;
			}
			else
			{
				DEBUG("f_truncate ERROR=%d\r\n", Status);
			}
		}
		else
		{
			DEBUG("f_lseek ERROR=%d\r\n", Status);
		}
		return ff_vfs_error(Status);		//错误代码转义
	}
	else //比文件大,计算大多少,在后面填充数据
	{
		uart_printf("=============vfs准备扩大文件:%uB\r\n", length);
		Status = f_lseek ((FIL*)fd, ((FIL*)fd)->obj.objsize);	//移动文件读写指针到结尾
		if(Status == FR_OK)
		{
			PackCnt = (length - ((FIL*)fd)->obj.objsize) / 512;		//计算整数包数量
			EndPackSize = (length - ((FIL*)fd)->obj.objsize) % 512;	//计算最后一包剩余数量
			pBuff = vfs_malloc(512);
			if(pBuff == NULL)
			{
				return -ENOMEM;
			}
			memset(pBuff, 0, 512);
			//循环填充数据
			for(i = 0;i < PackCnt;i ++)
			{
				Status = f_write ((FIL*)fd, pBuff, 512, (UINT *)&cnt);	
				if(Status != FR_OK)
				{
					DEBUG("f_write ERROR=%d\r\n", Status);
					break;
				}
			}
			if((Status == FR_OK) && EndPackSize)	//剩余不足512字节的也要写入
			{
				Status = f_write ((FIL*)fd, pBuff, EndPackSize, (UINT *)&cnt);	
				if(Status != FR_OK)
				{
					DEBUG("f_write ERROR=%d\r\n", Status);
				}
			}
			vfs_free(pBuff);	//释放内存
		}
		else
		{
			DEBUG("f_lseek ERROR=%d\r\n", Status);
		}
	}
	
	return ff_vfs_error(Status);		//错误代码转义
}


/*************************************************************************************************************************
* 函数			:	int ff_fcntl(int fd, int cmd, struct flock *lock)
* 功能			:	根据文件描述词来操作文件的特性
* 参数			:	fd:已经打开的文件描述符;cmd:命令;lock:特性
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_fcntl(int fd, int cmd, struct flock *lock)
{
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	uart_printf("ff_fcntl(0x%X, %d, %d-%d)\r\n",fd, cmd, lock->l_type, lock->l_whence);
	
	return 0;
}

/*************************************************************************************************************************
* 函数			:	int ff_fchmod(int fd, mode_t mode)
* 功能			:	改变现有文件的访问权限
* 参数			:	fd:已经打开的文件描述符;mode:文件访问权限
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_fchmod(int fd, mode_t mode)
{
	if(fd <= 0) return -ENXIO;							//文件指针为空,直接返回
	uart_printf("ff_fchmod(0x%X, %d)\r\n",fd, mode);
	
	return 0;
}

/*************************************************************************************************************************
* 函数			:	int ff_unlink(const char *path)
* 功能			:	从文件系统中删除文件
* 参数			:	path:需删除的文件路径
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_unlink(const char *path)
{
	FRESULT Status;
	FILINFO *pInfo;	
	
	if(path == NULL) return -ENXIO;							//文件指针为空,直接返回
	pInfo = vfs_malloc(sizeof(FILINFO));	//申请内存
	if(pInfo == NULL)
	{
		return -ENOMEM;
	}
	
	Status = f_stat (path, pInfo);			//先获取这个文件的信息,看看这文件是否存在,或者是否是文件
	if(Status == FR_OK)	
	{
		Status = f_unlink (path);	
		if(Status != FR_OK) 
		{
			DEBUG("f_unlink ERROR=%d\r\n", Status);
		}
	}
	else
	{
		DEBUG("f_stat ERROR=%d\r\n", Status);
	}
	vfs_free(pInfo);								//释放申请的内存
	
	return ff_vfs_error(Status);					//错误代码转义
}

/*************************************************************************************************************************
* 函数			:	int ff_unlink(const char *path)
* 功能			:	创建名为path的目录
* 参数			:	path:需创建的目录路径
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	如果已经存在path目录,则创建失败。
*************************************************************************************************************************/
int ff_mkdir(const char *path)
{
	FRESULT Status;
	
	if(path == NULL) return -ENXIO;							//文件指针为空,直接返回
	Status = f_mkdir (path);								//创建目录
	
	return ff_vfs_error(Status);							//错误代码转义
}

/*************************************************************************************************************************
* 函数			:	int ff_rmdir(const char *path)
* 功能			:	删除一个目录
* 参数			:	path:需删除的目录路径
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	删除目录时,目录必须为空
*************************************************************************************************************************/
int ff_rmdir(const char *path)
{
	FRESULT Status;
	FILINFO *pInfo;	
	
	if(path == NULL) return -ENXIO;							//文件指针为空,直接返回
	pInfo = vfs_malloc(sizeof(FILINFO));	//申请内存
	if(pInfo == NULL)
	{
		return -ENOMEM;
	}
	
	Status = f_stat (path, pInfo);			//先获取这个文件的信息,看看这文件是否存在,或者是否是文件
	if(Status == FR_INVALID_NAME)			//是文件夹
	{
		Status = f_unlink (path);	
		if(Status != FR_OK) 
		{
			DEBUG("f_unlink ERROR=%d\r\n", Status);
		}
	}
	else
	{
		if(Status != FR_OK)
		{
			DEBUG("f_stat ERROR=%d\r\n", Status);
		}
		else //由于是文件,造成的删除失败
		{
			vfs_free(pInfo);								//释放申请的内存
			return -ENOTDIR;
		}
	}
	vfs_free(pInfo);								//释放申请的内存
	
	return ff_vfs_error(Status);					//错误代码转义
}

/*************************************************************************************************************************
* 函数			:	int ff_fchown(int fd, uid_t owner, gid_t group)
* 功能			:	更改文件的用户ID和组ID
* 参数			:	path:文件路径;owner:用户id;group:组id
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
int ff_fchown(int fd, uid_t owner, gid_t group)
{
	uart_printf("ff_fchown(0x%X, %d, %d)\r\n",fd, owner, group);
	return 0;
}

/*************************************************************************************************************************
* 函数			:	uid_t ff_geteuid (void)
* 功能			:	获取用户有效 UID 值
* 参数			:	无
* 返回			:	UID值
* 依赖			:	FATFS
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	
*************************************************************************************************************************/
uid_t ff_geteuid (void)
{
	uart_printf("ff_geteuid()\r\n");
	return 0;
}


/*************************************************************************************************************************
* 函数			:	int ff_utimes(const char *path, const struct timeval times[2])
* 功能			:	修改一个文件的访问时间和修改时间
* 参数			:	path:文件路径;times:存储访问时间与修改时间
* 返回			:	0:成功;负数:返回错误码
* 依赖			:	ucos iii
* 作者			:	cp1300@139.com
* 时间			:	2020-09-29
* 最后修改时间 	: 	2020-09-29
* 说明			: 	times = NULL时,则访问时间和修改时间都设置为当前时间
*************************************************************************************************************************/
int ff_utimes(const char *path, const struct timeval times[2])
{
	uart_printf("ff_utimes(%s,)\r\n", path);
	return 0;
}

//ff_vfs.h

/*************************************************************************************************************
 * 文件名		:	ff_vfs.h
 * 功能			:	VFS虚拟文件系统支持
 * 作者			:	cp1300@139.com
 * 创建时间		:	2020-09-29
 * 最后修改时间	:	2020-09-29
 * 详细			:	兼容linux的vfs文件系统API支持,需要先初始化fatfs
*************************************************************************************************************/
#ifndef _FF_VFS_H_
#define _FF_VFS_H_
#ifdef __cplusplus
extern "C"
{
#endif

#include "typedef.h"
#include "FF.h"
#include <time.h>

//设备id
typedef int dev_t;	//32为int数据,高12位主设备号,低20位次设备号


typedef int off_t;				//文件偏移此处使用32bit格式,由于FATFS最大只支持4G大小文件,此处设置为只支持2GB文件大小

typedef struct {
    u32 dd_vfs_fd;
    u32 dd_rsv;
} ff_dir_t;

//文件属性
struct stat {
	dev_t st_dev;
	u32 st_size;		//文件大小
	u32 st_mode;		//模式
	time_t  st_actime;  //最后访问时间
    time_t  st_modtime; //最后修改时间
	u64 st_ino;
	u32 st_nlink;
	u32 st_blksize;
	u32 st_uid;
	u32 st_gid;
};


typedef struct {
    u32 d_ino;    /* file number */
    u8 d_type;   /* type of file */
    char    d_name[]; /* file name */
} ff_dirent_t;

typedef const struct fs_ops   fs_ops_t;

struct ff_utimbuf {
    time_t actime;  /**< time of last access */
    time_t modtime; /**< time of last modification */
};
//用于  utimes 修改文件的访问时间,未实现
struct timeval 
{
     time_t tv_sec;        /* seconds */
     time_t tv_usec;       /* microseconds */
};


/* for posix fcntl() and lockf() */
#define F_RDLCK		0
#define F_WRLCK		1
#define F_UNLCK		2

//打开文件的参数flags定义
#define O_RDONLY	(1 << 0)				//以只读方式打开文件
#define O_WRONLY	(1 << 1)				//以只写方式打开
#define O_RDWR		(O_RDONLY | O_WRONLY)	//以可读可写方式打开
#define O_ACCMODE	(O_RDWR)
#define O_CREAT		(1 << 8)	//文件不存在时创建文件
#define O_EXCL		(1 << 9)	//在打开文件时,如果文件存在而且同时指定的标志位O_CREAT,则返回-EEXIST;如果文件不存在,则创建文件
#define O_NOCTTY	(1 << 10)
#define O_TRUNC		(1 << 11)	//打开文件时,如果文件的长度不为0,则将文件的长度截短为0,下次写入文件时,从文件开始出写入数据
#define O_APPEND	(1 << 12)	//打开文件后,将文件的写入点设置为文件末尾,下次写入文件时,新写入的数据会追加到文件末尾
#define O_DSYNC		(1 << 13)
#define O_NONBLOCK	(1 << 14)
#define O_SYNC		(1 << 15)

//文件偏移参数
#define VFS_SEEK_SET		(0)	//文件偏移设置为从文件开始处offset字节处
#define VFS_SEEK_CUR		(1)	//文件偏移设置为相对于当前文件位置的offset字节处
#define VFS_SEEK_END		(2)	//文件偏移摄者为文件末尾的offset字节处

//访问权限测试值
#define	R_OK				(1 << 2)
#define	W_OK				(1 << 1)
#define	X_OK				(1 << 0)

//文件特性,并未实现
struct flock {
	short	l_type;
	short	l_whence;
	short	l_start;
    short	l_len;
};
#define F_DUPFD		0	/* dup */
#define F_GETFD		1	/* get close_on_exec */
#define F_SETFD		2	/* set/clear close_on_exec */
#define F_GETFL		3	/* get file->f_flags */
#define F_SETFL		4	/* set file->f_flags */
#ifndef F_GETLK
#define F_GETLK		5
#define F_SETLK		6
#define F_SETLKW	7
#endif //F_GETLK

//文件权限模式,并未实现
typedef unsigned int mode_t;

//用户与组id,并未实现
typedef unsigned int uid_t;
typedef unsigned int gid_t;

#define F_OK	0

int ff_vfs_init(void);									//初始化VFS系统。系统启动流程中组件初始化函数
int ff_open(const char *path, int flags, int mode);		//打开path所描述的文件或者设备
int ff_close(int fd);									//关闭已打开的文件描述符fd
int ff_read(int fd, void *buf, size_t nbytes);			//从打开的文件中读取若干字节到buffer
int ff_write(int fd, const void *buf, size_t nbytes);	//将buffer开始出的nbytes字节数据写入到已经打开的文件
off_t ff_lseek(int fd, off_t offset, int whence);		//重新设置已打开文件的偏移
int ff_sync(int fd);									//会将对文件系统元数据(metadata)的修改以及文件系统内部缓存中的数据写入底层文件系统中
int ff_stat(const char *path, struct stat *st);			//读取文件的属性信息,如文件大小、文件模式(权限、文件/文件夹)
int ff_fstat(int fd, struct stat *st);					//读取文件的属性信息,如文件大小、文件模式(权限、文件/文件夹)等信息到st指针指向的buffer
int ff_link(const char *oldpath, const char *newpath);	//为文件创建一个新的链接文件。如果目标文件存在,则不会覆盖
int ff_unlink(const char *path);						//从文件系统中删除文件名
int ff_remove(const char *path);						//从文件系统中删除文件名,它既可以删除文件,也可以删除目录。
int ff_rename(const char *oldpath, const char *newpath);//重命名一个文件,可以将文件从一个文件夹下通过重命名移动到另外一个文件夹下
ff_dir_t *ff_opendir(const char *path);					//打开目录名path对应的目录流,并返回目录流指针
int ff_closedir(ff_dir_t *dirp);						//关闭目录流。调用ff_closedir()后,目录流指针不再可用
ff_dirent_t *ff_readdir(ff_dir_t *dirp);				//返回一个指向ff_dirent_t的指针,该指针关联的目录流dirp的成员指针指向下一个成员
int ff_mkdir(const char *path);							//创建名为path的目录。如果已经存在path目录,则创建失败
int ff_rmdir(const char *path);							//删除一个目录。删除目录时,目录必须为空。
void ff_rewinddir(ff_dir_t *dirp);						//将目录流dirp的位置重置为目录的开始处。
int ff_telldir(ff_dir_t *dirp);							//返回与目录流dirp相关联的目录流的当前位置。
void ff_seekdir(ff_dir_t *dir, long loc);				//设置目录流的位置,下次调用ff_readdir()时目录流将从设置的位置开始读取目录
int ff_access(const char *path, int amode);				//检查当前程序是否可以访问path文件
int ff_chdir(const char *path);							//改变当前程序的工作目录到path路径。
char *ff_getcwd(char *buf, size_t size);				//返回当当前程序的绝对工作目录字符串指针,同时如果buf参数不为空,也将当前工作目录字符串复制到buf中
long ff_pathconf(const char *path, int name);			//函数返回配置文件的限制值,是与文件或目录相关联的运行时限制。
long ff_fpathconf(int fd, int name);					//返回配置文件的限制值
int ff_utime(const char *path, const struct ff_utimbuf *times);	//通过参数times的actime和modtime成员改变文件的访问时间和修改时间
int ff_ftruncate(int fd, off_t  length);				//指定文件大小
int ff_fcntl(int fd, int cmd, struct flock *lock);		//根据文件描述词来操作文件的特性
int ff_fchmod(int fd, mode_t mode);						//改变现有文件的访问权限
int ff_fchown(int fd, uid_t owner, gid_t group);		//更改文件的用户ID和组ID
uid_t ff_geteuid (void);								//获取用户有效 UID 值
int ff_utimes(const char *path, const struct timeval times[2]);//修改一个文件的访问时间和修改时间


#define S_ISREG(st_mode)			0					//是否是一个常规文件-未实现
#define S_ISDIR(st_mode)			0					//是否是一个目录-未实现

//标准VFS文件接口
#define open 		ff_open								//打开文件
#define close 		ff_close							//关闭已打开的文件
#define read		ff_read								//读取已打开的文件
#define write		ff_write							//写入已打开的文件
#define lseek		ff_lseek							//重新设置已打开文件的偏移
//#define sync		ff_sync								//同步文件,刷新缓存
#define fsync		ff_sync								//同步文件,刷新缓存
__inline int stat(const char *path, struct stat *st) {return ff_stat(path, st);}	//获取文件信息,有重名的结构体,这个地方只能使用内联函数
#define fstat		ff_fstat							//获取文件信息
#define access		ff_access							//测试访问权限
#define getcwd		ff_getcwd							//返回当当前程序的绝对工作目录
#define ftruncate	ff_ftruncate						//指定文件大小
#define fcntl		ff_fcntl							//根据文件描述词来操作文件的特性
#define fchmod		ff_fchmod							//改变现有文件的访问权限
#define unlink		ff_unlink							//从文件系统中删除文件
#define mkdir	 	ff_mkdir							//创建名为path的目录
#define rmdir 		ff_rmdir							//删除一个目录
//#define fchown		ff_fchown							//更改文件的用户ID和组ID
//#define geteuid		ff_geteuid							//获取用户有效 UID 值
#define utimes		ff_utimes							//修改一个文件的访问时间和修改时间


#ifdef __cplusplus
}
#endif

#endif //_FF_VFS_H_

下面这些接口就是sqlite3中需要的

//标准VFS文件接口
#define open 		ff_open								//打开文件
#define close 		ff_close							//关闭已打开的文件
#define read		ff_read								//读取已打开的文件
#define write		ff_write							//写入已打开的文件
#define lseek		ff_lseek							//重新设置已打开文件的偏移
//#define sync		ff_sync								//同步文件,刷新缓存
#define fsync		ff_sync								//同步文件,刷新缓存
__inline int stat(const char *path, struct stat *st) {return ff_stat(path, st);}	//获取文件信息,有重名的结构体,这个地方只能使用内联函数
#define fstat		ff_fstat							//获取文件信息
#define access		ff_access							//测试访问权限
#define getcwd		ff_getcwd							//返回当当前程序的绝对工作目录
#define ftruncate	ff_ftruncate						//指定文件大小
#define fcntl		ff_fcntl							//根据文件描述词来操作文件的特性
#define fchmod		ff_fchmod							//改变现有文件的访问权限
#define unlink		ff_unlink							//从文件系统中删除文件
#define mkdir	 	ff_mkdir							//创建名为path的目录
#define rmdir 		ff_rmdir							//删除一个目录
//#define fchown		ff_fchown							//更改文件的用户ID和组ID
//#define geteuid		ff_geteuid							//获取用户有效 UID 值
#define utimes		ff_utimes							//修改一个文件的访问时间和修改时间

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cp1300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值