View | Details | Raw Unified | Return to bug 176233
Collapse All | Expand All

(-)./lib/libc/gen/Makefile.inc (-1 / +2 lines)
Lines 10-16 Link Here
10
	alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
10
	alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
11
	clock.c closedir.c confstr.c \
11
	clock.c closedir.c confstr.c \
12
	crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
12
	crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
13
	dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \
13
	dlfcn.c drand48.c dup3.c \
14
	elf_utils.c erand48.c err.c errlst.c errno.c \
14
	exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
15
	exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
15
	fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
16
	fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
16
	getbootfile.c getbsize.c \
17
	getbootfile.c getbsize.c \
(-)./lib/libc/gen/Symbol.map (+1 lines)
Lines 382-387 Link Here
382
FBSD_1.3 {
382
FBSD_1.3 {
383
	 fdlopen;
383
	 fdlopen;
384
	__FreeBSD_libc_enter_restricted_mode;
384
	__FreeBSD_libc_enter_restricted_mode;
385
	dup3;
385
	getcontextx;
386
	getcontextx;
386
	gid_from_group;
387
	gid_from_group;
387
	nvis;
388
	nvis;
(-)./include/unistd.h (+3 lines)
Lines 326-331 Link Here
326
void	 closefrom(int);
326
void	 closefrom(int);
327
int	 dup(int);
327
int	 dup(int);
328
int	 dup2(int, int);
328
int	 dup2(int, int);
329
#if __BSD_VISIBLE
330
int	 dup3(int, int, int);
331
#endif
329
int	 execl(const char *, const char *, ...);
332
int	 execl(const char *, const char *, ...);
330
int	 execle(const char *, const char *, ...);
333
int	 execle(const char *, const char *, ...);
331
int	 execlp(const char *, const char *, ...);
334
int	 execlp(const char *, const char *, ...);
(-)lib/libc/sys/Makefile.inc (-1 / +1 lines)
Lines 132-138 Link Here
132
MLINKS+=clock_gettime.2 clock_getres.2 clock_gettime.2 clock_settime.2
132
MLINKS+=clock_gettime.2 clock_getres.2 clock_gettime.2 clock_settime.2
133
MLINKS+=cpuset.2 cpuset_getid.2 cpuset.2 cpuset_setid.2
133
MLINKS+=cpuset.2 cpuset_getid.2 cpuset.2 cpuset_setid.2
134
MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2
134
MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2
135
MLINKS+=dup.2 dup2.2
135
MLINKS+=dup.2 dup2.2 dup3.2
136
MLINKS+=execve.2 fexecve.2
136
MLINKS+=execve.2 fexecve.2
137
MLINKS+=extattr_get_file.2 extattr.2 \
137
MLINKS+=extattr_get_file.2 extattr.2 \
138
	extattr_get_file.2 extattr_delete_fd.2 \
138
	extattr_get_file.2 extattr_delete_fd.2 \
(-)lib/libc/sys/dup.2 (+103 lines)
Lines 43-48 Link Here
43
.Fn dup "int oldd"
43
.Fn dup "int oldd"
44
.Ft int
44
.Ft int
45
.Fn dup2 "int oldd" "int newd"
45
.Fn dup2 "int oldd" "int newd"
46
.In fcntl.h
47
.Ft int
48
.Fn dup3 "int oldd" "int newd" "int flags"
46
.Sh DESCRIPTION
49
.Sh DESCRIPTION
47
The
50
The
48
.Fn dup
51
.Fn dup
Lines 116-121 Link Here
116
.Fn dup2
119
.Fn dup2
117
is successful, and does nothing.
120
is successful, and does nothing.
118
.Pp
121
.Pp
122
The
123
.Fn dup3
124
function is otherwise much the same as
125
.Fn dup2
126
with the added ability to automatically set certain
127
important flags to the resulting new file descriptor.
128
.br
129
By setting the bit
130
.Dv O_CLOEXEC
131
in the flags one can mark the resulting file descriptor be
132
automatically closed during
133
.Fn execve
134
and other functions in the
135
.Fn exec*
136
family.
137
Since this feature is activated atomically inside the kernel
138
there is no risk that even in a threaded code another thread
139
could call any of the
140
.Fn exec*
141
functions before the descriptor has been marked to be closed.
142
.br
143
Setting the bit
144
.Dv O_NONBLOCK
145
in the flags marks the resulting file descriptor for non-blocking I/O.
146
.sp
147
There a couple of features in
148
.Fn dup3
149
which can have an impact on portability.
150
.br
151
Currently this implementation of
152
.Fn dup3
153
does not support the
154
.Nx
155
feature
156
.Dv O_NOSIGPIPE .
157
.br
158
Because the
159
.Fx
160
kernel can properly handle the case when
161
.Fa oldd
162
==
163
.Fa newd
164
this implementation of
165
.Fn dup3 
166
will not return an error like 
167
.Fn dup3 
168
on Linux when it receives two equal file descriptors as arguments.
169
Instead this implementation intentionally behaves like
170
.Fn dup3
171
in
172
.Nx
173
and sets the flags on the resulting file descriptor.
174
Thus any code that has worked on Linux should
175
work fine also on
176
.Fx
177
and/or
178
.Nx ,
179
but porting to the other direction may cause hiccups.
180
.Pp
181
Unlike the other two functions
182
.Fn dup3
183
is not implemented as a genuine system call but as a normal library function
184
depending on the features provided by the
185
.Fn fcntl
186
system call.
187
.Pp
119
The related
188
The related
120
.Xr cap_new 2
189
.Xr cap_new 2
121
system call allows file descriptors to be duplicated with restrictions on
190
system call allows file descriptors to be duplicated with restrictions on
Lines 138-143 Link Here
138
.It Bq Er EMFILE
207
.It Bq Er EMFILE
139
Too many descriptors are active.
208
Too many descriptors are active.
140
.El
209
.El
210
.sp
141
The
211
The
142
.Fn dup2
212
.Fn dup2
143
system call fails if:
213
system call fails if:
Lines 149-154 Link Here
149
.Fa newd
219
.Fa newd
150
argument is negative or exceeds the maximum allowable descriptor number
220
argument is negative or exceeds the maximum allowable descriptor number
151
.El
221
.El
222
.sp
223
The 
224
.Fn dup3
225
function fails if:
226
.Bl -tag -width Er
227
.It Bq Er EBADF
228
The
229
.Fa oldd
230
argument is not a valid active descriptor or the
231
.Fa newd
232
argument is negative or exceeds the maximum allowable descriptor number
233
.It Bq Er EINVAL
234
The
235
.Fa flags
236
argument containes unsupported bits.
237
Currently the only accepted bits are
238
.Dv O_CLOEXEC 
239
and
240
.Dv O_NONBLOCK .
241
.El
152
.Sh SEE ALSO
242
.Sh SEE ALSO
153
.Xr accept 2 ,
243
.Xr accept 2 ,
154
.Xr cap_new 2 ,
244
.Xr cap_new 2 ,
Lines 166-171 Link Here
166
.Fn dup2
256
.Fn dup2
167
system calls are expected to conform to
257
system calls are expected to conform to
168
.St -p1003.1-90 .
258
.St -p1003.1-90 .
259
.br
260
Currently the
261
.Fn dup3
262
entry is not dictated by any standard.
263
It is simply a natural extension the other two variants and
264
a compatibility feature to match a similar extension in other
265
UNIX like systems.
169
.Sh HISTORY
266
.Sh HISTORY
170
The
267
The
171
.Fn dup
268
.Fn dup
Lines 173-175 Link Here
173
.Fn dup2
270
.Fn dup2
174
functions appeared in
271
functions appeared in
175
.At v7 .
272
.At v7 .
273
.br
274
The
275
.Fn dup3
276
function appeared in
277
.Fx 9.1
278
STABLE branch.
(-)lib/libc/gen/dup3.c (+123 lines)
Added Link Here
1
/*-
2
 * Copyright (c) 2012 Jukka A. Ukkonen
3
 * All rights reserved.
4
 *
5
 * This software was developed by Jukka Ukkonen for FreeBSD.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include <sys/cdefs.h>
30
__FBSDID("$FreeBSD$");
31
32
#include "namespace.h"
33
#include <unistd.h>
34
#include <fcntl.h>
35
#include <errno.h>
36
#include "un-namespace.h"
37
38
/*
39
 * A bunch of checks just in case someone
40
 * tries to compile this on a too old system.
41
 */
42
43
#if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
44
#  define F_DUP2FD_CLOEXEC  _F_DUP2FD_CLOEXEC
45
#endif
46
47
#if !defined(F_DUP2FD_CLOEXEC)
48
#  error Neither F_DUP2FD_CLOEXEC nor _F_DUP2FD_CLOEXEC defined!
49
#endif
50
51
#if !defined(F_DUP2FD)
52
#  error F_DUP2FD not defined!
53
#endif
54
55
#if !defined(O_CLOEXEC)
56
#  error O_CLOEXEC not defined!
57
#endif
58
59
/*
60
 * In case FreeBSD ever becomes O_NOSIGPIPE aware,
61
 * we will instantly start using it.
62
 */
63
64
#if !defined(O_NOSIGPIPE)
65
#  define O_NOSIGPIPE	0
66
#endif
67
68
int
69
__dup3 (oldfd, newfd, flags)
70
	int oldfd;
71
	int newfd;
72
	int flags;
73
{
74
	int how;
75
	int ret;
76
77
#if 0
78
	/*
79
	 * This would be how Linux does it
80
	 * in pointlessly restrictive style.
81
	 * NetBSD does not do this.
82
	 * FreeBSD can also handle this case
83
	 * properly.
84
	 * ==> Anything which works on Linux
85
	 * will work also on {Free,Net}BSD.
86
	 * BSD code on Linux may experience
87
	 * hiccups, if someone relies on
88
	 * oldfd == newfd.
89
	 */
90
91
	if (oldfd == newfd) {
92
		errno = EINVAL;
93
		return (-1);
94
	}
95
#endif
96
97
	if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_NOSIGPIPE)) {
98
		errno = EINVAL;
99
		return (-1);
100
	}
101
102
	how = (flags & O_CLOEXEC) ? F_DUP2FD_CLOEXEC : F_DUP2FD;
103
104
	ret = _fcntl (oldfd, how, newfd);
105
106
	if (ret < 0)
107
		return (-1);
108
109
	newfd = ret;
110
111
	if (flags & (O_NONBLOCK | O_NOSIGPIPE)) {
112
		int flags2;
113
114
		flags2 = _fcntl (newfd, F_GETFL, 0);
115
		flags2 |= (flags & (O_NONBLOCK | O_NOSIGPIPE));
116
		(void) _fcntl (newfd, F_SETFL, flags2);
117
	}
118
119
	return (newfd);
120
}
121
122
__weak_reference(__dup3, dup3);
123
__weak_reference(__dup3, _dup3);

Return to bug 176233