/** * Opens a file at the specified path. The result of opening a nonexistent * file depends on the access flags specified. All intermediate directories * must already exist. * * The mode strings passed to fopen() map to nffs_open()'s access flags as * follows: * "r" - FS_ACCESS_READ * "r+" - FS_ACCESS_READ | FS_ACCESS_WRITE * "w" - FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE * "w+" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE * "a" - FS_ACCESS_WRITE | FS_ACCESS_APPEND * "a+" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_APPEND * * @param path The path of the file to open. * @param access_flags Flags controlling file access; see above table. * @param out_file On success, a pointer to the newly-created file * handle gets written here. * * @return 0 on success; nonzero on failure. */ static int nffs_open(const char *path, uint8_t access_flags, struct fs_file **out_fs_file) { int rc; struct nffs_file *out_file; nffs_lock(); if (!nffs_ready()) { rc = FS_EUNINIT; goto done; } rc = nffs_file_open(&out_file, path, access_flags); if (rc != 0) { goto done; } *out_fs_file = (struct fs_file *)out_file; done: nffs_unlock(); if (rc != 0) { *out_fs_file = NULL; } return rc; }
/** * Reads data from the specified file. If more data is requested than remains * in the file, all available data is retrieved. Note: this type of short read * results in a success return code. * * @param file The file to read from. * @param len The number of bytes to attempt to read. * @param out_data The destination buffer to read into. * @param out_len On success, the number of bytes actually read gets * written here. Pass null if you don't care. * * @return 0 on success; nonzero on failure. */ int nffs_file_read(struct nffs_file *file, uint32_t len, void *out_data, uint32_t *out_len) { uint32_t bytes_read; int rc; if (!nffs_ready()) { return FS_EUNINIT; } if (!(file->nf_access_flags & FS_ACCESS_READ)) { return FS_EACCESS; } rc = nffs_inode_read(file->nf_inode_entry, file->nf_offset, len, out_data, &bytes_read); if (rc != 0) { return rc; } file->nf_offset += bytes_read; if (out_len != NULL) { *out_len = bytes_read; } return 0; }
/** * Opens the directory at the specified path. The directory's contents can be * read with subsequent calls to nffs_readdir(). When you are done with the * directory handle, close it with nffs_closedir(). * * Unlinking files from the directory while it is open may result in * unpredictable behavior. New files can be created inside the directory. * * @param path The directory to open. * @param out_dir On success, points to the directory handle. * * @return 0 on success; * FS_ENOENT if the specified directory does not * exist; * other nonzero on error. */ static int nffs_opendir(const char *path, struct fs_dir **out_fs_dir) { int rc; struct nffs_dir **out_dir = (struct nffs_dir **)out_fs_dir; nffs_lock(); if (!nffs_ready()) { rc = FS_EUNINIT; goto done; } rc = nffs_dir_open(path, out_dir); done: nffs_unlock(); return rc; }
/** * Creates the directory represented by the specified path. All intermediate * directories must already exist. The specified path must start with a '/' * character. * * @param path The directory to create. * * @return 0 on success; * nonzero on failure. */ int nffs_mkdir(const char *path) { int rc; nffs_lock(); if (!nffs_ready()) { rc = NFFS_EUNINIT; goto done; } rc = nffs_path_new_dir(path, NULL); if (rc != 0) { goto done; } done: nffs_unlock(); return rc; }
/** * 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). * * @param from The source path. * @param to The destination path. * * @return 0 on success; * nonzero on failure. */ int nffs_rename(const char *from, const char *to) { int rc; nffs_lock(); if (!nffs_ready()) { rc = NFFS_EUNINIT; goto done; } rc = nffs_path_rename(from, to); if (rc != 0) { goto done; } rc = 0; done: nffs_unlock(); return rc; }
/** * Unlinks the file or directory at the specified path. If the path refers to * a directory, all the directory's descendants are recursively unlinked. Any * open file handles refering to an unlinked file remain valid, and can be * read from and written to. * * @path The path of the file or directory to unlink. * * @return 0 on success; nonzero on failure. */ int nffs_unlink(const char *path) { int rc; nffs_lock(); if (!nffs_ready()) { rc = NFFS_EUNINIT; goto done; } rc = nffs_path_unlink(path); if (rc != 0) { goto done; } rc = 0; done: nffs_unlock(); return rc; }
/** * Writes the supplied data to the current offset of the specified file handle. * * @param file The file to write to. * @param data The data to write. * @param len The number of bytes to write. * * @return 0 on success; nonzero on failure. */ int nffs_write(struct nffs_file *file, const void *data, int len) { int rc; nffs_lock(); if (!nffs_ready()) { rc = NFFS_EUNINIT; goto done; } rc = nffs_write_to_file(file, data, len); if (rc != 0) { goto done; } rc = 0; done: nffs_unlock(); return rc; }