diff --git a/configure.ac b/configure.ac index f3221bc591c79fe800074640a981cb782bf66195..9c9d9a4e9113f041f6c88b54ad5c99e26ade5990 100644 --- a/configure.ac +++ b/configure.ac @@ -530,7 +530,7 @@ AC_CHECK_FUNCS(fdatasync,, ]) dnl Check for non-standard system calls -AC_CHECK_FUNCS([accept4 eventfd fstatfs vmsplice]) +AC_CHECK_FUNCS([accept4 dup3 eventfd fstatfs vmsplice]) AH_BOTTOM([#include <vlc_fixups.h>]) diff --git a/include/vlc_fs.h b/include/vlc_fs.h index 9f03b1b1ac73d8297afea438d021aab3415e8954..51bfd60c8e44564e832473ebb8df1831cfe1f5de 100644 --- a/include/vlc_fs.h +++ b/include/vlc_fs.h @@ -53,4 +53,6 @@ VLC_EXPORT( int, utf8_lstat, ( const char *filename, struct stat *buf ) ); VLC_EXPORT( int, vlc_mkstemp, ( char * ) ); +VLC_EXPORT( int, vlc_dup, ( int ) ); + #endif diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 64466791b7f1f767cdeba80b09564d507981b7c9..d608ab34dea061b740af9e41b306ceacffe8f612 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -440,6 +440,7 @@ vlc_readdir vlc_scandir vlc_stat vlc_unlink +vlc_dup utf8_vfprintf var_AddCallback var_Change diff --git a/src/text/filesystem.c b/src/text/filesystem.c index fdb25fb4f2755a69f7ef8e8a018ef4e8afc9c9fc..6ebfc39a138c4cedfbaef7b250d0f3da34d86938 100644 --- a/src/text/filesystem.c +++ b/src/text/filesystem.c @@ -535,3 +535,32 @@ int vlc_mkstemp( char *template ) return -1; } +/** + * Duplicates a file descriptor. The new file descriptor has the close-on-exec + * descriptor flag set. + * @return a new file descriptor or -1 + */ +int vlc_dup (int oldfd) +{ + int newfd; + +#ifdef HAVE_DUP3 + /* Unfortunately, dup3() works like dup2(), not like plain dup(). So we + * need such contortion to find the new file descriptor while preserving + * thread safety of the file descriptor table. */ + newfd = vlc_open ("/dev/null", O_RDONLY); + if (likely(newfd != -1)) + { + if (likely(dup3 (oldfd, newfd, O_CLOEXEC) == newfd)) + return newfd; + close (newfd); + } +#endif + + newfd = dup (oldfd); +#ifdef HAVE_FCNTL + if (likely(newfd != -1)) + fcntl (newfd, F_SETFD, FD_CLOEXEC); +#endif + return newfd; +}