]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/accept4.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / accept4.c
CommitLineData
d4697bc9 1/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
bdcebfc4
UD
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2008.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
bdcebfc4
UD
18
19#include <errno.h>
20#include <signal.h>
21#include <sys/socket.h>
22
23#include <sysdep-cancel.h>
24#include <sys/syscall.h>
1e1dc4e8 25#include <kernel-features.h>
bdcebfc4 26
f93fc0b7
UD
27
28#ifdef __NR_accept4
bdcebfc4 29int
f93fc0b7 30accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
bdcebfc4
UD
31{
32 if (SINGLE_THREAD_P)
f93fc0b7 33 return INLINE_SYSCALL (accept4, 4, fd, addr.__sockaddr__, addr_len, flags);
bdcebfc4
UD
34
35 int oldtype = LIBC_CANCEL_ASYNC ();
36
f93fc0b7
UD
37 int result = INLINE_SYSCALL (accept4, 4, fd, addr.__sockaddr__, addr_len,
38 flags);
bdcebfc4
UD
39
40 LIBC_CANCEL_RESET (oldtype);
41
42 return result;
43}
1e1dc4e8
JJ
44#elif defined __NR_socketcall
45# ifndef __ASSUME_ACCEPT4
46extern int __internal_accept4 (int fd, __SOCKADDR_ARG addr,
47 socklen_t *addr_len, int flags)
48 attribute_hidden;
49
50static int have_accept4;
51
52int
53accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
54{
55 if (__builtin_expect (have_accept4 >= 0, 1))
56 {
57 int ret = __internal_accept4 (fd, addr, addr_len, flags);
58 /* The kernel returns -EINVAL for unknown socket operations.
59 We need to convert that error to an ENOSYS error. */
60 if (__builtin_expect (ret < 0, 0)
61 && have_accept4 == 0
62 && errno == EINVAL)
63 {
64 /* Try another call, this time with the FLAGS parameter
65 cleared and an invalid file descriptor. This call will not
66 cause any harm and it will return immediately. */
67 ret = __internal_accept4 (-1, addr, addr_len, 0);
68 if (errno == EINVAL)
69 {
70 have_accept4 = -1;
71 __set_errno (ENOSYS);
72 }
73 else
74 {
75 have_accept4 = 1;
76 __set_errno (EINVAL);
77 }
78 return -1;
79 }
80 return ret;
81 }
82 __set_errno (ENOSYS);
83 return -1;
84}
85# else
86/* When __ASSUME_ACCEPT4 accept4 is defined in internal_accept4.S. */
87# endif
bdcebfc4
UD
88#else
89int
f93fc0b7 90accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
bdcebfc4
UD
91{
92 __set_errno (ENOSYS);
93 return -1;
bdcebfc4 94}
f93fc0b7 95stub_warning (accept4)
bdcebfc4 96#endif