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:
Ramesh Thomas 2016-06-14 14:01:59 -07:00
commit 9394605211
6 changed files with 494 additions and 0 deletions

View file

@ -0,0 +1,5 @@
KERNEL_TYPE = nano
BOARD ?= qemu_x86
CONF_FILE = prj.conf
include ${ZEPHYR_BASE}/Makefile.inc

View 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)

View file

@ -0,0 +1,3 @@
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_FAT=y
CONFIG_FS_FAT_RAM_DISK=y

View file

@ -0,0 +1 @@
obj-y += main.o

View 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;
}
}

View 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