diff options
Diffstat (limited to 'otherlibs/unix/open.c')
-rw-r--r-- | otherlibs/unix/open.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/otherlibs/unix/open.c b/otherlibs/unix/open.c index 097a0455b..ecee01389 100644 --- a/otherlibs/unix/open.c +++ b/otherlibs/unix/open.c @@ -17,6 +17,9 @@ #include <signals.h> #include "unixsupport.h" #include <string.h> +#ifdef HAS_UNISTD +#include <unistd.h> +#endif #include <fcntl.h> #ifndef O_NONBLOCK @@ -31,16 +34,31 @@ #ifndef O_RSYNC #define O_RSYNC 0 #endif +#ifndef O_CLOEXEC +#define NEED_CLOEXEC_EMULATION +#define O_CLOEXEC 0 +#endif -static int open_flag_table[] = { +static int open_flag_table[14] = { O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL, - O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, 0 + O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, + 0, /* O_SHARE_DELETE, Windows-only */ + O_CLOEXEC +}; + +#ifdef NEED_CLOEXEC_EMULATION +static int open_cloexec_table[14] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + 0, + 1 }; +#endif CAMLprim value unix_open(value path, value flags, value perm) { CAMLparam3(path, flags, perm); - int ret, cv_flags; + int fd, cv_flags; char * p; cv_flags = convert_flag_list(flags, open_flag_table); @@ -48,9 +66,17 @@ CAMLprim value unix_open(value path, value flags, value perm) strcpy(p, String_val(path)); /* open on a named FIFO can block (PR#1533) */ enter_blocking_section(); - ret = open(p, cv_flags, Int_val(perm)); + fd = open(p, cv_flags, Int_val(perm)); leave_blocking_section(); stat_free(p); - if (ret == -1) uerror("open", path); - CAMLreturn (Val_int(ret)); + if (fd == -1) uerror("open", path); +#if defined(NEED_CLOEXEC_EMULATION) && defined(FD_CLOEXEC) + if (convert_flag_list(flags, open_cloexec_table) != 0) { + int flags = fcntl(fd, F_GETFD, 0); + if (flags == -1 || + fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + uerror("open", path); + } +#endif + CAMLreturn (Val_int(fd)); } |