Re: [RFC] Provide a file system API


Thomas, Ramesh
 

On 07/27/2016 10:03 AM, Mitsis, Peter wrote:
See [Peter]

-----Original Message-----
From: Ramesh Thomas [mailto:ramesh.thomas(a)intel.com]
Sent: July-26-16 9:37 PM
To: devel(a)lists.zephyrproject.org
Subject: [devel] [RFC] Provide a file system API

A file system is necessary to store data reliably and to be accessed in a
consistent and deterministic manner. Example applications are data
logging, media files and file based databases which would need to be
stored for later processing off-line or to be sent over radio in bursts
instead of per sample captured.

Related requirement:
https://jira.zephyrproject.org/browse/ZEP-228

***Proposal***
The Zephyr File System API will follow interfaces similar to stdio and
POSIX so it is familiar to users. However, it does not claim to be
compliant to POSIX or any other specification.

One of the goals is to keep clean separation of the file API layer and the
disk interface. Following diagram illustrates the layer separation:

+--------------------------+
| Zephyr File System API |
+--------------------------+
| Glue layer for FS module |
+--------------------------+
| File System module |
+--------------------------+
| Disk I/O interface |
+--------------------------+
| Storage media interface |
+--------------------------+

The File system module would be an implementation that provides clean
separation between the API layer and disk I/O. A glue layer will abstract
its own interface to that of the Zephyr FS API. The disk i/o interface
will use Zephyr's flash HAL.

***The File System API descriptions follow*** Gerrit link:
https://gerrit.zephyrproject.org/r/#/c/3402/9/include/fs.h

/**
* @brief File open
*
* Opens an existing file or create a new one and associates
* a stream with it.
*
* @param zfp Pointer to file object
* @param file_name The name of file to open
* @param mode Flags indicating open mode
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_open(ZFILE *zfp, const char *file_name, const char *mode);

/**
* @brief File close
*
* Flushes the associated stream and closes
* the file.
*
* @param zfp Pointer to the file object
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_close(ZFILE *zfp);

/**
* @brief File unlink
*
* Deletes the specified file or directory
*
* @param path Path to the file or directory to delete
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_unlink(const char *path);

/**
* @brief File read
*
* Reads items of data of size bytes long.
*
* @param zfp Pointer to the file object
* @param ptr Pointer to the data buffer
* @param size Number of bytes to be read
*
* @return Number of bytes read. On success, it will be equal to number of
* items requested to be read. Returns less than number of bytes
* requested if there are not enough bytes available in file. Will return
* -ERRNO code on error.
*/
ssize_t fs_read(ZFILE *zfp, void *ptr, size_t size);

/**
* @brief File write
*
* Writes items of data of size bytes long.
*
* @param zfp Pointer to the file object
* @param ptr Pointer to the data buffer
* @param size Number of bytes to be write
*
* @return Number of bytes written. On success, it will be equal to number
of
* bytes requested to be written. Will return -ERRNO code on error.
*/
ssize_t fs_write(ZFILE *zfp, void *ptr, size_t size);

/**
* @brief File seek
*
* Moves the file position to a new location in the file. The offset is
added
* to file position based on the 'from' parameter.
*
* @param zfp Pointer to the file object
* @param offset Relative location to move the file pointer to
* @param from Relative location from where offset is to be calculated.
* SEEK_SET = from beginning of file
* SEE_CUR = from current position,
* SEEK_END = from end of file.
*
* @retval 0 Success
* @retval -ERRNO errno code if error.
*/
int fs_seek(ZFILE *zfp, long offset, int from);


/**
* @brief Get current file position.
*
* Retrieves the current position in the file.
*
* @param zfp Pointer to the file object
*
* @retval position Current position in file
* Current revision does not validate the file object.
*/
long fs_tell(ZFILE *zfp);

/**
* @brief Get last error
*
* Retrieves the last error that occurred for the file.
*
* @param zfp Pointer to the file object
*
* @retval 0 if no error had occurred
* @retval -ERRNO errno code if error had occurred.
* Current revision does not validate the file object.
*/
int fs_error(ZFILE *zfp);

/**
* @brief Tests if EOF indicator is set for the file.
*
* Retrieves the EOF status of the file.
*
* @param zfp Pointer to the file object
*
* @retval 0 if not EOF
* @retval Non zero if EOF
* Current revision does not validate the file object.
*/
int fs_eof(ZFILE *zfp);

/**
* @brief Get file size
*
* Retrieves the size of the file.
*
* @param zfp Pointer to the file object
*
* @retval size of the file in bytes
* Current revision does not validate the file object.
*/
long fs_size(ZFILE *zfp);

/**
* @brief File system init
*
* Application calls this to initialize the FS interface. This should
* be the first function the application should call if it will be
* using the file system.
*
* @retval 0 Success
* @retval -ERRNO errno code if error.
*/
int fs_init(void);

/**
* @brief Creates and formats a volume
*
* Formats the storage media with underlying file system. This will
* typically be used by a provisioning tool during build or flashing
* of OS image. The file system configurations will be taken from
* Kconfig settings.
*
* @retval 0 Success
* @retval -ERRNO errno code if error.
*/
int fs_format(void);

/**
* @brief Mounts a volume
*
* Mounts an existing file system. The volume configurations
* are taken from Kconfig settings.
*
* @retval 0 Success
* @retval -ERRNO errno code if error.
*/
int fs_mount(void);

/**
* @brief Directory create
*
* Creates a new directory using specified path.
*
* @param path Path to the directory to create
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_mkdir(const char *path);

/**
* @brief Directory open
*
* Opens an existing directory specified by the path.
*
* @param zdp Pointer to the directory object
* @param path Path to the directory to open
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_opendir(ZDIR *zdp, const char *path);

/**
* @brief Directory read entry
*
* Reads directory entries of a open directory
*
* @param zdp Pointer to the directory object
* @param entry Pointer to dir_entry structure to read the entry into
* struct dir_entry will store following:
* attrib : Whether it is a file or directory
* name : name of file or directory
* size : size of file
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_readdir(ZDIR *zdp, struct dir_entry *entry);
[Peter] - Should we be using a re-entrant version? That is something with a signature more like readdir_r()? (My apologies if this has already been discussed.)
We don't have a non-re-entrant version so we don't need to differentiate
the way stdio needs to. Also we are not strictly following stdio signature.



/**
* @brief Directory close
*
* Closes an open directory.
*
* @param zdp Pointer to the directory object
*
* @retval 0 Success
* @retval -ERRNO errno code if error
*/
int fs_closedir(ZDIR *zdp);
[Peter]
I see the following functionality as missing. Is this intentional?
1. Some method to truncate/grow/shrink a file.
2. Some method to query the FS for stats such number of unused blocks
These functions can be useful and we can add them.

Join {devel@lists.zephyrproject.org to automatically receive all group messages.