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 //修改一个文件的访问时间和修改时间