/* * Copyright (c) 2016 Intel Corporation. * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_FS_FS_H_ #define ZEPHYR_INCLUDE_FS_FS_H_ #ifdef CONFIG_ARCH_POSIX #ifndef __ssize_t_defined typedef __SIZE_TYPE__ ssize_t; #define __ssize_t_defined #endif #ifndef __off_t_defined #ifndef __USE_FILE_OFFSET64 typedef long int off_t; #else typedef long long int off_t; #endif #define __off_t_defined #endif #else #include #endif #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief File System APIs * @defgroup file_system_api File System APIs * @{ */ struct fs_file_system_t; enum fs_dir_entry_type { /** Identifier for file entry */ FS_DIR_ENTRY_FILE = 0, /** Identifier for directory entry */ FS_DIR_ENTRY_DIR }; /** @brief Enumeration to uniquely identify file system types. * * Zephyr supports in-tree file systems and external ones. Each * requires a unique identifier used to register the file system * implementation and to associate a mount point with the file system * type. This anonymous enum defines global identifiers for the * in-tree file systems. * * External file systems should be registered using unique identifiers * starting at @c FS_TYPE_EXTERNAL_BASE. It is the responsibility of * applications that use external file systems to ensure that these * identifiers are unique if multiple file system implementations are * used by the application. */ enum { /** Identifier for in-tree FatFS file system. */ FS_FATFS = 0, /** Identifier for in-tree LittleFS file system. */ FS_LITTLEFS, /** Base identifier for external file systems. */ FS_TYPE_EXTERNAL_BASE, }; /** Flag prevents formatting device if requested file system not found */ #define FS_MOUNT_FLAG_NO_FORMAT BIT(0) /** Flag makes mounted file system read-only */ #define FS_MOUNT_FLAG_READ_ONLY BIT(1) /** Flag used in pre-defined mount structures that are to be mounted * on startup. * * This flag has no impact in user-defined mount structures. */ #define FS_MOUNT_FLAG_AUTOMOUNT BIT(2) /** * @brief File system mount info structure * * @param node Entry for the fs_mount_list list * @param type File system type * @param mnt_point Mount point directory name (ex: "/fatfs") * @param fs_data Pointer to file system specific data * @param storage_dev Pointer to backend storage device * @param mountp_len Length of Mount point string * @param fs Pointer to File system interface of the mount point * @param flags Mount flags */ struct fs_mount_t { sys_dnode_t node; int type; const char *mnt_point; void *fs_data; void *storage_dev; /* fields filled by file system core */ size_t mountp_len; const struct fs_file_system_t *fs; uint8_t flags; }; /** * @brief Structure to receive file or directory information * * Used in functions that reads the directory entries to get * file or directory information. * * @param dir_entry_type Whether file or directory * - FS_DIR_ENTRY_FILE * - FS_DIR_ENTRY_DIR * @param name Name of directory or file * @param size Size of file. 0 if directory */ struct fs_dirent { enum fs_dir_entry_type type; char name[MAX_FILE_NAME + 1]; size_t size; }; /** * @brief Structure to receive volume statistics * * Used to retrieve information about total and available space * in the volume. * * @param f_bsize Optimal transfer block size * @param f_frsize Allocation unit size * @param f_blocks Size of FS in f_frsize units * @param f_bfree Number of free blocks */ struct fs_statvfs { unsigned long f_bsize; unsigned long f_frsize; unsigned long f_blocks; unsigned long f_bfree; }; /** * @name fs_open open and creation mode flags * @{ */ /** Open for read flag */ #define FS_O_READ 0x01 /** Open for write flag */ #define FS_O_WRITE 0x02 /** Open for read-write flag combination */ #define FS_O_RDWR (FS_O_READ | FS_O_WRITE) /** Bitmask for read and write flags */ #define FS_O_MODE_MASK 0x03 /** Create file if it does not exist */ #define FS_O_CREATE 0x10 /** Open/create file for append */ #define FS_O_APPEND 0x20 /** Bitmask for open/create flags */ #define FS_O_FLAGS_MASK 0x30 /** Bitmask for open flags */ #define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK) /** * @} */ /** * @name fs_seek whence parameter values * @{ */ #ifndef FS_SEEK_SET /** Seek from the beginning of file */ #define FS_SEEK_SET 0 #endif #ifndef FS_SEEK_CUR /** Seek from a current position */ #define FS_SEEK_CUR 1 #endif #ifndef FS_SEEK_END /** Seek from the end of file */ #define FS_SEEK_END 2 #endif /** * @} */ /* * @brief Get the common mount flags for an fstab entry. * @param node_id the node identifier for a child entry in a * zephyr,fstab node. * @return a value suitable for initializing an fs_mount_t flags * member. */ #define FSTAB_ENTRY_DT_MOUNT_FLAGS(node_id) \ ((DT_PROP(node_id, automount) ? FS_MOUNT_FLAG_AUTOMOUNT : 0) \ | (DT_PROP(node_id, read_only) ? FS_MOUNT_FLAG_READ_ONLY : 0) \ | (DT_PROP(node_id, no_format) ? FS_MOUNT_FLAG_NO_FORMAT : 0)) /** * @brief The name under which a zephyr,fstab entry mount structure is * defined. */ #define FS_FSTAB_ENTRY(node_id) _CONCAT(z_fsmp_, node_id) /** * @brief Generate a declaration for the externally defined fstab * entry. * * This will evaluate to the name of a struct fs_mount_t object. */ #define FS_FSTAB_DECLARE_ENTRY(node_id) \ extern struct fs_mount_t FS_FSTAB_ENTRY(node_id) /** * @brief Initialize fs_file_t object * * Initializes the fs_file_t object; the function needs to be invoked * on object before first use with fs_open. * * @param zfp Pointer to file object * */ static inline void fs_file_t_init(struct fs_file_t *zfp) { *zfp = (struct fs_file_t){ 0 }; } /** * @brief Initialize fs_dir_t object * * Initializes the fs_dir_t object; the function needs to be invoked * on object before first use with fs_opendir. * * @param zdp Pointer to file object * */ static inline void fs_dir_t_init(struct fs_dir_t *zdp) { *zdp = (struct fs_dir_t){ 0 }; } /** * @brief Open or create file * * Opens or possibly creates a file and associates a stream with it. * * @details * @p flags can be 0 or a binary combination of one or more of the following * identifiers: * - @c FS_O_READ open for read * - @c FS_O_WRITE open for write * - @c FS_O_RDWR open for read/write (FS_O_READ | FS_O_WRITE) * - @c FS_O_CREATE create file if it does not exist * - @c FS_O_APPEND move to end of file before each write * * If @p flags are set to 0 the function will attempt to open an existing file * with no read/write access; this may be used to e.g. check if the file exists. * * @param zfp Pointer to a file object * @param file_name The name of a file to open * @param flags The mode flags * * @retval 0 on success; * @retval -EINVAL when a bad file name is given; * @retval -EROFS when opening read-only file for write, or attempting to * create a file on a system that has been mounted with the * FS_MOUNT_FLAG_READ_ONLY flag; * @retval -ENOENT when the file path is not possible (bad mount point); * @retval <0 an other negative errno code, depending on a file system back-end. */ int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags); /** * @brief Close file * * Flushes the associated stream and closes the file. * * @param zfp Pointer to the file object * * @retval 0 on success; * @retval <0 a negative errno code on error. */ int fs_close(struct fs_file_t *zfp); /** * @brief Unlink file * * Deletes the specified file or directory * * @param path Path to the file or directory to delete * * @retval 0 on success; * @retval -EROFS if file is read-only, or when file system has been mounted * with the FS_MOUNT_FLAG_READ_ONLY flag; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_unlink(const char *path); /** * @brief Rename file or directory * * Performs a rename and / or move of the specified source path to the * specified destination. The source path can refer to either a file or a * directory. All intermediate directories in the destination path must * already exist. If the source path refers to a file, the destination path * must contain a full filename path, rather than just the new parent * directory. If an object already exists at the specified destination path, * this function causes it to be unlinked prior to the rename (i.e., the * destination gets clobbered). * @note Current implementation does not allow moving files between mount * points. * * @param from The source path * @param to The destination path * * @retval 0 on success; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_rename(const char *from, const char *to); /** * @brief Read file * * Reads up to @p size bytes of data to @p ptr pointed buffer, returns number * of bytes read. A returned value may be lower than @p size if there were * fewer bytes available than requested. * * @param zfp Pointer to the file object * @param ptr Pointer to the data buffer * @param size Number of bytes to be read * * @retval >=0 a number of bytes read, on success; * @retval <0 a negative errno code on error. */ ssize_t fs_read(struct fs_file_t *zfp, void *ptr, size_t size); /** * @brief Write file * * Attempts to write @p size number of bytes to the specified file. * If a negative value is returned from the function, the file pointer has not * been advanced. * If the function returns a non-negative number that is lower than @p size, * the global @c errno variable should be checked for an error code, * as the device may have no free space for data. * * @param zfp Pointer to the file object * @param ptr Pointer to the data buffer * @param size Number of bytes to be written * * @retval >=0 a number of bytes written, on success; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on error. */ ssize_t fs_write(struct fs_file_t *zfp, const void *ptr, size_t size); /** * @brief Seek file * * Moves the file position to a new location in the file. The @p offset is added * to file position based on the @p whence parameter. * * @param zfp Pointer to the file object * @param offset Relative location to move the file pointer to * @param whence Relative location from where offset is to be calculated. * - @c FS_SEEK_SET for the beginning of the file; * - @c FS_SEEK_CUR for the current position; * - @c FS_SEEK_END for the end of the file. * * @retval 0 on success; * @retval -ENOTSUP if not supported by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_seek(struct fs_file_t *zfp, off_t offset, int whence); /** * @brief Get current file position. * * Retrieves and returns the current position in the file stream. * * @param zfp Pointer to the file object * * @retval >= 0 a current position in file; * @retval -ENOTSUP if not supported by underlying file system driver; * @retval <0 an other negative errno code on error. * * The current revision does not validate the file object. */ off_t fs_tell(struct fs_file_t *zfp); /** * @brief Truncate or extend an open file to a given size * * Truncates the file to the new length if it is shorter than the current * size of the file. Expands the file if the new length is greater than the * current size of the file. The expanded region would be filled with zeroes. * * @note In the case of expansion, if the volume got full during the * expansion process, the function will expand to the maximum possible length * and return success. Caller should check if the expanded size matches the * requested length. * * @param zfp Pointer to the file object * @param length New size of the file in bytes * * @retval 0 on success; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_truncate(struct fs_file_t *zfp, off_t length); /** * @brief Flush cached write data buffers of an open file * * The function flushes the cache of an open file; it can be invoked to ensure * data gets written to the storage media immediately, e.g. to avoid data loss * in case if power is removed unexpectedly. * @note Closing a file will cause caches to be flushed correctly so the * function need not be called when the file is being closed. * * @param zfp Pointer to the file object * * @retval 0 on success; * @retval <0 a negative errno code on error. */ int fs_sync(struct fs_file_t *zfp); /** * @brief Directory create * * Creates a new directory using specified path. * * @param path Path to the directory to create * * @retval 0 on success; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on 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 on success; * @retval <0 a negative errno code on error. */ int fs_opendir(struct fs_dir_t *zdp, const char *path); /** * @brief Directory read entry * * Reads directory entries of an open directory. In end-of-dir condition, * the function will return 0 and set the entry->name[0] to 0. * * @note: Most existing underlying file systems do not generate POSIX * special directory entries "." or "..". For consistency the * abstraction layer will remove these from lower layer results so * higher layers see consistent results. * * @param zdp Pointer to the directory object * @param entry Pointer to zfs_dirent structure to read the entry into * * @retval 0 on success or end-of-dir;; * @retval <0 a negative errno code on error. */ int fs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry); /** * @brief Directory close * * Closes an open directory. * * @param zdp Pointer to the directory object * * @retval 0 on success; * @retval <0 a negative errno code on error. */ int fs_closedir(struct fs_dir_t *zdp); /** * @brief Mount filesystem * * Perform steps needed for mounting a file system like * calling the file system specific mount function and adding * the mount point to mounted file system list. * * @note Current implementation of ELM FAT driver allows only following mount * points: "/RAM:","/NAND:","/CF:","/SD:","/SD2:","/USB:","/USB2:","/USB3:" * or mount points that consist of single digit, e.g: "/0:", "/1:" and so forth. * * @param mp Pointer to the fs_mount_t structure. Referenced object * is not changed if the mount operation failed. * A reference is captured in the fs infrastructure if the * mount operation succeeds, and the application must not * mutate the structure contents until fs_unmount is * successfully invoked on the same pointer. * * @retval 0 on success; * @retval -ENOENT when file system type has not been registered; * @retval -ENOTSUP when not supported by underlying file system driver; * @retval -EROFS if system requires formatting but @c FS_MOUNT_FLAG_READ_ONLY * has been set; * @retval <0 an other negative errno code on error. */ int fs_mount(struct fs_mount_t *mp); /** * @brief Unmount filesystem * * Perform steps needed to unmount a file system like * calling the file system specific unmount function and removing * the mount point from mounted file system list. * * @param mp Pointer to the fs_mount_t structure * * @retval 0 on success; * @retval -EINVAL if no system has been mounted at given mount point; * @retval -ENOTSUP when not supported by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_unmount(struct fs_mount_t *mp); /** * @brief Get path of mount point at index * * This function iterates through the list of mount points and returns * the directory name of the mount point at the given @p index. * On success @p index is incremented and @p name is set to the mount directory * name. If a mount point with the given @p index does not exist, @p name will * be set to @c NULL. * * @param index Pointer to mount point index * @param name Pointer to pointer to path name * * @retval 0 on success; * @retval -ENOENT if there is no mount point with given index. */ int fs_readmount(int *index, const char **name); /** * @brief File or directory status * * Checks the status of a file or directory specified by the @p path. * @note The file on a storage device may not be updated until it is closed. * * @param path Path to the file or directory * @param entry Pointer to the zfs_dirent structure to fill if the file or * directory exists. * * @retval 0 on success; * @retval <0 negative errno code on error. */ int fs_stat(const char *path, struct fs_dirent *entry); /** * @brief Retrieves statistics of the file system volume * * Returns the total and available space in the file system volume. * * @param path Path to the mounted directory * @param stat Pointer to the zfs_statvfs structure to receive the fs * statistics * * @retval 0 on success; * @retval -ENOTSUP when not implemented by underlying file system driver; * @retval <0 an other negative errno code on error. */ int fs_statvfs(const char *path, struct fs_statvfs *stat); /** * @brief Register a file system * * Register file system with virtual file system. * * @param type Type of file system (ex: @c FS_FATFS) * @param fs Pointer to File system * * @retval 0 on success; * @retval <0 negative errno code on error. */ int fs_register(int type, const struct fs_file_system_t *fs); /** * @brief Unregister a file system * * Unregister file system from virtual file system. * * @param type Type of file system (ex: @c FS_FATFS) * @param fs Pointer to File system * * @retval 0 on success; * @retval <0 negative errno code on error. */ int fs_unregister(int type, const struct fs_file_system_t *fs); /** * @} */ #ifdef __cplusplus } #endif #endif /* ZEPHYR_INCLUDE_FS_FS_H_ */