From: Émeric Maschino emeric.masch...@gmail.com
Subject: ia64: Add accept4() syscall
While debugging udev 170 failure on Debian Wheezy
(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=648325), it appears
that the issue was in fact due to missing accept4() in ia64.
This patch simply adds accept4() to ia64. The
arch/ia64/include/asm/unistd.h and arch/ia64/kernel/entry.S diffs
apply cleanly against 3.2-rc1.
Patch has been successfully tested running an ia64-targeted version of
test_accept4.c (modified from x86/x86_64-centric original version from
http://git.kernel.org/linus/de11defebf7677fb7ee91d9b089b78786fbb):
/* test_accept4.c
Copyright (C) 2008, Linux Foundation, written by Michael Kerrisk
mtk.manpa...@gmail.com
Licensed under the GNU GPLv2 or later.
*/
#define _GNU_SOURCE
#include unistd.h
#include sys/syscall.h
#include sys/socket.h
#include netinet/in.h
#include stdlib.h
#include fcntl.h
#include stdio.h
#include string.h
#define PORT_NUM 3
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
/**/
/* The following is what we need until glibc gets a wrapper for
accept4() */
/* Flags for socket(), socketpair(), accept4() */
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXECO_CLOEXEC
#endif
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK O_NONBLOCK
#endif
#define __NR_accept4 1334
static int
__accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int flags)
{
printf(Calling accept4(): flags = %x, flags);
if (flags != 0) {
printf( ();
if (flags SOCK_CLOEXEC)
printf(SOCK_CLOEXEC);
if ((flags SOCK_CLOEXEC) (flags SOCK_NONBLOCK))
printf( );
if (flags SOCK_NONBLOCK)
printf(SOCK_NONBLOCK);
printf());
}
printf(\n);
return syscall(__NR_accept4, fd, sockaddr, addrlen, flags);
}
/**/
static int
do_test(int lfd, struct sockaddr_in *conn_addr,
int closeonexec_flag, int nonblock_flag)
{
int connfd, acceptfd;
int fdf, flf, fdf_pass, flf_pass;
struct sockaddr_in claddr;
socklen_t addrlen;
printf(===\n);
connfd = socket(AF_INET, SOCK_STREAM, 0);
if (connfd == -1)
die(socket);
if (connect(connfd, (struct sockaddr *) conn_addr,
sizeof(struct sockaddr_in)) == -1)
die(connect);
addrlen = sizeof(struct sockaddr_in);
acceptfd = __accept4(lfd, (struct sockaddr *) claddr, addrlen,
closeonexec_flag | nonblock_flag);
if (acceptfd == -1) {
perror(accept4());
close(connfd);
return 0;
}
fdf = fcntl(acceptfd, F_GETFD);
if (fdf == -1)
die(fcntl:F_GETFD);
fdf_pass = ((fdf FD_CLOEXEC) != 0) ==
((closeonexec_flag SOCK_CLOEXEC) != 0);
printf(Close-on-exec flag is %sset (%s); ,
(fdf FD_CLOEXEC) ? : not ,
fdf_pass ? OK : failed);
flf = fcntl(acceptfd, F_GETFL);
if (flf == -1)
die(fcntl:F_GETFD);
flf_pass = ((flf O_NONBLOCK) != 0) ==
((nonblock_flag SOCK_NONBLOCK) !=0);
printf(nonblock flag is %sset (%s)\n,
(flf O_NONBLOCK) ? : not ,
flf_pass ? OK : failed);
close(acceptfd);
close(connfd);
printf(Test result: %s\n, (fdf_pass flf_pass) ? PASS : FAIL);
return fdf_pass flf_pass;
}
static int
create_listening_socket(int port_num)
{
struct sockaddr_in svaddr;
int lfd;
int optval;
memset(svaddr, 0, sizeof(struct sockaddr_in));
svaddr.sin_family = AF_INET;
svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
svaddr.sin_port = htons(port_num);
lfd = socket(AF_INET, SOCK_STREAM, 0);
if (lfd == -1)
die(socket);
optval = 1;
if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, optval,
sizeof(optval)) == -1)
die(setsockopt);
if (bind(lfd, (struct sockaddr *) svaddr,
sizeof(struct sockaddr_in)) == -1)
die(bind);
if (listen(lfd, 5) == -1)
die(listen);
return lfd;
}
int
main(int argc, char *argv[])
{
struct sockaddr_in conn_addr;
int lfd;
int port_num;
int passed;
passed = 1;
port_num = (argc 1) ? atoi(argv[1]) : PORT_NUM;
memset(conn_addr, 0, sizeof(struct sockaddr_in));
conn_addr.sin_family = AF_INET;
conn_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
conn_addr.sin_port = htons(port_num);
lfd = create_listening_socket(port_num);
if (!do_test(lfd, conn_addr, 0, 0))
passed = 0;
if (!do_test(lfd, conn_addr, SOCK_CLOEXEC, 0))
passed = 0;
if (!do_test(lfd, conn_addr, 0, SOCK_NONBLOCK))
passed = 0;
if (!do_test(lfd, conn_addr, SOCK_CLOEXEC, SOCK_NONBLOCK))
passed = 0;
close(lfd);
exit(passed ? EXIT_SUCCESS : EXIT_FAILURE);
}
Signed-off-by: Émeric Maschino emeric.masch...@gmail.com
---
diff -uprN -X