summaryrefslogtreecommitdiff
blob: a112d1fb44731f7bdcee5d3490ecc2d6e60ba228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
commit f3d451b81c4caa8cce7f55af6463ec685e79e227
Author: Gerd Stolpmann <gerd@gerd-stolpmann.de>
Date:   Sun Feb 26 21:04:49 2017 +0100

    ocaml-4.05: support for O_KEEPEXEC

diff --git a/code/src/netsys/Makefile b/code/src/netsys/Makefile
index cbc1ce2..cb70a09 100644
--- a/code/src/netsys/Makefile
+++ b/code/src/netsys/Makefile
@@ -56,7 +56,7 @@ OCAMLC_OPTIONS_FOR_netsys_c_xdr.c = -ccopt -O
 OCAMLC_OPTIONS += $(STRING_OPTS)
 OCAMLOPT_OPTIONS += $(STRING_OPTS)
 
-PP_OPTIONS = -pp "$(CPPO) $(DEF_O_SHARE_DELETE) $(DEF_O_CLOEXEC) $(PP_BYTES) $(PP_DEPRECATED)"
+PP_OPTIONS = -pp "$(CPPO) $(DEF_O_SHARE_DELETE) $(DEF_O_CLOEXEC) $(DEF_O_KEEPEXEC) $(PP_BYTES) $(PP_DEPRECATED)"
 
 INSTALL_EXTRA += netsys_c_event.h $(OOH_OBJECT)
 
diff --git a/code/src/netsys/configure b/code/src/netsys/configure
index 1325843..f4dbc09 100755
--- a/code/src/netsys/configure
+++ b/code/src/netsys/configure
@@ -437,6 +437,21 @@ else
     echo "no"
 fi
 
+######################################################################
+
+printf "Checking for O_KEEPEXEC... "
+mkdir -p tmp
+cat <<_EOF_ >tmp/t.ml
+let x = Unix.O_KEEPEXEC;;
+_EOF_
+
+def_o_keepexec="-D NO_O_KEEPEXEC"
+if ocaml unix.cma tmp/t.ml >/dev/null 2>/dev/null; then
+    echo "yes"
+    def_o_keepexec="-D HAVE_O_KEEPEXEC"
+else
+    echo "no"
+fi
 
 ######################################################################
 
@@ -445,6 +460,7 @@ cat <<EOF >Makefile.conf
 NETSYS_LINK_OPTIONS = $netsys_link_options
 DEF_O_SHARE_DELETE = $def_o_share_delete
 DEF_O_CLOEXEC = $def_o_cloexec
+DEF_O_KEEPEXEC = $def_o_keepexec
 OOH_OBJECT = $def_ooh_object
 EOF
 
diff --git a/code/src/netsys/netsys_c.c b/code/src/netsys/netsys_c.c
index a8b16be..4c30873 100644
--- a/code/src/netsys/netsys_c.c
+++ b/code/src/netsys/netsys_c.c
@@ -448,32 +448,43 @@ static int at_flags_table[] = {
 #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[] = {
   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_SHARE_DELETE */, O_CLOEXEC
+  O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC,
+  0 /* O_SHARE_DELETE */, 0 /* O_CLOEXEC */, 0 /* O_KEEPEXEC */
 };
 
-#ifdef NEED_CLOEXEC_EMULATION
+enum { CLOEXEC = 1, KEEPEXEC = 2 };
+
 static int open_cloexec_table[] = {
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CLOEXEC, KEEPEXEC
 };
+#ifndef HAVE_O_KEEPEXEC
+#define unix_cloexec_default 0
 #endif
+
 #endif
 
 CAMLprim value netsys_openat(value dirfd, value path, value flags, value perm)
 {
 #ifdef HAVE_AT
     CAMLparam4(dirfd, path, flags, perm);
-    int ret, cv_flags;
+    int ret, cv_flags, clo_flags, cloexec;
     char * p;
 
     /* shamelessly copied from ocaml distro */
     cv_flags = convert_flag_list(flags, open_flag_table);
+    clo_flags = convert_flag_list(flags, open_cloexec_table);
+    if (clo_flags & CLOEXEC)
+        cloexec = 1;
+    else if (clo_flags & KEEPEXEC)
+        cloexec = 0;
+    else
+        cloexec = unix_cloexec_default;
+#if defined(O_CLOEXEC)
+    if (cloexec) cv_flags |= O_CLOEXEC;
+#endif
     p = stat_alloc(string_length(path) + 1);
     strcpy(p, String_val(path));
     enter_blocking_section();
@@ -481,8 +492,8 @@ CAMLprim value netsys_openat(value dirfd, value path, value flags, value perm)
     leave_blocking_section();
     stat_free(p);
     if (ret == -1) uerror("openat", path);
-#if defined(NEED_CLOEXEC_EMULATION) && defined(FD_CLOEXEC)
-    if (convert_flag_list(flags, open_cloexec_table) != 0) {
+#if !defined(O_CLOEXEC)
+    {
         int flags = fcntl(Int_val(dirfd), F_GETFD, 0);
         if (flags == -1 || fcntl(Int_val(dirfd), F_SETFD, flags | FD_CLOEXEC) == -1)
           uerror("openat", path);
diff --git a/code/src/netsys/netsys_posix.ml b/code/src/netsys/netsys_posix.ml
index 602ceae..3bf3e7c 100644
--- a/code/src/netsys/netsys_posix.ml
+++ b/code/src/netsys/netsys_posix.ml
@@ -715,6 +715,12 @@ type at_flag = AT_EACCESS | AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
                AT_REMOVEDIR
 
 (* The stubs assume these type definitions: *)
+#ifdef HAVE_O_KEEPEXEC
+type open_flag1 = Unix.open_flag =
+    O_RDONLY | O_WRONLY | O_RDWR | O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
+  | O_EXCL | O_NOCTTY | O_DSYNC | O_SYNC | O_RSYNC | O_SHARE_DELETE
+  | O_CLOEXEC | O_KEEPEXEC
+#else
 #ifdef HAVE_O_CLOEXEC
 type open_flag1 = Unix.open_flag =
     O_RDONLY | O_WRONLY | O_RDWR | O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
@@ -731,6 +737,7 @@ type open_flag1 = Unix.open_flag =
   | O_EXCL | O_NOCTTY | O_DSYNC | O_SYNC | O_RSYNC
 #endif
 #endif
+#endif
 
 type access_permission1 = Unix.access_permission =
     R_OK | W_OK | X_OK | F_OK