dup3 syscall - atomic set O_CLOEXEC with dup2

Davide Italiano davide.italiano at gmail.com
Thu Jan 12 09:35:17 UTC 2012


On Thu, Jan 12, 2012 at 6:01 AM, Eitan Adler <lists at eitanadler.com> wrote:
> This is an implementation of dup3 for FreeBSD:
> man page here (with a FreeBSD patch coming soon):
> https://www.kernel.org/doc/man-pages/online/pages/man2/dup.2.html
>
> Is this implementation correct? If so any objection to adding this as
> a supported syscall?
>
>
> Index: sys/kern/kern_descrip.c
> ===================================================================
> --- sys/kern/kern_descrip.c     (revision 229830)
> +++ sys/kern/kern_descrip.c     (working copy)
> @@ -110,6 +110,7 @@
>  /* Flags for do_dup() */
>  #define DUP_FIXED      0x1     /* Force fixed allocation */
>  #define DUP_FCNTL      0x2     /* fcntl()-style errors */
> +#define DUP_CLOEXEC    0x4     /* Enable O_CLOEXEC on the new fs */
>
>  static int do_dup(struct thread *td, int flags, int old, int new,
>     register_t *retval);
> @@ -307,7 +308,39 @@
>        return (0);
>  }
>
> +#ifndef _SYS_SYSPROTO_H_
> +struct dup3_args {
> +       u_int   from;
> +       u_int   to;
> +       int     flags;
> +};
> +#endif
> +
>  /*
> + * Duplicate a file descriptor and allow for O_CLOEXEC
> + */
> +
> +/* ARGSUSED */
> +int
> +sys_dup3(struct thread * const td, struct dup3_args * const uap) {
> +
> +       KASSERT(td != NULL, ("%s: td == NULL", __func__));
> +       KASSERT(uap != NULL, ("%s: uap == NULL", __func__));
> +
> +       if (uap->from == uap->to)
> +               return EINVAL;
> +
> +       if (uap->flags & ~O_CLOEXEC)
> +               return EINVAL;
> +
> +       const int dupflags = (uap->flags == O_CLOEXEC) ?
> DUP_FIXED|DUP_CLOEXEC : DUP_FIXED;
> +
> +       return (do_dup(td, dupflags, (int)uap->from, (int)uap->to,
> +                   td->td_retval));
> +       return (0);
> +}
> +
> +/*
>  * Duplicate a file descriptor to a particular value.
>  *
>  * Note: keep in mind that a potential race condition exists when closing
> @@ -912,6 +945,9 @@
>                fdp->fd_lastfile = new;
>        *retval = new;
>
> +       if (flags & DUP_CLOEXEC)
> +               fdp->fd_ofileflags[new] |= UF_EXCLOSE;
> +
>        /*
>         * If we dup'd over a valid file, we now own the reference to it
>         * and must dispose of it using closef() semantics (as if a
> Index: sys/kern/syscalls.master
> ===================================================================
> --- sys/kern/syscalls.master    (revision 229830)
> +++ sys/kern/syscalls.master    (working copy)
> @@ -951,5 +951,6 @@
>                                    off_t offset, off_t len); }
>  531    AUE_NULL        STD     { int posix_fadvise(int fd, off_t offset, \
>                                    off_t len, int advice); }
> +532    AUE_NULL        STD     { int dup3(u_int from, u_int to, int flags); }
>  ; Please copy any additions and changes to the following compatability tables:
>  ; sys/compat/freebsd32/syscalls.master
> Index: sys/compat/freebsd32/syscalls.master
> ===================================================================
> --- sys/compat/freebsd32/syscalls.master        (revision 229830)
> +++ sys/compat/freebsd32/syscalls.master        (working copy)
> @@ -997,3 +997,4 @@
>                                    uint32_t offset1, uint32_t offset2,\
>                                    uint32_t len1, uint32_t len2, \
>                                    int advice); }
> +532    AUE_NULL        STD     { int dup3(u_int from, u_int to, int flags); }
>
>
> --
> Eitan Adler
> _______________________________________________
> freebsd-hackers at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"

>From what I can see it seems that dup3() is Linux specific and not
POSIX, so maybe there are some issues in adding it, but I may be
wrong.

Davide


More information about the freebsd-hackers mailing list