subsys: fs: Add Virtual File system Switch (VFS) support
Add support for Virtual File system Switch (VFS) by introducing mount point concept to Zephyr. This allows the applications to mount multiple file systems at different mount points (ex: "/fatfs" and "/nffs"). The mount point structure contains all the necessary info required to instantiate, mount and operate on file system. Decouple applications from directly accessing individual file systems API's or internal functions by introducing file system registration mechanism in VFS. Move the file system defination and mount responsibility to application so that application can decide which file system to use and where to mount. Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
This commit is contained in:
parent
9792951570
commit
25302b1980
8 changed files with 937 additions and 203 deletions
192
include/fs.h
192
include/fs.h
|
@ -8,23 +8,26 @@
|
||||||
#define _FS_H_
|
#define _FS_H_
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <misc/dlist.h>
|
||||||
#include <fs/fs_interface.h>
|
#include <fs/fs_interface.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create a fs_file_t type similar to FILE for familiarity */
|
struct fs_file_system_t;
|
||||||
typedef struct _fs_file_object fs_file_t;
|
|
||||||
|
|
||||||
/* Create a fs_dir_t type similar to DIR for familiarity */
|
|
||||||
typedef struct _fs_dir_object fs_dir_t;
|
|
||||||
|
|
||||||
enum fs_dir_entry_type {
|
enum fs_dir_entry_type {
|
||||||
FS_DIR_ENTRY_FILE,
|
FS_DIR_ENTRY_FILE = 0,
|
||||||
FS_DIR_ENTRY_DIR
|
FS_DIR_ENTRY_DIR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum fs_type {
|
||||||
|
FS_FATFS = 0,
|
||||||
|
FS_NFFS,
|
||||||
|
FS_TYPE_END,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File System
|
* @brief File System
|
||||||
* @defgroup file_system File System
|
* @defgroup file_system File System
|
||||||
|
@ -39,13 +42,27 @@ enum fs_dir_entry_type {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @var fs_file_t
|
/**
|
||||||
* @brief File object representing an open file
|
* @brief File system mount info structure
|
||||||
*/
|
*
|
||||||
|
* @param node Entry for the fs_mount_list list
|
||||||
/** @var fs_dir_t
|
* @param type File system type
|
||||||
* @brief Directory object representing an open directory
|
* @param mnt_point Mount point directory name (ex: "/fatfs")
|
||||||
|
* @param fs_data Pointer to file system specific data
|
||||||
|
* @param storage_dev Pointer to backend storage device
|
||||||
|
* @param mountp_len Length of Mount point string
|
||||||
|
* @param fs Pointer to File system interface of the mount point
|
||||||
*/
|
*/
|
||||||
|
struct fs_mount_t {
|
||||||
|
sys_dnode_t node;
|
||||||
|
enum fs_type type;
|
||||||
|
const char *mnt_point;
|
||||||
|
void *fs_data;
|
||||||
|
struct device *storage_dev;
|
||||||
|
/* fields filled by file system core */
|
||||||
|
size_t mountp_len;
|
||||||
|
const struct fs_file_system_t *fs;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure to receive file or directory information
|
* @brief Structure to receive file or directory information
|
||||||
|
@ -83,6 +100,56 @@ struct fs_statvfs {
|
||||||
unsigned long f_bfree;
|
unsigned long f_bfree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File System interface structure
|
||||||
|
*
|
||||||
|
* @param open Opens an existing file or create a new one
|
||||||
|
* @param read Reads items of data of size bytes long
|
||||||
|
* @param write Writes items of data of size bytes long
|
||||||
|
* @param lseek Moves the file position to a new location in the file
|
||||||
|
* @param tell Retrieves the current position in the file
|
||||||
|
* @param truncate Truncates the file to the new length
|
||||||
|
* @param sync Flush the cache of an open file
|
||||||
|
* @param close Flushes the associated stream and closes the file
|
||||||
|
* @param opendir Opens an existing directory specified by the path
|
||||||
|
* @param readdir Reads directory entries of a open directory
|
||||||
|
* @param closedir Closes an open directory
|
||||||
|
* @param mount Mount a file system
|
||||||
|
* @param unmount Unmount a file system
|
||||||
|
* @param unlink Deletes the specified file or directory
|
||||||
|
* @param rename Renames a file or directory
|
||||||
|
* @param mkdir Creates a new directory using specified path
|
||||||
|
* @param stat Checks the status of a file or directory specified by the path
|
||||||
|
* @param statvfs Returns the total and available space in the filesystem volume
|
||||||
|
*/
|
||||||
|
struct fs_file_system_t {
|
||||||
|
/* File operations */
|
||||||
|
int (*open)(struct fs_file_t *filp, const char *fs_path);
|
||||||
|
ssize_t (*read)(struct fs_file_t *filp, void *dest, size_t nbytes);
|
||||||
|
ssize_t (*write)(struct fs_file_t *filp,
|
||||||
|
const void *src, size_t nbytes);
|
||||||
|
int (*lseek)(struct fs_file_t *filp, off_t off, int whence);
|
||||||
|
off_t (*tell)(struct fs_file_t *filp);
|
||||||
|
int (*truncate)(struct fs_file_t *filp, off_t length);
|
||||||
|
int (*sync)(struct fs_file_t *filp);
|
||||||
|
int (*close)(struct fs_file_t *filp);
|
||||||
|
/* Directory operations */
|
||||||
|
int (*opendir)(struct fs_dir_t *dirp, const char *fs_path);
|
||||||
|
int (*readdir)(struct fs_dir_t *dirp, struct fs_dirent *entry);
|
||||||
|
int (*closedir)(struct fs_dir_t *dirp);
|
||||||
|
/* File system level operations */
|
||||||
|
int (*mount)(struct fs_mount_t *mountp);
|
||||||
|
int (*unmount)(struct fs_mount_t *mountp);
|
||||||
|
int (*unlink)(struct fs_mount_t *mountp, const char *name);
|
||||||
|
int (*rename)(struct fs_mount_t *mountp, const char *from,
|
||||||
|
const char *to);
|
||||||
|
int (*mkdir)(struct fs_mount_t *mountp, const char *name);
|
||||||
|
int (*stat)(struct fs_mount_t *mountp, const char *path,
|
||||||
|
struct fs_dirent *entry);
|
||||||
|
int (*statvfs)(struct fs_mount_t *mountp, const char *path,
|
||||||
|
struct fs_statvfs *stat);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -116,7 +183,7 @@ struct fs_statvfs {
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_open(fs_file_t *zfp, const char *file_name);
|
int fs_open(struct fs_file_t *zfp, const char *file_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File close
|
* @brief File close
|
||||||
|
@ -129,7 +196,7 @@ int fs_open(fs_file_t *zfp, const char *file_name);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_close(fs_file_t *zfp);
|
int fs_close(struct fs_file_t *zfp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File unlink
|
* @brief File unlink
|
||||||
|
@ -143,6 +210,26 @@ int fs_close(fs_file_t *zfp);
|
||||||
*/
|
*/
|
||||||
int fs_unlink(const char *path);
|
int fs_unlink(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File o directory rename
|
||||||
|
*
|
||||||
|
* Performs a rename and / or move of the specified source path to the
|
||||||
|
* specified destination. The source path can refer to either a file or a
|
||||||
|
* directory. All intermediate directories in the destination path must
|
||||||
|
* already exist. If the source path refers to a file, the destination path
|
||||||
|
* must contain a full filename path, rather than just the new parent
|
||||||
|
* directory. If an object already exists at the specified destination path,
|
||||||
|
* this function causes it to be unlinked prior to the rename (i.e., the
|
||||||
|
* estination gets clobbered).
|
||||||
|
*
|
||||||
|
* @param from The source path.
|
||||||
|
* @param to The destination path.
|
||||||
|
*
|
||||||
|
* @retval 0 Success;
|
||||||
|
* @retval -ERRNO errno code if error
|
||||||
|
*/
|
||||||
|
int fs_rename(const char *from, const char *to);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File read
|
* @brief File read
|
||||||
*
|
*
|
||||||
|
@ -157,7 +244,7 @@ int fs_unlink(const char *path);
|
||||||
* requested if there are not enough bytes available in file. Will return
|
* requested if there are not enough bytes available in file. Will return
|
||||||
* -ERRNO code on error.
|
* -ERRNO code on error.
|
||||||
*/
|
*/
|
||||||
ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size);
|
ssize_t fs_read(struct fs_file_t *zfp, void *ptr, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File write
|
* @brief File write
|
||||||
|
@ -178,7 +265,7 @@ ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size);
|
||||||
* In that case, it returns less number of bytes written than requested, but
|
* In that case, it returns less number of bytes written than requested, but
|
||||||
* not a negative -ERRNO value as in regular error case.
|
* not a negative -ERRNO value as in regular error case.
|
||||||
*/
|
*/
|
||||||
ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size);
|
ssize_t fs_write(struct fs_file_t *zfp, const void *ptr, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File seek
|
* @brief File seek
|
||||||
|
@ -196,7 +283,7 @@ ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error.
|
* @retval -ERRNO errno code if error.
|
||||||
*/
|
*/
|
||||||
int fs_seek(fs_file_t *zfp, off_t offset, int whence);
|
int fs_seek(struct fs_file_t *zfp, off_t offset, int whence);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get current file position.
|
* @brief Get current file position.
|
||||||
|
@ -208,7 +295,7 @@ int fs_seek(fs_file_t *zfp, off_t offset, int whence);
|
||||||
* @retval position Current position in file
|
* @retval position Current position in file
|
||||||
* Current revision does not validate the file object.
|
* Current revision does not validate the file object.
|
||||||
*/
|
*/
|
||||||
off_t fs_tell(fs_file_t *zfp);
|
off_t fs_tell(struct fs_file_t *zfp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Change the size of an open file
|
* @brief Change the size of an open file
|
||||||
|
@ -228,7 +315,7 @@ off_t fs_tell(fs_file_t *zfp);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_truncate(fs_file_t *zfp, off_t length);
|
int fs_truncate(struct fs_file_t *zfp, off_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Flushes any cached write of an open file
|
* @brief Flushes any cached write of an open file
|
||||||
|
@ -244,7 +331,7 @@ int fs_truncate(fs_file_t *zfp, off_t length);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_sync(fs_file_t *zfp);
|
int fs_sync(struct fs_file_t *zfp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Directory create
|
* @brief Directory create
|
||||||
|
@ -269,7 +356,7 @@ int fs_mkdir(const char *path);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_opendir(fs_dir_t *zdp, const char *path);
|
int fs_opendir(struct fs_dir_t *zdp, const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Directory read entry
|
* @brief Directory read entry
|
||||||
|
@ -284,7 +371,7 @@ int fs_opendir(fs_dir_t *zdp, const char *path);
|
||||||
* @return In end-of-dir condition, this will return 0 and set
|
* @return In end-of-dir condition, this will return 0 and set
|
||||||
* entry->name[0] = 0
|
* entry->name[0] = 0
|
||||||
*/
|
*/
|
||||||
int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry);
|
int fs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Directory close
|
* @brief Directory close
|
||||||
|
@ -296,7 +383,36 @@ int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry);
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_closedir(fs_dir_t *zdp);
|
int fs_closedir(struct fs_dir_t *zdp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mount filesystem
|
||||||
|
*
|
||||||
|
* Perform steps needed for mounting a file system like
|
||||||
|
* calling the file system specific mount function and adding
|
||||||
|
* the mount point to mounted file system list.
|
||||||
|
*
|
||||||
|
* @param mp Pointer to the fs_mount_t structure
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -ERRNO errno code if error
|
||||||
|
*/
|
||||||
|
int fs_mount(struct fs_mount_t *mp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmount filesystem
|
||||||
|
*
|
||||||
|
* Perform steps needed for unmounting a file system like
|
||||||
|
* calling the file system specific unmount function and removing
|
||||||
|
* the mount point from mounted file system list.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param mp Pointer to the fs_mount_t structure
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -ERRNO errno code if error
|
||||||
|
*/
|
||||||
|
int fs_unmount(struct fs_mount_t *mp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief File or directory status
|
* @brief File or directory status
|
||||||
|
@ -317,17 +433,45 @@ int fs_stat(const char *path, struct fs_dirent *entry);
|
||||||
*
|
*
|
||||||
* Returns the total and available space in the file system volume.
|
* Returns the total and available space in the file system volume.
|
||||||
*
|
*
|
||||||
|
* @param path Path to the mounted directory
|
||||||
* @param stat Pointer to zfs_statvfs structure to receive the fs statistics
|
* @param stat Pointer to zfs_statvfs structure to receive the fs statistics
|
||||||
*
|
*
|
||||||
* @retval 0 Success
|
* @retval 0 Success
|
||||||
* @retval -ERRNO errno code if error
|
* @retval -ERRNO errno code if error
|
||||||
*/
|
*/
|
||||||
int fs_statvfs(struct fs_statvfs *stat);
|
int fs_statvfs(const char *path, struct fs_statvfs *stat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a file system
|
||||||
|
*
|
||||||
|
* Register file system with virtual file system.
|
||||||
|
*
|
||||||
|
* @param type Type of file system (ex: FS_FATFS)
|
||||||
|
* @param fs Pointer to File system
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -ERRNO errno code if error
|
||||||
|
*/
|
||||||
|
int fs_register(enum fs_type type, struct fs_file_system_t *fs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregister a file system
|
||||||
|
*
|
||||||
|
* Unregister file system from virtual file system.
|
||||||
|
*
|
||||||
|
* @param type Type of file system (ex: FS_FATFS)
|
||||||
|
* @param fs Pointer to File system
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -ERRNO errno code if error
|
||||||
|
*/
|
||||||
|
int fs_unregister(enum fs_type type, struct fs_file_system_t *fs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FAT_FS_H_
|
|
||||||
#define _FAT_FS_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <ff.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FS_FILE_DEFINE(FIL fp);
|
|
||||||
FS_DIR_DEFINE(DIR dp);
|
|
||||||
|
|
||||||
#define MAX_FILE_NAME 12 /* Uses 8.3 SFN */
|
|
||||||
|
|
||||||
static inline off_t fs_tell(struct _fs_file_object *zfp)
|
|
||||||
{
|
|
||||||
return f_tell(&zfp->fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _FAT_FS_H_ */
|
|
|
@ -7,46 +7,64 @@
|
||||||
#ifndef _FS_INTERFACE_H_
|
#ifndef _FS_INTERFACE_H_
|
||||||
#define _FS_INTERFACE_H_
|
#define _FS_INTERFACE_H_
|
||||||
|
|
||||||
|
#ifdef CONFIG_FAT_FILESYSTEM_ELM
|
||||||
|
#include <ff.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_FILE_SYSTEM_NFFS
|
||||||
|
#include <nffs/nffs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#ifdef CONFIG_FILE_SYSTEM_NFFS
|
||||||
* @brief Macro to define _zfile_object structure
|
#define MAX_FILE_NAME 256
|
||||||
*
|
#else /* FAT_FS */
|
||||||
* This structure contains information about the open files. This
|
#define MAX_FILE_NAME 12 /* Uses 8.3 SFN */
|
||||||
* structure will be passed to the api functions as an opaque
|
|
||||||
* pointer.
|
|
||||||
*
|
|
||||||
* @param _file_object File structure used by underlying file system
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FS_FILE_DEFINE(_file_object) \
|
|
||||||
struct _fs_file_object { \
|
|
||||||
_file_object; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief Macro to define _zdir_object structure
|
|
||||||
*
|
|
||||||
* This structure contains information about the open directories. This
|
|
||||||
* structure will be passed to the directory api functions as an opaque
|
|
||||||
* pointer.
|
|
||||||
*
|
|
||||||
* @param _dir_object Directory structure used by underlying file system
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FS_DIR_DEFINE(_dir_object) \
|
|
||||||
struct _fs_dir_object { \
|
|
||||||
_dir_object; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_FAT_FILESYSTEM_ELM
|
|
||||||
#include <fs/fat_fs.h>
|
|
||||||
#elif CONFIG_FILE_SYSTEM_NFFS
|
|
||||||
#include <fs/nffs_fs.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct fs_mount_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File object representing an open file
|
||||||
|
*
|
||||||
|
* @param fatfs_fp FATFS file object structure
|
||||||
|
* @param nffs_fp NFFS file object structure
|
||||||
|
* @param mp Pointer to mount point structure
|
||||||
|
*/
|
||||||
|
struct fs_file_t {
|
||||||
|
union {
|
||||||
|
#ifdef CONFIG_FAT_FILESYSTEM_ELM
|
||||||
|
FIL fatfs_fp;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_FILE_SYSTEM_NFFS
|
||||||
|
struct nffs_file *nffs_fp;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
const struct fs_mount_t *mp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Directory object representing an open directory
|
||||||
|
*
|
||||||
|
* @param fatfs_dp FATFS directory object structure
|
||||||
|
* @param nffs_dp NFFS directory object structure
|
||||||
|
* @param mp Pointer to mount point structure
|
||||||
|
*/
|
||||||
|
struct fs_dir_t {
|
||||||
|
union {
|
||||||
|
#ifdef CONFIG_FAT_FILESYSTEM_ELM
|
||||||
|
DIR fatfs_dp;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_FILE_SYSTEM_NFFS
|
||||||
|
struct nffs_dir *nffs_dp;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
const struct fs_mount_t *mp;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017 Codecoup
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NFFS_FS_H_
|
|
||||||
#define _NFFS_FS_H_
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <nffs/nffs.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FS_FILE_DEFINE(struct nffs_file *fp);
|
|
||||||
FS_DIR_DEFINE(struct nffs_dir *dp);
|
|
||||||
|
|
||||||
#define MAX_FILE_NAME 256
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _NFFS_FS_H_ */
|
|
|
@ -3,6 +3,7 @@ if(CONFIG_FILE_SYSTEM)
|
||||||
zephyr_link_interface_ifdef(CONFIG_FILE_SYSTEM_NFFS NFFS)
|
zephyr_link_interface_ifdef(CONFIG_FILE_SYSTEM_NFFS NFFS)
|
||||||
|
|
||||||
zephyr_library()
|
zephyr_library()
|
||||||
|
zephyr_library_sources(fs.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_FAT_FILESYSTEM_ELM fat_fs.c)
|
zephyr_library_sources_ifdef(CONFIG_FAT_FILESYSTEM_ELM fat_fs.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_NFFS nffs_fs.c)
|
zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_NFFS nffs_fs.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_SHELL shell.c)
|
zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_SHELL shell.c)
|
||||||
|
|
|
@ -9,11 +9,10 @@
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <ff.h>
|
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <misc/__assert.h>
|
#include <misc/__assert.h>
|
||||||
|
|
||||||
static FATFS fat_fs; /* FatFs work area */
|
#define FATFS_MAX_FILE_NAME 12 /* Uses 8.3 SFN */
|
||||||
|
|
||||||
static int translate_error(int error)
|
static int translate_error(int error)
|
||||||
{
|
{
|
||||||
|
@ -54,28 +53,28 @@ static int translate_error(int error)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_open(fs_file_t *zfp, const char *file_name)
|
static int fatfs_open(struct fs_file_t *zfp, const char *file_name)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
u8_t fs_mode;
|
u8_t fs_mode;
|
||||||
|
|
||||||
fs_mode = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
|
fs_mode = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
|
||||||
|
|
||||||
res = f_open(&zfp->fp, file_name, fs_mode);
|
res = f_open(&zfp->fatfs_fp, file_name, fs_mode);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_close(fs_file_t *zfp)
|
static int fatfs_close(struct fs_file_t *zfp)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
res = f_close(&zfp->fp);
|
res = f_close(&zfp->fatfs_fp);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_unlink(const char *path)
|
static int fatfs_unlink(struct fs_mount_t *mountp, const char *path)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
|
@ -84,12 +83,12 @@ int fs_unlink(const char *path)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size)
|
static ssize_t fatfs_read(struct fs_file_t *zfp, void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
unsigned int br;
|
unsigned int br;
|
||||||
|
|
||||||
res = f_read(&zfp->fp, ptr, size, &br);
|
res = f_read(&zfp->fatfs_fp, ptr, size, &br);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
@ -97,12 +96,12 @@ ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size)
|
||||||
return br;
|
return br;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size)
|
static ssize_t fatfs_write(struct fs_file_t *zfp, const void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
unsigned int bw;
|
unsigned int bw;
|
||||||
|
|
||||||
res = f_write(&zfp->fp, ptr, size, &bw);
|
res = f_write(&zfp->fatfs_fp, ptr, size, &bw);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +109,7 @@ ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size)
|
||||||
return bw;
|
return bw;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_seek(fs_file_t *zfp, off_t offset, int whence)
|
static int fatfs_seek(struct fs_file_t *zfp, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
off_t pos;
|
off_t pos;
|
||||||
|
@ -120,46 +119,51 @@ int fs_seek(fs_file_t *zfp, off_t offset, int whence)
|
||||||
pos = offset;
|
pos = offset;
|
||||||
break;
|
break;
|
||||||
case FS_SEEK_CUR:
|
case FS_SEEK_CUR:
|
||||||
pos = f_tell(&zfp->fp) + offset;
|
pos = f_tell(&zfp->fatfs_fp) + offset;
|
||||||
break;
|
break;
|
||||||
case FS_SEEK_END:
|
case FS_SEEK_END:
|
||||||
pos = f_size(&zfp->fp) + offset;
|
pos = f_size(&zfp->fatfs_fp) + offset;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pos < 0) || (pos > f_size(&zfp->fp))) {
|
if ((pos < 0) || (pos > f_size(&zfp->fatfs_fp))) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = f_lseek(&zfp->fp, pos);
|
res = f_lseek(&zfp->fatfs_fp, pos);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_truncate(fs_file_t *zfp, off_t length)
|
static off_t fatfs_tell(struct fs_file_t *zfp)
|
||||||
|
{
|
||||||
|
return f_tell(&zfp->fatfs_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fatfs_truncate(struct fs_file_t *zfp, off_t length)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
off_t cur_length = f_size(&zfp->fp);
|
off_t cur_length = f_size(&zfp->fatfs_fp);
|
||||||
|
|
||||||
/* f_lseek expands file if new position is larger than file size */
|
/* f_lseek expands file if new position is larger than file size */
|
||||||
res = f_lseek(&zfp->fp, length);
|
res = f_lseek(&zfp->fatfs_fp, length);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < cur_length) {
|
if (length < cur_length) {
|
||||||
res = f_truncate(&zfp->fp);
|
res = f_truncate(&zfp->fatfs_fp);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Get actual length after expansion. This could be
|
* Get actual length after expansion. This could be
|
||||||
* less if there was not enough space in the volume
|
* less if there was not enough space in the volume
|
||||||
* to expand to the requested length
|
* to expand to the requested length
|
||||||
*/
|
*/
|
||||||
length = f_tell(&zfp->fp);
|
length = f_tell(&zfp->fatfs_fp);
|
||||||
|
|
||||||
res = f_lseek(&zfp->fp, cur_length);
|
res = f_lseek(&zfp->fatfs_fp, cur_length);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +178,7 @@ int fs_truncate(fs_file_t *zfp, off_t length)
|
||||||
u8_t c = 0;
|
u8_t c = 0;
|
||||||
|
|
||||||
for (int i = cur_length; i < length; i++) {
|
for (int i = cur_length; i < length; i++) {
|
||||||
res = f_write(&zfp->fp, &c, 1, &bw);
|
res = f_write(&zfp->fatfs_fp, &c, 1, &bw);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -184,16 +188,16 @@ int fs_truncate(fs_file_t *zfp, off_t length)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_sync(fs_file_t *zfp)
|
static int fatfs_sync(struct fs_file_t *zfp)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
|
|
||||||
res = f_sync(&zfp->fp);
|
res = f_sync(&zfp->fatfs_fp);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_mkdir(const char *path)
|
static int fatfs_mkdir(struct fs_mount_t *mountp, const char *path)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
|
@ -202,21 +206,21 @@ int fs_mkdir(const char *path)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_opendir(fs_dir_t *zdp, const char *path)
|
static int fatfs_opendir(struct fs_dir_t *zdp, const char *path)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
res = f_opendir(&zdp->dp, path);
|
res = f_opendir(&zdp->fatfs_dp, path);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry)
|
static int fatfs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
|
|
||||||
res = f_readdir(&zdp->dp, &fno);
|
res = f_readdir(&zdp->fatfs_dp, &fno);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
entry->type = ((fno.fattrib & AM_DIR) ?
|
entry->type = ((fno.fattrib & AM_DIR) ?
|
||||||
FS_DIR_ENTRY_DIR : FS_DIR_ENTRY_FILE);
|
FS_DIR_ENTRY_DIR : FS_DIR_ENTRY_FILE);
|
||||||
|
@ -227,16 +231,17 @@ int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_closedir(fs_dir_t *zdp)
|
static int fatfs_closedir(struct fs_dir_t *zdp)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
res = f_closedir(&zdp->dp);
|
res = f_closedir(&zdp->fatfs_dp);
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_stat(const char *path, struct fs_dirent *entry)
|
static int fatfs_stat(struct fs_mount_t *mountp,
|
||||||
|
const char *path, struct fs_dirent *entry)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
|
@ -252,7 +257,8 @@ int fs_stat(const char *path, struct fs_dirent *entry)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_statvfs(struct fs_statvfs *stat)
|
static int fatfs_statvfs(struct fs_mount_t *mountp,
|
||||||
|
const char *path, struct fs_statvfs *stat)
|
||||||
{
|
{
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
@ -273,13 +279,11 @@ int fs_statvfs(struct fs_statvfs *stat)
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fs_init(struct device *dev)
|
static int fatfs_mount(struct fs_mount_t *mountp)
|
||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
ARG_UNUSED(dev);
|
res = f_mount((FATFS *)mountp->fs_data, "", 1);
|
||||||
|
|
||||||
res = f_mount(&fat_fs, "", 1);
|
|
||||||
|
|
||||||
/* If no file system found then create one */
|
/* If no file system found then create one */
|
||||||
if (res == FR_NO_FILESYSTEM) {
|
if (res == FR_NO_FILESYSTEM) {
|
||||||
|
@ -287,13 +291,41 @@ static int fs_init(struct device *dev)
|
||||||
|
|
||||||
res = f_mkfs("", (FM_FAT | FM_SFD), 0, work, sizeof(work));
|
res = f_mkfs("", (FM_FAT | FM_SFD), 0, work, sizeof(work));
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = f_mount(&fat_fs, "", 1);
|
res = f_mount((FATFS *)mountp->fs_data, "", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__ASSERT((res == FR_OK), "FS init failed (%d)", translate_error(res));
|
__ASSERT((res == FR_OK), "FS init failed (%d)", translate_error(res));
|
||||||
|
|
||||||
return translate_error(res);
|
return translate_error(res);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_INIT(fs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
/* File system interface */
|
||||||
|
static struct fs_file_system_t fatfs_fs = {
|
||||||
|
.open = fatfs_open,
|
||||||
|
.close = fatfs_close,
|
||||||
|
.read = fatfs_read,
|
||||||
|
.write = fatfs_write,
|
||||||
|
.lseek = fatfs_seek,
|
||||||
|
.tell = fatfs_tell,
|
||||||
|
.truncate = fatfs_truncate,
|
||||||
|
.sync = fatfs_sync,
|
||||||
|
.opendir = fatfs_opendir,
|
||||||
|
.readdir = fatfs_readdir,
|
||||||
|
.closedir = fatfs_closedir,
|
||||||
|
.mount = fatfs_mount,
|
||||||
|
.unlink = fatfs_unlink,
|
||||||
|
.mkdir = fatfs_mkdir,
|
||||||
|
.stat = fatfs_stat,
|
||||||
|
.statvfs = fatfs_statvfs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int fatfs_init(struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
return fs_register(FS_FATFS, &fatfs_fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(fatfs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
|
564
subsys/fs/fs.c
Normal file
564
subsys/fs/fs.c
Normal file
|
@ -0,0 +1,564 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <fs.h>
|
||||||
|
|
||||||
|
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_FS_LEVEL
|
||||||
|
#include <logging/sys_log.h>
|
||||||
|
|
||||||
|
/* list of mounted file systems */
|
||||||
|
static sys_dlist_t fs_mnt_list;
|
||||||
|
|
||||||
|
/* lock to protect mount list operations */
|
||||||
|
static struct k_mutex mutex;
|
||||||
|
|
||||||
|
/* file system map table */
|
||||||
|
static struct fs_file_system_t *fs_map[FS_TYPE_END];
|
||||||
|
|
||||||
|
int get_mnt_point(struct fs_mount_t **mnt_pntp,
|
||||||
|
const char *name, size_t *match_len)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mnt_p = NULL, *itr;
|
||||||
|
size_t longest_match = 0;
|
||||||
|
size_t len, name_len = strlen(name);
|
||||||
|
sys_dnode_t *node;
|
||||||
|
|
||||||
|
k_mutex_lock(&mutex, K_FOREVER);
|
||||||
|
SYS_DLIST_FOR_EACH_NODE(&fs_mnt_list, node) {
|
||||||
|
itr = CONTAINER_OF(node, struct fs_mount_t, node);
|
||||||
|
len = itr->mountp_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move to next node if mount point length is
|
||||||
|
* shorter than longest_match match or if path
|
||||||
|
* name is shorter than the mount point name.
|
||||||
|
*/
|
||||||
|
if ((len < longest_match) || (len > name_len)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move to next node if name does not have a directory
|
||||||
|
* separator where mount point name ends.
|
||||||
|
*/
|
||||||
|
if ((len > 1) && (name[len] != '/') && (name[len] != '\0')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for mount point match */
|
||||||
|
if (strncmp(name, itr->mnt_point, len) == 0) {
|
||||||
|
mnt_p = itr;
|
||||||
|
longest_match = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
if (mnt_p == NULL) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mnt_pntp = mnt_p;
|
||||||
|
*match_len = mnt_p->mountp_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File operations */
|
||||||
|
int fs_open(struct fs_file_t *zfp, const char *file_name)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((file_name == NULL) ||
|
||||||
|
(strlen(file_name) <= 1) || (file_name[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, file_name, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
zfp->mp = mp;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->open != NULL) {
|
||||||
|
rc = zfp->mp->fs->open(zfp, &file_name[match_len]);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file open error (%d)", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_close(struct fs_file_t *zfp)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->close != NULL) {
|
||||||
|
rc = zfp->mp->fs->close(zfp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file close error (%d)", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zfp->mp = NULL;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t fs_read(struct fs_file_t *zfp, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->read != NULL) {
|
||||||
|
rc = zfp->mp->fs->read(zfp, ptr, size);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file read error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t fs_write(struct fs_file_t *zfp, const void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->write != NULL) {
|
||||||
|
rc = zfp->mp->fs->write(zfp, ptr, size);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file write error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_seek(struct fs_file_t *zfp, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->lseek != NULL) {
|
||||||
|
rc = zfp->mp->fs->lseek(zfp, offset, whence);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file seek error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t fs_tell(struct fs_file_t *zfp)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->tell != NULL) {
|
||||||
|
rc = zfp->mp->fs->tell(zfp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file tell error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_truncate(struct fs_file_t *zfp, off_t length)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->truncate != NULL) {
|
||||||
|
rc = zfp->mp->fs->truncate(zfp, length);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file truncate error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_sync(struct fs_file_t *zfp)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zfp->mp->fs->sync != NULL) {
|
||||||
|
rc = zfp->mp->fs->sync(zfp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("file sync error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Directory operations */
|
||||||
|
int fs_opendir(struct fs_dir_t *zdp, const char *abs_path)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((abs_path == NULL) ||
|
||||||
|
(strlen(abs_path) <= 1) || (abs_path[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, abs_path, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
zdp->mp = mp;
|
||||||
|
|
||||||
|
if (zdp->mp->fs->opendir != NULL) {
|
||||||
|
rc = zdp->mp->fs->opendir(zdp, &abs_path[match_len]);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("directory open error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zdp->mp->fs->readdir != NULL) {
|
||||||
|
rc = zdp->mp->fs->readdir(zdp, entry);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("directory read error (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_closedir(struct fs_dir_t *zdp)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if (zdp->mp->fs->closedir != NULL) {
|
||||||
|
rc = zdp->mp->fs->closedir(zdp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("directory close error (%d)", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zdp->mp = NULL;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filesystem operations */
|
||||||
|
int fs_mkdir(const char *abs_path)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((abs_path == NULL) ||
|
||||||
|
(strlen(abs_path) <= 1) || (abs_path[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, abs_path, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->fs->mkdir != NULL) {
|
||||||
|
rc = mp->fs->mkdir(mp, &abs_path[match_len]);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("failed to create directory (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_unlink(const char *abs_path)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((abs_path == NULL) ||
|
||||||
|
(strlen(abs_path) <= 1) || (abs_path[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, abs_path, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->fs->unlink != NULL) {
|
||||||
|
rc = mp->fs->unlink(mp, &abs_path[match_len]);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("failed to unlink path (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_rename(const char *from, const char *to)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((from == NULL) || (strlen(from) <= 1) || (from[0] != '/') ||
|
||||||
|
(to == NULL) || (strlen(to) <= 1) || (to[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, from, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure both files are mounted on the same path */
|
||||||
|
if (strncmp(from, to, match_len) != 0) {
|
||||||
|
SYS_LOG_ERR("mount point not same!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->fs->rename != NULL) {
|
||||||
|
rc = mp->fs->rename(mp, &from[match_len], &to[match_len]);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("failed to rename file or dir (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_stat(const char *abs_path, struct fs_dirent *entry)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((abs_path == NULL) ||
|
||||||
|
(strlen(abs_path) <= 1) || (abs_path[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, abs_path, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->fs->stat != NULL) {
|
||||||
|
rc = mp->fs->stat(mp, &abs_path[match_len], entry);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("failed get file or dir stat (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_statvfs(const char *abs_path, struct fs_statvfs *stat)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *mp;
|
||||||
|
size_t match_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((abs_path == NULL) ||
|
||||||
|
(strlen(abs_path) <= 1) || (abs_path[0] != '/')) {
|
||||||
|
SYS_LOG_ERR("invalid file name!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = get_mnt_point(&mp, abs_path, &match_len);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("%s:mount point not found!!", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mp->fs->statvfs != NULL) {
|
||||||
|
rc = mp->fs->statvfs(mp, &abs_path[match_len], stat);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("failed get file or dir stat (%d)", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_mount(struct fs_mount_t *mp)
|
||||||
|
{
|
||||||
|
struct fs_mount_t *itr;
|
||||||
|
struct fs_file_system_t *fs;
|
||||||
|
sys_dnode_t *node;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((mp == NULL) || (mp->mnt_point == NULL)) {
|
||||||
|
SYS_LOG_ERR("mount point not initialized!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_mutex_lock(&mutex, K_FOREVER);
|
||||||
|
/* Check if requested file system is registered */
|
||||||
|
if (mp->type >= FS_TYPE_END || fs_map[mp->type] == NULL) {
|
||||||
|
SYS_LOG_ERR("requested file system not registered!!");
|
||||||
|
rc = -ENOENT;
|
||||||
|
goto mount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get fs interface from file system map */
|
||||||
|
fs = fs_map[mp->type];
|
||||||
|
mp->mountp_len = strlen(mp->mnt_point);
|
||||||
|
|
||||||
|
if ((mp->mnt_point[0] != '/') ||
|
||||||
|
(strlen(mp->mnt_point) <= 1)) {
|
||||||
|
SYS_LOG_ERR("invalid mount point!!");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto mount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs->mount == NULL) {
|
||||||
|
SYS_LOG_ERR("fs ops functions not set!!");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto mount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if mount point already exists */
|
||||||
|
SYS_DLIST_FOR_EACH_NODE(&fs_mnt_list, node) {
|
||||||
|
itr = CONTAINER_OF(node, struct fs_mount_t, node);
|
||||||
|
/* continue if length does not match */
|
||||||
|
if (mp->mountp_len != itr->mountp_len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(mp->mnt_point, itr->mnt_point,
|
||||||
|
mp->mountp_len) == 0) {
|
||||||
|
SYS_LOG_ERR("mount Point already exists!!");
|
||||||
|
rc = -EBUSY;
|
||||||
|
goto mount_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc = fs->mount(mp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("fs mount error (%d)", rc);
|
||||||
|
goto mount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set mount point fs interface */
|
||||||
|
mp->fs = fs;
|
||||||
|
|
||||||
|
/* append to the mount list */
|
||||||
|
sys_dlist_append(&fs_mnt_list, &mp->node);
|
||||||
|
SYS_LOG_DBG("fs mouted, mount point:%s", mp->mnt_point);
|
||||||
|
|
||||||
|
mount_err:
|
||||||
|
k_mutex_unlock(&mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int fs_unmount(struct fs_mount_t *mp)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
if ((mp == NULL) || (mp->mnt_point == NULL) ||
|
||||||
|
(strlen(mp->mnt_point) <= 1)) {
|
||||||
|
SYS_LOG_ERR("invalid mount point!!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_mutex_lock(&mutex, K_FOREVER);
|
||||||
|
if ((mp->fs == NULL) || mp->fs->unmount == NULL) {
|
||||||
|
SYS_LOG_ERR("fs ops functions not set!!");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto unmount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mp->fs->unmount(mp);
|
||||||
|
if (rc < 0) {
|
||||||
|
SYS_LOG_ERR("fs unmount error (%d)", rc);
|
||||||
|
goto unmount_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear file system interface */
|
||||||
|
mp->fs = NULL;
|
||||||
|
|
||||||
|
/* remove mount node from the list */
|
||||||
|
sys_dlist_remove(&mp->node);
|
||||||
|
SYS_LOG_DBG("fs unmouted, mount point:%s", mp->mnt_point);
|
||||||
|
|
||||||
|
unmount_err:
|
||||||
|
k_mutex_unlock(&mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register File system */
|
||||||
|
int fs_register(enum fs_type type, struct fs_file_system_t *fs)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
k_mutex_lock(&mutex, K_FOREVER);
|
||||||
|
if (type >= FS_TYPE_END) {
|
||||||
|
SYS_LOG_ERR("failed to register File system!!");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto reg_err;
|
||||||
|
}
|
||||||
|
fs_map[type] = fs;
|
||||||
|
SYS_LOG_DBG("fs registered of type(%u)", type);
|
||||||
|
reg_err:
|
||||||
|
k_mutex_unlock(&mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unregister File system */
|
||||||
|
int fs_unregister(enum fs_type type, struct fs_file_system_t *fs)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
k_mutex_lock(&mutex, K_FOREVER);
|
||||||
|
if ((type >= FS_TYPE_END) ||
|
||||||
|
(fs_map[type] != fs)) {
|
||||||
|
SYS_LOG_ERR("failed to unregister File system!!");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto unreg_err;
|
||||||
|
}
|
||||||
|
fs_map[type] = NULL;
|
||||||
|
SYS_LOG_DBG("fs unregistered of type(%u)", type);
|
||||||
|
unreg_err:
|
||||||
|
k_mutex_unlock(&mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fs_init(struct device *dev)
|
||||||
|
{
|
||||||
|
k_mutex_init(&mutex);
|
||||||
|
sys_dlist_init(&fs_mnt_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(fs_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
|
@ -14,9 +14,10 @@
|
||||||
#include <crc16.h>
|
#include <crc16.h>
|
||||||
#include <misc/__assert.h>
|
#include <misc/__assert.h>
|
||||||
#include <misc/printk.h>
|
#include <misc/printk.h>
|
||||||
#include <nffs/nffs.h>
|
|
||||||
#include <nffs/os.h>
|
#include <nffs/os.h>
|
||||||
|
|
||||||
|
#define NFFS_MAX_FILE_NAME 256
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NFFS code keeps fs state in RAM but access to these structures is not
|
* NFFS code keeps fs state in RAM but access to these structures is not
|
||||||
* thread-safe - we need global lock for each fs operation to guarantee two
|
* thread-safe - we need global lock for each fs operation to guarantee two
|
||||||
|
@ -24,8 +25,11 @@
|
||||||
*/
|
*/
|
||||||
static struct k_mutex nffs_lock;
|
static struct k_mutex nffs_lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Get rid of global flash_dev which limits
|
||||||
|
* system to have multiple instances of NFFS.
|
||||||
|
*/
|
||||||
static struct device *flash_dev;
|
static struct device *flash_dev;
|
||||||
static struct nffs_flash_desc flash_desc;
|
|
||||||
|
|
||||||
K_MEM_SLAB_DEFINE(nffs_file_pool, sizeof(struct nffs_file),
|
K_MEM_SLAB_DEFINE(nffs_file_pool, sizeof(struct nffs_file),
|
||||||
CONFIG_FS_NFFS_NUM_FILES, 4);
|
CONFIG_FS_NFFS_NUM_FILES, 4);
|
||||||
|
@ -218,20 +222,20 @@ static int inode_to_dirent(struct nffs_inode_entry *inode,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_open(fs_file_t *zfp, const char *file_name)
|
static int nffs_open(struct fs_file_t *zfp, const char *file_name)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
zfp->fp = NULL;
|
zfp->nffs_fp = NULL;
|
||||||
|
|
||||||
if (!nffs_misc_ready()) {
|
if (!nffs_misc_ready()) {
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = nffs_file_open(&zfp->fp, file_name,
|
rc = nffs_file_open(&zfp->nffs_fp, file_name,
|
||||||
FS_ACCESS_READ | FS_ACCESS_WRITE);
|
FS_ACCESS_READ | FS_ACCESS_WRITE);
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
@ -239,15 +243,15 @@ int fs_open(fs_file_t *zfp, const char *file_name)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_close(fs_file_t *zfp)
|
static int nffs_close(struct fs_file_t *zfp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
rc = nffs_file_close(zfp->fp);
|
rc = nffs_file_close(zfp->nffs_fp);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
zfp->fp = NULL;
|
zfp->nffs_fp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
@ -255,7 +259,7 @@ int fs_close(fs_file_t *zfp)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_unlink(const char *path)
|
static int nffs_unlink(struct fs_mount_t *mountp, const char *path)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -268,14 +272,14 @@ int fs_unlink(const char *path)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size)
|
static ssize_t nffs_read(struct fs_file_t *zfp, void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
uint32_t br;
|
uint32_t br;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
rc = nffs_file_read(zfp->fp, size, ptr, &br);
|
rc = nffs_file_read(zfp->nffs_fp, size, ptr, &br);
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
|
||||||
|
@ -286,13 +290,13 @@ ssize_t fs_read(fs_file_t *zfp, void *ptr, size_t size)
|
||||||
return br;
|
return br;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size)
|
static ssize_t nffs_write(struct fs_file_t *zfp, const void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
rc = nffs_write_to_file(zfp->fp, ptr, size);
|
rc = nffs_write_to_file(zfp->nffs_fp, ptr, size);
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
|
||||||
|
@ -304,7 +308,7 @@ ssize_t fs_write(fs_file_t *zfp, const void *ptr, size_t size)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_seek(fs_file_t *zfp, off_t offset, int whence)
|
static int nffs_seek(struct fs_file_t *zfp, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
u32_t pos;
|
u32_t pos;
|
||||||
|
@ -317,10 +321,10 @@ int fs_seek(fs_file_t *zfp, off_t offset, int whence)
|
||||||
pos = offset;
|
pos = offset;
|
||||||
break;
|
break;
|
||||||
case FS_SEEK_CUR:
|
case FS_SEEK_CUR:
|
||||||
pos = zfp->fp->nf_offset + offset;
|
pos = zfp->nffs_fp->nf_offset + offset;
|
||||||
break;
|
break;
|
||||||
case FS_SEEK_END:
|
case FS_SEEK_END:
|
||||||
rc = nffs_inode_data_len(zfp->fp->nf_inode_entry, &len);
|
rc = nffs_inode_data_len(zfp->nffs_fp->nf_inode_entry, &len);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -332,32 +336,32 @@ int fs_seek(fs_file_t *zfp, off_t offset, int whence)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = nffs_file_seek(zfp->fp, pos);
|
rc = nffs_file_seek(zfp->nffs_fp, pos);
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t fs_tell(fs_file_t *zfp)
|
static off_t nffs_tell(struct fs_file_t *zfp)
|
||||||
{
|
{
|
||||||
u32_t offset;
|
u32_t offset;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
if (!zfp->fp) {
|
if (!zfp->nffs_fp) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = zfp->fp->nf_offset;
|
offset = zfp->nffs_fp->nf_offset;
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_truncate(fs_file_t *zfp, off_t length)
|
static int nffs_truncate(struct fs_file_t *zfp, off_t length)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* FIXME:
|
* FIXME:
|
||||||
|
@ -369,7 +373,7 @@ int fs_truncate(fs_file_t *zfp, off_t length)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_sync(fs_file_t *zfp)
|
static int nffs_sync(struct fs_file_t *zfp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Files are written to flash immediately so we do not need to support
|
* Files are written to flash immediately so we do not need to support
|
||||||
|
@ -379,7 +383,7 @@ int fs_sync(fs_file_t *zfp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_mkdir(const char *path)
|
static int nffs_mkdir(struct fs_mount_t *mountp, const char *path)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -397,34 +401,34 @@ int fs_mkdir(const char *path)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_opendir(fs_dir_t *zdp, const char *path)
|
static int nffs_opendir(struct fs_dir_t *zdp, const char *path)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
zdp->dp = NULL;
|
zdp->nffs_dp = NULL;
|
||||||
|
|
||||||
if (!nffs_misc_ready()) {
|
if (!nffs_misc_ready()) {
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = nffs_dir_open(path, &zdp->dp);
|
rc = nffs_dir_open(path, &zdp->nffs_dp);
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry)
|
static int nffs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry)
|
||||||
{
|
{
|
||||||
struct nffs_dirent *dirent;
|
struct nffs_dirent *dirent;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
rc = nffs_dir_read(zdp->dp, &dirent);
|
rc = nffs_dir_read(zdp->nffs_dp, &dirent);
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
rc = inode_to_dirent(dirent->nde_inode_entry, entry);
|
rc = inode_to_dirent(dirent->nde_inode_entry, entry);
|
||||||
|
@ -442,15 +446,15 @@ int fs_readdir(fs_dir_t *zdp, struct fs_dirent *entry)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_closedir(fs_dir_t *zdp)
|
static int nffs_closedir(struct fs_dir_t *zdp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
k_mutex_lock(&nffs_lock, K_FOREVER);
|
k_mutex_lock(&nffs_lock, K_FOREVER);
|
||||||
|
|
||||||
rc = nffs_dir_close(zdp->dp);
|
rc = nffs_dir_close(zdp->nffs_dp);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
zdp->dp = NULL;
|
zdp->nffs_dp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_mutex_unlock(&nffs_lock);
|
k_mutex_unlock(&nffs_lock);
|
||||||
|
@ -458,7 +462,8 @@ int fs_closedir(fs_dir_t *zdp)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_stat(const char *path, struct fs_dirent *entry)
|
static int nffs_stat(struct fs_mount_t *mountp,
|
||||||
|
const char *path, struct fs_dirent *entry)
|
||||||
{
|
{
|
||||||
struct nffs_path_parser parser;
|
struct nffs_path_parser parser;
|
||||||
struct nffs_inode_entry *parent;
|
struct nffs_inode_entry *parent;
|
||||||
|
@ -479,7 +484,8 @@ int fs_stat(const char *path, struct fs_dirent *entry)
|
||||||
return translate_error(rc);
|
return translate_error(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_statvfs(struct fs_statvfs *stat)
|
static int nffs_statvfs(struct fs_mount_t *mountp,
|
||||||
|
const char *path, struct fs_statvfs *stat)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* FIXME:
|
* FIXME:
|
||||||
|
@ -489,25 +495,22 @@ int fs_statvfs(struct fs_statvfs *stat)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fs_init(struct device *dev)
|
static int nffs_mount(struct fs_mount_t *mountp)
|
||||||
{
|
{
|
||||||
struct nffs_area_desc descs[CONFIG_NFFS_FILESYSTEM_MAX_AREAS + 1];
|
struct nffs_area_desc descs[CONFIG_NFFS_FILESYSTEM_MAX_AREAS + 1];
|
||||||
|
struct nffs_flash_desc *flash_desc =
|
||||||
|
(struct nffs_flash_desc *)mountp->fs_data;
|
||||||
int cnt;
|
int cnt;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ARG_UNUSED(dev);
|
/* Set flash device */
|
||||||
|
flash_dev = mountp->storage_dev;
|
||||||
|
|
||||||
k_mutex_init(&nffs_lock);
|
/* Set flash descriptor fields */
|
||||||
|
flash_desc->id = 0;
|
||||||
flash_dev = device_get_binding(CONFIG_FS_NFFS_FLASH_DEV_NAME);
|
flash_desc->sector_count = flash_get_page_count(flash_dev);
|
||||||
if (!flash_dev) {
|
flash_desc->area_offset = FLASH_AREA_NFFS_OFFSET;
|
||||||
return -ENODEV;
|
flash_desc->area_size = FLASH_AREA_NFFS_SIZE;
|
||||||
}
|
|
||||||
|
|
||||||
flash_desc.id = 0;
|
|
||||||
flash_desc.sector_count = flash_get_page_count(flash_dev);
|
|
||||||
flash_desc.area_offset = FLASH_AREA_NFFS_OFFSET;
|
|
||||||
flash_desc.area_size = FLASH_AREA_NFFS_SIZE;
|
|
||||||
|
|
||||||
rc = nffs_misc_reset();
|
rc = nffs_misc_reset();
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -515,7 +518,7 @@ static int fs_init(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt = CONFIG_NFFS_FILESYSTEM_MAX_AREAS;
|
cnt = CONFIG_NFFS_FILESYSTEM_MAX_AREAS;
|
||||||
rc = nffs_misc_desc_from_flash_area(&flash_desc, &cnt, descs);
|
rc = nffs_misc_desc_from_flash_area(flash_desc, &cnt, descs);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -537,4 +540,33 @@ static int fs_init(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_INIT(fs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
/* File system interface */
|
||||||
|
static struct fs_file_system_t nffs_fs = {
|
||||||
|
.open = nffs_open,
|
||||||
|
.close = nffs_close,
|
||||||
|
.read = nffs_read,
|
||||||
|
.write = nffs_write,
|
||||||
|
.lseek = nffs_seek,
|
||||||
|
.tell = nffs_tell,
|
||||||
|
.truncate = nffs_truncate,
|
||||||
|
.sync = nffs_sync,
|
||||||
|
.opendir = nffs_opendir,
|
||||||
|
.readdir = nffs_readdir,
|
||||||
|
.closedir = nffs_closedir,
|
||||||
|
.mount = nffs_mount,
|
||||||
|
.unlink = nffs_unlink,
|
||||||
|
.mkdir = nffs_mkdir,
|
||||||
|
.stat = nffs_stat,
|
||||||
|
.statvfs = nffs_statvfs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int nffs_init(struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
|
k_mutex_init(&nffs_lock);
|
||||||
|
|
||||||
|
return fs_register(FS_NFFS, &nffs_fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(nffs_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue