From 4b5360362e29583bdb2adf353f0f915112374cec Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 3 May 2020 17:38:48 +0800 Subject: [PATCH] fs/vfs: Add nx_ioctl/nx_fcntl function Signed-off-by: Xiang Xiao --- fs/vfs/fs_fcntl.c | 110 ++++++++++++++++++++++-------- fs/vfs/fs_ioctl.c | 153 ++++++++++++++++++++++++------------------ include/nuttx/fs/fs.h | 44 ++++++++++++ 3 files changed, 212 insertions(+), 95 deletions(-) diff --git a/fs/vfs/fs_fcntl.c b/fs/vfs/fs_fcntl.c index 084186c507..eafc0fe3bd 100644 --- a/fs/vfs/fs_fcntl.c +++ b/fs/vfs/fs_fcntl.c @@ -94,9 +94,9 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap) * or equal to the third argument, arg, taken as an integer of type * int. The new file descriptor shall refer to the same open file * description as the original file descriptor, and shall share any - * locks. The FD_CLOEXEC flag associated with the new file descriptor - * shall be cleared to keep the file open across calls to one of the - * exec functions. + * locks. The FD_CLOEXEC flag associated with the new file + * descriptor shall be cleared to keep the file open across calls to + * one of the exec functions. */ { @@ -107,10 +107,10 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap) break; case F_GETFD: - /* Get the file descriptor flags defined in that are associated - * with the file descriptor fd. File descriptor flags are associated - * with a single file descriptor and do not affect other file descriptors - * that refer to the same file. + /* Get the file descriptor flags defined in that are + * associated with the file descriptor fd. File descriptor flags are + * associated with a single file descriptor and do not affect other + * file descriptors that refer to the same file. */ { @@ -281,41 +281,33 @@ int file_fcntl(FAR struct file *filep, int cmd, ...) } /**************************************************************************** - * Name: fcntl + * Name: nx_fcntl and nx_vfcntl * * Description: - * fcntl() will perform the operation specified by 'cmd' on an open file. + * nx_fcntl() is similar to the standard 'fcntl' interface except that is + * not a cancellation point and it does not modify the errno variable. * - * Input Parameters: - * fd - File descriptor of the open file - * cmd - Identifies the operation to be performed. Command specific - * arguments may follow. + * nx_vfcntl() is identical except that it accepts a va_list as an argument + * versus taking a variable length list of arguments. + * + * nx_fcntl() and nx_vfcntl are internal NuttX interface and should not be + * called from applications. * * Returned Value: - * The returned value depends on the nature of the command but for all - * commands the return value of -1 (ERROR) indicates that an error has - * occurred and, in this case, the errno variable will be set - * appropriately + * Returns a non-negative number on success; A negated errno value is + * returned on any failure (see comments fcntl() for a list of appropriate + * errno values). * ****************************************************************************/ -int fcntl(int fd, int cmd, ...) +int nx_vfcntl(int fd, int cmd, va_list ap) { FAR struct file *filep; - va_list ap; int ret; - /* fcntl() is a cancellation point */ - - enter_cancellation_point(); - - /* Setup to access the variable argument list */ - - va_start(ap, cmd); - /* Did we get a valid file descriptor? */ - if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS) + if (fd < CONFIG_NFILE_DESCRIPTORS) { /* Get the file structure corresponding to the file descriptor. */ @@ -336,7 +328,7 @@ int fcntl(int fd, int cmd, ...) /* No... check for operations on a socket descriptor */ #ifdef CONFIG_NET - if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) + if (fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { /* Yes.. defer socket descriptor operations to net_vfcntl(). The * errno is not set on failures. @@ -353,6 +345,66 @@ int fcntl(int fd, int cmd, ...) } } + return ret; +} + +int nx_fcntl(int fd, int cmd, ...) +{ + va_list ap; + int ret; + + /* Setup to access the variable argument list */ + + va_start(ap, cmd); + + /* Let nx_vfcntl() do the real work. The errno is not set on + * failures. + */ + + ret = nx_vfcntl(fd, cmd, ap); + + va_end(ap); + return ret; +} + +/**************************************************************************** + * Name: fcntl + * + * Description: + * fcntl() will perform the operation specified by 'cmd' on an open file. + * + * Input Parameters: + * fd - File descriptor of the open file + * cmd - Identifies the operation to be performed. Command specific + * arguments may follow. + * + * Returned Value: + * The returned value depends on the nature of the command but for all + * commands the return value of -1 (ERROR) indicates that an error has + * occurred and, in this case, the errno variable will be set + * appropriately + * + ****************************************************************************/ + +int fcntl(int fd, int cmd, ...) +{ + va_list ap; + int ret; + + /* fcntl() is a cancellation point */ + + enter_cancellation_point(); + + /* Setup to access the variable argument list */ + + va_start(ap, cmd); + + /* Let nx_vfcntl() do the real work. The errno is not set on + * failures. + */ + + ret = nx_vfcntl(fd, cmd, ap); + va_end(ap); if (ret < 0) diff --git a/fs/vfs/fs_ioctl.c b/fs/vfs/fs_ioctl.c index 43e96c731a..3ea13d9679 100644 --- a/fs/vfs/fs_ioctl.c +++ b/fs/vfs/fs_ioctl.c @@ -102,6 +102,92 @@ int file_ioctl(FAR struct file *filep, int req, unsigned long arg) return (int)inode->u.i_ops->ioctl(filep, req, arg); } +/**************************************************************************** + * Name: nx_ioctl + * + * Description: + * nx_ioctl() is similar to the standard 'ioctl' interface except that is + * not a cancellation point and it does not modify the errno variable. + * + * nx_ioctl() is an internal NuttX interface and should not be called from + * applications. + * + * Returned Value: + * Returns a non-negative number on success; A negated errno value is + * returned on any failure (see comments ioctl() for a list of appropriate + * errno values). + * + ****************************************************************************/ + +int nx_ioctl(int fd, int req, unsigned long arg) +{ + FAR struct file *filep; + int ret; + + /* Did we get a valid file descriptor? */ + + if (fd >= CONFIG_NFILE_DESCRIPTORS) + { + /* Perform the socket ioctl */ + +#ifdef CONFIG_NET + if (fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) + { + ret = netdev_ioctl(fd, req, arg); + } + else +#endif + { + return -EBADF; + } + } + else + { + /* Get the file structure corresponding to the file descriptor. */ + + ret = fs_getfilep(fd, &filep); + if (ret < 0) + { + return ret; + } + + DEBUGASSERT(filep != NULL); + + /* Perform the file ioctl. */ + + ret = file_ioctl(filep, req, arg); + } + + /* Check for File system IOCTL commands that can be implemented via + * fcntl() + */ + + if (ret == -ENOTTY) + { + switch (req) + { + case FIONBIO: + { + DEBUGASSERT(arg != 0); + + if (*(FAR int *)((uintptr_t)arg)) + { + ret = nx_fcntl(fd, F_SETFL, + nx_fcntl(fd, F_GETFL) | O_NONBLOCK); + } + else + { + ret = nx_fcntl(fd, F_SETFL, + nx_fcntl(fd, F_GETFL) & ~O_NONBLOCK); + } + } + break; + } + } + + return ret; +} + /**************************************************************************** * Name: ioctl/fs_ioctl * @@ -137,74 +223,9 @@ int fs_ioctl(int fd, int req, unsigned long arg) int ioctl(int fd, int req, unsigned long arg) #endif { - FAR struct file *filep; int ret; - /* Did we get a valid file descriptor? */ - - if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) - { - /* Perform the socket ioctl */ - -#ifdef CONFIG_NET - if ((unsigned int)fd < - (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) - { - ret = netdev_ioctl(fd, req, arg); - } - else -#endif - { - ret = -EBADF; - goto errout; - } - } - else - { - /* Get the file structure corresponding to the file descriptor. */ - - ret = fs_getfilep(fd, &filep); - if (ret < 0) - { - goto errout; - } - - DEBUGASSERT(filep != NULL); - - /* Perform the file ioctl. */ - - ret = file_ioctl(filep, req, arg); - } - - /* Check for File system IOCTL commands that can be implemented via - * fcntl() - */ - - if (ret == -ENOTTY) - { - switch (req) - { - case FIONBIO: - { - DEBUGASSERT(arg != 0); - - if (*(FAR int *)((uintptr_t)arg)) - { - return fcntl(fd, F_SETFL, - fcntl(fd, F_GETFL) | O_NONBLOCK); - } - else - { - return fcntl(fd, F_SETFL, - fcntl(fd, F_GETFL) & ~O_NONBLOCK); - } - } - break; - } - } - -errout: - + ret = nx_ioctl(fd, req, arg); if (ret < 0) { set_errno(-ret); diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index f55fb74e0c..91147d9f01 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -81,6 +81,7 @@ # define _NX_READ(f,b,s) nx_read(f,b,s) # define _NX_WRITE(f,b,s) nx_write(f,b,s) # define _NX_SEEK(f,o,w) nx_seek(f,o,w) +# define _NX_IOCTL(f,r,a) nx_ioctl(f,r,a) # define _NX_STAT(p,s) nx_stat(p,s) # define _NX_GETERRNO(r) (-(r)) # define _NX_SETERRNO(r) set_errno(-(r)) @@ -95,6 +96,7 @@ # define _NX_READ(f,b,s) read(f,b,s) # define _NX_WRITE(f,b,s) write(f,b,s) # define _NX_SEEK(f,o,w) lseek(f,o,w) +# define _NX_IOCTL(f,r,a) ioctl(f,r,a) # define _NX_STAT(p,s) stat(p,s) # define _NX_GETERRNO(r) errno # define _NX_SETERRNO(r) @@ -1248,6 +1250,25 @@ int file_truncate(FAR struct file *filep, off_t length); int file_ioctl(FAR struct file *filep, int req, unsigned long arg); +/**************************************************************************** + * Name: nx_ioctl + * + * Description: + * nx_ioctl() is similar to the standard 'ioctl' interface except that is + * not a cancellation point and it does not modify the errno variable. + * + * nx_ioctl() is an internal NuttX interface and should not be called from + * applications. + * + * Returned Value: + * Returns a non-negative number on success; A negated errno value is + * returned on any failure (see comments ioctl() for a list of appropriate + * errno values). + * + ****************************************************************************/ + +int nx_ioctl(int fd, int req, unsigned long arg); + /**************************************************************************** * Name: file_vfcntl * @@ -1290,6 +1311,29 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap); int file_fcntl(FAR struct file *filep, int cmd, ...); +/**************************************************************************** + * Name: nx_fcntl and nx_vfcntl + * + * Description: + * nx_fcntl() is similar to the standard 'fcntl' interface except that is + * not a cancellation point and it does not modify the errno variable. + * + * nx_vfcntl() is identical except that it accepts a va_list as an argument + * versus taking a variable length list of arguments. + * + * nx_fcntl() and nx_vfcntl are internal NuttX interface and should not be + * called from applications. + * + * Returned Value: + * Returns a non-negative number on success; A negated errno value is + * returned on any failure (see comments fcntl() for a list of appropriate + * errno values). + * + ****************************************************************************/ + +int nx_vfcntl(int fd, int cmd, va_list ap); +int nx_fcntl(int fd, int cmd, ...); + /**************************************************************************** * Name: file_poll *