| /* |
| * Copyright (c) 2020 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/types.h> |
| #include <errno.h> |
| #include <zephyr/init.h> |
| #include <zephyr/fs/fs.h> |
| #include <zephyr/fs/fs_sys.h> |
| #include <zephyr/sys/__assert.h> |
| #include "test_fs.h" |
| |
| #define BUF_LEN 128 |
| static char buffer[BUF_LEN]; |
| static char *read_pos = buffer; |
| static char *cur = buffer; |
| static int file_length; |
| static struct fs_mount_t *mp[FS_TYPE_EXTERNAL_BASE]; |
| static bool nospace; |
| static int opendir_result; |
| |
| static |
| int temp_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags) |
| { |
| if (zfp == NULL || file_name == NULL) { |
| return -EINVAL; |
| } |
| |
| if (zfp->filep) { |
| if (strcmp(zfp->filep, file_name) == 0) { |
| /* file has been opened */ |
| return -EEXIST; |
| } |
| } |
| |
| if (!(flags & FS_O_MASK)) { |
| return -EINVAL; |
| } |
| |
| zfp->filep = (char *)file_name; |
| return 0; |
| } |
| |
| static int temp_close(struct fs_file_t *zfp) |
| { |
| if (zfp == NULL) { |
| return -EINVAL; |
| } |
| |
| if (zfp->filep) { |
| zfp->filep = NULL; |
| } else { |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| static int temp_unlink(struct fs_mount_t *mountp, const char *path) |
| { |
| if (mountp == NULL || path == NULL) { |
| return -EINVAL; |
| } |
| |
| if (strcmp(mountp->mnt_point, path) == 0) { |
| return -EPERM; |
| } |
| return 0; |
| } |
| |
| static int temp_rename(struct fs_mount_t *mountp, const char *from, |
| const char *to) |
| { |
| if (mountp == NULL || from == NULL || to == NULL) { |
| return -EINVAL; |
| } |
| |
| if (strcmp(to, TEST_FILE_EX) == 0) { |
| return -EINVAL; |
| } |
| return 0; |
| } |
| |
| static ssize_t temp_read(struct fs_file_t *zfp, void *ptr, size_t size) |
| { |
| unsigned int br; |
| |
| if (zfp == NULL || ptr == NULL) { |
| return -EINVAL; |
| } |
| |
| br = size; |
| if (read_pos - buffer + br > file_length) { |
| br = file_length - (read_pos - buffer); |
| } |
| memcpy(ptr, read_pos, br); |
| read_pos += br; |
| cur = read_pos; |
| |
| return br; |
| } |
| |
| static ssize_t temp_write(struct fs_file_t *zfp, const void *ptr, size_t size) |
| { |
| unsigned int bw; |
| |
| if (zfp == NULL || ptr == NULL) { |
| return -EINVAL; |
| } |
| |
| if (nospace) { |
| return -ENOSPC; |
| } |
| |
| bw = size; |
| if (file_length + bw > BUF_LEN) { |
| bw = BUF_LEN - file_length; |
| nospace = true; |
| } |
| |
| memcpy(buffer + file_length, ptr, bw); |
| file_length += bw; |
| cur = buffer + file_length; |
| |
| return bw; |
| } |
| |
| static int temp_seek(struct fs_file_t *zfp, off_t offset, int whence) |
| { |
| |
| if (!zfp) { |
| return -EINVAL; |
| } |
| |
| switch (whence) { |
| case FS_SEEK_SET: |
| cur = buffer + offset; |
| break; |
| case FS_SEEK_CUR: |
| cur += offset; |
| break; |
| case FS_SEEK_END: |
| cur = buffer + file_length + offset; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| if ((cur < buffer) || (cur > buffer + file_length)) { |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static off_t temp_tell(struct fs_file_t *zfp) |
| { |
| if (!zfp) { |
| return -EINVAL; |
| } |
| |
| if (nospace) { |
| return -ENOSPC; |
| } |
| |
| return cur - buffer; |
| } |
| |
| static int temp_truncate(struct fs_file_t *zfp, off_t length) |
| { |
| if (!zfp) { |
| return -EINVAL; |
| } |
| |
| if (length > BUF_LEN) { |
| return -EINVAL; |
| } |
| file_length = length; |
| return 0; |
| } |
| |
| static int temp_sync(struct fs_file_t *zfp) |
| { |
| if (!zfp) { |
| return -EINVAL; |
| } |
| |
| if (nospace) { |
| return -ENOSPC; |
| } |
| |
| return 0; |
| } |
| |
| static int temp_mkdir(struct fs_mount_t *mountp, const char *path) |
| { |
| if (mountp == NULL || path == NULL) { |
| return -EINVAL; |
| } |
| |
| if (strcmp(mountp->mnt_point, path) == 0) { |
| return -EPERM; |
| } |
| return 0; |
| } |
| |
| void mock_opendir_result(int ret) |
| { |
| opendir_result = ret; |
| } |
| |
| static int temp_opendir(struct fs_dir_t *zdp, const char *path) |
| { |
| if (zdp == NULL || path == NULL) { |
| return -EINVAL; |
| } |
| |
| if (opendir_result) { |
| return opendir_result; |
| } |
| |
| zdp->dirp = (char *)path; |
| return 0; |
| } |
| |
| static int i; |
| static int temp_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry) |
| { |
| if (!zdp) { |
| return -EINVAL; |
| } |
| |
| if (!entry) { |
| return -ENOENT; |
| } |
| |
| switch (i) { |
| case 0: |
| strcpy(entry->name, "."); |
| entry->type = FS_DIR_ENTRY_DIR; |
| i++; |
| break; |
| case 1: |
| strcpy(entry->name, "testdir"); |
| entry->type = FS_DIR_ENTRY_DIR; |
| i++; |
| break; |
| case 2: |
| strcpy(entry->name, "test.txt"); |
| entry->type = FS_DIR_ENTRY_FILE; |
| i++; |
| break; |
| case 3: |
| strcpy(entry->name, ".."); |
| entry->type = FS_DIR_ENTRY_DIR; |
| i++; |
| break; |
| default: |
| strcpy(entry->name, "\0"); |
| i = 0; |
| break; |
| } |
| return 0; |
| } |
| |
| static int temp_closedir(struct fs_dir_t *zdp) |
| { |
| if (!zdp) { |
| return -EINVAL; |
| } |
| |
| if (!(zdp->dirp)) { |
| return -EIO; |
| } |
| zdp->dirp = NULL; |
| return 0; |
| } |
| |
| static int temp_stat(struct fs_mount_t *mountp, |
| const char *path, struct fs_dirent *entry) |
| { |
| if (mountp == NULL || path == NULL || entry == NULL) { |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| static int temp_statvfs(struct fs_mount_t *mountp, |
| const char *path, struct fs_statvfs *stat) |
| { |
| if (mountp == NULL || path == NULL || stat == NULL) { |
| return -EINVAL; |
| } |
| |
| memset(stat, 0, sizeof(struct fs_statvfs)); |
| stat->f_bsize = 512; |
| return 0; |
| } |
| |
| static int temp_mount(struct fs_mount_t *mountp) |
| { |
| if (mountp == NULL) { |
| return -EINVAL; |
| } |
| |
| size_t len = strlen(mountp->mnt_point); |
| |
| if (mountp->mnt_point[len - 1] != ':') { |
| return -EINVAL; |
| } |
| mp[mountp->type] = mountp; |
| return 0; |
| } |
| |
| static int temp_unmount(struct fs_mount_t *mountp) |
| { |
| if (mountp == NULL) { |
| return -EINVAL; |
| } |
| |
| if (mp[mountp->type] == NULL) { |
| return -EINVAL; |
| } |
| mp[mountp->type] = NULL; |
| return 0; |
| } |
| |
| /* File system interface */ |
| struct fs_file_system_t temp_fs = { |
| .open = temp_open, |
| .close = temp_close, |
| .read = temp_read, |
| .write = temp_write, |
| .lseek = temp_seek, |
| .tell = temp_tell, |
| .truncate = temp_truncate, |
| .sync = temp_sync, |
| .opendir = temp_opendir, |
| .readdir = temp_readdir, |
| .closedir = temp_closedir, |
| .mount = temp_mount, |
| .unmount = temp_unmount, |
| .unlink = temp_unlink, |
| .rename = temp_rename, |
| .mkdir = temp_mkdir, |
| .stat = temp_stat, |
| .statvfs = temp_statvfs, |
| }; |