-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sys/vfs_util: add VFS helper functions #18038
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (C) 2021 ML!PA Consulting GmbH | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @defgroup sys_vfs_util VFS helper functions | ||
* @ingroup sys_vfs | ||
* @{ | ||
* | ||
* @file | ||
* @brief VFS helper functions | ||
* | ||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com> | ||
*/ | ||
|
||
#ifndef VFS_UTIL_H | ||
#define VFS_UTIL_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief Writes the content of a buffer to a file | ||
* If the file already exists, it will be overwritten. | ||
* | ||
* @param[in] file Destination file path | ||
* @param[in] buf Source buffer | ||
* @param[in] len Buffer size | ||
* | ||
* @return 0 on success | ||
* @return negative error from @ref vfs_open, @ref vfs_write | ||
*/ | ||
int vfs_file_from_buffer(const char *file, const void *buf, size_t len); | ||
|
||
/** | ||
* @brief Reads the content of a file to a buffer | ||
* | ||
* @param[in] file Source file path | ||
* @param[out] buf Destination buffer | ||
* @param[in] len Buffer size | ||
* | ||
* @return number of bytes read on success | ||
* @return -ENOSPC if the file was read successfully but is larger than | ||
* the provided buffer. Only the first @p len bytes were read. | ||
Comment on lines
+48
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this assurance is made toward the user, do we need to check that no other cause of error produces -ENOSPC? (It might be easier to just consider that a regular error with no guarantees -- also because that'd allow the implementation to instead stat the file after opening and return early without actually reading, if anyone wants to optimize that later.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think no fs will generate this error in the read path, but I could add if (res == -ENOSPC) {
res = -ENOMEM;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documenting at the file system API that ENOSP must not be returned by read functions would also have worked, but this is the more robust way. |
||
* @return negative error from @ref vfs_open, @ref vfs_read | ||
*/ | ||
int vfs_file_to_buffer(const char* file, void* buf, size_t len); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* VFS_UTIL_H */ | ||
/** @} */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include $(RIOTBASE)/Makefile.base |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* Copyright (C) 2021 Benjamin Valentin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_vfs_util | ||
* @{ | ||
* @file | ||
* @brief VFS layer helper functions | ||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com> | ||
* @} | ||
*/ | ||
|
||
#include <fcntl.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
|
||
#include "vfs.h" | ||
#include "vfs_util.h" | ||
|
||
#define ENABLE_DEBUG 0 | ||
#include "debug.h" | ||
|
||
int vfs_file_from_buffer(const char *file, const void *buf, size_t len) | ||
{ | ||
int res, fd = vfs_open(file, O_CREAT | O_TRUNC | O_WRONLY, 0644); | ||
|
||
if (fd < 0) { | ||
DEBUG("can't open %s for writing\n", file); | ||
return fd; | ||
} | ||
|
||
res = vfs_write(fd, buf, len); | ||
vfs_close(fd); | ||
|
||
if (res) { | ||
return res; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int vfs_file_to_buffer(const char* file, void* buf, size_t len) | ||
{ | ||
int res, fd = vfs_open(file, O_RDONLY, 0); | ||
|
||
if (fd < 0) { | ||
DEBUG("can't open %s for reading\n", file); | ||
return fd; | ||
} | ||
|
||
res = vfs_read(fd, buf, len); | ||
|
||
/* ENOSPC is used to signal truncation */ | ||
/* Just for future proofing - this error code is not returned by any fs in the read path. */ | ||
if (res == -ENOSPC) { | ||
DEBUG("read returned -ENOSPC\n"); | ||
res = -ENOMEM; | ||
} | ||
|
||
if (res > 0) { | ||
if (res < (int)len) { | ||
/* fill remaining buffer with 0 */ | ||
memset((char *)buf + res, 0, len - res); | ||
} else { | ||
/* check if there are more bytes in the file */ | ||
char c; | ||
if (vfs_read(fd, &c, sizeof(c)) > 0) { | ||
res = -ENOSPC; | ||
} | ||
} | ||
} | ||
|
||
vfs_close(fd); | ||
|
||
return res; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is the right place from the module point of view, it's hard to discover. Maybe add a pointer to the
vfs_read
doc saying that "To read a complete file into a buffer, see also @ref vfs_file_to_buffer", or merely a "@see vfs_file_to_buffer".