From d07afc934e272cbbd63e355d9e12db333b2e2978 Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Mon, 3 Feb 2020 22:21:54 +0800 Subject: [PATCH] fcntl: add O_CLOEXEC/FD_CLOEXEC support --- fs/vfs/fs_fcntl.c | 34 +++++++++++++++++++----- include/fcntl.h | 1 + net/socket/net_vfcntl.c | 42 +++++++++++++++++++++++------- net/socket/socket.h | 2 ++ sched/group/Make.defs | 2 ++ sched/group/group_setuptaskfiles.c | 8 ++++-- 6 files changed, 71 insertions(+), 18 deletions(-) diff --git a/fs/vfs/fs_fcntl.c b/fs/vfs/fs_fcntl.c index e8555496ad..cf52abd406 100644 --- a/fs/vfs/fs_fcntl.c +++ b/fs/vfs/fs_fcntl.c @@ -113,15 +113,37 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap) * that refer to the same file. */ + { + ret = filep->f_oflags & O_CLOEXEC ? FD_CLOEXEC : 0; + } + break; + case F_SETFD: - /* Set the file descriptor flags defined in , that are associated - * with fd, to the third argument, arg, taken as type int. If the - * FD_CLOEXEC flag in the third argument is 0, the file shall remain open - * across the exec functions; otherwise, the file shall be closed upon - * successful execution of one of the exec functions. + /* Set the file descriptor flags defined in , that are + * associated with fd, to the third argument, arg, taken as type int. + * If the FD_CLOEXEC flag in the third argument is 0, the file shall + * remain open across the exec functions; otherwise, the file shall + * be closed upon successful execution of one of the exec functions. */ - ret = -ENOSYS; + { + int oflags = va_arg(ap, int); + + if (oflags & ~FD_CLOEXEC) + { + ret = -ENOSYS; + break; + } + + if (oflags & FD_CLOEXEC) + { + filep->f_oflags |= O_CLOEXEC; + } + else + { + filep->f_oflags &= ~O_CLOEXEC; + } + } break; case F_GETFL: diff --git a/include/fcntl.h b/include/fcntl.h index 12ad7bbf51..82aa91be23 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -66,6 +66,7 @@ #define O_DSYNC O_SYNC /* Equivalent to OSYNC in NuttX */ #define O_BINARY (1 << 8) /* Open the file in binary (untranslated) mode. */ #define O_DIRECT (1 << 9) /* Avoid caching, write directly to hardware */ +#define O_CLOEXEC (1 << 10) /* Close on execute */ /* Unsupported, but required open flags */ diff --git a/net/socket/net_vfcntl.c b/net/socket/net_vfcntl.c index 51592d7dbf..7b44ca3010 100644 --- a/net/socket/net_vfcntl.c +++ b/net/socket/net_vfcntl.c @@ -110,21 +110,43 @@ int psock_vfcntl(FAR struct socket *psock, 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. */ + { + ret = _SS_ISCLOEXEC(psock->s_flags) ? FD_CLOEXEC : 0; + } + break; + case F_SETFD: - /* Set the file descriptor flags defined in , that are associated - * with fd, to the third argument, arg, taken as type int. If the - * FD_CLOEXEC flag in the third argument is 0, the file shall remain open - * across the exec functions; otherwise, the file shall be closed upon - * successful execution of one of the exec functions. + /* Set the file descriptor flags defined in , that are + * associated with fd, to the third argument, arg, taken as type int. + * If the FD_CLOEXEC flag in the third argument is 0, the file shall + * remain open across the exec functions; otherwise, the file shall + * be closed upon successful execution of one of the exec functions. */ - ret = -ENOSYS; /* F_GETFD and F_SETFD not implemented */ + { + int oflags = va_arg(ap, int); + + if (oflags & ~FD_CLOEXEC) + { + ret = -ENOSYS; + break; + } + + if (oflags & FD_CLOEXEC) + { + psock->s_flags |= _SF_CLOEXEC; + } + else + { + psock->s_flags &= ~_SF_CLOEXEC; + } + } break; case F_GETFL: diff --git a/net/socket/socket.h b/net/socket/socket.h index ee901b251b..5a3cfe3f88 100644 --- a/net/socket/socket.h +++ b/net/socket/socket.h @@ -57,6 +57,7 @@ /* Definitions of 8-bit socket flags */ +#define _SF_CLOEXEC 0x04 /* Bit 2: Close on execute */ #define _SF_NONBLOCK 0x08 /* Bit 3: Don't block if no data (TCP/READ only) */ #define _SF_LISTENING 0x10 /* Bit 4: SOCK_STREAM is listening */ #define _SF_BOUND 0x20 /* Bit 5: SOCK_STREAM is bound to an address */ @@ -73,6 +74,7 @@ /* Macro to manage the socket state and flags */ +#define _SS_ISCLOEXEC(s) (((s) & _SF_CLOEXEC) != 0) #define _SS_ISNONBLOCK(s) (((s) & _SF_NONBLOCK) != 0) #define _SS_ISLISTENING(s) (((s) & _SF_LISTENING) != 0) #define _SS_ISBOUND(s) (((s) & _SF_BOUND) != 0) diff --git a/sched/group/Make.defs b/sched/group/Make.defs index a8039475e7..d59fce3eb2 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -76,3 +76,5 @@ endif DEPPATH += --dep-path group VPATH += :group + +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)net} diff --git a/sched/group/group_setuptaskfiles.c b/sched/group/group_setuptaskfiles.c index b632c91343..21532e5f81 100644 --- a/sched/group/group_setuptaskfiles.c +++ b/sched/group/group_setuptaskfiles.c @@ -41,11 +41,13 @@ #include #include +#include #include #include #include "sched/sched.h" +#include "socket/socket.h" #include "group/group.h" /**************************************************************************** @@ -114,7 +116,8 @@ static inline void sched_dupfiles(FAR struct task_tcb_s *tcb) * i-node structure. */ - if (parent[i].f_inode) + if (parent[i].f_inode && + (parent[i].f_oflags & O_CLOEXEC) == 0) { /* Yes... duplicate it for the child */ @@ -170,7 +173,8 @@ static inline void sched_dupsockets(FAR struct task_tcb_s *tcb) * reference count. */ - if (parent[i].s_crefs > 0) + if (parent[i].s_crefs > 0 && + !_SS_ISCLOEXEC(parent[i].s_flags)) { /* Yes... duplicate it for the child */