diff --git a/components/fs/BUILD.gn b/components/fs/BUILD.gn index 094d2edc..5114fdd3 100644 --- a/components/fs/BUILD.gn +++ b/components/fs/BUILD.gn @@ -29,6 +29,7 @@ declare_args() { enable_ohos_kernel_liteos_m_fatfs = true + enable_ohos_kernel_liteos_m_littlefs = false } group("fs") { @@ -36,4 +37,7 @@ group("fs") { if (enable_ohos_kernel_liteos_m_fatfs == true) { deps += [ "fatfs:fatfs" ] } + if (enable_ohos_kernel_liteos_m_littlefs == true) { + deps += [ "littlefs:littlefs" ] + } } diff --git a/components/fs/littlefs/BUILD.gn b/components/fs/littlefs/BUILD.gn new file mode 100644 index 00000000..f3d8c9ea --- /dev/null +++ b/components/fs/littlefs/BUILD.gn @@ -0,0 +1,45 @@ +# 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. + +static_library("littlefs") { + sources = [ + "lfs_api.c", + ] + + include_dirs = [ + "../../../kernel/arch/include", + "../../../kernel/include", + "../../../utils", + "../../../kal/cmsis", + "../../../kal", + "../../../kal/posix/include", + "./", + "//third_party/littlefs/include", + ] +} diff --git a/components/fs/littlefs/lfs_api.c b/components/fs/littlefs/lfs_api.c new file mode 100644 index 00000000..d96c8624 --- /dev/null +++ b/components/fs/littlefs/lfs_api.c @@ -0,0 +1,343 @@ +/* + * 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 "lfs_api.h" +#include "iCunit.h" + +lfs_t g_lfs; +FileDirInfo g_lfsDir[LFS_MAX_OPEN_DIRS]; + +FileOpInfo g_fsOp; +static LittleFsHandleStruct g_handle[LITTLE_FS_MAX_OPEN_FILES]; +struct dirent g_nameValue; +struct fsmap_t g_fsmap[MAX_FILE_SYSTEM_LEN]; +static pthread_mutex_t g_FslocalMutex = PTHREAD_MUTEX_INITIALIZER; + +FileOpInfo GetFsOpInfo(void) +{ + return g_fsOp; +} + +LittleFsHandleStruct *GetFreeFd(int *fd) +{ + for (int i = 0; i < LITTLE_FS_MAX_OPEN_FILES; i++) { + if (g_handle[i].useFlag == 0) { + *fd = i; + g_handle[i].useFlag = 1; + return &(g_handle[i]); + } + } + + *fd = INVALID_FD; + return NULL; +} + +lfs_dir_t *GetFreeDir() +{ + for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { + if (g_lfsDir[i].useFlag == 0) { + g_lfsDir[i].useFlag = 1; + return &(g_lfsDir[i].dir); + } + } + + return NULL; +} + +int InitMountInfo(const char *fileSystemType, const struct MountOps *fsMops) +{ + int len = strlen(fileSystemType) + 1; + for (int i = 0; i < MAX_FILE_SYSTEM_LEN; i++) { + if (g_fsmap[i].fileSystemtype == NULL) { + g_fsmap[i].fileSystemtype = (char*)malloc(len); + memcpy_s(g_fsmap[i].fileSystemtype, len, fileSystemType, len); + g_fsmap[i].fs_mops = fsMops; + return VFS_OK; + } + } + + return VFS_ERROR; +} + +const struct fsmap_t *mount_finds(const char*fileSystemtype) +{ + struct fsmap_t *m = NULL; + + for (int i = 0; i < MAX_FILE_SYSTEM_LEN; i++) { + m = &(g_fsmap[i]); + if (m->fileSystemtype && strcmp(fileSystemtype, m->fileSystemtype) == 0) { + return m; + } + } + + return (const struct fsmap_t *)NULL; +} + +const struct MountOps g_fsMnt = { + +}; + +struct FileOps lfs_vops = { + +}; + +int LfsMount(const char * source, const char * target, const char * fileSystemType, unsigned long mountflags, + const void * data) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + g_fsOp.fsVops = &lfs_vops; + ret = lfs_mount(&g_lfs, (struct lfs_config*)data); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsUmount(const char * target) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_unmount(&g_lfs); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsUnlink(const char * fileName) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_remove(&g_lfs, fileName); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsMkdir(const char * dirName, mode_t mode) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_mkdir(&g_lfs, dirName); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsRmdir(const char * dirName) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_remove(&g_lfs, dirName); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +DIR *LfsOpendir(const char * dirName) +{ + int ret; + + lfs_dir_t *dir = GetFreeDir(); + if (dir == NULL) { + return NULL; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_dir_open(&g_lfs, dir, dirName); + pthread_mutex_unlock(&g_FslocalMutex); + + if (ret == 0) { + return (DIR *)dir; + } else { + return NULL; + } +} + +struct direct *LfsReaddir(DIR * dir) +{ + int ret; + struct lfs_info lfsInfo; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_dir_read(&g_lfs, (lfs_dir_t *)dir, &lfsInfo); + if (ret == 0) { + (void)memcpy_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; + } + + pthread_mutex_unlock(&g_FslocalMutex); + return NULL; +} + +int LfsCloseDir(DIR * dir) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_remove(&g_lfs, dirName); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsOpen(const char * path, int openFlag, int mode) +{ + int fd = INVALID_FD; + + pthread_mutex_lock(&g_FslocalMutex); + LittleFsHandleStruct *fsHandle = GetFreeDir(&fd); + if (fd == INVALID_FD) { + goto errout; + } + + int err = lfs_file_open(lfs_t * lfs, lfs_file_t * file, const char * path, int flags); + if (err != 0) { + goto errout; + } + + pthread_mutex_unlock(&g_FslocalMutex); + return fd; +errout: + pthread_mutex_unlock(&g_FslocalMutex); + return INVALID_FD; +} + +int LfsRead(int fd, void * buf, unsigned int len) +{ + int ret = VFS_ERROR; + + if (fd >= LITTLE_FS_MAX_OPEN_FILES && fd < 0) { + return ret; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_read(&g_lfs, &(g_handle[fd].file), buf, len); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsWrite(int fd, const void * buf, unsigned int len) +{ + int ret = VFS_ERROR; + + if (fd >= LITTLE_FS_MAX_OPEN_FILES && fd < 0) { + return ret; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_write(&g_lfs, &(g_handle[fd].file), buf, len); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsSeek(int fd, off_t offset, int whence) +{ + int ret = VFS_ERROR; + + if (fd >= LITTLE_FS_MAX_OPEN_FILES && fd < 0) { + return ret; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_seek(&g_lfs, &(g_handle[fd].file), offset, whence); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsClose(int fd) +{ + int ret = VFS_ERROR; + + if (fd >= LITTLE_FS_MAX_OPEN_FILES && fd < 0) { + return ret; + } + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_close(&g_lfs, &(g_handle[fd].file)); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsRename(const char * oldName, const char * newName) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_rename(oldName, newName); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsStat(const char * path, struct stat * buf) +{ + int ret; + struct lfs_info info; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_stat(&g_lfs, path, &info); + if (ret = 0) { + buf->st_size = info.size; + } + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + +int LfsFsync(int fd) +{ + int ret; + + pthread_mutex_lock(&g_FslocalMutex); + ret = lfs_file_sync(&g_lfs, &(g_handle[fd].file)); + pthread_mutex_unlock(&g_FslocalMutex); + + return ret; +} + diff --git a/components/fs/littlefs/lfs_api.h b/components/fs/littlefs/lfs_api.h new file mode 100644 index 00000000..8c0ceece --- /dev/null +++ b/components/fs/littlefs/lfs_api.h @@ -0,0 +1,132 @@ +/* + * 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 "lfs.h" +#include "lfs_util.h" +#include "dirent.h" +#include "bits/alltypes.h" +#include "sys/stat.h" +#include "memory.h" +#include "pthread.h" + +#define INVALID_FD (-1) + +typedef unsigned mode_t; + +#ifndef VFS_ERROR +#define VFS_ERROR (-1) +#endif + +#ifndef VFS_OK +#define VFS_OK 0 +#endif + +typedef struct { + uint8_t useFlag; + lfs_file_t file; +} LittleFsHandleStruct; + +struct MountOps { + int {*Mount}(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, + const void *data); + int (*Umount)(const char* target); +}; + +struct fsmap_t { + const char *fileSystemtype; + const struct MountOps *fs_mops; +}; + +struct FileOps { + int (*Open)(const char *path, int openFlag, int mode); + int (*Close)(int fd); + int (*Unlink)(const char *fileName); + int (*Rmdir)(const char *dirName); + int (*Mkdir)(const char *dirName, mode_t mode); + struct direct *(*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); + int (*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); +}; + +typedef struct { + struct FileOps *fsVops; +} FileOpInfo; + +typedef struct { + uint8_t useFlag; + lfs_dir_t dir; +} FileDirInfo; + +#define LITTLE_FS_MAX_OPEN_FILES 100 +#define LITTLE_FS_STANDARD_NAME_LENGTH 50 + +#define MAX_DEF_BUF_NUM 21 +#define MAX_BUFFER_LEN 100 +#define MAX_WRITE_FILE_LEN 500 +#define MAX_READ_FILE_LEN 500 +#define MAX_FILE_SYSTEM_LEN 2 + +#ifndef LFS_MAX_OPEN_DIRS +#define LFS_MAX_OPEN_DIRS 10 +#endif + +LittleFsHandleStruct *GetFreeFd(int *fd); + +int InitMountInfo(const char *fileSystemType, const struct MountOps *fsMops); +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 *path, int openFlag, int mode); +int LfsRead(int fd, void *buf, unsigned int len); +int LfsWrite(int fd, const void *buf, unsigned int len); +int 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); + +FileOpInfo GetFsOpInfo(void); +const struct fsmap_t *mount_findfs(const char *filesystemtype); + +