From 09034de68a4aa752f34a2bc7ada6237c4cf9cd83 Mon Sep 17 00:00:00 2001 From: Guangyao Ma Date: Sat, 9 Oct 2021 10:07:59 +0800 Subject: [PATCH] refactor: liteos-m vfs refactory close #I4RV26 Change-Id: I76d5d5128d37efa5fbcde6d105c78f4d7be607de Signed-off-by: Guangyao Ma --- Kconfig | 2 +- components/fs/fatfs/Kconfig | 35 +- components/fs/fatfs/fatfs.c | 1110 +++++-------- components/fs/fatfs/fatfs.h | 62 +- components/fs/littlefs/BUILD.gn | 2 +- components/fs/littlefs/lfs_adapter.c | 596 +++++++ .../fs/littlefs/{lfs_api.h => lfs_adapter.h} | 64 +- components/fs/littlefs/lfs_api.c | 891 ----------- components/fs/vfs/BUILD.gn | 24 +- components/fs/vfs/Kconfig | 6 +- components/fs/vfs/fs_operations.h | 82 - components/fs/vfs/los_fs.c | 649 -------- components/fs/vfs/los_fs.h | 100 +- components/fs/vfs/vfs_config.h | 52 +- components/fs/vfs/vfs_files.c | 98 ++ components/fs/vfs/vfs_files.h | 104 ++ components/fs/vfs/vfs_fs.c | 1392 +++++++++++++++++ components/fs/vfs/vfs_init.c | 54 + components/fs/vfs/vfs_maps.c | 87 ++ components/fs/vfs/vfs_maps.h | 69 + components/fs/vfs/vfs_mount.c | 294 ++++ components/fs/vfs/vfs_mount.h | 76 + components/fs/vfs/vfs_operations.h | 64 + components/fs/vfs/vfs_partition.c | 104 ++ components/fs/vfs/vfs_partition.h | 51 + kal/libc/newlib/porting/include/sys/socket.h | 6 +- kal/libc/newlib/porting/include/sys/uio.h | 5 + kal/libc/newlib/porting/src/fs.c | 7 +- kernel/src/los_init.c | 9 + 29 files changed, 3499 insertions(+), 2596 deletions(-) create mode 100644 components/fs/littlefs/lfs_adapter.c rename components/fs/littlefs/{lfs_api.h => lfs_adapter.h} (54%) delete mode 100644 components/fs/littlefs/lfs_api.c delete mode 100644 components/fs/vfs/fs_operations.h delete mode 100644 components/fs/vfs/los_fs.c create mode 100644 components/fs/vfs/vfs_files.c create mode 100644 components/fs/vfs/vfs_files.h create mode 100644 components/fs/vfs/vfs_fs.c create mode 100644 components/fs/vfs/vfs_init.c create mode 100644 components/fs/vfs/vfs_maps.c create mode 100644 components/fs/vfs/vfs_maps.h create mode 100644 components/fs/vfs/vfs_mount.c create mode 100644 components/fs/vfs/vfs_mount.h create mode 100644 components/fs/vfs/vfs_operations.h create mode 100644 components/fs/vfs/vfs_partition.c create mode 100644 components/fs/vfs/vfs_partition.h diff --git a/Kconfig b/Kconfig index dadbeb5a..882e6003 100644 --- a/Kconfig +++ b/Kconfig @@ -408,7 +408,7 @@ endmenu ######################## config options of filesystem ################## menu "FileSystem" -rsource "components/fs/Kconfig" +rsource "components/fs/vfs/Kconfig" endmenu diff --git a/components/fs/fatfs/Kconfig b/components/fs/fatfs/Kconfig index 705b9101..e3b456fa 100644 --- a/components/fs/fatfs/Kconfig +++ b/components/fs/fatfs/Kconfig @@ -36,39 +36,8 @@ config FS_FAT help Answer Y to enable LiteOS support fat filesystem. -config FS_FAT_CACHE - bool "Enable FAT Cache" - default y +config SUPPORT_FATFS + bool depends on FS_FAT - help - Answer Y to enable LiteOS fat filesystem support cache. - -config FS_FAT_CACHE_SYNC_THREAD - bool "Enable FAT Cache Sync Thread" - default n - depends on FS_FAT_CACHE - help - Answer Y to enable LiteOS fat filesystem support cache sync thread. - -config FS_FAT_CHINESE - bool "Enable Chinese" - default y - depends on FS_FAT - help - Answer Y to enable LiteOS fat filesystem support Chinese. - -config FS_FAT_VIRTUAL_PARTITION - bool "Enabel Virtual Partition" default n - depends on FS_FAT -config FS_FAT_VOLUMES - int - depends on FS_FAT - default 32 if PLATFORM_HI3731 - default 16 - -config FS_FAT_DISK - bool "Enable partinfo for storage device" - depends on FS_FAT - default y diff --git a/components/fs/fatfs/fatfs.c b/components/fs/fatfs/fatfs.c index 48365d98..11819fc8 100644 --- a/components/fs/fatfs/fatfs.c +++ b/components/fs/fatfs/fatfs.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 Huawei Device 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: @@ -41,7 +41,11 @@ #include "los_compiler.h" #include "los_debug.h" #include "cmsis_os2.h" -#include "fs_operations.h" +#include "vfs_files.h" +#include "vfs_operations.h" +#include "vfs_partition.h" +#include "vfs_maps.h" +#include "vfs_mount.h" /* the max name length of different parts should not bigger than 32 */ #define FS_DRIVE_NAME_MAX_LEN 32 @@ -54,27 +58,16 @@ #define FS_LOCK_TIMEOUT_SEC 15 #endif /* FS_LOCK_TIMEOUT_SEC */ -#define PART_NAME 0x0 -#define VOLUME_NAME 0x1 -#define PATH_NAME 0x2 -#define NAME_MASK 0x3 - -typedef struct { - UINT8 useFlag; - FIL fil; -} FatHandleStruct; - -static FatHandleStruct g_handle[FAT_MAX_OPEN_FILES] = {0}; -static DIR g_dir[FAT_MAX_OPEN_DIRS] = {0}; -static FATFS g_fatfs[FF_VOLUMES] = {0}; static UINT8 g_workBuffer[FF_MAX_SS]; -static UINT32 g_fileNum = 0; -static UINT32 g_dirNum = 0; -static struct dirent g_retValue; -static pthread_mutex_t g_fsMutex = PTHREAD_MUTEX_INITIALIZER; - -static const char * const g_volPath[FF_VOLUMES] = {FF_VOLUME_STRS}; -static BOOL g_volWriteEnable[FF_VOLUMES] = {FALSE}; +static pthread_mutex_t g_fatfsMutex = PTHREAD_MUTEX_INITIALIZER; +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 FsLock(void) { @@ -85,11 +78,11 @@ static int FsLock(void) } ret = clock_gettime(CLOCK_REALTIME, &absTimeout); if (ret != 0) { - PRINTK("clock gettime err 0x%x!\r\n", errno); + PRINT_ERR("clock gettime err 0x%x!\r\n", errno); return errno; } absTimeout.tv_sec += FS_LOCK_TIMEOUT_SEC; - ret = pthread_mutex_timedlock(&g_fsMutex, &absTimeout); + ret = pthread_mutex_timedlock(&g_fatfsMutex, &absTimeout); return ret; } @@ -98,24 +91,17 @@ static void FsUnlock(void) if (osKernelGetState() != osKernelRunning) { return; } - (void)pthread_mutex_unlock(&g_fsMutex); -} - -static bool IsValidFd(int fd) -{ - if ((fd < 0) || (fd >= FAT_MAX_OPEN_FILES) || (g_handle[fd].useFlag == 0)) { - return false; - } - return true; + (void)pthread_mutex_unlock(&g_fatfsMutex); } static int FsChangeDrive(const char *path) { INT32 res; - CHAR tmpPath[FS_DRIVE_NAME_MAX_LEN] = { "/" }; /* the max name length of different parts is 16 */ errno_t retErr; - UINT16 pathLen; - pathLen = strlen((char const *)path); + 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 */ @@ -124,99 +110,29 @@ static int FsChangeDrive(const char *path) retErr = strncpy_s(tmpPath + 1, (FS_DRIVE_NAME_MAX_LEN - 1), (char const *)path, pathLen); if (retErr != EOK) { - return FS_FAILURE; + return LOS_NOK; } res = f_chdrive(tmpPath); if (res != FR_OK) { - return FS_FAILURE; + return LOS_NOK; } - return FS_SUCCESS; + return LOS_OK; } -static int FsPartitionMatch(const char *path, int flag) +static int Remount(struct MountPoint *mp, unsigned long mountflags) { - INT32 ret; - UINT32 index; - CHAR tmpName[FF_MAX_LFN] = {0}; - - if (path == NULL) { - return FS_FAILURE; - } - - switch ((UINT32)flag & NAME_MASK) { - case VOLUME_NAME: - ret = sscanf_s(path, "/%[^/]", tmpName, FF_MAX_LFN); - if (ret <= 0) { - return FS_FAILURE; - } - break; - case PATH_NAME: - ret = sscanf_s(path, "%[^/]", tmpName, FF_MAX_LFN); - if (ret <= 0) { - return FS_FAILURE; - } - break; - case PART_NAME: - default: - ret = strcpy_s(tmpName, FF_MAX_LFN, path); - if (ret != EOK) { - return FS_FAILURE; - } - } - - for (index = 0; index < FF_VOLUMES; index++) { - if (strcmp(tmpName, g_volPath[index]) == 0) { - return index; - } - } - return FS_FAILURE; -} - -static int Remount(const char *path, unsigned long mountflags) -{ - INT32 index; - - index = FsPartitionMatch(path, PART_NAME); - if (index == FS_FAILURE) { - PRINTK("Wrong volume path!\r\n"); - errno = ENOENT; - return FS_FAILURE; - } + FATFS *fatfs = (FATFS *)mp->mData; /* remount is not allowed when the device is not mounted. */ - if (g_fatfs[index].fs_type == 0) { + if (fatfs->fs_type == 0) { errno = EINVAL; - return FS_FAILURE; - } - g_volWriteEnable[index] = (mountflags & MS_RDONLY) ? FALSE : TRUE; - - return FS_SUCCESS; -} - -static bool FsCheckByPath(const char *path) -{ - INT32 index; - - index = FsPartitionMatch(path, PATH_NAME); - if (index == FS_FAILURE) { - return FS_FAILURE; + return LOS_NOK; } + mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE; - return g_volWriteEnable[index]; -} - -static bool FsCheckByID(int id) -{ - INT32 index; - - for (index = 0; index < FF_VOLUMES; index++) { - if (g_fatfs[index].id == id) { - return g_volWriteEnable[index]; - } - } - return false; + return LOS_OK; } static unsigned int FatFsGetMode(int oflags) @@ -318,430 +234,357 @@ static int FatfsErrno(int result) return status; } -int fatfs_mount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data) +char * GetLdPath(const char *source) { - INT32 index; - FRESULT res; - INT32 ret; + int ret; + int partId = GetPartIdByPartName(source); + if ((partId < 0) || (partId >= MAX_PARTITION_NUM)) { + return NULL; + } - if ((target == NULL) || (filesystemtype == NULL)) { - errno = EFAULT; - return FS_FAILURE; + char *volPath = g_volPath[partId]; + char *ldPath = (char *)malloc(strlen(volPath) + 1); + if (ldPath == NULL) { + return NULL; } + (void)memset_s(ldPath, strlen(volPath) + 1, 0, strlen(volPath) + 1); + + /* Convert volPath to ldpath, for example, convert "inner" to "/inner" */ + *ldPath = '/'; + ret = strcpy_s(ldPath + 1, strlen(volPath), volPath); + if (ret != EOK) { + free(ldPath); + return NULL; + } + + return ldPath; +} + +void PutLdPath(const char *ldPath) +{ + if (ldPath != NULL) { + free((void *)ldPath); + } +} + +int FatfsMount(struct MountPoint *mp, unsigned long mountflags, + const void *data) +{ + FRESULT res; + INT32 ret; + FATFS *fs = NULL; + ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (mountflags & MS_REMOUNT) { - ret = Remount(target, mountflags); - goto OUT; - } - - if (strcmp(filesystemtype, "fat") != 0) { - errno = ENODEV; - ret = FS_FAILURE; - goto OUT; + char *ldPath = GetLdPath(mp->mDev); + if (ldPath == NULL) { + errno = EFAULT; + ret = LOS_NOK; + goto ERROUT; } - index = FsPartitionMatch(target, VOLUME_NAME); - if (index == FS_FAILURE) { - errno = ENODEV; - ret = FS_FAILURE; - goto OUT; + if (mountflags & MS_REMOUNT) { + ret = Remount(mp, mountflags); + goto ERROUT; } - /* If the volume has been mounted */ - if (g_fatfs[index].fs_type != 0) { - errno = EBUSY; - ret = FS_FAILURE; - goto OUT; + fs = (FATFS *)malloc(sizeof(FATFS)); + if (fs == NULL) { + errno = ENOMEM; + ret = LOS_NOK; + goto ERROUT; } + (void)memset_s(fs, sizeof(FATFS), 0, sizeof(FATFS)); + mp->mData = (void *)fs; - res = f_mount(&g_fatfs[index], target, 1); + res = f_mount((FATFS *)mp->mData, ldPath, 1); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; - goto OUT; + ret = LOS_NOK; + goto ERROUT; } - g_volWriteEnable[index] = (mountflags & MS_RDONLY) ? FALSE : TRUE; - ret = FS_SUCCESS; + PutLdPath(ldPath); + FsUnlock(); + return LOS_OK; -OUT: +ERROUT: + free(fs); + mp->mData = NULL; + PutLdPath(ldPath); FsUnlock(); return ret; } -int fatfs_umount(const char *target) +int FatfsUmount(struct MountPoint *mp) { FRESULT res; INT32 ret; - INT32 index; - - if (target == NULL) { - errno = EFAULT; - return FS_FAILURE; - } + INT32 volId; + FATFS *fatfs = (FATFS *)mp->mData; ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - index = FsPartitionMatch(target, VOLUME_NAME); - if (index == FS_FAILURE) { - errno = ENOENT; - ret = FS_FAILURE; + char *ldPath = GetLdPath(mp->mDev); + if (ldPath == NULL) { + errno = EFAULT; + ret = LOS_NOK; goto OUT; } /* The volume is not mounted */ - if (g_fatfs[index].fs_type == 0) { + if (fatfs->fs_type == 0) { errno = EINVAL; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } + volId = GetPartIdByPartName(mp->mDev); /* umount is not allowed when a file or diretory is opened. */ - if (f_checkopenlock(index) != FR_OK) { + if (f_checkopenlock(volId) != FR_OK) { errno = EBUSY; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - res = f_mount((FATFS *)NULL, target, 0); + res = f_mount((FATFS *)NULL, ldPath, 0); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - if (g_fatfs[index].win != NULL) { - ff_memfree(g_fatfs[index].win); + if (fatfs->win != NULL) { + ff_memfree(fatfs->win); } - (void)memset_s(&g_fatfs[index], sizeof(FATFS), 0x0, sizeof(FATFS)); + free(mp->mData); + mp->mData = NULL; - ret = FS_SUCCESS; + ret = LOS_OK; OUT: + PutLdPath(ldPath); FsUnlock(); return ret; } -static int CloseAll(int index) +int FatfsUmount2(struct MountPoint *mp, int flag) { - INT32 i; - FRESULT res; - - for (i = 0; i < FAT_MAX_OPEN_FILES; i++) { - if (g_fileNum <= 0) { - break; - } - if ((g_handle[i].useFlag == 1) && (g_handle[i].fil.obj.fs == &g_fatfs[index])) { - res = f_close(&g_handle[i].fil); - if (res != FR_OK) { - errno = FatfsErrno(res); - return FS_FAILURE; - } - (void)memset_s(&g_handle[i], sizeof(FatHandleStruct), 0x0, sizeof(FatHandleStruct)); - g_fileNum--; - } - } - - for (i = 0; i < FAT_MAX_OPEN_DIRS; i++) { - if (g_dirNum <= 0) { - break; - } - if (g_dir[i].obj.fs == &g_fatfs[index]) { - res = f_closedir(&g_dir[i]); - if (res != FR_OK) { - errno = FatfsErrno(res); - return FS_FAILURE; - } - (void)memset_s(&g_dir[i], sizeof(DIR), 0x0, sizeof(DIR)); - g_dirNum--; - } - } - - return FS_SUCCESS; -} - -int fatfs_umount2(const char *target, int flag) -{ - INT32 index; INT32 ret; UINT32 flags; FRESULT res; - - if (target == NULL) { - errno = EFAULT; - return FS_FAILURE; - } + FATFS *fatfs = (FATFS *)mp->mData; flags = MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW; if ((UINT32)flag & ~flags) { errno = EINVAL; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - index = FsPartitionMatch(target, VOLUME_NAME); - if (index == FS_FAILURE) { - errno = ENOENT; - ret = FS_FAILURE; + char *ldPath = GetLdPath(mp->mDev); + if (ldPath == NULL) { + errno = EFAULT; + ret = LOS_NOK; goto OUT; } /* The volume is not mounted */ - if (g_fatfs[index].fs_type == 0) { + if (fatfs->fs_type == 0) { errno = EINVAL; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - if ((UINT32)flag & MNT_FORCE) { - ret = CloseAll(index); - if (ret != FS_SUCCESS) { - goto OUT; - } - } - - res = f_mount((FATFS *)NULL, target, 0); + res = f_mount((FATFS *)NULL, ldPath, 0); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - if (g_fatfs[index].win != NULL) { - ff_memfree(g_fatfs[index].win); + if (fatfs->win != NULL) { + ff_memfree(fatfs->win); } - (void)memset_s(&g_fatfs[index], sizeof(FATFS), 0x0, sizeof(FATFS)); - ret = FS_SUCCESS; + free(mp->mData); + mp->mData = NULL; + + ret = LOS_OK; OUT: + PutLdPath(ldPath); FsUnlock(); return ret; } -int fatfs_open(const char *path, int oflag, ...) +int FatfsOpen(struct File *file, const char *path, int oflag) { FRESULT res; - UINT32 i; - UINT32 openNum = 0; UINT32 fmode; INT32 ret; - FILINFO fileInfo = {0}; + FIL *fp = NULL; if (path == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } fmode = FatFsGetMode(oflag); + fp = (FIL *)malloc(sizeof(FIL)); + if (fp == NULL) { + errno = ENOMEM; + return LOS_NOK; + } + ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; - } - - if (g_fileNum >= FAT_MAX_OPEN_FILES) { - PRINTK("FAT g_fileNum is out of range 0x%x!\r\n", g_fileNum); - errno = ENFILE; - ret = FS_FAILURE; - goto OUT; - } - - for (i = 0; i < FAT_MAX_OPEN_FILES; i++) { - if (g_handle[i].useFlag == 0) { - openNum = i; - break; - } - } - - if (i >= FAT_MAX_OPEN_FILES) { - PRINTK("FAT opennum is out of range 0x%x!\r\n", openNum); - errno = ENFILE; - ret = FS_FAILURE; - goto OUT; + free(fp); + return LOS_NOK; } ret = FsChangeDrive(path); - if (ret != FS_SUCCESS) { - PRINTK("FAT open ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT open ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; + free(fp); goto OUT; } - /* cannot creat a new file in the write protected part */ - if ((((UINT32)oflag & O_CREAT) != 0) && (!FsCheckByPath(path))) { - res = f_stat(path, &fileInfo); - if ((res == FR_NO_FILE) || (res == FR_NO_PATH)) { - PRINTK("FAT creat err 0x%x!\r\n", res); - errno = EACCES; - ret = FS_FAILURE; - goto OUT; - } - } - - res = f_open(&g_handle[openNum].fil, path, fmode); + res = f_open(fp, path, fmode); if (res != FR_OK) { - PRINTK("FAT open err 0x%x!\r\n", res); + PRINT_ERR("FAT open err 0x%x!\r\n", res); + free(fp); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - g_handle[openNum].useFlag = 1; - g_fileNum++; - - ret = openNum; + file->fData = (void *)fp; OUT: FsUnlock(); return ret; } -int fatfs_close(int fd) +int FatfsClose(struct File *file) { FRESULT res; INT32 ret; + FIL *fp = (FIL *)file->fData; ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!IsValidFd(fd)) { - FsUnlock(); - errno = EBADF; - return FS_FAILURE; - } - - if (g_handle[fd].fil.obj.fs == NULL) { + if ((fp == NULL) || (fp->obj.fs == NULL)) { FsUnlock(); errno = ENOENT; - return FS_FAILURE; + return LOS_NOK; } - res = f_close(&g_handle[fd].fil); + res = f_close(fp); if (res != FR_OK) { - PRINTK("FAT close err 0x%x!\r\n", res); + PRINT_ERR("FAT close err 0x%x!\r\n", res); FsUnlock(); errno = FatfsErrno(res); - return FS_FAILURE; + return LOS_NOK; } #if !FF_FS_TINY - if (g_handle[fd].fil.buf != NULL) { - (void)ff_memfree(g_handle[fd].fil.buf); + if (fp->buf != NULL) { + (void)ff_memfree(fp->buf); } #endif - - (void)memset_s(&g_handle[fd], sizeof(FatHandleStruct), 0x0, sizeof(FatHandleStruct)); - - if (g_fileNum > 0) { - g_fileNum--; - } - + free(file->fData); + file->fData = NULL; FsUnlock(); - return FS_SUCCESS; + return LOS_OK; } -ssize_t fatfs_read(int fd, void *buf, size_t nbyte) +ssize_t FatfsRead(struct File *file, char *buf, size_t nbyte) { FRESULT res; INT32 ret; UINT32 lenRead; + FIL *fp = (FIL *)file->fData; if (buf == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - - if (!IsValidFd(fd)) { - FsUnlock(); - errno = EBADF; - return FS_FAILURE; - } - - if (g_handle[fd].fil.obj.fs == NULL) { + if (fp == NULL) { FsUnlock(); errno = ENOENT; - return FS_FAILURE; + return LOS_NOK; } - res = f_read(&g_handle[fd].fil, buf, nbyte, &lenRead); + res = f_read(fp, buf, nbyte, &lenRead); if (res != FR_OK) { FsUnlock(); errno = FatfsErrno(res); - return FS_FAILURE; + return LOS_NOK; } FsUnlock(); return (ssize_t)lenRead; } -ssize_t fatfs_write(int fd, const void *buf, size_t nbyte) +ssize_t FatfsWrite(struct File *file, const char *buf, size_t nbyte) { FRESULT res; INT32 ret; UINT32 lenWrite; static BOOL overFlow = FALSE; + FIL *fp = (FIL *)file->fData; if (buf == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; - } - - if (!IsValidFd(fd)) { - errno = EBADF; - goto ERROUT; + return LOS_NOK; } - if (g_handle[fd].fil.obj.fs == NULL) { + if ((fp ==NULL) || (fp->obj.fs == NULL)) { errno = ENOENT; goto ERROUT; } - if (!FsCheckByID(g_handle[fd].fil.obj.fs->id)) { - errno = EACCES; - goto ERROUT; - } - - res = f_write(&g_handle[fd].fil, buf, nbyte, &lenWrite); + res = f_write(fp, buf, nbyte, &lenWrite); if ((res == FR_OK) && (lenWrite == 0) && (nbyte != 0) && (overFlow == FALSE)) { overFlow = TRUE; - PRINTK("FAT write err 0x%x!\r\n", fd); + PRINT_ERR("FAT write!\r\n"); } if ((res != FR_OK) || (nbyte != lenWrite)) { @@ -754,27 +597,23 @@ ssize_t fatfs_write(int fd, const void *buf, size_t nbyte) ERROUT: FsUnlock(); - return FS_FAILURE; + return LOS_NOK; } -off_t fatfs_lseek(int fd, off_t offset, int whence) +off_t FatfsLseek(struct File *file, off_t offset, int whence) { FRESULT res; INT32 ret; off_t pos; + FIL *fp = (FIL *)file->fData; ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!IsValidFd(fd)) { - errno = EBADF; - goto ERROUT; - } - - if (g_handle[fd].fil.obj.fs == NULL) { + if ((fp == NULL) || (fp->obj.fs == NULL)) { errno = ENOENT; goto ERROUT; } @@ -782,116 +621,76 @@ off_t fatfs_lseek(int fd, off_t offset, int whence) if (whence == SEEK_SET) { pos = 0; } else if (whence == SEEK_CUR) { - pos = f_tell(&g_handle[fd].fil); + pos = f_tell(fp); } else if (whence == SEEK_END) { - pos = f_size(&g_handle[fd].fil); + pos = f_size(fp); } else { errno = EINVAL; goto ERROUT; } - res = f_lseek(&g_handle[fd].fil, offset + pos); + res = f_lseek(fp, offset + pos); if (res != FR_OK) { errno = FatfsErrno(res); goto ERROUT; } - pos = f_tell(&g_handle[fd].fil); + pos = f_tell(fp); FsUnlock(); return pos; ERROUT: FsUnlock(); - return FS_FAILURE; + return LOS_NOK; } /* Remove the specified FILE */ -int fatfs_unlink(const char *path) +int FatfsUnlink(struct MountPoint *mp, const char *path) { FRESULT res; INT32 ret; if (path == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!FsCheckByPath(path)) { + if (!mp->mWriteEnable) { errno = EACCES; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } ret = FsChangeDrive(path); - if (ret != FS_SUCCESS) { - PRINTK("FAT ulink ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT unlink ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_unlink(path); if (res != FR_OK) { - PRINTK("FAT ulink err 0x%x!\r\n", res); + PRINT_ERR("FAT unlink err 0x%x!\r\n", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -/* Return information about a file */ -int fatfs_fstat(int fd, struct stat *buf) -{ - INT32 ret; - - if (buf == NULL) { - errno = EFAULT; - return FS_FAILURE; - } - - ret = FsLock(); - if (ret != 0) { - errno = ret; - return FS_FAILURE; - } - - if (!IsValidFd(fd)) { - FsUnlock(); - errno = EBADF; - return FS_FAILURE; - } - - if (g_handle[fd].fil.obj.fs == NULL) { - FsUnlock(); - errno = ENOENT; - return FS_FAILURE; - } - - buf->st_size = f_size(&g_handle[fd].fil); - buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH | - S_IXUSR | S_IXGRP | S_IXOTH; - if (g_handle[fd].fil.obj.attr & AM_RDO) { - buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - } - - FsUnlock(); - return FS_SUCCESS; -} - -int fatfs_stat(const char *path, struct stat *buf) +int FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf) { FRESULT res; FILINFO fileInfo = {0}; @@ -899,28 +698,28 @@ int fatfs_stat(const char *path, struct stat *buf) if ((path == NULL) || (buf == NULL)) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } ret = FsChangeDrive(path); - if (ret != FS_SUCCESS) { - PRINTK("FAT stat ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT stat ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_stat(path, &fileInfo); if (res != FR_OK) { - PRINTK("FAT stat err 0x%x!\r\n", res); + PRINT_ERR("FAT stat err 0x%x!\r\n", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } @@ -938,7 +737,7 @@ int fatfs_stat(const char *path, struct stat *buf) buf->st_mode |= S_IFDIR; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); @@ -946,311 +745,294 @@ OUT: } /* Synchronize all changes to Flash */ -int fatfs_fsync(int fd) +int FatfsSync(struct File *file) { FRESULT res; INT32 ret; + FIL *fp = (FIL *)file->fData; ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!IsValidFd(fd)) { - errno = EBADF; - ret = FS_FAILURE; - goto OUT; - } - - if (g_handle[fd].fil.obj.fs == NULL) { + if ((fp == NULL) || (fp->obj.fs == NULL)) { errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - if (!FsCheckByID(g_handle[fd].fil.obj.fs->id)) { - errno = EACCES; - ret = FS_FAILURE; - goto OUT; - } - - res = f_sync(&g_handle[fd].fil); + res = f_sync(fp); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -int fatfs_mkdir(const char *path, mode_t mode) +int FatfsMkdir(struct MountPoint *mp, const char *path) { FRESULT res; INT32 ret; if (path == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!FsCheckByPath(path)) { + if (!mp->mWriteEnable) { errno = EACCES; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } ret = FsChangeDrive(path); - if (ret != FS_SUCCESS) { - PRINTK("FAT mkdir ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT mkdir ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_mkdir(path); if (res != FR_OK) { - PRINTK("FAT mkdir err 0x%x!\r\n", res); + PRINT_ERR("FAT mkdir err 0x%x!\r\n", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -DIR *fatfs_opendir(const char *dirName) +int FatfsOpendir(struct Dir *dir, const char *dirName) { FRESULT res; - UINT32 openNum = 0; - UINT32 i; INT32 ret; + DIR *dp = NULL; if (dirName == NULL) { errno = EFAULT; - return NULL; - } - - ret = FsLock(); - if (ret != 0) { - errno = ret; - return NULL; - } - - if (g_dirNum >= FAT_MAX_OPEN_DIRS) { - PRINTK("FAT opendir g_dirNum err 0x%x!\r\n", g_dirNum); - errno = ENFILE; goto ERROUT; } - for (i = 0; i < FAT_MAX_OPEN_DIRS; i++) { - if (g_dir[i].dir == NULL) { - openNum = i; - break; - } + dp = (DIR *)malloc(sizeof(DIR)); + if (dp == NULL) { + errno = ENOENT; + goto ERROUT; } - if (i >= FAT_MAX_OPEN_DIRS) { - PRINTK("FAT dir opennum is out of range 0x%x!\r\n", openNum); - errno = ENFILE; + ret = FsLock(); + if (ret != 0) { + errno = ret; goto ERROUT; } ret = FsChangeDrive(dirName); - if (ret != FS_SUCCESS) { - PRINTK("FAT opendir ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT opendir ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; goto ERROUT; } - res = f_opendir(&g_dir[openNum], dirName); + res = f_opendir(dp, dirName); if (res != FR_OK) { - g_dir[openNum].dir = NULL; - PRINTK("FAT opendir err 0x%x!\r\n", res); + PRINT_ERR("FAT opendir err 0x%x!\r\n", res); errno = FatfsErrno(res); goto ERROUT; } - g_dirNum++; + dir->dData = dp; + dir->dOffset = 0; FsUnlock(); - return &g_dir[openNum]; + return LOS_OK; ERROUT: + if (dp != NULL) { + free(dp); + } FsUnlock(); - return NULL; + return LOS_NOK; } -struct dirent *fatfs_readdir(DIR *dir) +int FatfsReaddir(struct Dir *dir, struct dirent *dent) { FRESULT res; INT32 ret; FILINFO fileInfo = {0}; + DIR *dp = NULL; - if (dir == NULL) { + if ((dir == NULL) || (dir->dData == NULL)) { errno = EBADF; - return NULL; + return LOS_NOK; } + dp = (DIR *)dir->dData; ret = FsLock(); if (ret != 0) { errno = ret; - return NULL; + return LOS_NOK; } - res = f_readdir(dir, &fileInfo); + res = f_readdir(dp, &fileInfo); /* if res not ok or fname is NULL , return NULL */ if ((res != FR_OK) || (fileInfo.fname[0] == 0x0)) { - PRINTK("FAT readdir err 0x%x!\r\n", res); + PRINT_ERR("FAT readdir err 0x%x!\r\n", res); errno = FatfsErrno(res); FsUnlock(); - return NULL; + return LOS_NOK; } - (void)memcpy_s(g_retValue.d_name, sizeof(g_retValue.d_name), fileInfo.fname, sizeof(g_retValue.d_name)); + (void)memcpy_s(dent->d_name, sizeof(dent->d_name), + fileInfo.fname, sizeof(dent->d_name)); if (fileInfo.fattrib & AM_DIR) { - g_retValue.d_type = DT_DIR; + dent->d_type = DT_DIR; } else { - g_retValue.d_type = DT_REG; + dent->d_type = DT_REG; } FsUnlock(); - return &g_retValue; + return LOS_OK; } -int fatfs_closedir(DIR *dir) +int FatfsClosedir(struct Dir *dir) { FRESULT res; INT32 ret; + DIR *dp = NULL; - if (dir == NULL) { + if ((dir == NULL) || (dir->dData == NULL)) { errno = EBADF; - return FS_FAILURE; + return LOS_NOK; } + dp = dir->dData; ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - g_dirNum--; - - res = f_closedir(dir); + res = f_closedir(dp); if (res != FR_OK) { - PRINTK("FAT closedir err 0x%x!\r\n", res); + PRINT_ERR("FAT closedir err 0x%x!\r\n", res); FsUnlock(); errno = FatfsErrno(res); - return FS_FAILURE; + return LOS_NOK; } - dir->dir = NULL; + + free(dir->dData); + dir->dData = NULL; FsUnlock(); - return FS_SUCCESS; + return LOS_OK; } -int fatfs_rmdir(const char *path) +int FatfsRmdir(struct MountPoint *mp, const char *path) { FRESULT res; INT32 ret; - if (path == NULL) { + if ((path == NULL) || (mp == NULL)) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!FsCheckByPath(path)) { + if (!mp->mWriteEnable) { errno = EACCES; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } ret = FsChangeDrive(path); - if (ret != FS_SUCCESS) { - PRINTK("FAT rmdir ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT rmdir ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_rmdir(path); if (res != FR_OK) { - PRINTK("FAT rmdir err 0x%x!\r\n", res); + PRINT_ERR("FAT rmdir err 0x%x!\r\n", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -int fatfs_rename(const char *oldName, const char *newName) +int FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName) { FRESULT res; INT32 ret; if ((oldName == NULL) || (newName == NULL)) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } - if (!FsCheckByPath(oldName) || !FsCheckByPath(newName)) { + if (!mp->mWriteEnable) { errno = EACCES; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } ret = FsChangeDrive(oldName); - if (ret != FS_SUCCESS) { - PRINTK("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret); + if (ret != LOS_OK) { + PRINT_ERR("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret); errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_rename(oldName, newName); if (res != FR_OK) { - PRINTK("FAT frename err 0x%x!\r\n", res); + PRINT_ERR("FAT frename err 0x%x!\r\n", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -int fatfs_statfs(const char *path, struct statfs *buf) +int FatfsStatfs(const char *path, struct statfs *buf) { FATFS *fs = NULL; UINT32 freeClust; @@ -1259,28 +1041,28 @@ int fatfs_statfs(const char *path, struct statfs *buf) if ((path == NULL) || (buf == NULL)) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; + return LOS_NOK; } ret = FsChangeDrive(path); if (ret != FR_OK) { - PRINTK("FAT f_getfree ChangeDrive err %d.", ret); + PRINT_ERR("FAT f_getfree ChangeDrive err %d.", ret); errno = FatfsErrno(FR_INVALID_PARAMETER); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } res = f_getfree(path, &freeClust, &fs); if (res != FR_OK) { - PRINTK("FAT f_getfree err 0x%x.", res); + PRINT_ERR("FAT f_getfree err 0x%x.", res); errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } buf->f_bfree = freeClust; @@ -1293,315 +1075,203 @@ int fatfs_statfs(const char *path, struct statfs *buf) buf->f_bsize = FF_MIN_SS * fs->csize; #endif - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -static int do_truncate(int fd, off_t length, UINT count) +static int DoTruncate(struct File *file, off_t length, UINT32 count) { FRESULT res = FR_OK; - INT32 ret = FS_SUCCESS; + INT32 ret = LOS_OK; DWORD csz; + FIL *fp = (FIL *)file->fData; - csz = (DWORD)(g_handle[fd].fil.obj.fs)->csize * SS(g_handle[fd].fil.obj.fs); /* Cluster size */ + csz = (DWORD)(fp->obj.fs)->csize * SS(fp->obj.fs); /* Cluster size */ if (length > csz * count) { #if FF_USE_EXPAND - res = f_expand(&g_handle[fd].fil, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE); + res = f_expand(fp, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE); #else errno = ENOSYS; - ret = FS_FAILURE; + ret = LOS_NOK; return ret; #endif } else if (length < csz * count) { - res = f_truncate(&g_handle[fd].fil, (FSIZE_t)length); + res = f_truncate(fp, (FSIZE_t)length); } if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; return ret; } - g_handle[fd].fil.obj.objsize = length; /* Set file size to length */ - g_handle[fd].fil.flag |= 0x40; /* Set modified flag */ + fp->obj.objsize = length; /* Set file size to length */ + fp->flag |= 0x40; /* Set modified flag */ return ret; } -int fatfs_ftruncate(int fd, off_t length) +int FatfsTruncate(struct File *file, off_t length) { FRESULT res; INT32 ret; UINT count; DWORD fclust; + FIL *fp = (FIL *)file->fData; if ((length < 0) || (length > UINT_MAX)) { errno = EINVAL; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; - } - - if (!IsValidFd(fd)) { - errno = EBADF; - ret = FS_FAILURE; - goto OUT; + return LOS_NOK; } - if (g_handle[fd].fil.obj.fs == NULL) { + if ((fp == NULL) || (fp->obj.fs == NULL)) { errno = ENOENT; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - if (!FsCheckByID(g_handle[fd].fil.obj.fs->id)) { - errno = EACCES; - ret = FS_FAILURE; - goto OUT; - } - - res = f_getclustinfo(&g_handle[fd].fil, &fclust, &count); + res = f_getclustinfo(fp, &fclust, &count); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = do_truncate(fd, length, count); + ret = DoTruncate(file, length, count); if (ret != FR_OK) { goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -int fatfs_fdisk(int pdrv, const unsigned int *partTbl) +int FatfsFdisk(const char *dev, int *partTbl, int arrayNum) { - INT32 index; + int pdrv; FRESULT res; INT32 ret; - if (partTbl == NULL) { + if ((dev == NULL) || (partTbl == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + pdrv = GetDevIdByDevName(dev); + if (pdrv < 0) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - /* fdisk is not allowed when the device has been mounted. */ - for (index = 0; index < FF_VOLUMES; index++) { - if ((g_fatfs[index].pdrv == pdrv) && (g_fatfs[index].fs_type != 0)) { - errno = EBUSY; - ret = FS_FAILURE; - goto OUT; - } - } - res = f_fdisk(pdrv, (DWORD const *)partTbl, g_workBuffer); if (res != FR_OK) { errno = FatfsErrno(res); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: FsUnlock(); return ret; } -int fatfs_format(const char *dev, int sectors, int option) +int FatfsFormat(const char *partName, void *privData) { - INT32 index; FRESULT res; INT32 ret; MKFS_PARM opt = {0}; + int option = *(int *)privData; + char *dev = NULL; /* logical driver */ + + if (partName == NULL) { + errno = EFAULT; + return LOS_NOK; + } + dev = GetLdPath(partName); if (dev == NULL) { errno = EFAULT; - return FS_FAILURE; + return LOS_NOK; } ret = FsLock(); if (ret != 0) { errno = ret; - return FS_FAILURE; - } - - index = FsPartitionMatch(dev, VOLUME_NAME); - if (index == FS_FAILURE) { - errno = ENOENT; - ret = FS_FAILURE; - goto OUT; + PutLdPath(dev); + return LOS_NOK; } - /* format is not allowed when the device has been mounted. */ - if (g_fatfs[index].fs_type != 0) { - errno = EBUSY; - ret = FS_FAILURE; - goto OUT; - } - - opt.fmt = option, - opt.n_sect = sectors, + 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); - ret = FS_FAILURE; + ret = LOS_NOK; goto OUT; } - ret = FS_SUCCESS; + ret = LOS_OK; OUT: + PutLdPath(dev); FsUnlock(); return ret; } -ssize_t fatfs_pread(int fd, void *buf, size_t nbyte, off_t offset) -{ - INT32 ret; - off_t savepos, pos; - - if (buf == NULL) { - errno = EFAULT; - return FS_FAILURE; - } - - ret = FsLock(); - if (ret != 0) { - errno = ret; - return FS_FAILURE; - } - - if (!IsValidFd(fd)) { - FsUnlock(); - errno = EBADF; - return FS_FAILURE; - } - - savepos = (off_t)fatfs_lseek(fd, 0, SEEK_CUR); - if (savepos == (off_t)-1) { - errno = FatfsErrno(savepos); - return FS_FAILURE; - } - - pos = (off_t)fatfs_lseek(fd, offset, SEEK_SET); - if (pos == (off_t)-1) { - errno = FatfsErrno(pos); - return FS_FAILURE; - } - - ret = fatfs_read(fd, buf, nbyte); - if (ret < 0) { - FsUnlock(); - errno = FatfsErrno(ret); - return FS_FAILURE; - } - - pos = (off_t)fatfs_lseek(fd, savepos, SEEK_SET); - if ((pos == (off_t)-1) && (ret >= 0)) { - errno = FatfsErrno(pos); - return FS_FAILURE; - } +static struct MountOps g_fatfsMnt = { + .mount = FatfsMount, + .umount = FatfsUmount, + .umount2 = FatfsUmount2, + .statfs = FatfsStatfs, +}; - FsUnlock(); +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, +}; - return (ssize_t)ret; -} +static struct FsManagement g_fatfsMgt = { + .fdisk = FatfsFdisk, + .format = FatfsFormat, +}; -ssize_t fatfs_pwrite(int fd, const void *buf, size_t nbyte, off_t offset) +void FatFsInit(void) { - INT32 ret; - off_t savepos, pos; - - if (buf == NULL) { - errno = EFAULT; - return FS_FAILURE; - } - - ret = FsLock(); - if (ret != 0) { - errno = ret; - return FS_FAILURE; - } - - if (!IsValidFd(fd)) { - FsUnlock(); - errno = EBADF; - return FS_FAILURE; - } - - savepos = (off_t)fatfs_lseek(fd, 0, SEEK_CUR); - if (savepos == (off_t)-1) { - errno = FatfsErrno(savepos); - return FS_FAILURE; - } - - pos = (off_t)fatfs_lseek(fd, offset, SEEK_SET); - if (pos == (off_t)-1) { - errno = FatfsErrno(pos); - return FS_FAILURE; - } - - ret = fatfs_write(fd, buf, nbyte); - if (ret < 0) { - FsUnlock(); - errno = FatfsErrno(ret); - return FS_FAILURE; - } - - pos = (off_t)fatfs_lseek(fd, savepos, SEEK_SET); - if ((pos == (off_t)-1) && (ret >= 0)) { - errno = FatfsErrno(pos); - return FS_FAILURE; - } - - FsUnlock(); - - return (ssize_t)ret; + (void)OsFsRegister("vfat", &g_fatfsMnt, &g_fatfsFops, &g_fatfsMgt); } - -struct MountOps g_fatfsMnt = { - .Mount = fatfs_mount, - .Umount = fatfs_umount, - .Umount2 = fatfs_umount2, - .Statfs = fatfs_statfs, -}; - -struct FileOps g_fatfsFops = { - .Mkdir = fatfs_mkdir, - .Unlink = fatfs_unlink, - .Rmdir = fatfs_rmdir, - .Opendir = fatfs_opendir, - .Readdir = fatfs_readdir, - .Closedir = fatfs_closedir, - .Open = fatfs_open, - .Close = fatfs_close, - .Write = fatfs_write, - .Read = fatfs_read, - .Seek = fatfs_lseek, - .Rename = fatfs_rename, - .Getattr = fatfs_stat, - .Fsync = fatfs_fsync, - .Fstat = fatfs_fstat, - .Pread = fatfs_pread, - .Pwrite = fatfs_pwrite, -}; diff --git a/components/fs/fatfs/fatfs.h b/components/fs/fatfs/fatfs.h index 05672a16..db5e4531 100644 --- a/components/fs/fatfs/fatfs.h +++ b/components/fs/fatfs/fatfs.h @@ -32,14 +32,7 @@ #ifndef _FATFS_H #define _FATFS_H -#include "dirent.h" -#include "fatfs_conf.h" -#include "fcntl.h" -#include "fs_config.h" -#include "sys/mount.h" -#include "sys/stat.h" -#include "sys/statfs.h" -#include "unistd.h" +#include "ff.h" #ifdef __cplusplus #if __cplusplus @@ -47,58 +40,7 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -int fatfs_mount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data); -int fatfs_umount(const char *target); -int fatfs_umount2(const char *target, int flag); -int fatfs_open(const char *path, int oflag, ...); -int fatfs_close(int fd); -ssize_t fatfs_read(int fd, void *buf, size_t nbyte); -ssize_t fatfs_write(int fd, const void *buf, size_t nbyte); -off_t fatfs_lseek(int fd, off_t offset, int whence); -int fatfs_unlink(const char *path); -int fatfs_fstat(int fd, struct stat *buf); -int fatfs_stat(const char *path, struct stat *buf); -int fatfs_fsync(int fd); -int fatfs_mkdir(const char *path, mode_t mode); -DIR *fatfs_opendir(const char *dirName); -struct dirent *fatfs_readdir(DIR *dir); -int fatfs_closedir(DIR *dir); -int fatfs_rmdir(const char *path); -int fatfs_rename(const char *oldName, const char *newName); -int fatfs_statfs(const char *path, struct statfs *buf); -int fatfs_ftruncate(int fd, off_t length); -ssize_t fatfs_pread(int fd, void *buf, size_t nbyte, off_t offset); -ssize_t fatfs_pwrite(int fd, const void *buf, size_t nbyte, off_t offset); - -/** - * @brief divide a physical drive (SD card, U disk, and MMC card), this function is OHOS-specific - * @param pdrv physical drive number. - * @param partTbl list of partition size to create on the drive. - * -- item is <= 100: specifies the partition size in percentage of the entire drive space. - * -- item is > 100: specifies number of sectors. - * @return fdisk result - * @retval -1 fdisk error - * @retval 0 fdisk successful - */ -int fatfs_fdisk(int pdrv, const unsigned int *partTbl); - -/** - * @brief format FAT device (SD card, U disk, and MMC card), this function is OHOS-specific - * @param dev device name. - * @param sectors sectors per cluster, can be 0 OR power of 2. The sector size for standard FAT volumes is 512 bytes. - * -- sector number is 0 OR >128: automatically choose the appropriate cluster size. - * -- sector number is 1 ~ 128: cluster size = sectors per cluster * 512B. - * @param option file system type. - * -- FMT_FAT - * -- FMT_FAT32 - * -- FMT_ANY - * @return format result - * @retval -1 format error - * @retval 0 format successful - */ -int fatfs_format(const char *dev, int sectors, int option); +void FatFsInit(void); #ifdef __cplusplus #if __cplusplus diff --git a/components/fs/littlefs/BUILD.gn b/components/fs/littlefs/BUILD.gn index a7faa85a..e835bda2 100644 --- a/components/fs/littlefs/BUILD.gn +++ b/components/fs/littlefs/BUILD.gn @@ -34,7 +34,7 @@ module_switch = defined(LOSCFG_FS_LITTLEFS) module_name = get_path_info(rebase_path("."), "name") kernel_module(module_name) { configs += [ "$LITEOSTOPDIR:warn_config" ] - sources = LITTLEFS_SRC_FILES_FOR_KERNEL_MODULE + [ "lfs_api.c" ] + sources = LITTLEFS_SRC_FILES_FOR_KERNEL_MODULE + [ "lfs_adapter.c" ] } config("public") { diff --git a/components/fs/littlefs/lfs_adapter.c b/components/fs/littlefs/lfs_adapter.c new file mode 100644 index 00000000..71c774b3 --- /dev/null +++ b/components/fs/littlefs/lfs_adapter.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 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 "lfs_adapter.h" +#include "los_config.h" +#include "vfs_files.h" +#include "vfs_operations.h" +#include "vfs_partition.h" +#include "vfs_maps.h" +#include "vfs_mount.h" +#include "securec.h" + +struct dirent g_nameValue; +static pthread_mutex_t g_FslocalMutex = PTHREAD_MUTEX_INITIALIZER; + +static int ConvertFlagToLfsOpenFlag (int oflags) +{ + int lfsOpenFlag = 0; + + if (oflags & O_CREAT) { + lfsOpenFlag |= LFS_O_CREAT; + } + + if (oflags & O_EXCL) { + lfsOpenFlag |= LFS_O_EXCL; + } + + if (oflags & O_TRUNC) { + lfsOpenFlag |= LFS_O_TRUNC; + } + + if (oflags & O_APPEND) { + lfsOpenFlag |= LFS_O_APPEND; + } + + if (oflags & O_RDWR) { + lfsOpenFlag |= LFS_O_RDWR; + } + + if (oflags & O_WRONLY) { + lfsOpenFlag |= LFS_O_WRONLY; + } + + if (oflags == O_RDONLY) { + lfsOpenFlag |= LFS_O_RDONLY; + } + + return lfsOpenFlag; +} + +static int LittlefsErrno(int result) +{ + return (result < 0) ? -result : result; +} + +int LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data) +{ + int ret; + lfs_t *mountHdl = NULL; + + if ((mp == NULL) || (mp->mPath == NULL) || (data == NULL)) { + errno = EFAULT; + ret = LOS_NOK; + goto errout; + } + + mountHdl = (lfs_t *)malloc(sizeof(lfs_t)); + if (mountHdl == NULL) { + errno = ENODEV; + ret = LOS_NOK; + goto errout; + } + (void)memset_s(mountHdl, sizeof(lfs_t), 0, sizeof(lfs_t)); + mp->mData = (void *)mountHdl; + + ret = lfs_mount((lfs_t *)mp->mData, (struct lfs_config *)data); + if (ret != 0) { + ret = lfs_format((lfs_t *)mp->mData, (struct lfs_config*)data); + if (ret == 0) { + ret = lfs_mount((lfs_t *)mp->mData, (struct lfs_config*)data); + } + } + + if (ret != 0) { + free(mountHdl); + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + +errout: + return ret; +} + +int LfsUmount(struct MountPoint *mp) +{ + int ret; + + if (mp == NULL) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + ret = lfs_unmount((lfs_t *)mp->mData); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + free(mp->mData); + mp->mData = NULL; + return ret; +} + +int LfsUnlink(struct MountPoint *mp, const char *fileName) +{ + int ret; + + if ((mp == NULL) || (fileName == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + ret = lfs_remove((lfs_t *)mp->mData, fileName); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsMkdir(struct MountPoint *mp, const char *dirName) +{ + int ret; + + if ((dirName == NULL) || (mp == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + lfs_t *lfs = (lfs_t *)mp->mData; + + ret = lfs_mkdir(lfs, dirName); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsRmdir(struct MountPoint *mp, const char *dirName) +{ + int ret; + lfs_t *lfs = NULL; + + if (mp == NULL) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + lfs = (lfs_t *)mp->mData; + + if (dirName == NULL) { + errno = EFAULT; + return LOS_NOK; + } + + ret = lfs_remove(lfs, dirName); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsOpendir(struct Dir *dir, const char *dirName) +{ + int ret; + + if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + lfs_t *lfs = (lfs_t *)dir->dMp->mData; + lfs_dir_t *dirInfo = (lfs_dir_t *)malloc(sizeof(lfs_dir_t)); + if (dirInfo == NULL) { + errno = ENOMEM; + return LOS_NOK; + } + + (void)memset_s(dirInfo, sizeof(lfs_dir_t), 0, sizeof(lfs_dir_t)); + ret = lfs_dir_open(lfs, dirInfo, dirName); + if (ret != 0) { + free(dirInfo); + errno = LittlefsErrno(ret); + goto errout; + } + + dir->dData = dirInfo; + dir->dOffset = 0; + + return LOS_OK; + +errout: + return LOS_NOK; +} + +int LfsReaddir(struct Dir *dir, struct dirent *dent) +{ + int ret; + struct lfs_info lfsInfo; + + if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL) || + (dent == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (dir->dData == NULL) { + errno = EBADF; + return LOS_NOK; + } + + lfs_t *lfs = (lfs_t *)dir->dMp->mData; + lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData; + + ret = lfs_dir_read(lfs, dirInfo, &lfsInfo); + if (ret == TRUE) { + pthread_mutex_lock(&g_FslocalMutex); + (void)strncpy_s(dent->d_name, sizeof(dent->d_name), lfsInfo.name, strlen(lfsInfo.name) + 1); + if (lfsInfo.type == LFS_TYPE_DIR) { + dent->d_type = DT_DIR; + } else if (lfsInfo.type == LFS_TYPE_REG) { + dent->d_type = DT_REG; + } + + dent->d_reclen = lfsInfo.size; + pthread_mutex_unlock(&g_FslocalMutex); + + return LOS_OK; + } + + if (ret != 0) { + errno = LittlefsErrno(ret); + } + + return LOS_NOK; +} + +int LfsClosedir(struct Dir *dir) +{ + int ret; + + if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (dir->dData == NULL) { + errno = EBADF; + return LOS_NOK; + } + + lfs_t *lfs = (lfs_t *)dir->dMp->mData; + lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData; + + ret = lfs_dir_close(lfs, dirInfo); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + free(dirInfo); + dir->dData = NULL; + + return ret; +} + +int LfsOpen(struct File *file, const char *pathName, int openFlag) +{ + int ret; + lfs_file_t *lfsHandle = NULL; + + if ((pathName == NULL) || (file == NULL) || (file->fMp == NULL) || + (file->fMp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + lfsHandle = (lfs_file_t *)malloc(sizeof(lfs_file_t)); + if (lfsHandle == NULL) { + errno = ENOMEM; + return LOS_NOK; + } + + int lfsOpenFlag = ConvertFlagToLfsOpenFlag(openFlag); + ret = lfs_file_open((lfs_t *)file->fMp->mData, lfsHandle, pathName, lfsOpenFlag); + if (ret != 0) { + free(lfsHandle); + errno = LittlefsErrno(ret); + goto errout; + } + + file->fData = (void *)lfsHandle; + return ret; + +errout: + return INVALID_FD; +} + +int LfsRead(struct File *file, char *buf, size_t len) +{ + int ret; + struct MountPoint *mp = NULL; + lfs_file_t *lfsHandle = NULL; + + if (buf == NULL) { + errno = EFAULT; + return LOS_NOK; + } + + if ((file == NULL) || (file->fData == NULL)) { + errno = EBADF; + return LOS_NOK; + } + + lfsHandle = (lfs_file_t *)file->fData; + mp = file->fMp; + if ((mp == NULL) || (mp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + ret = lfs_file_read((lfs_t *)mp->mData, lfsHandle, buf, len); + if (ret < 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + return ret; +} + +int LfsWrite(struct File *file, const char *buf, size_t len) +{ + int ret; + struct MountPoint *mp = NULL; + lfs_file_t *lfsHandle = NULL; + + if (buf == NULL) { + errno = EFAULT; + return LOS_NOK; + } + + if ((file == NULL) || (file->fData == NULL)) { + errno = EBADF; + return LOS_NOK; + } + + lfsHandle = (lfs_file_t *)file->fData; + mp = file->fMp; + if ((mp == NULL) || (mp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + ret = lfs_file_write((lfs_t *)mp->mData, lfsHandle, buf, len); + if (ret < 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + return ret; +} + +off_t LfsSeek(struct File *file, off_t offset, int whence) +{ + off_t ret; + struct MountPoint *mp = NULL; + lfs_file_t *lfsHandle = NULL; + + if ((file == NULL) || (file->fData == NULL)) { + errno = EBADF; + return LOS_NOK; + } + + lfsHandle = (lfs_file_t *)file->fData; + mp = file->fMp; + if ((mp == NULL) || (mp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + ret = (off_t)lfs_file_seek((lfs_t *)mp->mData, lfsHandle, offset, whence); + if (ret < 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsClose(struct File *file) +{ + INT32 ret; + struct MountPoint *mp = NULL; + lfs_file_t *lfsHandle = NULL; + + if ((file == NULL) || (file->fData == NULL)) { + errno = EBADF; + return LOS_NOK; + } + + lfsHandle = (lfs_file_t *)file->fData; + mp = file->fMp; + if ((mp == NULL) || (mp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_close((lfs_t *)mp->mData, lfsHandle); + pthread_mutex_unlock(&g_FslocalMutex); + + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + free(file->fData); + file->fData = NULL; + return ret; +} + +int LfsRename(struct MountPoint *mp, const char *oldName, const char *newName) +{ + int ret; + + if ((mp == NULL) || (oldName == NULL) || (newName == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + ret = lfs_rename((lfs_t *)mp->mData, oldName, newName); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsStat(struct MountPoint *mp, const char *path, struct stat *buf) +{ + int ret; + struct lfs_info info; + + if ((mp == NULL) || (path == NULL) || (buf == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + if (mp->mData == NULL) { + errno = ENOENT; + return LOS_NOK; + } + + ret = lfs_stat((lfs_t *)mp->mData, path, &info); + if (ret == 0) { + buf->st_size = info.size; + if (info.type == LFS_TYPE_REG) { + buf->st_mode = S_IFREG; + } else { + buf->st_mode = S_IFDIR; + } + } else { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + + return ret; +} + +int LfsSync(struct File *file) +{ + int ret; + struct MountPoint *mp = NULL; + + if ((file == NULL) || (file->fData == NULL)) { + errno = EBADF; + return LOS_NOK; + } + + if ((file->fMp == NULL) || (file->fMp->mData == NULL)) { + errno = EFAULT; + return LOS_NOK; + } + + mp = file->fMp; + ret = lfs_file_sync((lfs_t *)mp->mData, (lfs_file_t *)file->fData); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + return ret; +} + +static struct MountOps g_lfsMnt = { + .mount = LfsMount, + .umount = LfsUmount, + .umount2 = NULL, + .statfs = NULL, +}; + +static struct FileOps g_lfsFops = { + .open = LfsOpen, + .close = LfsClose, + .read = LfsRead, + .write = LfsWrite, + .lseek = LfsSeek, + .stat = LfsStat, + .truncate = NULL, + .unlink = LfsUnlink, + .rename = LfsRename, + .ioctl = NULL, /* not support */ + .sync = LfsSync, + .rmdir = LfsRmdir, + .opendir = LfsOpendir, + .readdir = LfsReaddir, + .closedir = LfsClosedir, + .mkdir = LfsMkdir, +}; + +static struct FsManagement g_lfsMgt = { + .fdisk = NULL, + .format = NULL, +}; + +void LfsInit(void) +{ + (void)OsFsRegister("littlefs", &g_lfsMnt, &g_lfsFops, &g_lfsMgt); +} diff --git a/components/fs/littlefs/lfs_api.h b/components/fs/littlefs/lfs_adapter.h similarity index 54% rename from components/fs/littlefs/lfs_api.h rename to components/fs/littlefs/lfs_adapter.h index 2258efbc..fa05e21d 100644 --- a/components/fs/littlefs/lfs_api.h +++ b/components/fs/littlefs/lfs_adapter.h @@ -29,15 +29,15 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _LFS_API_H_ -#define _LFS_API_H_ +#ifndef _LFS_ADAPTER_H_ +#define _LFS_ADAPTER_H_ #include "fcntl.h" #include "sys/stat.h" #include "dirent.h" #include "errno.h" -#include "fs_operations.h" +#include "vfs_operations.h" #include "lfs.h" #include "lfs_conf.h" #include "lfs_util.h" @@ -46,59 +46,5 @@ #define INVALID_FD (-1) -#ifndef VFS_ERROR -#define VFS_ERROR (-1) -#endif - -#ifndef VFS_OK -#define VFS_OK 0 -#endif - -typedef struct { - uint8_t useFlag; - const char *pathName; - lfs_t *lfsHandle; - lfs_file_t file; -} LittleFsHandleStruct; - -struct FileOpInfo { - uint8_t useFlag; - const struct FileOps *fsVops; - char *dirName; - lfs_t lfsInfo; -}; - -typedef struct { - uint8_t useFlag; - char *dirName; - lfs_t *lfsHandle; - lfs_dir_t dir; -} FileDirInfo; - -LittleFsHandleStruct *GetFreeFd(int *fd); - -int LfsMount(const char *source, const char *target, const char *fileSystemType, unsigned long mountflags, - const void *data); - -int LfsUmount(const char *target); -int LfsUnlink(const char *fileName); -int LfsMkdir(const char *dirName, mode_t mode); -int LfsRmdir(const char *dirName); -DIR *LfsOpendir(const char *dirName); -struct dirent *LfsReaddir(DIR *dir); -int LfsClosedir(DIR *dir); -int LfsOpen(const char *pathName, int openFlag, ...); -int LfsRead(int fd, void *buf, unsigned int len); -int LfsWrite(int fd, const void *buf, unsigned int len); -off_t LfsSeek(int fd, off_t offset, int whence); -int LfsClose(int fd); -int LfsRename(const char *oldName, const char *newName); -int LfsStat(const char *path, struct stat *buf); -int LfsFsync(int fd); -int LfsFstat(int fd, struct stat *buf); -int SetDefaultMountPath(int pathNameIndex, const char* target); -int LfsPread(int fd, void *buf, size_t nbyte, off_t offset); -int LfsPwrite(int fd, const void *buf, size_t nbyte, off_t offset); - -#endif /* _LFS_API_H_ */ - +void LfsInit(void); +#endif /* _LFS_ADAPTER_H_ */ diff --git a/components/fs/littlefs/lfs_api.c b/components/fs/littlefs/lfs_api.c deleted file mode 100644 index 3e9d930e..00000000 --- a/components/fs/littlefs/lfs_api.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 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 "lfs_api.h" -#include "los_config.h" -#include "securec.h" - -lfs_t g_lfs; -FileDirInfo g_lfsDir[LFS_MAX_OPEN_DIRS] = {0}; - -struct FileOpInfo g_fsOp[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0}; -static LittleFsHandleStruct g_handle[LOSCFG_LFS_MAX_OPEN_FILES] = {0}; -struct dirent g_nameValue; -static pthread_mutex_t g_FslocalMutex = PTHREAD_MUTEX_INITIALIZER; -static const char *g_littlefsMntName[LOSCFG_LFS_MAX_MOUNT_SIZE] = {"/a"}; - -LittleFsHandleStruct *LfsAllocFd(const char *fileName, int *fd) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_OPEN_FILES; i++) { - if (g_handle[i].useFlag == 0) { - *fd = i; - g_handle[i].useFlag = 1; - g_handle[i].pathName = strdup(fileName); - pthread_mutex_unlock(&g_FslocalMutex); - return &(g_handle[i]); - } - } - pthread_mutex_unlock(&g_FslocalMutex); - *fd = INVALID_FD; - return NULL; -} - -static void LfsFreeFd(int fd) -{ - pthread_mutex_lock(&g_FslocalMutex); - g_handle[fd].useFlag = 0; - if (g_handle[fd].pathName != NULL) { - free((void *)g_handle[fd].pathName); - g_handle[fd].pathName = NULL; - } - - if (g_handle[fd].lfsHandle != NULL) { - g_handle[fd].lfsHandle = NULL; - } - pthread_mutex_unlock(&g_FslocalMutex); -} - -BOOL CheckFileIsOpen(const char *fileName) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_OPEN_FILES; i++) { - if (g_handle[i].useFlag == 1) { - if (strcmp(g_handle[i].pathName, fileName) == 0) { - pthread_mutex_unlock(&g_FslocalMutex); - return TRUE; - } - } - } - pthread_mutex_unlock(&g_FslocalMutex); - return FALSE; -} - -static BOOL LfsFdIsValid(int fd) -{ - if (fd >= LOSCFG_LFS_MAX_OPEN_FILES || fd < 0) { - return FALSE; - } - if (g_handle[fd].lfsHandle == NULL) { - return FALSE; - } - return TRUE; -} - -FileDirInfo *GetFreeDir(const char *dirName) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { - if (g_lfsDir[i].useFlag == 0) { - g_lfsDir[i].useFlag = 1; - g_lfsDir[i].dirName = strdup(dirName); - pthread_mutex_unlock(&g_FslocalMutex); - return &(g_lfsDir[i]); - } - } - pthread_mutex_unlock(&g_FslocalMutex); - return NULL; -} - -void FreeDirInfo(const char *dirName) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { - if (g_lfsDir[i].useFlag == 1 && strcmp(g_lfsDir[i].dirName, dirName) == 0) { - g_lfsDir[i].useFlag = 0; - if (g_lfsDir[i].dirName) { - free(g_lfsDir[i].dirName); - g_lfsDir[i].dirName = NULL; - } - pthread_mutex_unlock(&g_FslocalMutex); - } - } - pthread_mutex_unlock(&g_FslocalMutex); -} - -BOOL CheckDirIsOpen(const char *dirName) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { - if (g_lfsDir[i].useFlag == 1) { - if (strcmp(g_lfsDir[i].dirName, dirName) == 0) { - pthread_mutex_unlock(&g_FslocalMutex); - return TRUE; - } - } - } - pthread_mutex_unlock(&g_FslocalMutex); - return FALSE; -} - -int GetFirstLevelPathLen(const char *pathName) -{ - int len = 1; - for (int i = 1; i < strlen(pathName) + 1; i++) { - if (pathName[i] == '/') { - break; - } - len++; - } - - return len; -} - -BOOL CheckPathIsMounted(const char *pathName, struct FileOpInfo **fileOpInfo) -{ - char tmpName[LITTLEFS_MAX_LFN_LEN] = {0}; - int len = GetFirstLevelPathLen(pathName); - - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { - if (g_fsOp[i].useFlag == 1) { - (void)strncpy_s(tmpName, LITTLEFS_MAX_LFN_LEN, pathName, len); - if (strcmp(tmpName, g_fsOp[i].dirName) == 0) { - *fileOpInfo = &(g_fsOp[i]); - pthread_mutex_unlock(&g_FslocalMutex); - return TRUE; - } - } - } - pthread_mutex_unlock(&g_FslocalMutex); - return FALSE; -} - -struct FileOpInfo *AllocMountRes(const char* target, const struct FileOps *fileOps) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { - if (g_fsOp[i].useFlag == 0 && strcmp(target, g_littlefsMntName[i]) == 0) { - g_fsOp[i].useFlag = 1; - g_fsOp[i].fsVops = fileOps; - g_fsOp[i].dirName = strdup(target); - pthread_mutex_unlock(&g_FslocalMutex); - return &(g_fsOp[i]); - } - } - - pthread_mutex_unlock(&g_FslocalMutex); - return NULL; -} - -int SetDefaultMountPath(int pathNameIndex, const char* target) -{ - if (pathNameIndex >= LOSCFG_LFS_MAX_MOUNT_SIZE) { - return VFS_ERROR; - } - - pthread_mutex_lock(&g_FslocalMutex); - g_littlefsMntName[pathNameIndex] = strdup(target); - pthread_mutex_unlock(&g_FslocalMutex); - return VFS_OK; -} - -struct FileOpInfo *GetMountRes(const char *target, int *mountIndex) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { - if (g_fsOp[i].useFlag == 1) { - if (g_fsOp[i].dirName && strcmp(target, g_fsOp[i].dirName) == 0) { - *mountIndex = i; - pthread_mutex_unlock(&g_FslocalMutex); - return &(g_fsOp[i]); - } - } - } - - pthread_mutex_unlock(&g_FslocalMutex); - return NULL; -} - -int FreeMountResByIndex(int mountIndex) -{ - if (mountIndex < 0 || mountIndex >= LOSCFG_LFS_MAX_MOUNT_SIZE) { - return VFS_ERROR; - } - - pthread_mutex_lock(&g_FslocalMutex); - if (g_fsOp[mountIndex].useFlag == 1 && g_fsOp[mountIndex].dirName != NULL) { - g_fsOp[mountIndex].useFlag = 0; - free(g_fsOp[mountIndex].dirName); - g_fsOp[mountIndex].dirName = NULL; - } - pthread_mutex_unlock(&g_FslocalMutex); - - return VFS_OK; -} - -int FreeMountRes(const char *target) -{ - pthread_mutex_lock(&g_FslocalMutex); - for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { - if (g_fsOp[i].useFlag == 1) { - if (g_fsOp[i].dirName && strcmp(target, g_fsOp[i].dirName) == 0) { - g_fsOp[i].useFlag = 0; - free(g_fsOp[i].dirName); - g_fsOp[i].dirName = NULL; - pthread_mutex_unlock(&g_FslocalMutex); - return VFS_OK; - } - } - } - - pthread_mutex_unlock(&g_FslocalMutex); - return VFS_ERROR; -} - -static int ConvertFlagToLfsOpenFlag (int oflags) -{ - int lfsOpenFlag = 0; - - if (oflags & O_CREAT) { - lfsOpenFlag |= LFS_O_CREAT; - } - - if (oflags & O_EXCL) { - lfsOpenFlag |= LFS_O_EXCL; - } - - if (oflags & O_TRUNC) { - lfsOpenFlag |= LFS_O_TRUNC; - } - - if (oflags & O_APPEND) { - lfsOpenFlag |= LFS_O_APPEND; - } - - if (oflags & O_RDWR) { - lfsOpenFlag |= LFS_O_RDWR; - } - - if (oflags & O_WRONLY) { - lfsOpenFlag |= LFS_O_WRONLY; - } - - if (oflags == O_RDONLY) { - lfsOpenFlag |= LFS_O_RDONLY; - } - - return lfsOpenFlag; -} - -static int LittlefsErrno(int result) -{ - return (result < 0) ? -result : result; -} - -const struct MountOps g_lfsMnt = { - .Mount = LfsMount, - .Umount = LfsUmount, -}; - -const struct FileOps g_lfsFops = { - .Mkdir = LfsMkdir, - .Unlink = LfsUnlink, - .Rmdir = LfsRmdir, - .Opendir = LfsOpendir, - .Readdir = LfsReaddir, - .Closedir = LfsClosedir, - .Open = LfsOpen, - .Close = LfsClose, - .Write = LfsWrite, - .Read = LfsRead, - .Seek = LfsSeek, - .Rename = LfsRename, - .Getattr = LfsStat, - .Fsync = LfsFsync, - .Fstat = LfsFstat, - .Pread = LfsPread, - .Pwrite = LfsPwrite, -}; - -int LfsMount(const char *source, const char *target, const char *fileSystemType, unsigned long mountflags, - const void *data) -{ - int ret; - struct FileOpInfo *fileOpInfo = NULL; - - if (target == NULL || fileSystemType == NULL || data == NULL) { - errno = EFAULT; - ret = VFS_ERROR; - goto ERROUT; - } - - if (strcmp(fileSystemType, "littlefs") != 0) { - errno = ENODEV; - ret = VFS_ERROR; - goto ERROUT; - } - - if (CheckPathIsMounted(target, &fileOpInfo)) { - errno = EBUSY; - ret = VFS_ERROR; - goto ERROUT; - } - - // select free mount resource - fileOpInfo = AllocMountRes(target, &g_lfsFops); - if (fileOpInfo == NULL) { - errno = ENODEV; - ret = VFS_ERROR; - goto ERROUT; - } - - ret = lfs_mount(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); - if (ret != 0) { - ret = lfs_format(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); - if (ret == 0) { - ret = lfs_mount(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); - } - } - - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - -ERROUT: - return ret; -} - -int LfsUmount(const char *target) -{ - int ret; - int mountIndex = -1; - struct FileOpInfo *fileOpInfo = NULL; - - if (target == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - fileOpInfo = GetMountRes(target, &mountIndex); - if (fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_unmount(&(fileOpInfo->lfsInfo)); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - (void)FreeMountResByIndex(mountIndex); - return ret; -} - -int LfsUnlink(const char *fileName) -{ - int ret; - struct FileOpInfo *fileOpInfo = NULL; - - if (fileName == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (CheckPathIsMounted(fileName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_remove(&(fileOpInfo->lfsInfo), fileName); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsMkdir(const char *dirName, mode_t mode) -{ - int ret; - struct FileOpInfo *fileOpInfo = NULL; - - if (dirName == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (CheckPathIsMounted(dirName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_mkdir(&(fileOpInfo->lfsInfo), dirName); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsRmdir(const char *dirName) -{ - int ret; - - struct FileOpInfo *fileOpInfo = NULL; - - if (dirName == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (CheckPathIsMounted(dirName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_remove(&(fileOpInfo->lfsInfo), dirName); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -DIR *LfsOpendir(const char *dirName) -{ - int ret; - struct FileOpInfo *fileOpInfo = NULL; - - if (dirName == NULL) { - errno = EFAULT; - goto ERROUT; - } - - if (CheckPathIsMounted(dirName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - goto ERROUT; - } - - if (CheckDirIsOpen(dirName)) { - errno = EBUSY; - goto ERROUT; - } - - FileDirInfo *dirInfo = GetFreeDir(dirName); - if (dirInfo == NULL) { - errno = ENFILE; - goto ERROUT; - } - - ret = lfs_dir_open(&(fileOpInfo->lfsInfo), (lfs_dir_t *)(&(dirInfo->dir)), dirName); - - if (ret != 0) { - FreeDirInfo(dirName); - errno = LittlefsErrno(ret); - goto ERROUT; - } - - dirInfo->lfsHandle = &(fileOpInfo->lfsInfo); - - return (DIR *)dirInfo; - -ERROUT: - return NULL; -} - -struct dirent *LfsReaddir(DIR *dir) -{ - int ret; - struct lfs_info lfsInfo; - - FileDirInfo *dirInfo = (FileDirInfo *)dir; - - if (dirInfo == NULL || dirInfo->lfsHandle == NULL) { - errno = EBADF; - return NULL; - } - - ret = lfs_dir_read(dirInfo->lfsHandle, (lfs_dir_t *)(&(dirInfo->dir)), &lfsInfo); - if (ret == TRUE) { - pthread_mutex_lock(&g_FslocalMutex); - (void)strncpy_s(g_nameValue.d_name, sizeof(g_nameValue.d_name), lfsInfo.name, strlen(lfsInfo.name) + 1); - if (lfsInfo.type == LFS_TYPE_DIR) { - g_nameValue.d_type = DT_DIR; - } else if (lfsInfo.type == LFS_TYPE_REG) { - g_nameValue.d_type = DT_REG; - } - - g_nameValue.d_reclen = lfsInfo.size; - pthread_mutex_unlock(&g_FslocalMutex); - - return &g_nameValue; - } - - if (ret != 0) { - errno = LittlefsErrno(ret); - } - - return NULL; -} - -int LfsClosedir(DIR *dir) -{ - int ret; - FileDirInfo *dirInfo = (FileDirInfo *)dir; - - if (dirInfo == NULL || dirInfo->lfsHandle == NULL) { - errno = EBADF; - return VFS_ERROR; - } - - ret = lfs_dir_close(dirInfo->lfsHandle, (lfs_dir_t *)(&(dirInfo->dir))); - - FreeDirInfo(dirInfo->dirName); - - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsOpen(const char *pathName, int openFlag, ...) -{ - int fd = INVALID_FD; - int err = INVALID_FD; - - struct FileOpInfo *fileOpInfo = NULL; - - if (pathName == NULL) { - errno = EFAULT; - goto ERROUT; - } - - if (CheckPathIsMounted(pathName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - goto ERROUT; - } - // if file is already open, return invalid fd - if (CheckFileIsOpen(pathName)) { - errno = EBUSY; - goto ERROUT; - } - - LittleFsHandleStruct *fsHandle = LfsAllocFd(pathName, &fd); - if (fd == INVALID_FD) { - errno = ENFILE; - goto ERROUT; - } - - int lfsOpenFlag = ConvertFlagToLfsOpenFlag(openFlag); - err = lfs_file_open(&(fileOpInfo->lfsInfo), &(fsHandle->file), pathName, lfsOpenFlag); - if (err != 0) { - LfsFreeFd(fd); - errno = LittlefsErrno(err); - goto ERROUT; - } - - g_handle[fd].lfsHandle = &(fileOpInfo->lfsInfo); - return fd; - -ERROUT: - return INVALID_FD; -} - -int LfsRead(int fd, void *buf, unsigned int len) -{ - int ret; - - if (buf == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - ret = lfs_file_read(g_handle[fd].lfsHandle, &(g_handle[fd].file), buf, len); - if (ret < 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - return ret; -} - -int LfsWrite(int fd, const void *buf, unsigned int len) -{ - int ret; - - if (buf == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - ret = lfs_file_write(g_handle[fd].lfsHandle, &(g_handle[fd].file), buf, len); - if (ret < 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - return ret; -} - -off_t LfsSeek(int fd, off_t offset, int whence) -{ - off_t ret; - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - ret = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), offset, whence); - if (ret < 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsClose(int fd) -{ - int ret; - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - pthread_mutex_lock(&g_FslocalMutex); - ret = lfs_file_close(g_handle[fd].lfsHandle, &(g_handle[fd].file)); - pthread_mutex_unlock(&g_FslocalMutex); - - LfsFreeFd(fd); - - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsRename(const char *oldName, const char *newName) -{ - int ret; - struct FileOpInfo *fileOpInfo = NULL; - - if (oldName == NULL || newName == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (CheckPathIsMounted(oldName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_rename(&(fileOpInfo->lfsInfo), oldName, newName); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsStat(const char *path, struct stat *buf) -{ - int ret; - struct lfs_info info; - struct FileOpInfo *fileOpInfo = NULL; - - if (path == NULL || buf == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (CheckPathIsMounted(path, &fileOpInfo) == FALSE || fileOpInfo == NULL) { - errno = ENOENT; - return VFS_ERROR; - } - - ret = lfs_stat(&(fileOpInfo->lfsInfo), path, &info); - if (ret == 0) { - buf->st_size = info.size; - if (info.type == LFS_TYPE_REG) { - buf->st_mode = S_IFREG; - } else { - buf->st_mode = S_IFDIR; - } - } else { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - return ret; -} - -int LfsFsync(int fd) -{ - int ret; - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - ret = lfs_file_sync(g_handle[fd].lfsHandle, &(g_handle[fd].file)); - if (ret != 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - return ret; -} - -int LfsFstat(int fd, struct stat *buf) -{ - int ret; - struct lfs_info info; - - if (buf == NULL) { - errno = EFAULT; - return FS_FAILURE; - } - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - ret = lfs_stat(g_handle[fd].lfsHandle, g_handle[fd].pathName, &info); - if (ret == 0) { - buf->st_size = info.size; - if (info.type == LFS_TYPE_REG) { - buf->st_mode = S_IFREG; - } else { - buf->st_mode = S_IFDIR; - } - } else { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - return ret; -} - -int LfsPread(int fd, void *buf, size_t nbyte, off_t offset) -{ - int ret; - off_t savepos, pos; - - if (buf == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - savepos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), 0, SEEK_CUR); - if (savepos == (off_t)-1) { - errno = LittlefsErrno(savepos); - return VFS_ERROR; - } - - pos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), offset, SEEK_SET); - if (pos == (off_t)-1) { - errno = LittlefsErrno(pos); - return VFS_ERROR; - } - - ret = lfs_file_read(g_handle[fd].lfsHandle, &(g_handle[fd].file), buf, nbyte); - if (ret < 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - pos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), savepos, SEEK_SET); - if ((pos == (off_t)-1) && (ret >= 0)) { - errno = LittlefsErrno(pos); - return VFS_ERROR; - } - - return ret; -} - -int LfsPwrite(int fd, const void *buf, size_t nbyte, off_t offset) -{ - int ret; - off_t savepos, pos; - - if (buf == NULL) { - errno = EFAULT; - return VFS_ERROR; - } - - if (LfsFdIsValid(fd) == FALSE) { - errno = EBADF; - return VFS_ERROR; - } - - savepos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), 0, SEEK_CUR); - if (savepos == (off_t)-1) { - errno = LittlefsErrno(savepos); - return VFS_ERROR; - } - - pos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), offset, SEEK_SET); - if (pos == (off_t)-1) { - errno = LittlefsErrno(pos); - return VFS_ERROR; - } - - ret = lfs_file_write(g_handle[fd].lfsHandle, &(g_handle[fd].file), buf, nbyte); - if (ret < 0) { - errno = LittlefsErrno(ret); - ret = VFS_ERROR; - } - - pos = (off_t)lfs_file_seek(g_handle[fd].lfsHandle, &(g_handle[fd].file), savepos, SEEK_SET); - if ((pos == (off_t)-1) && (ret >= 0)) { - errno = LittlefsErrno(pos); - return VFS_ERROR; - } - - return ret; -} \ No newline at end of file diff --git a/components/fs/vfs/BUILD.gn b/components/fs/vfs/BUILD.gn index 94061d2d..4f7a680a 100644 --- a/components/fs/vfs/BUILD.gn +++ b/components/fs/vfs/BUILD.gn @@ -1,5 +1,4 @@ -# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. -# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# Copyright (c) 2022-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: @@ -32,7 +31,26 @@ import("//kernel/liteos_m/liteos.gni") module_switch = defined(LOSCFG_FS_VFS) module_name = get_path_info(rebase_path("."), "name") kernel_module(module_name) { - sources = [ "los_fs.c" ] + sources = [ + "vfs_files.c", + "vfs_fs.c", + "vfs_init.c", + "vfs_maps.c", + "vfs_mount.c", + "vfs_partition.c", + ] + + include_dirs = [ + "//kernel/liteos_m/kernel/arch/include", + "//kernel/liteos_m/kernel/include", + "//kernel/liteos_m/utils", + "../", + ".", + ] + + deps = [ "//kernel/liteos_m/kal" ] + configs += [ "$LITEOSTOPDIR:warn_config" ] + cflags = [ "-Wno-parentheses" ] } config("public") { diff --git a/components/fs/vfs/Kconfig b/components/fs/vfs/Kconfig index b51be4b5..66971deb 100644 --- a/components/fs/vfs/Kconfig +++ b/components/fs/vfs/Kconfig @@ -1,5 +1,5 @@ # Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. -# Copyright (c) 2020-2021 Huawei Device 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: @@ -30,5 +30,9 @@ config FS_VFS bool "Enable FS VFS" default y + help Answer Y to enable LiteOS support VFS. + +source "components/fs/littlefs/Kconfig" +source "components/fs/fatfs/Kconfig" diff --git a/components/fs/vfs/fs_operations.h b/components/fs/vfs/fs_operations.h deleted file mode 100644 index f0acfdf6..00000000 --- a/components/fs/vfs/fs_operations.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 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. - */ - -#ifndef _FS_OPERATIONS_H_ -#define _FS_OPERATIONS_H_ - -#include "fcntl.h" -#include "dirent.h" -#include "unistd.h" -#include "sys/mount.h" -#include "sys/stat.h" -#include "sys/statfs.h" - -#define FS_SUCCESS 0 -#define FS_FAILURE (-1) -#define MAX_FILESYSTEM_LEN 2 - -struct MountOps { - int (*Mount)(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, - const void *data); - int (*Umount)(const char* target); - int (*Umount2)(const char* target, int flag); - int (*Statfs)(const char *path, struct statfs *buf); -}; - -struct FsMap { - const char *fileSystemtype; - const struct MountOps *fsMops; - const struct FileOps *fsFops; -}; - -struct FileOps { - int (*Open)(const char *path, int openFlag, ...); - int (*Close)(int fd); - int (*Unlink)(const char *fileName); - int (*Rmdir)(const char *dirName); - int (*Mkdir)(const char *dirName, mode_t mode); - struct dirent *(*Readdir)(DIR *dir); - DIR *(*Opendir)(const char *dirName); - int (*Closedir)(DIR *dir); - int (*Read)(int fd, void *buf, size_t len); - int (*Write)(int fd, const void *buf, size_t len); - off_t (*Seek)(int fd, off_t offset, int whence); - int (*Getattr)(const char *path, struct stat *buf); - int (*Rename)(const char *oldName, const char *newName); - int (*Fsync)(int fd); - int (*Fstat)(int fd, struct stat *buf); - int (*Stat)(const char *path, struct stat *buf); - int (*Ftruncate)(int fd, off_t length); - int (*Pread)(int fd, void *buf, size_t nbyte, off_t offset); - int (*Pwrite)(int fd, const void *buf, size_t nbyte, off_t offset); -}; - -#endif /* _FS_OPERATIONS_H_ */ diff --git a/components/fs/vfs/los_fs.c b/components/fs/vfs/los_fs.c deleted file mode 100644 index 5fb95380..00000000 --- a/components/fs/vfs/los_fs.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 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. - */ - -#include "los_fs.h" -#include "los_config.h" -#include "fs_operations.h" -#if (LOSCFG_SUPPORT_FATFS == 1) -#include "fatfs.h" -#endif -#include "dirent.h" -#include "errno.h" -#include "fcntl.h" -#include "securec.h" -#include "stdio.h" -#include "stdlib.h" -#include "string.h" -#include "sys/mount.h" -#include "sys/statfs.h" -#include "sys/stat.h" -#include "unistd.h" - -#ifdef LOSCFG_NET_LWIP_SACK -#define _BSD_SOURCE -#include "lwip/sockets.h" -#endif - -#include "vfs_config.h" - -#ifdef LOSCFG_RANDOM_DEV -#include "hks_client.h" -#define RANDOM_DEV_FD CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS -#define RANDOM_DEV_PATH "/dev/random" -#endif - -#if (LOSCFG_POSIX_PIPE_API == 1) -#include "pipe_impl.h" -#ifdef LOSCFG_RANDOM_DEV -#define PIPE_DEV_FD (RANDOM_DEV_FD + 1) -#else -#define PIPE_DEV_FD (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS) -#endif - -int PollQueryFd(int fd, struct PollTable *table) -{ - if (fd >= PIPE_DEV_FD) { - return PipePoll(fd, table); - } - - return -ENODEV; -} -#endif - -#define FREE_AND_SET_NULL(ptr) do { \ - free(ptr); \ - ptr = NULL; \ -} while (0) - -#ifdef LOSCFG_RANDOM_DEV -/** - * @brief Get canonical form of a given path based on cwd(Current working directory). - * - * @param cwd Indicates the current working directory. - * @param path Indicates the path to be canonicalization. - * @param buf Indicates the pointer to the buffer where the result will be return. - * @param bufSize Indicates the size of the buffer. - * @return Returns the length of the canonical path. - * - * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/'). - * if the buffer is not big enough the result will be truncated, but the return value will always be the - * length of the canonical path. - */ -static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize) -{ - size_t offset; - if (!path) { - path = ""; - } - - if (!cwd || path[0] == '/') { - cwd = ""; - } - - offset = strlen("///") + 1; // three '/' and one '\0' - size_t tmpLen = strlen(cwd) + strlen(path) + offset; - char *tmpBuf = (char *)malloc(tmpLen); - if (tmpBuf == NULL) { - return FS_SUCCESS; - } - - if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) { - free(tmpBuf); - return FS_SUCCESS; - } - - char *p; - /* replace /./ to / */ - offset = strlen("/./") - 1; - while ((p = strstr(tmpBuf, "/./")) != NULL) { - if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) { - free(tmpBuf); - return FS_SUCCESS; - } - } - - /* replace // to / */ - while ((p = strstr(tmpBuf, "//")) != NULL) { - if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) { - free(tmpBuf); - return FS_SUCCESS; - } - } - - /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */ - offset = strlen("/../") - 1; - while ((p = strstr(tmpBuf, "/../")) != NULL) { - char *start = p; - while (start > tmpBuf && *(start - 1) != '/') { - --start; - } - if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) { - free(tmpBuf); - return FS_SUCCESS; - } - } - - size_t totalLen = strlen(tmpBuf); - /* strip the last / */ - if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') { - tmpBuf[--totalLen] = 0; - } - - if (!buf || bufSize == 0) { - free(tmpBuf); - return totalLen; - } - - if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) { - free(tmpBuf); - return FS_SUCCESS; - } - - buf[bufSize - 1] = 0; - free(tmpBuf); - return totalLen; -} -#endif - -static struct FsMap g_fsmap[MAX_FILESYSTEM_LEN] = {0}; -static struct FsMap *g_fs = NULL; - -static void InitMountInfo(void) -{ -#if (LOSCFG_SUPPORT_FATFS == 1) - extern struct MountOps g_fatfsMnt; - extern struct FileOps g_fatfsFops; - g_fsmap[0].fileSystemtype = strdup("fat"); - g_fsmap[0].fsMops = &g_fatfsMnt; - g_fsmap[0].fsFops = &g_fatfsFops; -#endif -#if (LOSCFG_SUPPORT_LITTLEFS == 1) - extern struct MountOps g_lfsMnt; - extern struct FileOps g_lfsFops; - g_fsmap[1].fileSystemtype = strdup("littlefs"); - g_fsmap[1].fsMops = &g_lfsMnt; - g_fsmap[1].fsFops = &g_lfsFops; -#endif -} - -static struct FsMap *MountFindfs(const char *fileSystemtype) -{ - struct FsMap *m = NULL; - - for (int i = 0; i < MAX_FILESYSTEM_LEN; i++) { - m = &(g_fsmap[i]); - if (m->fileSystemtype && strcmp(fileSystemtype, m->fileSystemtype) == 0) { - return m; - } - } - - return NULL; -} - -int LOS_FsMount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data) -{ - static int initFlag = 0; - - if (initFlag == 0) { - InitMountInfo(); - initFlag = 1; - } - - g_fs = MountFindfs(filesystemtype); - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - - if (g_fs->fsMops == NULL || g_fs->fsMops->Mount == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - - return g_fs->fsMops->Mount(source, target, filesystemtype, mountflags, data); -} - -int LOS_FsUmount(const char *target) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsMops == NULL || g_fs->fsMops->Umount == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsMops->Umount(target); -} - -int LOS_FsUmount2(const char *target, int flag) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsMops == NULL || g_fs->fsMops->Umount2 == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsMops->Umount2(target, flag); -} - -int LOS_Open(const char *path, int oflag, ...) -{ -#ifdef LOSCFG_RANDOM_DEV - unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY; - if ((unsigned)oflag & ~flags) { - errno = EINVAL; - return FS_FAILURE; - } - - size_t pathLen = strlen(path) + 1; - char *canonicalPath = (char *)malloc(pathLen); - if (!canonicalPath) { - errno = ENOMEM; - return FS_FAILURE; - } - if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) { - FREE_AND_SET_NULL(canonicalPath); - errno = ENOMEM; - return FS_FAILURE; - } - - if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) { - FREE_AND_SET_NULL(canonicalPath); - if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) { - errno = EPERM; - return FS_FAILURE; - } - if ((unsigned)oflag & O_DIRECTORY) { - errno = ENOTDIR; - return FS_FAILURE; - } - return RANDOM_DEV_FD; - } - if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) { - FREE_AND_SET_NULL(canonicalPath); - if ((unsigned)oflag & O_DIRECTORY) { - errno = EPERM; - return FS_FAILURE; - } - errno = EISDIR; - return FS_FAILURE; - } - FREE_AND_SET_NULL(canonicalPath); -#endif - -#if (LOSCFG_POSIX_PIPE_API == 1) - if ((path != NULL) && !strncmp(path, PIPE_DEV_PATH, strlen(PIPE_DEV_PATH))) { - return PipeOpen(path, oflag, PIPE_DEV_FD); - } -#endif - - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Open == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Open(path, oflag); -} - -int LOS_Close(int fd) -{ -#ifdef LOSCFG_RANDOM_DEV - if (fd == RANDOM_DEV_FD) { - return FS_SUCCESS; - } -#endif -#ifdef LOSCFG_NET_LWIP_SACK - if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { - return closesocket(fd); - } -#endif - -#if (LOSCFG_POSIX_PIPE_API == 1) - if (fd >= PIPE_DEV_FD) { - return PipeClose(fd); - } -#endif - - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Close == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Close(fd); -} - -ssize_t LOS_Read(int fd, void *buf, size_t nbyte) -{ -#ifdef LOSCFG_RANDOM_DEV - if (fd == RANDOM_DEV_FD) { - if (nbyte == 0) { - return FS_SUCCESS; - } - if (buf == NULL) { - errno = EINVAL; - return FS_FAILURE; - } - if (nbyte > 1024) { /* 1024, max random_size */ - nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */ - } - struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte}; - if (hks_generate_random(&key) != 0) { - errno = EIO; - return FS_FAILURE; - } - return (ssize_t)nbyte; - } -#endif -#ifdef LOSCFG_NET_LWIP_SACK - if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { - return recv(fd, buf, nbyte, 0); - } -#endif - -#if (LOSCFG_POSIX_PIPE_API == 1) - if (fd >= PIPE_DEV_FD) { - return PipeRead(fd, buf, nbyte); - } -#endif - - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Read == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Read(fd, buf, nbyte); -} - -ssize_t LOS_Write(int fd, const void *buf, size_t nbyte) -{ -#ifdef LOSCFG_RANDOM_DEV - if (fd == RANDOM_DEV_FD) { - errno = EBADF; /* "/dev/random" is readonly */ - return FS_FAILURE; - } -#endif -#ifdef LOSCFG_NET_LWIP_SACK - if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { - return send(fd, buf, nbyte, 0); - } -#endif - -#if (LOSCFG_POSIX_PIPE_API == 1) - if (fd >= PIPE_DEV_FD) { - return PipeWrite(fd, buf, nbyte); - } -#endif - - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Write == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Write(fd, buf, nbyte); -} - -off_t LOS_Lseek(int fd, off_t offset, int whence) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Seek == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Seek(fd, offset, whence); -} - -int LOS_Unlink(const char *path) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Unlink == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Unlink(path); -} - -int LOS_Fstat(int fd, struct stat *buf) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Fstat == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Fstat(fd, buf); -} - -int LOS_Stat(const char *path, struct stat *buf) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Getattr == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Getattr(path, buf); -} - -int LOS_Fsync(int fd) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Fsync == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Fsync(fd); -} - -int LOS_Mkdir(const char *path, mode_t mode) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Mkdir == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Mkdir(path, mode); -} - -DIR *LOS_Opendir(const char *dirName) -{ - if (g_fs == NULL) { - errno = ENODEV; - return NULL; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Opendir == NULL) { - errno = ENOSYS; - return NULL; - } - return g_fs->fsFops->Opendir(dirName); -} - -struct dirent *LOS_Readdir(DIR *dir) -{ - if (g_fs == NULL) { - errno = ENODEV; - return NULL; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Readdir == NULL) { - errno = ENOSYS; - return NULL; - } - return g_fs->fsFops->Readdir(dir); -} - -int LOS_Closedir(DIR *dir) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Closedir == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Closedir(dir); -} - -int LOS_Rmdir(const char *path) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Rmdir == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Rmdir(path); -} - -int LOS_Rename(const char *oldName, const char *newName) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Rename == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Rename(oldName, newName); -} - -int LOS_Statfs(const char *path, struct statfs *buf) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsMops == NULL || g_fs->fsMops->Statfs == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsMops->Statfs(path, buf); -} - -int LOS_Ftruncate(int fd, off_t length) -{ - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Ftruncate == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Ftruncate(fd, length); -} - -ssize_t LOS_Pread(int fd, void *buf, size_t nbyte, off_t offset) -{ -#ifdef LOSCFG_RANDOM_DEV - if (fd == RANDOM_DEV_FD) { - if (nbyte == 0) { - return FS_SUCCESS; - } - if (buf == NULL) { - errno = EINVAL; - return FS_FAILURE; - } - if (nbyte > 1024) { /* 1024, max random_size */ - nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */ - } - struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte}; - if (hks_generate_random(&key) != 0) { - errno = EIO; - return FS_FAILURE; - } - return (ssize_t)nbyte; - } -#endif - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Pread == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Pread(fd, buf, nbyte, offset); -} - -ssize_t LOS_Pwrite(int fd, const void *buf, size_t nbyte, off_t offset) -{ -#ifdef LOSCFG_RANDOM_DEV - if (fd == RANDOM_DEV_FD) { - errno = EBADF; /* "/dev/random" is readonly */ - return FS_FAILURE; - } -#endif - if (g_fs == NULL) { - errno = ENODEV; - return FS_FAILURE; - } - if (g_fs->fsFops == NULL || g_fs->fsFops->Pwrite == NULL) { - errno = ENOSYS; - return FS_FAILURE; - } - return g_fs->fsFops->Pwrite(fd, buf, nbyte, offset); -} diff --git a/components/fs/vfs/los_fs.h b/components/fs/vfs/los_fs.h index 7cbca811..9aed69d2 100644 --- a/components/fs/vfs/los_fs.h +++ b/components/fs/vfs/los_fs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 Huawei Device 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: @@ -30,18 +30,19 @@ */ /** - * @defgroup los_vfs fs + * @defgroup los_fs fs * @ingroup kernel */ -#ifndef _LOS_VFS_H_ -#define _LOS_VFS_H_ +#ifndef _LOS_FS_H_ +#define _LOS_FS_H_ #include "los_config.h" #include "dirent.h" #include "sys/mount.h" #include "sys/statfs.h" #include "sys/stat.h" +#include "sys/uio.h" #include "unistd.h" #ifdef __cplusplus @@ -50,51 +51,72 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -int LOS_Open(const char *path, int oflag, ...); - +int LOS_Open(const char *path, int flags, ...); int LOS_Close(int fd); - -ssize_t LOS_Read(int fd, void *buf, size_t nbyte); - -ssize_t LOS_Write(int fd, const void *buf, size_t nbyte); - -off_t LOS_Lseek(int fd, off_t offset, int whence); - +ssize_t LOS_Read(int fd, void *buff, size_t bytes); +ssize_t LOS_Write(int fd, const void *buff, size_t bytes); +off_t LOS_Lseek(int fd, off_t off, int whence); +int LOS_Stat(const char *path, struct stat *stat); +int LOS_Statfs(const char *path, struct statfs *buf); int LOS_Unlink(const char *path); - -int LOS_Fstat(int fd, struct stat *buf); - -int LOS_Stat(const char *path, struct stat *buf); - +int LOS_Rename(const char *oldpath, const char *newpath); int LOS_Fsync(int fd); - -int LOS_Mkdir(const char *path, mode_t mode); - -DIR *LOS_Opendir(const char *dirName); - +DIR *LOS_Opendir(const char *path); struct dirent *LOS_Readdir(DIR *dir); - int LOS_Closedir(DIR *dir); - +int LOS_Mkdir(const char *path, mode_t mode); int LOS_Rmdir(const char *path); - -int LOS_Rename(const char *oldName, const char *newName); - -int LOS_Statfs(const char *path, struct statfs *buf); - +int LOS_Lstat(const char *path, struct stat *buffer); +int LOS_Fstat(int fd, struct stat *buf); +int LOS_Fcntl(int fd, int cmd, ...); +int LOS_Ioctl(int fd, int req, ...); +ssize_t LOS_Readv(int fd, const struct iovec *iovBuf, int iovcnt); +ssize_t LOS_Writev(int fd, const struct iovec *iovBuf, int iovcnt); +ssize_t LOS_Pread(int fd, void *buff, size_t bytes, off_t off); +ssize_t LOS_Pwrite(int fd, const void *buff, size_t bytes, off_t off); +int LOS_Isatty(int fd); +int LOS_Access(const char *path, int amode); int LOS_Ftruncate(int fd, off_t length); - -int LOS_FsUmount2(const char *target, int flag); - int LOS_FsUmount(const char *target); - +int LOS_FsUmount2(const char *target, int flag); int LOS_FsMount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, + const char *fsType, unsigned long mountflags, const void *data); +/* + * @brief Divide the device into partitions. + * + * @param dev Device name, which customized by caller, it is recommended to + * name it as: "emmc0", "emmc1", "flash0", etc. The name is combined with + * "device_type" + "device_id", and the last character is device_id. + * device_id >= 0 && device_id <= 9. + * @param fsType Filesystem type. + * @param lengthArray List of partition size. For example: + * [0x10000000, 0x2000000], 256M and 512M partitions will be created and + * left all will not allocated. + * @param partNum Length of 'lengthArray'. + * + * @return Return LOS_NOK if error. Return LOS_OK if success. + * Partition naming rules: + * In the current vfs, after successfully calling the 'fdisk' hook, + * "partNum" partitions will be created. + * The partition naming rules is: + * The name is a combination of: 'deviceName'+'p'+'partitionId', + * such as "emmc0p0", "emmc0p1", "emmc0p2"... + */ +int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, + int partnum); -ssize_t LOS_Pread(int fd, void *buf, size_t nbyte, off_t offset); - -ssize_t LOS_Pwrite(int fd, const void *buf, size_t nbyte, off_t offset); +/* + * @brief Format a partition. + * + * @param partName PartitionName, following the rule of fdisk hook. + * @param data For FatFs, the data indicates a pointer to a byte which + * specifies combination of FAT type flags, FM_FAT, FM_FAT32, FM_EXFAT and + * bitwise-or of these three, FM_ANY. + * + * @return Return LOS_NOK if error. Return LOS_OK if success. + */ +int LOS_PartitionFormat(const char *partName, char *fsType, void *data); #ifdef __cplusplus #if __cplusplus @@ -102,4 +124,4 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ -#endif /* _LOS_FS_H_ */ \ No newline at end of file +#endif /* _LOS_FS_H_ */ diff --git a/components/fs/vfs/vfs_config.h b/components/fs/vfs/vfs_config.h index a3538a34..54fd2ca2 100644 --- a/components/fs/vfs/vfs_config.h +++ b/components/fs/vfs/vfs_config.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 Huawei Device 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: @@ -32,54 +32,8 @@ #ifndef _VFS_CONFIG_H_ #define _VFS_CONFIG_H_ -#define PATH_MAX 256 -#define CONFIG_DISABLE_MQUEUE // disable posix mqueue inode configure - -/* file system configur */ - -#define CONFIG_FS_WRITABLE // enable file system can be written -#define CONFIG_FS_READABLE // enable file system can be read -#define CONFIG_DEBUG_FS // enable vfs debug function - - -/* fatfs cache configur */ -/* config block size for fat file system, only can be 0,32,64,128,256,512,1024 */ -#define CONFIG_FS_FAT_SECTOR_PER_BLOCK 64 - -/* config block num for fat file system */ -#define CONFIG_FS_FAT_READ_NUMS 7 -#define CONFIG_FS_FAT_BLOCK_NUMS 28 - -#ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD - -/* config the priority of sync task */ - -#define CONFIG_FS_FAT_SYNC_THREAD_PRIO 10 - -/* config dirty ratio of bcache for fat file system */ - -#define CONFIG_FS_FAT_DIRTY_RATIO 60 - -/* config time interval of sync thread for fat file system, in milliseconds */ - -#define CONFIG_FS_FAT_SYNC_INTERVAL 5000 -#endif - -#define CONFIG_FS_FLASH_BLOCK_NUM 1 - -#define CONFIG_FS_MAX_LNK_CNT 40 - -/* nfs configure */ - -#define CONFIG_NFS_MACHINE_NAME "IPC" // nfs device name is IPC -#define CONFIG_NFS_MACHINE_NAME_SIZE 3 // size of nfs machine name - - /* file descriptors configure */ -#define CONFIG_NFILE_STREAMS 1 // enable file stream -#define CONFIG_STDIO_BUFFER_SIZE 0 -#define CONFIG_NUNGET_CHARS 0 #define MIN_START_FD 3 // 0,1,2 are used for stdin,stdout,stderr respectively /* net configure */ @@ -87,12 +41,8 @@ #ifdef LOSCFG_NET_LWIP_SACK // enable socket and net function #include "lwip/lwipopts.h" #define CONFIG_NSOCKET_DESCRIPTORS LWIP_CONFIG_NUM_SOCKETS // max numbers of socket descriptor -#define CONFIG_NET_SENDFILE 1 // enable sendfile function -#define CONFIG_NET_TCP 1 // enable sendfile and send function #else #define CONFIG_NSOCKET_DESCRIPTORS 0 -#define CONFIG_NET_SENDFILE 0 // disable sendfile function -#define CONFIG_NET_TCP 0 // disable sendfile and send function #endif /* max numbers of other descriptors except socket descriptors */ diff --git a/components/fs/vfs/vfs_files.c b/components/fs/vfs/vfs_files.c new file mode 100644 index 00000000..24ea1891 --- /dev/null +++ b/components/fs/vfs/vfs_files.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022-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. + */ +#include "vfs_files.h" +#include "errno.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "los_config.h" +#include "vfs_config.h" +#include "vfs_mount.h" +#include "vfs_operations.h" + +static struct File g_files[NR_OPEN_DEFAULT]; + +int FileToFd(struct File *file) +{ + if (file == NULL) { + return LOS_NOK; + } + return file - g_files + MIN_START_FD; +} + +struct File *FdToFile(int fd) +{ + if ((fd < MIN_START_FD) || (fd >= CONFIG_NFILE_DESCRIPTORS)) { + return NULL; + } + return &g_files[fd - MIN_START_FD]; +} + +struct File *VfsFileGet(void) +{ + int i; + /* protected by g_fsMutex */ + for (i = 0; i < NR_OPEN_DEFAULT; i++) { + if (g_files[i].fStatus == FILE_STATUS_NOT_USED) { + g_files[i].fStatus = FILE_STATUS_INITING; + return &g_files[i]; + } + } + + return NULL; +} + +struct File *VfsFileGetSpec(int fd) +{ + if ((fd < MIN_START_FD) || (fd >= CONFIG_NFILE_DESCRIPTORS)) { + return NULL; + } + if (g_files[fd - MIN_START_FD].fStatus == FILE_STATUS_NOT_USED) { + g_files[fd - MIN_START_FD].fStatus = FILE_STATUS_INITING; + return &g_files[fd - MIN_START_FD]; + } + + return NULL; +} + +void VfsFilePut(struct File *file) +{ + if (file == NULL) { + return; + } + file->fFlags = 0; + file->fFops = NULL; + file->fData = NULL; + file->fMp = NULL; + file->fOffset = 0; + file->fOwner = -1; + file->fullPath = NULL; + file->fStatus = FILE_STATUS_NOT_USED; +} diff --git a/components/fs/vfs/vfs_files.h b/components/fs/vfs/vfs_files.h new file mode 100644 index 00000000..ac7b7ff0 --- /dev/null +++ b/components/fs/vfs/vfs_files.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef _VFS_FILES_H_ +#define _VFS_FILES_H_ + +#include "dirent.h" +#include "sys/stat.h" +#include "unistd.h" +#include "los_compiler.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define FILE_STATUS_NOT_USED 0 +#define FILE_STATUS_INITING 1 +#define FILE_STATUS_READY 2 +#define FILE_STATUS_CLOSING 3 + +struct FileOps; +struct File; +struct Dir; +struct MountPoint; + +struct FileOps { + int (*open)(struct File *, const char *, int); + int (*close)(struct File *); + ssize_t (*read)(struct File *, char *, size_t); + ssize_t (*write)(struct File *, const char *, size_t); + off_t (*lseek)(struct File *, off_t, int); + int (*stat)(struct MountPoint *, const char *, struct stat *); + int (*truncate)(struct File *, off_t); + int (*unlink)(struct MountPoint *, const char *); + int (*rename)(struct MountPoint *, const char *, const char *); + int (*ioctl)(struct File *, int, unsigned long); + int (*sync)(struct File *); + int (*opendir)(struct Dir *, const char *); + int (*readdir)(struct Dir *, struct dirent *); + int (*closedir)(struct Dir *); + int (*mkdir)(struct MountPoint *, const char *); + int (*rmdir)(struct MountPoint *, const char *); +}; + +struct File { + const struct FileOps *fFops; + UINT32 fFlags; + UINT32 fStatus; + off_t fOffset; + INT32 fOwner; + struct MountPoint *fMp; + void *fData; /* file system opreations handle, fatfs FIL, etc. */ + const char *fullPath; +}; + +struct Dir { + struct MountPoint *dMp; + struct dirent dDent; + off_t dOffset; + void *dData; +}; + +int FileToFd(struct File *file); +struct File *FdToFile(int fd); +struct File *VfsFileGet(void); +struct File *VfsFileGetSpec(int fd); +void VfsFilePut(struct File *file); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _VFS_FILES_H_ */ diff --git a/components/fs/vfs/vfs_fs.c b/components/fs/vfs/vfs_fs.c new file mode 100644 index 00000000..37f42f5e --- /dev/null +++ b/components/fs/vfs/vfs_fs.c @@ -0,0 +1,1392 @@ +/* + * Copyright (c) 2022-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 "los_fs.h" +#include +#include +#include +#include +#include +#include +#include "errno.h" +#include "fcntl.h" +#include "los_mux.h" +#include "los_debug.h" +#include "limits.h" +#include "securec.h" +#include "vfs_config.h" +#include "vfs_files.h" +#include "vfs_maps.h" +#include "vfs_mount.h" +#include "vfs_operations.h" + +#ifdef LOSCFG_NET_LWIP_SACK +#include "lwipopts.h" +#include "lwip/sockets.h" +#define CONFIG_NSOCKET_DESCRIPTORS LWIP_CONFIG_NUM_SOCKETS +#else +#define CONFIG_NSOCKET_DESCRIPTORS 0 +#endif + +#ifndef CONFIG_NFILE_DESCRIPTORS +#define CONFIG_NFILE_DESCRIPTORS 256 +#endif + +#ifdef LOSCFG_RANDOM_DEV +#include "hks_client.h" +#define RANDOM_DEV_FD CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS +#define RANDOM_DEV_PATH "/dev/random" +#endif + +#if (LOSCFG_POSIX_PIPE_API == 1) +#include "pipe_impl.h" +#ifdef LOSCFG_RANDOM_DEV +#define PIPE_DEV_FD (RANDOM_DEV_FD + 1) +#else +#define PIPE_DEV_FD (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS) +#endif + +int PollQueryFd(int fd, struct PollTable *table) +{ + if (fd >= PIPE_DEV_FD) { + return PipePoll(fd, table); + } + + return -ENODEV; +} +#endif + +#define FREE_AND_SET_NULL(ptr) do { \ + free(ptr); \ + ptr = NULL; \ +} while (0) + +#define LOS_FCNTL (O_NONBLOCK | O_NDELAY | O_APPEND | O_SYNC) +#define IOV_MAX_CNT 4 + +UINT32 g_fsMutex; + +int VfsLock(void) +{ + if (LOS_MuxPend(g_fsMutex, LOS_WAIT_FOREVER) != LOS_OK) { + PRINT_ERR("VfsLock failed!"); + return LOS_NOK; + } + + return LOS_OK; +} + +void VfsUnlock(void) +{ + (void)LOS_MuxPost(g_fsMutex); +} + +#ifdef LOSCFG_RANDOM_DEV +/** + * @brief Get canonical form of a given path based on cwd(Current working directory). + * + * @param cwd Indicates the current working directory. + * @param path Indicates the path to be canonicalization. + * @param buf Indicates the pointer to the buffer where the result will be return. + * @param bufSize Indicates the size of the buffer. + * @return Returns the length of the canonical path. + * + * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/'). + * if the buffer is not big enough the result will be truncated, but the return value will always be the + * length of the canonical path. + */ +static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize) +{ + size_t offset; + if (!path) { + path = ""; + } + + if ((!cwd) || (path[0] == '/')) { + cwd = ""; + } + + offset = strlen("///") + 1; // three '/' and one '\0' + size_t tmpLen = strlen(cwd) + strlen(path) + offset; + char *tmpBuf = (char *)malloc(tmpLen); + if (tmpBuf == NULL) { + return LOS_OK; + } + + if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) { + free(tmpBuf); + return LOS_OK; + } + + char *p; + /* replace /./ to / */ + offset = strlen("/./") - 1; + while ((p = strstr(tmpBuf, "/./")) != NULL) { + if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) { + free(tmpBuf); + return LOS_OK; + } + } + + /* replace // to / */ + while ((p = strstr(tmpBuf, "//")) != NULL) { + if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) { + free(tmpBuf); + return LOS_OK; + } + } + + /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */ + offset = strlen("/../") - 1; + while ((p = strstr(tmpBuf, "/../")) != NULL) { + char *start = p; + while (start > tmpBuf && *(start - 1) != '/') { + --start; + } + if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) { + free(tmpBuf); + return LOS_OK; + } + } + + size_t totalLen = strlen(tmpBuf); + /* strip the last / */ + if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') { + tmpBuf[--totalLen] = 0; + } + + if ((!buf) || (bufSize == 0)) { + free(tmpBuf); + return totalLen; + } + + if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) { + free(tmpBuf); + return LOS_OK; + } + + buf[bufSize - 1] = 0; + free(tmpBuf); + return totalLen; +} +#endif + +static int VfsOpen(const char *path, int flags) +{ + struct File *file = NULL; + int fd = -1; + const char *pathInMp = NULL; + struct MountPoint *mp = NULL; + + if ((path == NULL) || (path[strlen(path) - 1] == '/')) { + VFS_ERRNO_SET(EINVAL); + return fd; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return fd; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') || + (mp->mFs->fsFops == NULL) || (mp->mFs->fsFops->open == NULL)) { + /* path is not in any mountpoint */ + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + return fd; + } + + if ((mp->mWriteEnable == FALSE) && + (flags & (O_CREAT | O_WRONLY | O_RDWR))) { + /* can't create file in read only mp */ + VFS_ERRNO_SET(EACCES); + VfsUnlock(); + return fd; + } + + file = VfsFileGet(); + if (file == NULL) { + VFS_ERRNO_SET(ENFILE); + VfsUnlock(); + return fd; + } + + file->fullPath = strdup(path); + if (file->fullPath == NULL) { + VFS_ERRNO_SET(ENOMEM); + VfsFilePut(file); + VfsUnlock(); + return LOS_NOK; + } + + file->fFlags = (UINT32)flags; + file->fOffset = 0; + file->fData = NULL; + file->fFops = mp->mFs->fsFops; + file->fMp = mp; + file->fOwner = LOS_CurTaskIDGet(); + + if (file->fFops->open(file, pathInMp, flags) == 0) { + mp->mRefs++; + fd = FileToFd(file); + file->fStatus = FILE_STATUS_READY; /* file now ready to use */ + } else { + VfsFilePut(file); + } + + VfsUnlock(); + return fd; +} + +/* attach to a file and then set new status */ + +static struct File *VfsAttachFile(int fd, UINT32 status) +{ + struct File *file = NULL; + + if ((fd < 0) || (fd >= CONFIG_NFILE_DESCRIPTORS)) { + VFS_ERRNO_SET(EBADF); + return NULL; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EFAULT); + return NULL; + } + + file = FdToFile(fd); + if ((file == NULL) || (file->fMp == NULL)) { + VFS_ERRNO_SET(EBADF); + VfsUnlock(); + return NULL; + } + + if (file->fStatus != FILE_STATUS_READY) { + VFS_ERRNO_SET(EBADF); + VfsUnlock(); + return NULL; + } + + file->fStatus = status; + return file; +} + +static struct File *VfsAttachFileReady(int fd) +{ + return VfsAttachFile(fd, FILE_STATUS_READY); +} + +static struct File *VfsAttachFileWithStatus(int fd, int status) +{ + return VfsAttachFile(fd, (UINT32)status); +} + +static void VfsDetachFile(const struct File *file) +{ + (void)file; + VfsUnlock(); +} + +static int VfsClose(int fd) +{ + struct File *file = NULL; + int ret = LOS_NOK; + + file = VfsAttachFileWithStatus(fd, FILE_STATUS_CLOSING); + if (file == NULL) { + return ret; + } + + if ((file->fFops != NULL) && (file->fFops->close != NULL)) { + ret = file->fFops->close(file); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + if ((ret == 0) && (file->fMp != NULL)) { + file->fMp->mRefs--; + } + + if (file->fullPath != NULL) { + free((void *)file->fullPath); + } + + VfsDetachFile(file); + + VfsFilePut(file); + + return ret; +} + +static ssize_t VfsRead(int fd, char *buff, size_t bytes) +{ + struct File *file = NULL; + ssize_t ret = (ssize_t)-1; + + if (buff == NULL) { + VFS_ERRNO_SET(EFAULT); + return ret; + } + + if (bytes == 0) { + return 0; + } + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if ((file->fFlags & O_ACCMODE) == O_WRONLY) { + VFS_ERRNO_SET(EACCES); + } else if ((file->fFops != NULL) && (file->fFops->read != NULL)) { + ret = file->fFops->read(file, buff, bytes); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + /* else ret will be -1 */ + VfsDetachFile(file); + + return ret; +} + +static ssize_t VfsWrite(int fd, const void *buff, size_t bytes) +{ + struct File *file = NULL; + ssize_t ret = LOS_NOK; + + if ((buff == NULL) || (bytes == 0)) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if ((file->fFlags & O_ACCMODE) == O_RDONLY) { + VFS_ERRNO_SET(EACCES); + } else if ((file->fFops != NULL) && (file->fFops->write != NULL)) { + ret = file->fFops->write(file, buff, bytes); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + /* else ret will be -1 */ + VfsDetachFile(file); + + return ret; +} + +static off_t VfsLseek(int fd, off_t off, int whence) +{ + struct File *file; + off_t ret = LOS_NOK; + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if ((file->fFops == NULL) || (file->fFops->lseek == NULL)) { + ret = file->fOffset; + } else { + ret = file->fFops->lseek(file, off, whence); + } + + VfsDetachFile(file); + + return ret; +} + +static int VfsStat(const char *path, struct stat *stat) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + + if ((path == NULL) || (stat == NULL)) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) { + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + return ret; + } + + if (mp->mFs->fsFops->stat != NULL) { + ret = mp->mFs->fsFops->stat(mp, pathInMp, stat); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsUnlock(); + return ret; +} + +static int VfsStatfs(const char *path, struct statfs *buf) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + + if ((path == NULL) || (buf == NULL)) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) { + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + return ret; + } + + if (mp->mFs->fsFops->stat != NULL) { + ret = mp->mFs->fsMops->statfs(pathInMp, buf); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsUnlock(); + return ret; +} + +static int VfsUnlink(const char *path) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + + if (path == NULL) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') || + (mp->mFs->fsFops->unlink == NULL)) { + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + return ret; + } + + ret = mp->mFs->fsFops->unlink(mp, pathInMp); + + VfsUnlock(); + return ret; +} + +static int VfsRename(const char *old, const char *new) +{ + struct MountPoint *mpOld = NULL; + struct MountPoint *mpNew = NULL; + const char *pathInMpOld = NULL; + const char *pathInMpNew = NULL; + int ret = LOS_NOK; + + if ((old == NULL) || (new == NULL)) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + mpOld = VfsMpFind(old, &pathInMpOld); + + if (pathInMpOld == NULL) { + VFS_ERRNO_SET(EINVAL); + VfsUnlock(); + return ret; + } + + if ((mpOld == NULL) || (*pathInMpOld == '\0') || + (mpOld->mFs->fsFops->unlink == NULL)) { + VFS_ERRNO_SET(EINVAL); + VfsUnlock(); + return ret; + } + + mpNew = VfsMpFind(new, &pathInMpNew); + if ((mpNew == NULL) || (pathInMpNew == NULL) || (*pathInMpNew == '\0') || (mpNew->mFs->fsFops->unlink == NULL)) { + VFS_ERRNO_SET(EINVAL); + VfsUnlock(); + return ret; + } + + if (mpOld != mpNew) { + VFS_ERRNO_SET(EXDEV); + VfsUnlock(); + return ret; + } + + if (mpOld->mFs->fsFops->rename != NULL) { + ret = mpOld->mFs->fsFops->rename(mpOld, pathInMpOld, pathInMpNew); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsUnlock(); + return ret; +} + +static int VfsIoctl(int fd, int func, ...) +{ + va_list ap; + unsigned long arg; + struct File *file = NULL; + int ret = LOS_NOK; + + va_start(ap, func); + arg = va_arg(ap, unsigned long); + va_end(ap); + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if ((file->fFops != NULL) && (file->fFops->ioctl != NULL)) { + ret = file->fFops->ioctl(file, func, arg); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsDetachFile(file); + + return ret; +} + +static int VfsSync(int fd) +{ + struct File *file; + int ret = LOS_NOK; + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if (file->fMp->mWriteEnable == FALSE) { + VFS_ERRNO_SET(EACCES); + VfsDetachFile(file); + return ret; + } + + if ((file->fFops != NULL) && (file->fFops->sync != NULL)) { + ret = file->fFops->sync(file); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsDetachFile(file); + + return ret; +} + +static DIR *VfsOpendir(const char *path) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + struct Dir *dir = NULL; + UINT32 ret; + + if (path == NULL) { + VFS_ERRNO_SET(EINVAL); + return NULL; + } + + dir = (struct Dir *)malloc(sizeof(struct Dir)); + if (dir == NULL) { + VFS_ERRNO_SET(ENOMEM); + return NULL; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + free(dir); + return NULL; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL)) { + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + free(dir); + return NULL; + } + + if (mp->mFs->fsFops->opendir == NULL) { + VFS_ERRNO_SET(ENOTSUP); + VfsUnlock(); + free(dir); + return NULL; + } + + dir->dMp = mp; + dir->dOffset = 0; + + ret = (UINT32)mp->mFs->fsFops->opendir(dir, pathInMp); + if (ret == 0) { + mp->mRefs++; + } else { + free(dir); + } + + VfsUnlock(); + return (DIR *)dir; +} + +static struct dirent *VfsReaddir(DIR *d) +{ + struct dirent *ret = NULL; + struct Dir *dir = (struct Dir *)d; + + if ((dir == NULL) || (dir->dMp == NULL)) { + VFS_ERRNO_SET(EINVAL); + return NULL; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return NULL; + } + + if ((dir->dMp->mFs != NULL) && (dir->dMp->mFs->fsFops != NULL) && + (dir->dMp->mFs->fsFops->readdir != NULL)) { + if (dir->dMp->mFs->fsFops->readdir(dir, &dir->dDent) == 0) { + ret = &dir->dDent; + } else { + VFS_ERRNO_SET(EBADF); + } + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + VfsUnlock(); + + return ret; +} + +static int VfsClosedir(DIR *d) +{ + struct MountPoint *mp = NULL; + int ret = LOS_NOK; + struct Dir *dir = (struct Dir *)d; + + if ((dir == NULL) || (dir->dMp == NULL)) { + VFS_ERRNO_SET(EBADF); + return ret; + } + + mp = dir->dMp; + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + if ((dir->dMp->mFs != NULL) && (dir->dMp->mFs->fsFops != NULL) && + (dir->dMp->mFs->fsFops->closedir != NULL)) { + ret = dir->dMp->mFs->fsFops->closedir(dir); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + if (ret == 0) { + mp->mRefs--; + } else { + VFS_ERRNO_SET(EBADF); + } + + VfsUnlock(); + free(dir); + dir = NULL; + return ret; +} + +static int VfsMkdir(const char *path, int mode) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + (void)mode; + + if (path == NULL) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return ret; + } + + mp = VfsMpFind(path, &pathInMp); + if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) { + VFS_ERRNO_SET(ENOENT); + VfsUnlock(); + return ret; + } + + if (mp->mFs->fsFops->mkdir != NULL) { + ret = mp->mFs->fsFops->mkdir(mp, pathInMp); + } else { + VFS_ERRNO_SET(ENOTSUP); + ret = LOS_NOK; + } + + VfsUnlock(); + return ret; +} + +static int VfsVfcntl(struct File *filep, int cmd, va_list ap) +{ + int ret; + UINT32 flags; + + if ((filep == NULL) || (filep->fFops == NULL)) { + return -EBADF; + } + + if (cmd == F_GETFL) { + ret = (int)(filep->fFlags); + } else if (cmd == F_SETFL) { + flags = (UINT32)va_arg(ap, int); + flags &= LOS_FCNTL; + filep->fFlags &= ~LOS_FCNTL; + filep->fFlags |= flags; + ret = LOS_OK; + } else { + ret = -ENOSYS; + } + return ret; +} + +static ssize_t VfsPread(int fd, void *buff, size_t bytes, off_t off) +{ + off_t savepos, pos; + ssize_t ret; + + if (buff == NULL) { + VFS_ERRNO_SET(EFAULT); + return LOS_NOK; + } + + if (bytes == 0) { + return 0; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return LOS_NOK; + } + + savepos = LOS_Lseek(fd, 0, SEEK_CUR); + if (savepos == (off_t)-1) { + VfsUnlock(); + return LOS_NOK; + } + + pos = LOS_Lseek(fd, off, SEEK_SET); + if (pos == (off_t)-1) { + VfsUnlock(); + return LOS_NOK; + } + + ret = LOS_Read(fd, buff, bytes); + pos = LOS_Lseek(fd, savepos, SEEK_SET); + if ((pos == (off_t)-1) && (ret >= 0)) { + VfsUnlock(); + return LOS_NOK; + } + + VfsUnlock(); + return ret; +} + +static ssize_t VfsPwrite(int fd, const void *buff, size_t bytes, off_t off) +{ + ssize_t ret; + off_t savepos, pos; + + if (buff == NULL) { + VFS_ERRNO_SET(EFAULT); + return LOS_NOK; + } + + if (bytes == 0) { + return 0; + } + + if (VfsLock() != LOS_OK) { + VFS_ERRNO_SET(EAGAIN); + return LOS_NOK; + } + + savepos = LOS_Lseek(fd, 0, SEEK_CUR); + if (savepos == (off_t)-1) { + VfsUnlock(); + return LOS_NOK; + } + + pos = LOS_Lseek(fd, off, SEEK_SET); + if (pos == (off_t)-1) { + VfsUnlock(); + return LOS_NOK; + } + + ret = LOS_Write(fd, buff, bytes); + pos = LOS_Lseek(fd, savepos, SEEK_SET); + if ((pos == (off_t)-1) && (ret >= 0)) { + VfsUnlock(); + return LOS_NOK; + } + + VfsUnlock(); + return ret; +} + +static int MapToPosixRet(int ret) +{ + return ((ret) < 0 ? -1 : (ret)); +} + +/* POSIX interface */ +int LOS_Open(const char *path, int flags, ...) +{ +#ifdef LOSCFG_RANDOM_DEV + unsigned flagMask = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY; + if ((unsigned)flags & ~flagMask) { + errno = EINVAL; + return LOS_NOK; + } + + size_t pathLen = strlen(path) + 1; + char *canonicalPath = (char *)malloc(pathLen); + if (!canonicalPath) { + errno = ENOMEM; + return LOS_NOK; + } + if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) { + FREE_AND_SET_NULL(canonicalPath); + errno = ENOMEM; + return LOS_NOK; + } + + if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) { + FREE_AND_SET_NULL(canonicalPath); + if ((O_ACCMODE & (unsigned)flags) != O_RDONLY) { + errno = EPERM; + return LOS_NOK; + } + if ((unsigned)flags & O_DIRECTORY) { + errno = ENOTDIR; + return LOS_NOK; + } + return RANDOM_DEV_FD; + } + if ((strcmp(canonicalPath, "/") == 0) || + (strcmp(canonicalPath, "/dev") == 0)) { + FREE_AND_SET_NULL(canonicalPath); + if ((unsigned)flags & O_DIRECTORY) { + errno = EPERM; + return LOS_NOK; + } + errno = EISDIR; + return LOS_NOK; + } + FREE_AND_SET_NULL(canonicalPath); +#endif +#if (LOSCFG_POSIX_PIPE_API == 1) + if ((path != NULL) && !strncmp(path, PIPE_DEV_PATH, strlen(PIPE_DEV_PATH))) { + return PipeOpen(path, flags, PIPE_DEV_FD); + } +#endif + + int ret = VfsOpen(path, flags); + return MapToPosixRet(ret); +} + +int LOS_Close(int fd) +{ +#ifdef LOSCFG_RANDOM_DEV + if (fd == RANDOM_DEV_FD) { + return LOS_OK; + } +#endif +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return closesocket(fd); + } +#endif /* LOSCFG_NET_LWIP_SACK */ +#if (LOSCFG_POSIX_PIPE_API == 1) + if (fd >= PIPE_DEV_FD) { + return PipeClose(fd); + } +#endif + + int ret = LOS_NOK; + if (fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsClose(fd); + } + return MapToPosixRet(ret); +} + +ssize_t LOS_Read(int fd, void *buff, size_t bytes) +{ +#ifdef LOSCFG_RANDOM_DEV + if (fd == RANDOM_DEV_FD) { + if (nbyte == 0) { + return FS_SUCCESS; + } + if (buf == NULL) { + errno = EINVAL; + return FS_FAILURE; + } + if (nbyte > 1024) { /* 1024, max random_size */ + nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */ + } + struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte}; + if (hks_generate_random(&key) != 0) { + errno = EIO; + return FS_FAILURE; + } + return (ssize_t)nbyte; + } +#endif +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return recv(fd, buff, bytes, 0); + } +#endif /* LOSCFG_NET_LWIP_SACK */ + +#if (LOSCFG_POSIX_PIPE_API == 1) + if (fd >= PIPE_DEV_FD) { + return PipeRead(fd, buff, bytes); + } +#endif + + ssize_t ret = LOS_NOK; + if (fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsRead(fd, buff, bytes); + } + + return MapToPosixRet(ret); +} + +ssize_t LOS_Write(int fd, const void *buff, size_t bytes) +{ +#ifdef LOSCFG_RANDOM_DEV + if (fd == RANDOM_DEV_FD) { + errno = EBADF; /* "/dev/random" is readonly */ + return LOS_NOK; + } +#endif +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && + fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return send(fd, buff, bytes, 0); + } +#endif /* LOSCFG_NET_LWIP_SACK */ + +#if (LOSCFG_POSIX_PIPE_API == 1) + if (fd >= PIPE_DEV_FD) { + return PipeWrite(fd, buff, bytes); + } +#endif + + ssize_t ret = LOS_NOK; + if (fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsWrite(fd, buff, bytes); + } + + return MapToPosixRet(ret); +} + +off_t LOS_Lseek(int fd, off_t off, int whence) +{ + off_t ret = VfsLseek(fd, off, whence); + return ret; +} + +int LOS_Stat(const char *path, struct stat *stat) +{ + int ret = VfsStat(path, stat); + return MapToPosixRet(ret); +} + +int LOS_Statfs(const char *path, struct statfs *buf) +{ + int ret = VfsStatfs(path, buf); + return MapToPosixRet(ret); +} + +int LOS_Unlink(const char *path) +{ + int ret = VfsUnlink(path); + return MapToPosixRet(ret); +} + +int LOS_Rename(const char *oldpath, const char *newpath) +{ + int ret = VfsRename(oldpath, newpath); + return MapToPosixRet(ret); +} + +int LOS_Fsync(int fd) +{ + int ret = VfsSync(fd); + return MapToPosixRet(ret); +} + +DIR *LOS_Opendir(const char *path) +{ + return VfsOpendir(path); +} + +struct dirent *LOS_Readdir(DIR *dir) +{ + return VfsReaddir(dir); +} + +int LOS_Closedir(DIR *dir) +{ + int ret = VfsClosedir(dir); + return MapToPosixRet(ret); +} + +int LOS_Mkdir(const char *path, mode_t mode) +{ + int ret = VfsMkdir(path, (int)mode); + return MapToPosixRet(ret); +} + +int LOS_Rmdir(const char *path) +{ + int ret = VfsUnlink(path); + return MapToPosixRet(ret); +} + +int LOS_Lstat(const char *path, struct stat *buffer) +{ + return stat(path, buffer); +} + +int LOS_Fstat(int fd, struct stat *buf) +{ + struct File *filep; + int ret; + filep = VfsAttachFileReady(fd); + if ((filep == NULL) || (filep->fMp == NULL) || filep->fullPath == NULL) { + return LOS_NOK; + } + ret = stat(filep->fullPath, buf); + VfsDetachFile(filep); + return ret; +} + +int LOS_Fcntl(int fd, int cmd, ...) +{ + struct File *filep = NULL; + va_list ap; + int ret; + va_start(ap, cmd); + + if (fd < CONFIG_NFILE_DESCRIPTORS) { + filep = VfsAttachFileReady(fd); + ret = VfsVfcntl(filep, cmd, ap); + VfsDetachFile(filep); + } else { + ret = -EBADF; +#ifdef LOSCFG_NET_LWIP_SACK + int arg = va_arg(ap, int); + ret = lwip_fcntl(fd, (long)cmd, arg); + va_end(ap); + return ret; +#endif /* LOSCFG_NET_LWIP_SACK */ + } + + va_end(ap); + + if (ret < 0) { + VFS_ERRNO_SET(-ret); + ret = LOS_NOK; + } + return ret; +} + +int LOS_Ioctl(int fd, int req, ...) +{ + int ret; + va_list ap; + va_start(ap, req); + if (fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsIoctl(fd, req, ap); + } else { + ret = -EBADF; +#ifdef LOSCFG_NET_LWIP_SACK + UINTPTR arg = va_arg(ap, UINTPTR); + ret = lwip_ioctl(fd, (long)req, (void *)arg); +#endif /* LOSCFG_NET_LWIP_SACK */ + } + + va_end(ap); + return ret; +} + +ssize_t LOS_Readv(int fd, const struct iovec *iovBuf, int iovcnt) +{ + int i; + int ret; + char *buf = NULL; + char *curBuf = NULL; + char *readBuf = NULL; + size_t bufLen = 0; + size_t bytesToRead; + ssize_t totalBytesRead; + size_t totalLen; + const struct iovec *iov = (const struct iovec *)iovBuf; + + if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) { + return LOS_NOK; + } + + for (i = 0; i < iovcnt; ++i) { + if ((SSIZE_MAX - bufLen) < iov[i].iov_len) { + return LOS_NOK; + } + bufLen += iov[i].iov_len; + } + if (bufLen == 0) { + return LOS_NOK; + } + totalLen = bufLen * sizeof(char); + buf = (char *)malloc(totalLen); + if (buf == NULL) { + return LOS_NOK; + } + + totalBytesRead = read(fd, buf, bufLen); + if ((size_t)totalBytesRead < totalLen) { + totalLen = (size_t)totalBytesRead; + } + curBuf = buf; + for (i = 0; i < iovcnt; ++i) { + readBuf = (char *)iov[i].iov_base; + bytesToRead = iov[i].iov_len; + + size_t lenToRead = totalLen < bytesToRead ? totalLen : bytesToRead; + ret = memcpy_s(readBuf, bytesToRead, curBuf, lenToRead); + if (ret != LOS_OK) { + free(buf); + return LOS_NOK; + } + if (totalLen < (size_t)bytesToRead) { + break; + } + curBuf += bytesToRead; + totalLen -= bytesToRead; + } + free(buf); + return totalBytesRead; +} + +ssize_t LOS_Writev(int fd, const struct iovec *iovBuf, int iovcnt) +{ + int i; + int ret; + char *buf = NULL; + char *curBuf = NULL; + char *writeBuf = NULL; + size_t bufLen = 0; + size_t bytesToWrite; + ssize_t totalBytesWritten; + size_t totalLen; + const struct iovec *iov = iovBuf; + + if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) { + return LOS_NOK; + } + + for (i = 0; i < iovcnt; ++i) { + if ((SSIZE_MAX - bufLen) < iov[i].iov_len) { + VFS_ERRNO_SET(EINVAL); + return LOS_NOK; + } + bufLen += iov[i].iov_len; + } + if (bufLen == 0) { + return LOS_NOK; + } + totalLen = bufLen * sizeof(char); + buf = (char *)malloc(totalLen); + if (buf == NULL) { + return LOS_NOK; + } + curBuf = buf; + for (i = 0; i < iovcnt; ++i) { + writeBuf = (char *)iov[i].iov_base; + bytesToWrite = iov[i].iov_len; + if (((ssize_t)totalLen <= 0) || ((ssize_t)bytesToWrite <= 0)) { + continue; + } + ret = memcpy_s(curBuf, totalLen, writeBuf, bytesToWrite); + if (ret != LOS_OK) { + free(buf); + return LOS_NOK; + } + curBuf += bytesToWrite; + totalLen -= bytesToWrite; + } + + totalBytesWritten = write(fd, buf, bufLen); + free(buf); + + return totalBytesWritten; +} + +int LOS_Isatty(int fd) +{ + (void)fd; + return 0; +} + +int LOS_Access(const char *path, int amode) +{ + int result; + mode_t mode; + struct stat buf; + + result = stat(path, &buf); + if (result != 0) { + return LOS_NOK; + } + + mode = buf.st_mode; + if ((unsigned int)amode & R_OK) { + if ((mode & (S_IROTH | S_IRGRP | S_IRUSR)) == 0) { + VFS_ERRNO_SET(EACCES); + return LOS_NOK; + } + } + if ((unsigned int)amode & W_OK) { + if ((mode & (S_IWOTH | S_IWGRP | S_IWUSR)) == 0) { + VFS_ERRNO_SET(EACCES); + return LOS_NOK; + } + } + if ((unsigned int)amode & X_OK) { + if ((mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) { + VFS_ERRNO_SET(EACCES); + return LOS_NOK; + } + } + return 0; +} + +int LOS_Ftruncate(int fd, off_t length) +{ + int ret = LOS_NOK; + struct File *file = NULL; + + if (length <= 0) { + VFS_ERRNO_SET(EINVAL); + return ret; + } + + file = VfsAttachFileReady(fd); + if (file == NULL) { + return ret; + } + + if (file->fMp->mWriteEnable == FALSE) { + VFS_ERRNO_SET(EACCES); + VfsDetachFile(file); + return ret; + } + + if ((file->fFlags & O_ACCMODE) == O_RDONLY) { + VFS_ERRNO_SET(EACCES); + } else if ((file->fFops != NULL) && (file->fFops->truncate != NULL)) { + ret = file->fFops->truncate(file, length); + } else { + VFS_ERRNO_SET(ENOTSUP); + } + + /* else ret will be -1 */ + VfsDetachFile(file); + return ret; +} + +ssize_t LOS_Pread(int fd, void *buff, size_t bytes, off_t off) +{ + ssize_t ret = LOS_NOK; + if (fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsPread(fd, buff, bytes, off); + } + + return MapToPosixRet(ret); +} + +ssize_t LOS_Pwrite(int fd, const void *buff, size_t bytes, off_t off) +{ + ssize_t ret = LOS_NOK; + if (fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS) { + ret = VfsPwrite(fd, buff, bytes, off); + } + + return MapToPosixRet(ret); +} diff --git a/components/fs/vfs/vfs_init.c b/components/fs/vfs/vfs_init.c new file mode 100644 index 00000000..b2bec004 --- /dev/null +++ b/components/fs/vfs/vfs_init.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022-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. + */ +#include "stdlib.h" +#include "vfs_operations.h" +#if (LOSCFG_SUPPORT_LITTLEFS == 1) +#include "lfs_adapter.h" +#endif +#if (LOSCFG_SUPPORT_FATFS == 1) +#include "fatfs.h" +#endif +#include "los_compiler.h" +#include "los_mux.h" + +int OsVfsInit(void) +{ + if (LOS_MuxCreate(&g_fsMutex) != LOS_OK) { + return LOS_NOK; + } +#if (LOSCFG_SUPPORT_FATFS == 1) + FatFsInit(); +#endif + +#if (LOSCFG_SUPPORT_LITTLEFS == 1) + LfsInit(); +#endif + return LOS_OK; +} diff --git a/components/fs/vfs/vfs_maps.c b/components/fs/vfs/vfs_maps.c new file mode 100644 index 00000000..f9d17970 --- /dev/null +++ b/components/fs/vfs/vfs_maps.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022-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. + */ + +#include "vfs_maps.h" +#include "vfs_operations.h" +#include +#include "securec.h" +#include "los_debug.h" +#include "los_compiler.h" + +struct FsMap *g_fsMap = NULL; + +struct FsMap *VfsFsMapGet(const char *fsType) +{ + struct FsMap *curr = g_fsMap; + + (void)VfsLock(); + while (curr != NULL) { + if ((curr->fsType != NULL) && (fsType != NULL) && + (strcmp(curr->fsType, fsType) == 0)) { + (void)VfsUnlock(); + return curr; + } + curr = curr->next; + } + + VfsUnlock(); + return NULL; +} + +int OsFsRegister(const char *fsType, struct MountOps *fsMops, + struct FileOps *fsFops, struct FsManagement *fsMgt) +{ + if ((fsMops == NULL) || (fsFops == NULL)) { + return LOS_NOK; + } + + struct FsMap *newfs = (struct FsMap *)malloc(sizeof(struct FsMap)); + if (newfs == NULL) { + PRINT_ERR("Fs register malloc failed, fsType %s.\n", fsType); + return LOS_NOK; + } + (void)memset_s(newfs, sizeof(struct FsMap), 0, sizeof(struct FsMap)); + + newfs->fsType = strdup(fsType); + if (newfs->fsType == NULL) { + free(newfs); + return LOS_NOK; + } + + newfs->fsMops = fsMops; + newfs->fsFops = fsFops; + newfs->fsMgt = fsMgt; + newfs->fsRefs = 0; + + (void)VfsLock(); + newfs->next = g_fsMap; + g_fsMap = newfs; + + VfsUnlock(); + return LOS_OK; +} diff --git a/components/fs/vfs/vfs_maps.h b/components/fs/vfs/vfs_maps.h new file mode 100644 index 00000000..78bb63df --- /dev/null +++ b/components/fs/vfs/vfs_maps.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef _VFS_MAPS_H_ +#define _VFS_MAPS_H_ + +#include "los_compiler.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +struct MountOps; + +struct FsManagement { + int (*fdisk)(const char *dev, int *lengthArray, int partNum); + int (*format)(const char *partName, void *data); +}; + + +struct FsMap { + const char *fsType; + const struct MountOps *fsMops; + const struct FileOps *fsFops; + const struct FsManagement *fsMgt; + UINT32 fsRefs; + struct FsMap *next; +}; + +int OsFsRegister(const char *fsType, struct MountOps *fsMops, + struct FileOps *fsFops, struct FsManagement *fsMgt); +struct FsMap *VfsFsMapGet(const char *fsType); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _VFS_MAPS_H_ */ diff --git a/components/fs/vfs/vfs_mount.c b/components/fs/vfs/vfs_mount.c new file mode 100644 index 00000000..bde918f6 --- /dev/null +++ b/components/fs/vfs/vfs_mount.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2022-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. + */ +#include "vfs_mount.h" +#include "vfs_files.h" +#include "vfs_maps.h" +#include "vfs_config.h" +#include "stdlib.h" +#include "string.h" +#include "vfs_operations.h" +#include "los_compiler.h" +#include "los_debug.h" +#include "los_fs.h" +#include "los_mux.h" + +struct MountPoint *g_mountPoints = NULL; + +static void MpDeleteFromList(struct MountPoint *mp) +{ + struct MountPoint *prev = NULL; + + /* delete mp from mount list */ + if (g_mountPoints == mp) { + g_mountPoints = mp->mNext; + } else { + for (prev = g_mountPoints; prev != NULL; prev = prev->mNext) { + if (prev->mNext != mp) { + continue; + } + + prev->mNext = mp->mNext; + break; + } + } +} + +struct MountPoint *VfsMpFind(const char *path, const char **pathInMp) +{ + struct MountPoint *mp = g_mountPoints; + struct MountPoint *bestMp = NULL; + int bestMatches = 0; + if (path == NULL) { + return NULL; + } + if (pathInMp != NULL) { + *pathInMp = NULL; + } + while ((mp != NULL) && (mp->mPath != NULL)) { + const char *mPath = mp->mPath; + const char *iPath = path; + const char *t = NULL; + int matches = 0; + do { + while ((*mPath == '/') && (*(mPath + 1) != '/')) { + mPath++; + } + while ((*iPath == '/') && (*(iPath + 1) != '/')) { + iPath++; + } + + t = strchr(mPath, '/'); + if (t == NULL) { + t = strchr(mPath, '\0'); + } + if ((t == mPath) || (t == NULL)) { + break; + } + if (strncmp(mPath, iPath, (size_t)(t - mPath)) != 0) { + goto next; /* this mount point do not match, check next */ + } + + iPath += (t - mPath); + if ((*iPath != '\0') && (*iPath != '/')) { + goto next; + } + + matches += (t - mPath); + mPath += (t - mPath); + } while (*mPath != '\0'); + + if (matches > bestMatches) { + bestMatches = matches; + bestMp = mp; + + while ((*iPath == '/') && (*(iPath + 1) != '/')) { + iPath++; + } + + if (pathInMp != NULL) { + *pathInMp = path; + } + } + next: + mp = mp->mNext; + } + return bestMp; +} + +int LOS_FsMount(const char *source, const char *target, + const char *fsType, unsigned long mountflags, + const void *data) +{ + int ret; + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + + /* target must begin with '/', for example /system, /data, etc. */ + if ((target == NULL) || (target[0] != '/')) { + return LOS_NOK; + } + + (void)VfsLock(); + /* find mp by target, to see if it was mounted */ + mp = VfsMpFind(target, &pathInMp); + if (mp != NULL && pathInMp != NULL) { + goto errout; + } + + /* Find fsMap coresponding to the fsType */ + struct FsMap *mFs = VfsFsMapGet(fsType); + if ((mFs == NULL) || (mFs->fsMops == NULL) || + (mFs->fsMops->mount == NULL)) { + goto errout; + } + + mp = (struct MountPoint *)malloc(sizeof(struct MountPoint)); + if (mp == NULL) { + goto errout; + } + + mp->mFs = mFs; + mp->mDev = NULL; + if (source != NULL) { + mp->mDev = strdup(source); + if (mp->mDev == NULL) { + goto errout; + } + } + + mp->mPath = strdup(target); + if (mp->mPath == NULL) { + goto errout; + } + + ret = mp->mFs->fsMops->mount(mp, mountflags, data); + if (ret != 0) { + /* errno is set */ + PRINT_ERR("mount failed, source %s, target %s.\n", source, target); + goto errout; + } + mp->mRefs = 0; + mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE; + mp->mFs->fsRefs++; + mp->mNext = g_mountPoints; + g_mountPoints = mp; + VfsUnlock(); + return LOS_OK; + +errout: + free((void *)mp->mPath); + free((void *)mp->mDev); + free(mp); + VfsUnlock(); + return LOS_NOK; +} + +int LOS_FsUmount(const char *target) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + + (void)VfsLock(); + if (target == NULL) { + goto errout; + } + + mp = VfsMpFind(target, &pathInMp); + if ((mp == NULL) || (mp->mRefs != 0)) { + goto errout; + } + + if ((mp->mFs == NULL) || (mp->mFs->fsMops == NULL) || + (mp->mFs->fsMops->umount == NULL)) { + goto errout; + } + + ret = mp->mFs->fsMops->umount(mp); + if (ret != 0) { + /* errno is set */ + goto errout; + } + + /* delete mp from mount list */ + MpDeleteFromList(mp); + mp->mFs->fsRefs--; + free((void *)mp->mPath); + free((void *)mp->mDev); + free(mp); + + VfsUnlock(); + return LOS_OK; + +errout: + PRINT_ERR("umount2 failed, target %s.\n", target); + VfsUnlock(); + return LOS_NOK; +} + +static void CloseFdsInMp(struct MountPoint *mp) +{ + for (int fd = 0; fd < NR_OPEN_DEFAULT; fd++) { + struct File *f = FdToFile(fd); + if (f == NULL) { + continue; + } + if ((f->fMp == mp) && + (f->fFops != NULL) && + (f->fFops->close != NULL)) { + (void)f->fFops->close(f); + } + } +} + +int LOS_FsUmount2(const char *target, int flag) +{ + struct MountPoint *mp = NULL; + const char *pathInMp = NULL; + int ret = LOS_NOK; + + (void)VfsLock(); + if (target == NULL) { + goto errout; + } + + mp = VfsMpFind(target, &pathInMp); + if ((mp == NULL) || (mp->mRefs != 0) || + (mp->mFs == NULL) || (mp->mFs->fsMops == NULL) || + (mp->mFs->fsMops->umount2 == NULL)) { + goto errout; + } + + /* Close all files under the mount point */ + if ((UINT32)flag & MNT_FORCE) { + CloseFdsInMp(mp); + } + + ret = mp->mFs->fsMops->umount2(mp, flag); + if (ret != 0) { + /* errno is set */ + goto errout; + } + + /* delete mp from mount list */ + MpDeleteFromList(mp); + mp->mFs->fsRefs--; + free((void *)mp->mPath); + free((void *)mp->mDev); + free(mp); + + VfsUnlock(); + return LOS_OK; + +errout: + PRINT_ERR("umount2 failed, target %s.\n", target); + VfsUnlock(); + return LOS_NOK; +} diff --git a/components/fs/vfs/vfs_mount.h b/components/fs/vfs/vfs_mount.h new file mode 100644 index 00000000..5507141d --- /dev/null +++ b/components/fs/vfs/vfs_mount.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef _VFS_MOUNT_H_ +#define _VFS_MOUNT_H_ + +#include "sys/statfs.h" +#include "los_compiler.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +struct FsMap; +struct MountPoint; + +struct MountOps { + int (*mount)(struct MountPoint *mp, unsigned long mountflags, + const void *data); + int (*umount)(struct MountPoint *mp); + int (*umount2)(struct MountPoint *mp, int flag); + int (*statfs)(const char *path, struct statfs *buf); +}; + +struct MountPoint { + struct FsMap *mFs; /* file system info */ + struct MountPoint *mNext; /* point to next mount point */ + const char *mPath; /* target path, /system, /usr, etc. */ + const char *mDev; /* device, "emmc0p0", "emmc0p1", etc. */ + UINT32 mRefs; /* reference to mount point */ + void *mData; /* specific file system handle */ + BOOL mWriteEnable; /* writable flag */ +}; + +extern struct MountPoint *g_mountPoints; +#define LOS_MP_FOR_EACH_ENTRY(prev) \ + for (prev = g_mountPoints; prev != NULL; prev = prev->mNext) + +struct MountPoint *VfsMpFind(const char *path, const char **pathInMp); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _VFS_MOUNT_H_ */ diff --git a/components/fs/vfs/vfs_operations.h b/components/fs/vfs/vfs_operations.h new file mode 100644 index 00000000..4ee430f9 --- /dev/null +++ b/components/fs/vfs/vfs_operations.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef _VFS_OPERATIONS_H_ +#define _VFS_OPERATIONS_H_ + +#include "errno.h" +#include "fcntl.h" +#include "dirent.h" +#include "stdint.h" +#include "unistd.h" +#include "sys/mount.h" +#include "sys/stat.h" +#include "sys/statfs.h" +#include "los_compiler.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define VFS_ERRNO_SET(err) (errno = (err)) + +extern UINT32 g_fsMutex; + +int OsVfsInit(void); +int VfsLock(void); +void VfsUnlock(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _VFS_OPERATIONS_H_ */ diff --git a/components/fs/vfs/vfs_partition.c b/components/fs/vfs/vfs_partition.c new file mode 100644 index 00000000..0c6167fc --- /dev/null +++ b/components/fs/vfs/vfs_partition.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022-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. + */ +#include "vfs_partition.h" +#include "vfs_operations.h" +#include "los_fs.h" +#include "los_list.h" +#include "vfs_maps.h" +#include "vfs_mount.h" +#include "securec.h" +#include "stdlib.h" +#include "string.h" + +int GetPartIdByPartName(const char *partName) +{ + if (partName == NULL) { + return LOS_NOK; + } + + /* the character next to p is the partId */ + char *p = strrchr(partName, 'p'); + if (p + 1 != NULL) { + return atoi(p + 1); + } + + return LOS_NOK; +} + +int GetDevIdByDevName(const char *dev) +{ + if (dev == NULL) { + return LOS_NOK; + } + + /* last character is the deviceId */ + char *p = (char *)dev + strlen(dev) - 1; + if (p != NULL) { + return atoi(p); + } + + return LOS_NOK; +} + +int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, + int partnum) +{ + int ret = LOS_NOK; + struct FsMap *fMap = VfsFsMapGet(fsType); + if ((fMap != NULL) && (fMap->fsMgt != NULL) && + (fMap->fsMgt->fdisk != NULL)) { + ret = fMap->fsMgt->fdisk(dev, lengthArray, partnum); + } + + return ret; +} + +int LOS_PartitionFormat(const char *partName, char *fsType, void *data) +{ + int ret = LOS_NOK; + + /* check if the device is mounted by iterate the mp list + format is not allowed when the device has been mounted. */ + struct MountPoint *iter = NULL; + LOS_MP_FOR_EACH_ENTRY(iter) { + if ((iter->mFs != NULL) && (iter->mFs->fsType != NULL) && + strcmp(iter->mFs->fsType, fsType) == 0) { + errno = EBUSY; + return LOS_NOK; + } + } + + struct FsMap *fMap = VfsFsMapGet(fsType); + if ((fMap != NULL) && (fMap->fsMgt != NULL) && + (fMap->fsMgt->format != NULL)) { + ret = fMap->fsMgt->format(partName, data); + } + return ret; +} diff --git a/components/fs/vfs/vfs_partition.h b/components/fs/vfs/vfs_partition.h new file mode 100644 index 00000000..6edbefbf --- /dev/null +++ b/components/fs/vfs/vfs_partition.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef _VFS_PARTITION_H_ +#define _VFS_PARTITION_H_ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define MAX_PARTITION_NUM 4 + +int GetPartIdByPartName(const char *partName); +int GetDevIdByDevName(const char *dev); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _VFS_PARTITION_H_ */ diff --git a/kal/libc/newlib/porting/include/sys/socket.h b/kal/libc/newlib/porting/include/sys/socket.h index 1379fe2a..20cad71c 100644 --- a/kal/libc/newlib/porting/include/sys/socket.h +++ b/kal/libc/newlib/porting/include/sys/socket.h @@ -33,6 +33,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -41,11 +42,6 @@ extern "C" { typedef unsigned socklen_t; typedef unsigned short sa_family_t; -struct iovec { - void *iov_base; - size_t iov_len; -}; - struct msghdr { void *msg_name; socklen_t msg_namelen; diff --git a/kal/libc/newlib/porting/include/sys/uio.h b/kal/libc/newlib/porting/include/sys/uio.h index ffd46f77..46963651 100644 --- a/kal/libc/newlib/porting/include/sys/uio.h +++ b/kal/libc/newlib/porting/include/sys/uio.h @@ -40,6 +40,11 @@ extern "C" { #define UIO_MAXIOV 1024 +struct iovec { + void *iov_base; + size_t iov_len; +}; + ssize_t readv(int, const struct iovec *, int); ssize_t writev(int, const struct iovec *, int); diff --git a/kal/libc/newlib/porting/src/fs.c b/kal/libc/newlib/porting/src/fs.c index b8acfad7..4c8e1178 100644 --- a/kal/libc/newlib/porting/src/fs.c +++ b/kal/libc/newlib/porting/src/fs.c @@ -144,7 +144,12 @@ int ftruncate(int fd, off_t length) int ioctl(int fd, int req, ...) { - return -1; + va_list ap; + va_start(ap, req); + int ret; + ret = LOS_Ioctl(fd, req, ap); + va_end(ap); + return ret; } ssize_t pread(int fd, void *buf, size_t nbyte, off_t offset) diff --git a/kernel/src/los_init.c b/kernel/src/los_init.c index 8cf81c2d..5aca0e52 100644 --- a/kernel/src/los_init.c +++ b/kernel/src/los_init.c @@ -30,6 +30,7 @@ */ #include "stdarg.h" +#include "vfs_operations.h" #include "los_arch.h" #include "los_config.h" #include "los_debug.h" @@ -215,6 +216,14 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_KernelInit(VOID) } #endif +#if (LOSCFG_FS_VFS == 1) + ret = OsVfsInit(); + if (ret != LOS_OK) { + PRINT_ERR("OsVfsInit error\n"); + return ret; + } +#endif + ret = OsIdleTaskCreate(); if (ret != LOS_OK) { return ret; -- Gitee