subsys/fs: Add open flags parameter to fs_open
The fs_open has been extended with support for open flags. Currently supported flags are: FS_O_READ -- open for read FS_O_WRITE -- open for write FS_O_CREATE -- create file if it does not exist FS_O_APPEND -- move to the end of file before each write The FAT FS and LittleFS front-ends within the Zephyr has also been modified to utilize the flags. Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
parent
555fc6dbd5
commit
cac07629bf
20 changed files with 130 additions and 45 deletions
|
@ -113,7 +113,7 @@ struct fs_statvfs {
|
|||
/**
|
||||
* @brief File System interface structure
|
||||
*
|
||||
* @param open Opens an existing file or create a new one
|
||||
* @param open Opens or creates a file, depending on flags given
|
||||
* @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
|
||||
|
@ -134,7 +134,8 @@ struct fs_statvfs {
|
|||
*/
|
||||
struct fs_file_system_t {
|
||||
/* File operations */
|
||||
int (*open)(struct fs_file_t *filp, const char *fs_path);
|
||||
int (*open)(struct fs_file_t *filp, const char *fs_path,
|
||||
fs_mode_t flags);
|
||||
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);
|
||||
|
@ -160,6 +161,17 @@ struct fs_file_system_t {
|
|||
struct fs_statvfs *stat);
|
||||
};
|
||||
|
||||
#define FS_O_READ 0x01
|
||||
#define FS_O_WRITE 0x02
|
||||
#define FS_O_RDWR (FS_O_READ | FS_O_WRITE)
|
||||
#define FS_O_MODE_MASK 0x03
|
||||
|
||||
#define FS_O_CREATE 0x10
|
||||
#define FS_O_APPEND 0x20
|
||||
#define FS_O_FLAGS_MASK 0x30
|
||||
|
||||
#define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK)
|
||||
|
||||
#ifndef FS_SEEK_SET
|
||||
#define FS_SEEK_SET 0 /* Seek from beginning of file. */
|
||||
#endif
|
||||
|
@ -170,20 +182,29 @@ struct fs_file_system_t {
|
|||
#define FS_SEEK_END 2 /* Seek from end of file. */
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief File open
|
||||
*
|
||||
* Opens an existing file or create a new one and associates
|
||||
* a stream with it.
|
||||
* Opens or creates, if does not exist, file depending on flags provided
|
||||
* and associates a stream with it.
|
||||
*
|
||||
* @param zfp Pointer to file object
|
||||
* @param file_name The name of file to open
|
||||
* @param flags The mode flags
|
||||
*
|
||||
* @p flags can be empty, or combination of one or more of following flags:
|
||||
* FS_O_READ open for read
|
||||
* FS_O_WRITE open for write
|
||||
* FS_O_RDWR open for read/write (<tt>FS_O_READ | FS_O_WRITE</tt>)
|
||||
* FS_O_CREATE create file if it does not exist
|
||||
* FS_O_APPEND move to end of file before each write
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -ERRNO errno code if error
|
||||
* @retval -EINVAL when bad file name is given
|
||||
* @retval -NOENT when file path is not possible (bad mount point)
|
||||
* @retval other negative error code, depending on file system back-end.
|
||||
*/
|
||||
int fs_open(struct fs_file_t *zfp, const char *file_name);
|
||||
int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags);
|
||||
|
||||
/**
|
||||
* @brief File close
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef ZEPHYR_INCLUDE_FS_FS_INTERFACE_H_
|
||||
#define ZEPHYR_INCLUDE_FS_FS_INTERFACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -24,6 +26,9 @@ extern "C" {
|
|||
#define MAX_FILE_NAME 12
|
||||
#endif /* filesystem selection */
|
||||
|
||||
/* Type for fs_open flags */
|
||||
typedef uint8_t fs_mode_t;
|
||||
|
||||
struct fs_mount_t;
|
||||
|
||||
/**
|
||||
|
@ -35,6 +40,7 @@ struct fs_mount_t;
|
|||
struct fs_file_t {
|
||||
void *filep;
|
||||
const struct fs_mount_t *mp;
|
||||
fs_mode_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,7 +87,7 @@ void main(void)
|
|||
|
||||
struct fs_file_t file;
|
||||
|
||||
rc = fs_open(&file, fname);
|
||||
rc = fs_open(&file, fname, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc < 0) {
|
||||
printk("FAIL: open %s: %d\n", fname, rc);
|
||||
goto out;
|
||||
|
|
|
@ -63,7 +63,25 @@ static int translate_error(int error)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int fatfs_open(struct fs_file_t *zfp, const char *file_name)
|
||||
static uint8_t translate_flags(fs_mode_t flags)
|
||||
{
|
||||
uint8_t fat_mode = 0;
|
||||
|
||||
fat_mode |= (flags & FS_O_READ) ? FA_READ : 0;
|
||||
fat_mode |= (flags & FS_O_WRITE) ? FA_WRITE : 0;
|
||||
fat_mode |= (flags & FS_O_CREATE) ? FA_OPEN_ALWAYS : 0;
|
||||
/* NOTE: FA_APPEND is not translated because FAT FS does not
|
||||
* support append semantics of the Zephyr, where file position
|
||||
* is forwarded to the end before each write, the fatfs_write
|
||||
* will be tasked with setting a file position to the end,
|
||||
* if FA_APPEND flag is present.
|
||||
*/
|
||||
|
||||
return fat_mode;
|
||||
}
|
||||
|
||||
static int fatfs_open(struct fs_file_t *zfp, const char *file_name,
|
||||
fs_mode_t mode)
|
||||
{
|
||||
FRESULT res;
|
||||
uint8_t fs_mode;
|
||||
|
@ -76,7 +94,7 @@ static int fatfs_open(struct fs_file_t *zfp, const char *file_name)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fs_mode = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
|
||||
fs_mode = translate_flags(mode);
|
||||
|
||||
res = f_open(zfp->filep, &file_name[1], fs_mode);
|
||||
|
||||
|
@ -143,10 +161,23 @@ static ssize_t fatfs_read(struct fs_file_t *zfp, 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 = FR_OK;
|
||||
unsigned int bw;
|
||||
off_t pos = f_size((FIL *)zfp->filep);
|
||||
|
||||
/* FA_APPEND flag means that file has been opened for append.
|
||||
* The FAT FS write does not support the POSIX append semantics,
|
||||
* to always write at the end of file, so set file position
|
||||
* at the end before each write if FA_APPEND is set.
|
||||
*/
|
||||
if (zfp->flags & FS_O_APPEND) {
|
||||
res = f_lseek(zfp->filep, pos);
|
||||
}
|
||||
|
||||
if (res == FR_OK) {
|
||||
res = f_write(zfp->filep, ptr, size, &bw);
|
||||
}
|
||||
|
||||
res = f_write(zfp->filep, ptr, size, &bw);
|
||||
if (res != FR_OK) {
|
||||
return translate_error(res);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <errno.h>
|
||||
#include <init.h>
|
||||
#include <fs/fs.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#define LOG_LEVEL CONFIG_FS_LOG_LEVEL
|
||||
|
@ -75,11 +76,14 @@ static int fs_get_mnt_point(struct fs_mount_t **mnt_pntp,
|
|||
}
|
||||
|
||||
/* File operations */
|
||||
int fs_open(struct fs_file_t *zfp, const char *file_name)
|
||||
int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
|
||||
{
|
||||
struct fs_mount_t *mp;
|
||||
int rc = -EINVAL;
|
||||
|
||||
/* COpy flags to zfp for use with other fs_ API calls */
|
||||
zfp->flags = flags;
|
||||
|
||||
if ((file_name == NULL) ||
|
||||
(strlen(file_name) <= 1) || (file_name[0] != '/')) {
|
||||
LOG_ERR("invalid file name!!");
|
||||
|
@ -95,7 +99,7 @@ int fs_open(struct fs_file_t *zfp, const char *file_name)
|
|||
zfp->mp = mp;
|
||||
|
||||
if (zfp->mp->fs->open != NULL) {
|
||||
rc = zfp->mp->fs->open(zfp, file_name);
|
||||
rc = zfp->mp->fs->open(zfp, file_name, flags);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("file open error (%d)", rc);
|
||||
return rc;
|
||||
|
|
|
@ -181,14 +181,29 @@ static void release_file_data(struct fs_file_t *fp)
|
|||
fp->filep = NULL;
|
||||
}
|
||||
|
||||
static int littlefs_open(struct fs_file_t *fp, const char *path)
|
||||
static int lfs_flags_from_zephyr(unsigned int zflags)
|
||||
{
|
||||
int flags = (zflags & FS_O_CREATE) ? LFS_O_CREAT : 0;
|
||||
|
||||
/* LFS_O_READONLY and LFS_O_WRONLY can be selected at the same time,
|
||||
* this is not a mistake, together they create RDWR access.
|
||||
*/
|
||||
flags |= (zflags & FS_O_READ) ? LFS_O_RDONLY : 0;
|
||||
flags |= (zflags & FS_O_WRITE) ? LFS_O_WRONLY : 0;
|
||||
|
||||
flags |= (zflags & FS_O_APPEND) ? LFS_O_APPEND : 0;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int littlefs_open(struct fs_file_t *fp, const char *path,
|
||||
fs_mode_t zflags)
|
||||
{
|
||||
struct fs_littlefs *fs = fp->mp->fs_data;
|
||||
struct lfs *lfs = &fs->lfs;
|
||||
int flags = LFS_O_CREAT | LFS_O_RDWR;
|
||||
int ret;
|
||||
int flags = lfs_flags_from_zephyr(zflags);
|
||||
int ret = k_mem_slab_alloc(&file_data_pool, &fp->filep, K_NO_WAIT);
|
||||
|
||||
ret = k_mem_slab_alloc(&file_data_pool, &fp->filep, K_NO_WAIT);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ static int cmd_trunc(const struct shell *shell, size_t argc, char **argv)
|
|||
length = 0;
|
||||
}
|
||||
|
||||
err = fs_open(&file, path);
|
||||
err = fs_open(&file, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (err) {
|
||||
shell_error(shell, "Failed to open %s (%d)", path, err);
|
||||
return -ENOEXEC;;
|
||||
|
@ -277,7 +277,7 @@ static int cmd_read(const struct shell *shell, size_t argc, char **argv)
|
|||
|
||||
shell_print(shell, "File size: %zd", dirent.size);
|
||||
|
||||
err = fs_open(&file, path);
|
||||
err = fs_open(&file, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (err) {
|
||||
shell_error(shell, "Failed to open %s (%d)", path, err);
|
||||
return -ENOEXEC;
|
||||
|
@ -376,7 +376,7 @@ static int cmd_write(const struct shell *shell, size_t argc, char **argv)
|
|||
arg_offset = 2;
|
||||
}
|
||||
|
||||
err = fs_open(&file, path);
|
||||
err = fs_open(&file, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (err) {
|
||||
shell_error(shell, "Failed to open %s (%d)", path, err);
|
||||
return -ENOEXEC;
|
||||
|
|
|
@ -123,7 +123,7 @@ static int settings_file_load_priv(struct settings_store *cs, line_load_cb cb,
|
|||
|
||||
lines = 0;
|
||||
|
||||
rc = fs_open(&file, cf->cf_name);
|
||||
rc = fs_open(&file, cf->cf_name, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ static int settings_file_create_or_replace(struct fs_file_t *zfp,
|
|||
}
|
||||
}
|
||||
|
||||
return fs_open(zfp, file_name);
|
||||
return fs_open(zfp, file_name, FS_O_CREATE | FS_O_RDWR);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -240,7 +240,7 @@ static int settings_file_save_and_compress(struct settings_file *cf,
|
|||
size_t new_name_len;
|
||||
size_t val1_off;
|
||||
|
||||
if (fs_open(&rf, cf->cf_name) != 0) {
|
||||
if (fs_open(&rf, cf->cf_name, FS_O_CREATE | FS_O_RDWR) != 0) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,7 @@ static int settings_file_save_priv(struct settings_store *cs, const char *name,
|
|||
/*
|
||||
* Open the file to add this one value.
|
||||
*/
|
||||
rc = fs_open(&file, cf->cf_name);
|
||||
rc = fs_open(&file, cf->cf_name, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc == 0) {
|
||||
rc = fs_seek(&file, 0, FS_SEEK_END);
|
||||
if (rc == 0) {
|
||||
|
|
|
@ -35,7 +35,7 @@ static int test_mkdir(void)
|
|||
return res;
|
||||
}
|
||||
|
||||
res = fs_open(&filep, TEST_DIR_FILE);
|
||||
res = fs_open(&filep, TEST_DIR_FILE, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -21,7 +21,7 @@ static int test_file_open(void)
|
|||
}
|
||||
|
||||
/* Verify fs_open() */
|
||||
res = fs_open(&filep, TEST_FILE);
|
||||
res = fs_open(&filep, TEST_FILE, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -26,7 +26,7 @@ static int create_file(const char *path)
|
|||
struct fs_file_t fp;
|
||||
int res = 0;
|
||||
if (!check_file_dir_exists(path)) {
|
||||
res = fs_open(&fp, path);
|
||||
res = fs_open(&fp, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (!res) {
|
||||
res = fs_close(&fp);
|
||||
} else {
|
||||
|
|
|
@ -40,7 +40,7 @@ static int test_mkdir(const char *dir, const char *file)
|
|||
return res;
|
||||
}
|
||||
|
||||
res = fs_open(&filep, file);
|
||||
res = fs_open(&filep, file, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -26,7 +26,7 @@ static int test_file_open(const char *path)
|
|||
}
|
||||
|
||||
/* Verify fs_open() */
|
||||
res = fs_open(&filep, path);
|
||||
res = fs_open(&filep, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -82,7 +82,8 @@ static int create_write_hello(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
HELLO,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"open hello failed");
|
||||
|
||||
|
@ -148,7 +149,8 @@ static int verify_hello(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
HELLO,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"verify hello open failed");
|
||||
|
||||
|
@ -178,7 +180,8 @@ static int seek_within_hello(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
HELLO,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"verify hello open failed");
|
||||
|
||||
|
@ -244,7 +247,8 @@ static int truncate_hello(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
HELLO,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"verify hello open failed");
|
||||
|
||||
|
@ -333,7 +337,8 @@ static int sync_goodbye(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
GOODBYE,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"sync goodbye failed");
|
||||
|
||||
|
@ -395,7 +400,8 @@ static int verify_goodbye(const struct fs_mount_t *mp)
|
|||
zassert_equal(fs_open(&file,
|
||||
testfs_path_init(&path, mp,
|
||||
GOODBYE,
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"verify goodbye failed");
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ static int check_mkdir(struct fs_mount_t *mp)
|
|||
testfs_path_extend(testfs_path_copy(&fpath,
|
||||
&dpath),
|
||||
"file",
|
||||
TESTFS_PATH_END)),
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR),
|
||||
0,
|
||||
"creat in dir failed");
|
||||
zassert_equal(fs_close(&file), 0,
|
||||
|
|
|
@ -77,7 +77,7 @@ static int write_read(const char *tag,
|
|||
TC_PRINT("creating and writing %zu %zu-byte blocks\n",
|
||||
nbuf, buf_size);
|
||||
|
||||
rc = fs_open(&file, path.path);
|
||||
rc = fs_open(&file, path.path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc != 0) {
|
||||
TC_PRINT("Failed to open %s for write: %d\n", path.path, rc);
|
||||
goto out_buf;
|
||||
|
@ -116,7 +116,7 @@ static int write_read(const char *tag,
|
|||
(uint32_t)(total * 1000U / (t1 - t0)),
|
||||
(uint32_t)(total * 1000U / (t1 - t0) / 1024U));
|
||||
|
||||
rc = fs_open(&file, path.path);
|
||||
rc = fs_open(&file, path.path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc != 0) {
|
||||
TC_PRINT("Failed to open %s for write: %d\n", path.path, rc);
|
||||
goto out_buf;
|
||||
|
|
|
@ -235,7 +235,8 @@ int testfs_build(struct testfs_path *root,
|
|||
rc = fs_open(&file,
|
||||
testfs_path_extend(root,
|
||||
cp->name,
|
||||
TESTFS_PATH_END));
|
||||
TESTFS_PATH_END),
|
||||
FS_O_CREATE | FS_O_RDWR);
|
||||
TC_PRINT("create at %s with %u from 0x%02x: %d\n",
|
||||
root->path, cp->size, cp->value, rc);
|
||||
if (rc == 0) {
|
||||
|
@ -295,7 +296,7 @@ static int check_layout_entry(struct testfs_path *pp,
|
|||
if (statp->type == FS_DIR_ENTRY_FILE) {
|
||||
struct fs_file_t file;
|
||||
|
||||
rc = fs_open(&file, pp->path);
|
||||
rc = fs_open(&file, pp->path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc < 0) {
|
||||
TC_PRINT("%s: content check open failed: %d\n",
|
||||
pp->path, rc);
|
||||
|
|
|
@ -39,7 +39,7 @@ int test_mkdir(const char *dir_path, const char *file)
|
|||
return res;
|
||||
}
|
||||
|
||||
res = fs_open(&filep, file_path);
|
||||
res = fs_open(&filep, file_path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -22,7 +22,7 @@ int test_file_open(struct fs_file_t *filep, const char *file_path)
|
|||
}
|
||||
|
||||
/* Verify fs_open() */
|
||||
res = fs_open(filep, file_path);
|
||||
res = fs_open(filep, file_path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (res) {
|
||||
TC_PRINT("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
|
|
|
@ -151,7 +151,7 @@ int fsutil_read_file(const char *path, off_t offset, size_t len, void *dst,
|
|||
int rc;
|
||||
ssize_t r_len = 0;
|
||||
|
||||
rc = fs_open(&file, path);
|
||||
rc = fs_open(&file, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ int fsutil_write_file(const char *path, const void *data, size_t len)
|
|||
struct fs_file_t file;
|
||||
int rc;
|
||||
|
||||
rc = fs_open(&file, path);
|
||||
rc = fs_open(&file, path, FS_O_CREATE | FS_O_RDWR);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue