openharmony_kernel_liteos_m/components/fs/fatfs/fatfs.c

998 lines
24 KiB
C

/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE 1
#include "ff.h"
#include "fatfs.h"
#include "errno.h"
#include "stdbool.h"
#include "limits.h"
#include "pthread.h"
#include "time.h"
#include "securec.h"
#include "los_compiler.h"
#include "los_debug.h"
#include "los_sched.h"
#include "vfs_files.h"
#include "vfs_operations.h"
#include "vfs_partition.h"
#include "vfs_maps.h"
#include "vfs_mount.h"
#include "los_fs.h"
/* the max name length of different parts should not bigger than 32 */
#define FS_DRIVE_NAME_MAX_LEN 32
#ifndef FAT_MAX_OPEN_DIRS
#define FAT_MAX_OPEN_DIRS 8
#endif /* FAT_MAX_OPEN_DIRS */
#ifndef FS_LOCK_TIMEOUT_SEC
#define FS_LOCK_TIMEOUT_SEC 15
#endif /* FS_LOCK_TIMEOUT_SEC */
static UINT8 g_workBuffer[FF_MAX_SS];
static char *g_volPath[FF_VOLUMES] = {FF_VOLUME_STRS};
PARTITION VolToPart[] = {
{ 0, 0, 1, 0, 0 },
{ 0, 0, 2, 0, 0 },
{ 0, 0, 3, 0, 0 },
{ 0, 0, 4, 0, 0 }
};
static int FsChangeDrive(const char *path)
{
INT32 res;
errno_t retErr;
UINT16 pathLen = strlen((char const *)path);
/* the max name length of different parts is 16 */
CHAR tmpPath[FS_DRIVE_NAME_MAX_LEN] = { "/" };
/* make sure the path begin with "/", the path like /xxx/yyy/... */
if (pathLen >= (FS_DRIVE_NAME_MAX_LEN - 1)) {
/* 2: except first flag "/" and last end flag */
pathLen = FS_DRIVE_NAME_MAX_LEN - 2;
}
retErr = strncpy_s(tmpPath + 1, (FS_DRIVE_NAME_MAX_LEN - 1), (char const *)path, pathLen);
if (retErr != EOK) {
return (int)LOS_NOK;
}
res = f_chdrive(tmpPath);
if (res != FR_OK) {
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
static int Remount(struct MountPoint *mp, unsigned long mountflags)
{
FATFS *fatfs = (FATFS *)mp->mData;
/* remount is not allowed when the device is not mounted. */
if (fatfs->fs_type == 0) {
errno = EINVAL;
return (int)LOS_NOK;
}
mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE;
return (int)LOS_OK;
}
static unsigned int FatFsGetMode(int oflags)
{
UINT32 fmode = FA_READ;
if ((UINT32)oflags & O_WRONLY) {
fmode |= FA_WRITE;
}
if (((UINT32)oflags & O_ACCMODE) & O_RDWR) {
fmode |= FA_WRITE;
}
/* Creates a new file if the file is not existing, otherwise, just open it. */
if ((UINT32)oflags & O_CREAT) {
fmode |= FA_OPEN_ALWAYS;
/* Creates a new file. If the file already exists, the function shall fail. */
if ((UINT32)oflags & O_EXCL) {
fmode |= FA_CREATE_NEW;
}
}
/* Creates a new file. If the file already exists, its length shall be truncated to 0. */
if ((UINT32)oflags & O_TRUNC) {
fmode |= FA_CREATE_ALWAYS;
}
return fmode;
}
static int FatfsErrno(int result)
{
INT32 status = 0;
if (result < 0) {
return result;
}
/* FatFs errno to Libc errno */
switch (result) {
case FR_OK:
break;
case FR_NO_FILE:
case FR_NO_PATH:
case FR_NO_FILESYSTEM:
status = ENOENT;
break;
case FR_INVALID_NAME:
status = EINVAL;
break;
case FR_EXIST:
case FR_INVALID_OBJECT:
status = EEXIST;
break;
case FR_DISK_ERR:
case FR_NOT_READY:
case FR_INT_ERR:
status = EIO;
break;
case FR_WRITE_PROTECTED:
status = EROFS;
break;
case FR_MKFS_ABORTED:
case FR_INVALID_PARAMETER:
status = EINVAL;
break;
case FR_NO_SPACE_LEFT:
status = ENOSPC;
break;
case FR_NO_DIRENTRY:
status = ENFILE;
break;
case FR_NO_EMPTY_DIR:
status = ENOTEMPTY;
break;
case FR_IS_DIR:
status = EISDIR;
break;
case FR_NO_DIR:
status = ENOTDIR;
break;
case FR_NO_EPERM:
case FR_DENIED:
status = EPERM;
break;
case FR_LOCKED:
status = EBUSY;
break;
default:
status = result;
break;
}
return status;
}
char * GetLdPath(const char *source)
{
#define LDPATH_PAD 2 // 2 means: strlen("/") + len of '\0'
int ret;
int partId = GetPartIdByPartName(source);
if ((partId < 0) || (partId >= MAX_PARTITION_NUM)) {
return NULL;
}
char *volPath = g_volPath[partId];
char *ldPath = (char *)LOSCFG_FS_MALLOC_HOOK(strlen(volPath) + LDPATH_PAD);
if (ldPath == NULL) {
return NULL;
}
(void)memset_s(ldPath, strlen(volPath) + LDPATH_PAD, 0, strlen(volPath) + LDPATH_PAD);
/* Convert volPath to ldpath, for example, convert "inner" to "/inner" */
*ldPath = '/';
ret = strcpy_s(ldPath + 1, strlen(volPath)+1, volPath);
if (ret != EOK) {
LOSCFG_FS_FREE_HOOK(ldPath);
return NULL;
}
return ldPath;
}
void PutLdPath(const char *ldPath)
{
if (ldPath != NULL) {
LOSCFG_FS_FREE_HOOK((void *)ldPath);
}
}
int FatfsMount(struct MountPoint *mp, unsigned long mountflags,
const void *data)
{
FRESULT res;
FATFS *fs = NULL;
if (mountflags & MS_REMOUNT) {
return Remount(mp, mountflags);
}
char *ldPath = GetLdPath(mp->mDev);
if (ldPath == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
fs = (FATFS *)LOSCFG_FS_MALLOC_HOOK(sizeof(FATFS));
if (fs == NULL) {
errno = ENOMEM;
PutLdPath(ldPath);
return (int)LOS_NOK;
}
(void)memset_s(fs, sizeof(FATFS), 0, sizeof(FATFS));
res = f_mount(fs, ldPath, 1);
if (res != FR_OK) {
LOSCFG_FS_FREE_HOOK(fs);
PutLdPath(ldPath);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
mp->mData = (void *)fs;
PutLdPath(ldPath);
return (int)LOS_OK;
}
int FatfsUmount(struct MountPoint *mp)
{
int volId;
FRESULT res;
char *ldPath = NULL;
FATFS *fatfs = (FATFS *)mp->mData;
/* The volume is not mounted */
if (fatfs->fs_type == 0) {
errno = EINVAL;
return (int)LOS_NOK;
}
volId = GetPartIdByPartName(mp->mDev);
/* umount is not allowed when a file or directory is opened. */
if (f_checkopenlock(volId) != FR_OK) {
errno = EBUSY;
return (int)LOS_NOK;
}
ldPath = GetLdPath(mp->mDev);
if (ldPath == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
res = f_mount((FATFS *)NULL, ldPath, 0);
if (res != FR_OK) {
errno = FatfsErrno(res);
PutLdPath(ldPath);
return (int)LOS_NOK;
}
if (fatfs->win != NULL) {
ff_memfree(fatfs->win);
}
LOSCFG_FS_FREE_HOOK(mp->mData);
mp->mData = NULL;
PutLdPath(ldPath);
return (int)LOS_OK;
}
int FatfsUmount2(struct MountPoint *mp, int flag)
{
UINT32 flags;
FRESULT res;
char *ldPath = NULL;
FATFS *fatfs = (FATFS *)mp->mData;
flags = MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW;
if ((UINT32)flag & ~flags) {
errno = EINVAL;
return (int)LOS_NOK;
}
/* The volume is not mounted */
if (fatfs->fs_type == 0) {
errno = EINVAL;
return (int)LOS_NOK;
}
ldPath = GetLdPath(mp->mDev);
if (ldPath == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
res = f_mount((FATFS *)NULL, ldPath, 0);
if (res != FR_OK) {
PutLdPath(ldPath);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
if (fatfs->win != NULL) {
ff_memfree(fatfs->win);
}
LOSCFG_FS_FREE_HOOK(mp->mData);
mp->mData = NULL;
PutLdPath(ldPath);
return (int)LOS_OK;
}
int FatfsOpen(struct File *file, const char *path, int oflag)
{
FRESULT res;
UINT32 fmode;
FIL *fp = NULL;
int ret;
if (path == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
fmode = FatFsGetMode(oflag);
fp = (FIL *)LOSCFG_FS_MALLOC_HOOK(sizeof(FIL));
if (fp == NULL) {
errno = ENOMEM;
return (int)LOS_NOK;
}
(void)memset_s(fp, sizeof(FIL), 0, sizeof(FIL));
ret = FsChangeDrive(path);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT open ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
LOSCFG_FS_FREE_HOOK(fp);
return (int)LOS_NOK;
}
res = f_open(fp, path, fmode);
if (res != FR_OK) {
PRINT_ERR("FAT open err 0x%x!\r\n", res);
LOSCFG_FS_FREE_HOOK(fp);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
file->fData = (void *)fp;
return (int)LOS_OK;
}
int FatfsClose(struct File *file)
{
FRESULT res;
FIL *fp = (FIL *)file->fData;
if ((fp == NULL) || (fp->obj.fs == NULL)) {
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_close(fp);
if (res != FR_OK) {
PRINT_ERR("FAT close err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
#if !FF_FS_TINY
if (fp->buf != NULL) {
(void)ff_memfree(fp->buf);
}
#endif
LOSCFG_FS_FREE_HOOK(file->fData);
file->fData = NULL;
return (int)LOS_OK;
}
ssize_t FatfsRead(struct File *file, char *buf, size_t nbyte)
{
FRESULT res;
UINT32 lenRead;
FIL *fp = (FIL *)file->fData;
if (buf == NULL) {
errno = EFAULT;
return (ssize_t)LOS_NOK;
}
if (fp == NULL) {
errno = ENOENT;
return (ssize_t)LOS_NOK;
}
res = f_read(fp, buf, nbyte, &lenRead);
if (res != FR_OK) {
errno = FatfsErrno(res);
return (ssize_t)LOS_NOK;
}
return (ssize_t)lenRead;
}
ssize_t FatfsWrite(struct File *file, const char *buf, size_t nbyte)
{
FRESULT res;
UINT32 lenWrite;
static BOOL overFlow = FALSE;
FIL *fp = (FIL *)file->fData;
if (buf == NULL) {
errno = EFAULT;
return (ssize_t)LOS_NOK;
}
if ((fp == NULL) || (fp->obj.fs == NULL)) {
errno = ENOENT;
return (ssize_t)LOS_NOK;
}
res = f_write(fp, buf, nbyte, &lenWrite);
if ((res == FR_OK) && (lenWrite == 0) && (nbyte != 0) && (overFlow == FALSE)) {
overFlow = TRUE;
PRINT_ERR("FAT write err!\r\n");
}
if ((res != FR_OK) || (nbyte != lenWrite)) {
errno = FatfsErrno(res);
return (ssize_t)LOS_NOK;
}
return (ssize_t)lenWrite;
}
off_t FatfsLseek(struct File *file, off_t offset, int whence)
{
FRESULT res;
off_t pos;
FIL *fp = (FIL *)file->fData;
if ((fp == NULL) || (fp->obj.fs == NULL)) {
errno = ENOENT;
return (off_t)LOS_NOK;
}
if (whence == SEEK_SET) {
pos = 0;
} else if (whence == SEEK_CUR) {
pos = f_tell(fp);
} else if (whence == SEEK_END) {
pos = f_size(fp);
} else {
errno = EINVAL;
return (off_t)LOS_NOK;
}
res = f_lseek(fp, offset + pos);
if (res != FR_OK) {
errno = FatfsErrno(res);
return (off_t)LOS_NOK;
}
pos = f_tell(fp);
return pos;
}
/* Remove the specified FILE */
int FatfsUnlink(struct MountPoint *mp, const char *path)
{
FRESULT res;
int ret;
if (path == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
if (!mp->mWriteEnable) {
errno = EACCES;
return (int)LOS_NOK;
}
ret = FsChangeDrive(path);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT unlink ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_unlink(path);
if (res != FR_OK) {
PRINT_ERR("FAT unlink err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf)
{
FRESULT res;
FILINFO fileInfo = {0};
int ret;
if ((path == NULL) || (buf == NULL)) {
errno = EFAULT;
return (int)LOS_NOK;
}
ret = FsChangeDrive(path);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT stat ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_stat(path, &fileInfo);
if (res != FR_OK) {
PRINT_ERR("FAT stat err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
buf->st_size = fileInfo.fsize;
buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH |
S_IXUSR | S_IXGRP | S_IXOTH;
if (fileInfo.fattrib & AM_RDO) {
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
if (fileInfo.fattrib & AM_DIR) {
buf->st_mode &= ~S_IFREG;
buf->st_mode |= S_IFDIR;
}
return (int)LOS_OK;
}
/* Synchronize all changes to Flash */
int FatfsSync(struct File *file)
{
FRESULT res;
FIL *fp = (FIL *)file->fData;
if ((fp == NULL) || (fp->obj.fs == NULL)) {
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_sync(fp);
if (res != FR_OK) {
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsMkdir(struct MountPoint *mp, const char *path)
{
FRESULT res;
int ret;
if (path == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
if (!mp->mWriteEnable) {
errno = EACCES;
return (int)LOS_NOK;
}
ret = FsChangeDrive(path);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT mkdir ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_mkdir(path);
if (res != FR_OK) {
PRINT_ERR("FAT mkdir err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsOpendir(struct Dir *dir, const char *dirName)
{
FRESULT res;
DIR *dp = NULL;
int ret;
if (dirName == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
ret = FsChangeDrive(dirName);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT opendir ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
dp = (DIR *)LOSCFG_FS_MALLOC_HOOK(sizeof(DIR));
if (dp == NULL) {
errno = ENOENT;
return (int)LOS_NOK;
}
(void)memset_s(dp, sizeof(DIR), 0, sizeof(DIR));
res = f_opendir(dp, dirName);
if (res != FR_OK) {
PRINT_ERR("FAT opendir err 0x%x!\r\n", res);
LOSCFG_FS_FREE_HOOK(dp);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
dir->dData = dp;
dir->dOffset = 0;
return (int)LOS_OK;
}
int FatfsReaddir(struct Dir *dir, struct dirent *dent)
{
FRESULT res;
FILINFO fileInfo = {0};
DIR *dp = NULL;
if ((dir == NULL) || (dir->dData == NULL)) {
errno = EBADF;
return (int)LOS_NOK;
}
dp = (DIR *)dir->dData;
res = f_readdir(dp, &fileInfo);
/* if res not ok or fname is NULL , return NULL */
if ((res != FR_OK) || (fileInfo.fname[0] == 0x0)) {
PRINT_ERR("FAT readdir err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
(void)memcpy_s(dent->d_name, sizeof(dent->d_name),
fileInfo.fname, sizeof(dent->d_name));
if (fileInfo.fattrib & AM_DIR) {
dent->d_type = DT_DIR;
} else {
dent->d_type = DT_REG;
}
return (int)LOS_OK;
}
int FatfsClosedir(struct Dir *dir)
{
FRESULT res;
DIR *dp = NULL;
if ((dir == NULL) || (dir->dData == NULL)) {
errno = EBADF;
return (int)LOS_NOK;
}
dp = dir->dData;
res = f_closedir(dp);
if (res != FR_OK) {
PRINT_ERR("FAT closedir err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
LOSCFG_FS_FREE_HOOK(dir->dData);
dir->dData = NULL;
return (int)LOS_OK;
}
int FatfsRmdir(struct MountPoint *mp, const char *path)
{
FRESULT res;
int ret;
if ((path == NULL) || (mp == NULL)) {
errno = EFAULT;
return (int)LOS_NOK;
}
if (!mp->mWriteEnable) {
errno = EACCES;
return (int)LOS_NOK;
}
ret = FsChangeDrive(path);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT rmdir ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_rmdir(path);
if (res != FR_OK) {
PRINT_ERR("FAT rmdir err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName)
{
FRESULT res;
int ret;
if ((oldName == NULL) || (newName == NULL)) {
errno = EFAULT;
return (int)LOS_NOK;
}
if (!mp->mWriteEnable) {
errno = EACCES;
return (int)LOS_NOK;
}
ret = FsChangeDrive(oldName);
if (ret != (int)LOS_OK) {
PRINT_ERR("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret);
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_rename(oldName, newName);
if (res != FR_OK) {
PRINT_ERR("FAT frename err 0x%x!\r\n", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsStatfs(const char *path, struct statfs *buf)
{
FATFS *fs = NULL;
UINT32 freeClust;
FRESULT res;
int ret;
if ((path == NULL) || (buf == NULL)) {
errno = EFAULT;
return (int)LOS_NOK;
}
ret = FsChangeDrive(path);
if (ret != FR_OK) {
PRINT_ERR("FAT f_getfree ChangeDrive err %d.", ret);
errno = FatfsErrno(FR_INVALID_PARAMETER);
return (int)LOS_NOK;
}
res = f_getfree(path, &freeClust, &fs);
if (res != FR_OK) {
PRINT_ERR("FAT f_getfree err 0x%x.", res);
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
buf->f_bfree = freeClust;
buf->f_bavail = freeClust;
/* Cluster #0 and #1 is for VBR, reserve sectors and fat */
buf->f_blocks = fs->n_fatent - 2;
#if FF_MAX_SS != FF_MIN_SS
buf->f_bsize = fs->ssize * fs->csize;
#else
buf->f_bsize = FF_MIN_SS * fs->csize;
#endif
return (int)LOS_OK;
}
static int DoTruncate(struct File *file, off_t length, UINT32 count)
{
FRESULT res = FR_OK;
DWORD csz;
FIL *fp = (FIL *)file->fData;
csz = (DWORD)(fp->obj.fs)->csize * SS(fp->obj.fs); /* Cluster size */
if (length > csz * count) {
#if FF_USE_EXPAND
res = f_expand(fp, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE);
#else
errno = ENOSYS;
return (int)LOS_NOK;
#endif
} else if (length < csz * count) {
res = f_truncate(fp, (FSIZE_t)length);
}
if (res != FR_OK) {
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
fp->obj.objsize = length; /* Set file size to length */
fp->flag |= 0x40; /* Set modified flag */
return (int)LOS_OK;
}
int FatfsTruncate(struct File *file, off_t length)
{
FRESULT res;
UINT count;
DWORD fclust;
FIL *fp = (FIL *)file->fData;
if ((length < 0) || (length > UINT_MAX)) {
errno = EINVAL;
return (int)LOS_NOK;
}
if ((fp == NULL) || (fp->obj.fs == NULL)) {
errno = ENOENT;
return (int)LOS_NOK;
}
res = f_getclustinfo(fp, &fclust, &count);
if (res != FR_OK) {
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return DoTruncate(file, length, count);
}
int FatfsFdisk(const char *dev, int *partTbl, int arrayNum)
{
int pdrv;
FRESULT res;
if ((dev == NULL) || (partTbl == NULL)) {
errno = EFAULT;
return (int)LOS_NOK;
}
pdrv = GetDevIdByDevName(dev);
if (pdrv < 0) {
errno = EFAULT;
return (int)LOS_NOK;
}
res = f_fdisk(pdrv, (DWORD const *)partTbl, g_workBuffer);
if (res != FR_OK) {
errno = FatfsErrno(res);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
int FatfsFormat(const char *partName, void *privData)
{
FRESULT res;
MKFS_PARM opt = {0};
int option = *(int *)privData;
char *dev = NULL; /* logical driver */
if (partName == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
dev = GetLdPath(partName);
if (dev == NULL) {
errno = EFAULT;
return (int)LOS_NOK;
}
opt.fmt = option;
opt.n_sect = 0; /* use default allocation unit size depends on the volume
size. */
res = f_mkfs(dev, &opt, g_workBuffer, FF_MAX_SS);
if (res != FR_OK) {
errno = FatfsErrno(res);
PutLdPath(dev);
return (int)LOS_NOK;
}
return (int)LOS_OK;
}
static struct MountOps g_fatfsMnt = {
.mount = FatfsMount,
.umount = FatfsUmount,
.umount2 = FatfsUmount2,
.statfs = FatfsStatfs,
};
static struct FileOps g_fatfsFops = {
.open = FatfsOpen,
.close = FatfsClose,
.read = FatfsRead,
.write = FatfsWrite,
.lseek = FatfsLseek,
.stat = FatfsStat,
.truncate = FatfsTruncate,
.unlink = FatfsUnlink,
.rename = FatfsRename,
.ioctl = NULL, /* not support */
.sync = FatfsSync,
.opendir = FatfsOpendir,
.readdir = FatfsReaddir,
.closedir = FatfsClosedir,
.mkdir = FatfsMkdir,
.rmdir = FatfsRmdir,
};
static struct FsManagement g_fatfsMgt = {
.fdisk = FatfsFdisk,
.format = FatfsFormat,
};
void FatFsInit(void)
{
(void)OsFsRegister("vfat", &g_fatfsMnt, &g_fatfsFops, &g_fatfsMgt);
}