/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). * All rights reserved. * * This software is supplied "AS IS" without any warranties. * RDA assumes no responsibility or liability for the use of the software, * conveys no license or title under any patent, copyright, or mask work * right to the product. RDA reserves the right to make changes in the * software without notification. RDA also make no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. */ #ifndef __SFFS_H__ #define __SFFS_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct blockDevice; /** * opaque data structure of SFFS */ typedef struct sffsFs sffsFs_t; /** * create a SFFS instance * * @param pdev pointer of block device * @param block_cache_count block cache count * @param read_only whether to mount as read-only * @return * - SFFS pointer on success * - NULL on failure, typical failure is root block mismatch */ sffsFs_t *sffsMount(struct blockDevice *pdev, size_t block_cache_count, bool read_only); /** * delete the SFFS instance * * @param fs SFFS pointer * @return * - 0 on success */ int sffsUnmount(sffsFs_t *fs); /** * remount SFFS with flags * * The only supported flag is \a MS_RDONLY. * * @param fs SFFS pointer * @param flags remount flags * @return * - 0 for success */ int sffsRemount(sffsFs_t *fs, unsigned flags); /** * format SFFS on block device * * @param pdev block device pointer * @return * - 0 for success * - -EINVAL: invalid parameter * - -ENOMEM: out of memory */ int sffsMakeFs(struct blockDevice *pdev); /** * refer to open(2) * * It is permitted to open one file multiple times. * * It is not supported to open an existed directory. * * @param fs SFFS pointer * @param path path in file system * @param mode open mode (O_CREAT, O_ACCMODE, O_TRUNC) * @return * - file descriptor on success * - -ENOENT: not exist, and without O_CREAT * - -EROFS: create on read-only file system * - -ENOTDIR: parent directory not exist at create * - -ENOSPC: out of space * - -ENAMETOOLONG: name is too long * - -ENOMEM: out of memory */ int sffsOpen(sffsFs_t *fs, const char *path, int mode); /** * refer to close(2) * * @param fs SFFS pointer * @param fd file descriptor * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EBADF: invalid file descriptor */ int sffsClose(sffsFs_t *fs, int fd); /** * refer to write(2) * * On failure, the return value is the negative errno. Written bytes won't * be returned. * * @param fs SFFS pointer * @param fd file descriptor * @param data data pointer to be written * @param size data size to be written * @return * - written size on success * - -EINVAL: invalid SFFS pointer * - -EBADF: invalid file descriptor * - -EROFS: write on read-only file system * - -ENOSPC: out of space * - -EOVERFLOW: exceed maximum large file size */ ssize_t sffsWrite(sffsFs_t *fs, int fd, const void *data, size_t size); /** * refer to read(2) * * When there are no enough size in the file, the read size is returned. * On other failures, the return value is the negative errno. Read bytes * won't be returned. * * @param fs SFFS pointer * @param fd file descriptor * @param data data pointer to be read * @param size data size to be read * @return * - read size on success * - -EINVAL: invalid SFFS pointer * - -EBADF: invalid file descriptor */ ssize_t sffsRead(sffsFs_t *fs, int fd, void *data, size_t size); /** * refer to lseek(2) * * When the seek position is larger than file size, the position will be * set to end of file silently. * * @param fs SFFS pointer * @param fd file descriptor * @param offset seek offset * @param mode seek mode (SEEK_SET, SEEK_CUR, SEEK_END) * @return * - 0 on success * - -EINVAL: invalid SFFS pointer, or invalid seek mode * - -EBADF: invalid file descriptor */ off_t sffsSeek(sffsFs_t *fs, int fd, off_t offset, int mode); /** * refer to ftruncate(2) * * Support both increase and decrease file size. At increase file size, * the extended part is undefined. * * @param fs SFFS pointer * @param fd file descriptor * @param length truncate new length * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EBADF: invalid file descriptor * - -EROFS: write on read-only file system * - -EACCES: file descriptor is opened as read-only * - -ENOSPC: out of space * - -EOVERFLOW: exceed maximum large file size */ int sffsFtruncate(sffsFs_t *fs, int fd, off_t length); /** * refer to fstat(2) * * @param fs SFFS pointer * @param fd file descriptor * @param st output stat pointer * @return * - 0 on success * - -EINVAL: invalid SFFS pointer, or invalid output pointer * - -EBADF: invalid file descriptor */ int sffsFstat(sffsFs_t *fs, int fd, struct stat *st); /** * refer to unlink(2) * * @param fs SFFS pointer * @param name file path in file system * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EROFS: write on read-only file system * - -ENOENT: file not exist * - -EBUSY: file is opened */ int sffsUnlink(sffsFs_t *fs, const char *name); /** * refer to rename(2) * * Support 3 kinds of rename: * - rename file to an existed directory, but destination file not exist * - rename file to an existed file * - rename directory to an existed empty directory * * @param fs SFFS pointer * @param src source file or directory path in file system * @param dst destination file or directory path in file system * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EROFS: read-only file system * - -ENOENT: source not exist * - -EBUSY: source file or directory is opened * - -ENOTDIR: * - source is file, and destination in non-exist directory * - source is directory, and destination is not existed directory * - -EISDIR: source is file, and destination is existed directory * - -ENOTEMPTY: source is directory, and destination is not empty * - -ENAMETOOLONG: destination name is too long */ int sffsRename(sffsFs_t *fs, const char *src, const char *dst); /** * refer to statvfs(3) * * @param fs SFFS pointer * @param buf output pointer * @return * - 0 on success * - -EINVAL: invalid SFFS pointer, or output pointer */ int sffsStatVfs(sffsFs_t *fs, struct statvfs *buf); /** * refer to sync(2) * * @param fs SFFS pointer * @return * - 0 on success * - -EINVAL: invalid SFFS pointer */ int sffsSync(sffsFs_t *fs); /** * refer to mkdir(2) * * @param fs SFFS pointer * @param name directory path in file system * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EROFS: read-only file system * - -EEXIST: the path is existed * - -ENOTDIR: parent of the path not exist * - -ENOSPC: out of space * - -ENAMETOOLONG: destination name is too long */ int sffsMkDir(sffsFs_t *fs, const char *name); /** * refer to rmdir(2) * * @param fs SFFS pointer * @param name directory path in file system * @return * - 0 on success * - -EINVAL: invalid SFFS pointer * - -EROFS: read-only file system * - -EACCES: can't remove file system root directory * - -ENOENT: path not exists * - -ENOTDIR: parent of path not exists * - -EBUSY: path is opened * - -ENOTEMPTY: directory is not empty */ int sffsRmDir(sffsFs_t *fs, const char *name); /** * refer to opendir(3) * * @param fs SFFS pointer * @param name directory path in file system * @return * - DIR pointer on success * - NULL on fail */ DIR *sffsOpenDir(sffsFs_t *fs, const char *name); /** * refer to closedir(3) * * @param fs SFFS pointer * @param dir DIR pointer to be closed * @return * - 0 on success * - -EINVAL: invalid SFFS pointer, or DIR pointer */ int sffsCloseDir(sffsFs_t *fs, DIR *dir); /** * refer to readdir_r(3) * * At the end of directory, the return value is 0, and \a *result will be * NULL. * * @param fs SFFS pointer * @param dir DIR pointer to be read * @param entry output dirent pointer * @param result output pointer of dirent pointer * @return * - 0 on success * - -EINVAL: invalid SFFS pointer, or DIR pointer, or entry pointer * - -EBADF: invalid DIR */ int sffsReadDirR(sffsFs_t *fs, DIR *dir, struct dirent *entry, struct dirent **result); /** * refer to readdir(3) * * @param fs SFFS pointer * @param dir DIR pointer to be read * @return * - dirent pointer on success * - NULL on fail, or end of directory */ struct dirent *sffsReadDir(sffsFs_t *fs, DIR *dir); /** * refer to telldir(3) * * @param fs SFFS pointer * @param dir DIR pointer to be read * @return * - current location on success * - -EINVAL: invalid SFFS pointer, or DIR pointer */ long sffsTellDir(sffsFs_t *fs, DIR *dir); /** * refer to seekdir(3) * * @param fs SFFS pointer * @param dir DIR pointer to be read * @param loc seek location */ void sffsSeekDir(sffsFs_t *fs, DIR *dir, long loc); /** * write all content to a file in safe mode * * Comparing to \p sffsFileWrite, when the file already exists, and there * are power failure during write, either the file content to the new data, * or the content is kept as original. * * Due to the original file won't be deleted before the new data are * written, there should exist enough free blocks for the whole new data. * * @param fs SFFS pointer * @param path path in file system * @param data data pointer to be written * @param size data size to be written * @return * - written size on success, it is the same as \p size parameter * - -EINVAL: invalid SFFS pointer * - -EROFS: create on read-only file system * - -ENOTDIR: parent directory not exist at create * - -EISDIR: path exists, but is directory * - -ENOSPC: out of space * - -ENAMETOOLONG: name is too long * - -EOVERFLOW: exceed maximum large file size */ ssize_t sffsSfileWrite(sffsFs_t *fs, const char *path, const void *data, size_t size); /** * write all content to a file * * @param fs SFFS pointer * @param path path in file system * @param data data pointer to be written * @param size data size to be written * @return * - written size on success, it is the same as \p size parameter * - -EINVAL: invalid SFFS pointer * - -EROFS: create on read-only file system * - -ENOTDIR: parent directory not exist at create * - -EISDIR: path exists, but is directory * - -ENOSPC: out of space * - -ENAMETOOLONG: name is too long * - -EOVERFLOW: exceed maximum large file size */ ssize_t sffsFileWrite(sffsFs_t *fs, const char *path, const void *data, size_t size); /** * estimate block count needed for specified file size * * @param fs SFFS pointer * @param size file size to be estimated * @return * - needed block count * - -EOVERFLOW: exceed maximum large file size */ int sffsFileBlockNeeded(sffsFs_t *fs, size_t size); /** * block write count for statistic * * @param fs SFFS pointer * @return * - block write count * - -EINVAL: invalid SFFS pointer */ int sffsBlockWriteCount(sffsFs_t *fs); /** * set reserved block count only for sffsSfileWrite * * Due to \p sffsSfileWrite will need extra blocks, this can set reserved * block count, which will only be used during \p sffsSfileWrite. * * In most cases, \p sffsSfileWrite is used for important information, and * failure is unacceptable. With proper reserved blocks, it won't fail due * to ENOSPC. * * Even current free block count is less than \p count, it will success. * * Another approach is to create independent partition for important files. * * @param fs SFFS pointer * @param count reserved block count only for sffsSfileWrite * @return * - 0 on success * - -EINVAL on invalid parameter */ int sffsSetSfileReserveCount(sffsFs_t *fs, size_t count); #ifdef __cplusplus } #endif #endif //__SFFS_H__