fs: Add a sample app to demo Zephyr file system API
Demonstrates the Zephyr file system APIs. This currently runs on FAT FS using RAM emulation of disk. Origin: Original Jira: ZEP-285 ZEP-228 ZEP-481 ZEP-446 Change-Id: If459b8c2f819a2a38c8c4d805ec3f689dfcdef17 Signed-off-by: Ramesh Thomas <ramesh.thomas@intel.com>
This commit is contained in:
parent
e89c739e6f
commit
9394605211
6 changed files with 494 additions and 0 deletions
5
samples/fs/fat_fs/Makefile
Normal file
5
samples/fs/fat_fs/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
KERNEL_TYPE = nano
|
||||
BOARD ?= qemu_x86
|
||||
CONF_FILE = prj.conf
|
||||
|
||||
include ${ZEPHYR_BASE}/Makefile.inc
|
93
samples/fs/fat_fs/README.txt
Normal file
93
samples/fs/fat_fs/README.txt
Normal file
|
@ -0,0 +1,93 @@
|
|||
Title: Zephyr File System Demo
|
||||
|
||||
Description:
|
||||
|
||||
Demonstrates basic file and dir operations using the Zephyr file system.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Building and Running Project:
|
||||
|
||||
While this demo uses RAM to emulate storage, it can be tested using QEMU.
|
||||
|
||||
Following command will build it for running on QEMU:
|
||||
|
||||
make qemu
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
Problems caused by out-dated project information can be addressed by
|
||||
issuing one of the following commands then rebuilding the project:
|
||||
|
||||
make clean # discard results of previous builds
|
||||
# but keep existing configuration info
|
||||
or
|
||||
make pristine # discard results of previous builds
|
||||
# and restore pre-defined configuration info
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Sample Output:
|
||||
|
||||
File System Demo!
|
||||
|
||||
Creating new file testfile.txt
|
||||
Opened file testfile.txt
|
||||
Data successfully written!
|
||||
Data written:"hello world!"
|
||||
|
||||
Data successfully read!
|
||||
Data read:"hello world!"
|
||||
|
||||
Closed file testfile.txt
|
||||
File (testfile.txt) deleted successfully!
|
||||
Created dir sub1!
|
||||
Created dir sub2!
|
||||
Created dir sub1/sub3!
|
||||
Creating new file testfile.txt
|
||||
Opened file testfile.txt
|
||||
Creating new file sub1/testfile.txt
|
||||
Opened file sub1/testfile.txt
|
||||
Creating new file sub2/testfile.txt
|
||||
Opened file sub2/testfile.txt
|
||||
Creating new file sub1/sub3/file1.txt
|
||||
Opened file sub1/sub3/file1.txt
|
||||
Creating new file sub1/sub3/file2.txt
|
||||
Opened file sub1/sub3/file2.txt
|
||||
Data successfully written!
|
||||
Data written:"1"
|
||||
|
||||
Data successfully written!
|
||||
Data written:"12"
|
||||
|
||||
Data successfully written!
|
||||
Data written:"123"
|
||||
|
||||
Data successfully written!
|
||||
Data written:"1234"
|
||||
|
||||
Data successfully written!
|
||||
Data written:"12345"
|
||||
|
||||
Closed file testfile.txt
|
||||
Closed file sub1/testfile.txt
|
||||
Closed file sub2/testfile.txt
|
||||
Closed file sub1/sub3/file1.txt
|
||||
Closed file sub1/sub3/file2.txt
|
||||
|
||||
Listing dir /:
|
||||
[DIR ] SUB1
|
||||
[DIR ] SUB2
|
||||
[FILE] TESTFILE.TXT (size = 1)
|
||||
|
||||
Listing dir sub1:
|
||||
[DIR ] SUB3
|
||||
[FILE] TESTFILE.TXT (size = 2)
|
||||
|
||||
Listing dir sub2:
|
||||
[FILE] TESTFILE.TXT (size = 3)
|
||||
|
||||
Listing dir sub1/sub3:
|
||||
[FILE] FILE1.TXT (size = 4)
|
||||
[FILE] FILE2.TXT (size = 5)
|
3
samples/fs/fat_fs/prj.conf
Normal file
3
samples/fs/fat_fs/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_FILE_SYSTEM=y
|
||||
CONFIG_FILE_SYSTEM_FAT=y
|
||||
CONFIG_FS_FAT_RAM_DISK=y
|
1
samples/fs/fat_fs/src/Makefile
Normal file
1
samples/fs/fat_fs/src/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
obj-y += main.o
|
379
samples/fs/fat_fs/src/main.c
Normal file
379
samples/fs/fat_fs/src/main.c
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <misc/printk.h>
|
||||
#include <fs.h>
|
||||
|
||||
static void file_tests(void);
|
||||
static void dir_tests(void);
|
||||
|
||||
#define TEST_SUB_DIR "sub1"
|
||||
#define TEST_FILE "testfile.txt"
|
||||
|
||||
/*
|
||||
* @file
|
||||
* @brief File system demo
|
||||
* Demonstrates the ZEPHYR File System APIs
|
||||
*/
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printk("File System Demo!\n\n");
|
||||
|
||||
file_tests();
|
||||
dir_tests();
|
||||
}
|
||||
|
||||
static int check_file_dir_exists(const char *path)
|
||||
{
|
||||
int res;
|
||||
struct zfs_dirent entry;
|
||||
|
||||
res = fs_stat(path, &entry);
|
||||
|
||||
return !res;
|
||||
}
|
||||
|
||||
static int open_file(ZFILE *fp, const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (check_file_dir_exists(path)) {
|
||||
printk("Opening existing file %s\n", path);
|
||||
} else {
|
||||
printk("Creating new file %s\n", path);
|
||||
}
|
||||
|
||||
res = fs_open(fp, path);
|
||||
if (res) {
|
||||
printk("Failed opening file [%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("Opened file %s\n", path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const char test_str[] = "hello world!";
|
||||
|
||||
static int write_test(ZFILE *fp, off_t ofs, const char *str)
|
||||
{
|
||||
ssize_t brw;
|
||||
int res;
|
||||
|
||||
res = fs_seek(fp, ofs, SEEK_SET);
|
||||
if (res) {
|
||||
printk("fs_seek failed [%d]\n", res);
|
||||
fs_close(fp);
|
||||
return res;
|
||||
}
|
||||
|
||||
brw = fs_write(fp, (char *)str, strlen(str));
|
||||
if (brw < 0) {
|
||||
printk("Failed writing to file [%d]\n", brw);
|
||||
fs_close(fp);
|
||||
return brw;
|
||||
}
|
||||
if (brw < strlen(str)) {
|
||||
printk("Unable to complete write. Volume full.\n");
|
||||
printk("Number of bytes written: [%d]\n", brw);
|
||||
fs_close(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk("Data successfully written!\n");
|
||||
printk("Data written:\"%s\"\n\n", str);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int read_test(ZFILE *fp, off_t ofs, size_t sz, char *read_buff)
|
||||
{
|
||||
ssize_t brw;
|
||||
int res;
|
||||
|
||||
res = fs_seek(fp, ofs, SEEK_SET);
|
||||
if (res) {
|
||||
printk("fs_seek failed [%d]\n", res);
|
||||
fs_close(fp);
|
||||
return res;
|
||||
}
|
||||
|
||||
brw = fs_read(fp, read_buff, sz);
|
||||
if (brw < 0) {
|
||||
printk("Failed reading file [%d]\n", brw);
|
||||
fs_close(fp);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("Data successfully read!\n");
|
||||
read_buff[brw] = 0;
|
||||
printk("Data read:\"%s\"\n\n", read_buff);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int close_file(ZFILE *fp, const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = fs_close(fp);
|
||||
if (res) {
|
||||
printk("Error closing file [%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("Closed file %s\n", path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int delete_test(const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Delete the file and verify checking its status */
|
||||
res = fs_unlink(path);
|
||||
if (res) {
|
||||
printk("Error deleting file [%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Check if file was deleted */
|
||||
if (check_file_dir_exists(path)) {
|
||||
printk("Failed deleting %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk("File (%s) deleted successfully!\n", path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void file_tests(void)
|
||||
{
|
||||
ZFILE fp;
|
||||
int res;
|
||||
char read_buff[80];
|
||||
|
||||
res = open_file(&fp, TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = write_test(&fp, 0, test_str);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = read_test(&fp, 0, strlen(test_str), read_buff);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(test_str, read_buff)) {
|
||||
printk("Error - Data read does not match data written\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Data read matches data written!\n");
|
||||
|
||||
res = close_file(&fp, TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = delete_test(TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int create_dir(const char *path)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = fs_mkdir(path);
|
||||
if (res) {
|
||||
printk("Error creating dir[%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("Created dir %s!\n", path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Deletes files and sub directories one level deep */
|
||||
static int remove_dir(const char *path)
|
||||
{
|
||||
int res;
|
||||
ZDIR dp;
|
||||
static struct zfs_dirent entry;
|
||||
char file_path[80];
|
||||
|
||||
if (!check_file_dir_exists(path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = fs_opendir(&dp, path);
|
||||
if (res) {
|
||||
printk("Error opening dir[%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("\nRemoving files and sub directories in %s\n", path);
|
||||
for (;;) {
|
||||
res = fs_readdir(&dp, &entry);
|
||||
|
||||
/* entry.name[0] == 0 means end-of-dir */
|
||||
if (res || entry.name[0] == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Delete file or sub directory */
|
||||
|
||||
sprintf(file_path, "%s/%s", path, entry.name);
|
||||
printk("Removing %s\n", file_path);
|
||||
|
||||
res = fs_unlink(file_path);
|
||||
if (res) {
|
||||
printk("Error deleting file/dir [%d]\n", res);
|
||||
fs_closedir(&dp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
fs_closedir(&dp);
|
||||
|
||||
/* Remove the sub directory */
|
||||
res = fs_unlink(path);
|
||||
if (res) {
|
||||
printk("Error removing dir [%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("Removed dir %s!\n", path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int list_dir(const char *path)
|
||||
{
|
||||
int res;
|
||||
ZDIR dp;
|
||||
static struct zfs_dirent entry;
|
||||
|
||||
res = fs_opendir(&dp, path);
|
||||
if (res) {
|
||||
printk("Error opening dir[%d]\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk("\nListing dir %s:\n", path);
|
||||
for (;;) {
|
||||
res = fs_readdir(&dp, &entry);
|
||||
|
||||
/* entry.name[0] == 0 means end-of-dir */
|
||||
if (res || entry.name[0] == 0) {
|
||||
break;
|
||||
}
|
||||
if (entry.type == DIR_ENTRY_DIR) {
|
||||
printk("[DIR ] %s\n", entry.name);
|
||||
} else {
|
||||
printk("[FILE] %s (size = %d)\n",
|
||||
entry.name, entry.size);
|
||||
}
|
||||
}
|
||||
|
||||
fs_closedir(&dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dir_tests(void)
|
||||
{
|
||||
ZFILE fp[2];
|
||||
int res;
|
||||
|
||||
/* Remove sub dir if already exists */
|
||||
res = remove_dir(TEST_SUB_DIR);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a sub directory */
|
||||
res = create_dir(TEST_SUB_DIR);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Open or create files */
|
||||
|
||||
res = open_file(&fp[0], TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = open_file(&fp[1], TEST_SUB_DIR "/" TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write to files to check size info */
|
||||
res = write_test(&fp[0], 0, "1");
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = write_test(&fp[1], 0, "12");
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close the files in the directories */
|
||||
|
||||
res = close_file(&fp[0], TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = close_file(&fp[1], TEST_SUB_DIR "/" TEST_FILE);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* List the files in root and sub dir */
|
||||
res = list_dir("/");
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = list_dir(TEST_SUB_DIR);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove sub dir */
|
||||
res = remove_dir(TEST_SUB_DIR);
|
||||
if (res) {
|
||||
return;
|
||||
}
|
||||
}
|
13
samples/fs/fat_fs/testcase.ini
Normal file
13
samples/fs/fat_fs/testcase.ini
Normal file
|
@ -0,0 +1,13 @@
|
|||
[test-nano]
|
||||
tags = fs
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
||||
platform_whitelist = qemu_x86
|
||||
kernel = nano
|
||||
|
||||
[test-micro]
|
||||
tags = fs
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
||||
platform_whitelist = qemu_x86
|
||||
kernel = micro
|
Loading…
Add table
Add a link
Reference in a new issue