From a1faeb9ca1e8751e714dcff4dd92a374a376e9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= <joakim.nohlgard@eistec.se> Date: Mon, 11 Jul 2016 06:33:14 +0200 Subject: [PATCH] newlib: Use vfs for file I/O syscalls --- sys/newlib/syscalls.c | 330 +++++++++++++++++++++++++++++++----------- 1 file changed, 244 insertions(+), 86 deletions(-) diff --git a/sys/newlib/syscalls.c b/sys/newlib/syscalls.c index d44d4c9e7b..c2e1a9e7b9 100644 --- a/sys/newlib/syscalls.c +++ b/sys/newlib/syscalls.c @@ -39,6 +39,9 @@ #include "irq.h" #include "log.h" #include "periph/pm.h" +#if MODULE_VFS +#include "vfs.h" +#endif #include "uart_stdio.h" @@ -152,137 +155,307 @@ int _kill_r(struct _reent *r, pid_t pid, int sig) return -1; } +#if MODULE_VFS /** * @brief Open a file * - * @param r TODO - * @param name TODO - * @param mode TODO + * This is a wrapper around @c vfs_open * - * @return TODO + * @param r pointer to reent structure + * @param name file name to open + * @param flags flags, see man 3p open + * @param mode mode, file creation mode if the file is created when opening + * + * @return fd number (>= 0) on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ int _open_r(struct _reent *r, const char *name, int flags, int mode) { - (void) name; - (void) flags; - (void) mode; - r->_errno = ENODEV; /* not implemented yet */ - return -1; + int fd = vfs_open(name, flags, mode); + if (fd < 0) { + /* vfs returns negative error codes */ + r->_errno = -fd; + return -1; + } + return fd; } /** - * @brief Read from a file + * @brief Read bytes from an open file * - * All input is read from UART_0. The function will block until a byte is actually read. + * This is a wrapper around @c vfs_read * - * Note: the read function does not buffer - data will be lost if the function is not - * called fast enough. + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() + * @param[out] dest destination buffer + * @param[in] count maximum number of bytes to read * - * TODO: implement more sophisticated read call. + * @return number of bytes read on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error + */ +_ssize_t _read_r(struct _reent *r, int fd, void *dest, size_t count) +{ + int res = vfs_read(fd, dest, count); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return res; +} + +/** + * @brief Write bytes to an open file * - * @param r TODO - * @param fd TODO - * @param buffer TODO - * @param int TODO + * This is a wrapper around @c vfs_write * - * @return TODO + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] src source data buffer + * @param[in] count maximum number of bytes to write + * + * @return number of bytes written on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ -_ssize_t _read_r(struct _reent *r, int fd, void *buffer, size_t count) +_ssize_t _write_r(struct _reent *r, int fd, const void *src, size_t count) { - (void)r; - (void)fd; - return uart_stdio_read(buffer, count); + int res = vfs_write(fd, src, count); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return res; } /** - * @brief Write characters to a file + * @brief Close an open file * - * All output is currently directed to UART_0, independent of the given file descriptor. - * The write call will further block until the byte is actually written to the UART. + * This is a wrapper around @c vfs_close * - * TODO: implement more sophisticated write call. + * If this call returns an error, the fd should still be considered invalid and + * no further attempt to use it shall be made, not even to retry @c close() * - * @param r TODO - * @param fd TODO - * @param data TODO - * @param int TODO + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() * - * @return TODO + * @return 0 on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ -_ssize_t _write_r(struct _reent *r, int fd, const void *data, size_t count) +int _close_r(struct _reent *r, int fd) { - (void) r; - (void) fd; - return uart_stdio_write(data, count); + int res = vfs_close(fd); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return res; } /** - * @brief Close a file + * @brief Query or set options on an open file * - * @param r TODO - * @param fd TODO + * This is a wrapper around @c vfs_fcntl * - * @return TODO + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] cmd fcntl command, see man 3p fcntl + * @param[in] arg argument to fcntl command, see man 3p fcntl + * + * @return 0 on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ -int _close_r(struct _reent *r, int fd) +int _fcntl_r (struct _reent *r, int fd, int cmd, int arg) { - (void) fd; - r->_errno = ENODEV; /* not implemented yet */ - return -1; + int res = vfs_fcntl(fd, cmd, arg); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return res; } /** - * @brief Set position in a file + * @brief Seek to position in file * - * @param r TODO - * @param fd TODO - * @param pos TODO - * @param dir TODO + * This is a wrapper around @c vfs_lseek * - * @return TODO + * @p whence determines the function of the seek and should be set to one of + * the following values: + * + * - @c SEEK_SET: Seek to absolute offset @p off + * - @c SEEK_CUR: Seek to current location + @p off + * - @c SEEK_END: Seek to end of file + @p off + * + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() + * @param[in] off seek offset + * @param[in] whence determines the seek method, see detailed description + * + * @return the new seek location in the file on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ -_off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int dir) +_off_t _lseek_r(struct _reent *r, int fd, _off_t off, int whence) { - (void) fd; - (void) pos; - (void) dir; - r->_errno = ENODEV; /* not implemented yet */ - return -1; + int res = vfs_lseek(fd, off, whence); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return res; } /** - * @brief Status of an open file + * @brief Get status of an open file * - * @param r TODO - * @param fd TODO - * @param stat TODO + * This is a wrapper around @c vfs_fstat * - * @return TODO + * @param[in] r pointer to reent structure + * @param[in] fd open file descriptor obtained from @c open() + * @param[out] buf pointer to stat struct to fill + * + * @return 0 on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ -int _fstat_r(struct _reent *r, int fd, struct stat *st) +int _fstat_r(struct _reent *r, int fd, struct stat *buf) { - (void) fd; - (void) st; - r->_errno = ENODEV; /* not implemented yet */ - return -1; + int res = vfs_fstat(fd, buf); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return 0; } /** * @brief Status of a file (by name) * - * @param r TODO - * @param name TODO - * @param stat TODO + * This is a wrapper around @c vfs_fstat * - * @return TODO + * @param[in] r pointer to reent structure + * @param[in] name path to file + * @param[out] buf pointer to stat struct to fill + * + * @return 0 on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error + */ +int _stat_r(struct _reent *r, const char *name, struct stat *st) +{ + int res = vfs_stat(name, st); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return 0; +} + +/** + * @brief Unlink (delete) a file + * + * @param[in] r pointer to reent structure + * @param[in] path path to file to be deleted + * + * @return 0 on success + * @return -1 on error, @c r->_errno set to a constant from errno.h to indicate the error */ +int _unlink_r(struct _reent *r, const char *path) +{ + int res = vfs_unlink(path); + if (res < 0) { + /* vfs returns negative error codes */ + r->_errno = -res; + return -1; + } + return 0; +} + +#else /* MODULE_VFS */ + +/* Fallback stdio_uart wrappers for when VFS is not used, does not allow any + * other file access */ +/* + * Fallback read function + * + * All input is read from uart_stdio regardless of fd number. The function will + * block until a byte is actually read. + * + * Note: the read function does not buffer - data will be lost if the function is not + * called fast enough. + */ +_ssize_t _read_r(struct _reent *r, int fd, void *buffer, size_t count) +{ + (void)r; + (void)fd; + return uart_stdio_read(buffer, count); +} + +/* + * Fallback write function + * + * All output is directed to uart_stdio, independent of the given file descriptor. + * The write call will further block until the byte is actually written to the UART. + */ +_ssize_t _write_r(struct _reent *r, int fd, const void *data, size_t count) +{ + (void) r; + (void) fd; + return uart_stdio_write(data, count); +} + +/* Stubs to avoid linking errors, these functions do not have any effect */ +int _open_r(struct _reent *r, const char *name, int flags, int mode) +{ + (void) name; + (void) flags; + (void) mode; + r->_errno = ENODEV; + return -1; +} + +int _close_r(struct _reent *r, int fd) +{ + (void) fd; + r->_errno = ENODEV; + return -1; +} + +_off_t _lseek_r(struct _reent *r, int fd, _off_t pos, int dir) +{ + (void) fd; + (void) pos; + (void) dir; + r->_errno = ENODEV; + return -1; +} + +int _fstat_r(struct _reent *r, int fd, struct stat *st) +{ + (void) fd; + (void) st; + r->_errno = ENODEV; + return -1; +} + int _stat_r(struct _reent *r, const char *name, struct stat *st) { (void) name; (void) st; - r->_errno = ENODEV; /* not implemented yet */ + r->_errno = ENODEV; + return -1; +} + +int _unlink_r(struct _reent *r, const char *path) +{ + (void) path; + r->_errno = ENODEV; return -1; } +#endif /* MODULE_VFS */ /** * @brief Query whether output stream is a terminal @@ -303,21 +476,6 @@ int _isatty_r(struct _reent *r, int fd) return 0; } -/** - * @brief Remove a file's directory entry - * - * @param r TODO - * @param path TODO - * - * @return TODO - */ -int _unlink_r(struct _reent *r, const char *path) -{ - (void) path; - r->_errno = ENODEV; /* not implemented yet */ - return -1; -} - /** * @brief Send a signal to a thread * -- GitLab