On Fri, 2008-11-14 at 12:40 -0500, Michael Kerrisk wrote:
> > Here's the latest version, for review-n-test enjoyment:
>
> Andrew,
>
> I made a few small tweaks to the changelog: wording fixes, and para
> break fixes; other than that, changed the text to say that I rewrote
> (rather than updated) the test program. Please substitute it with the
> following.
>
> Cheers,
>
> Michael
Michael,
I just did a quick patch for your test to run on LTP. If you have no
issue(s), can we add this to LTP ?
LTP-list,
Can you also enrich this patch ?
--
diff -uprN
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c
---
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c
1970-01-01 05:30:00.000000000 +0530
+++
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c
2008-11-17 16:42:25.000000000 +0530
@@ -0,0 +1,293 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (C) 2008, Linux Foundation,
*/
+/* written by Michael Kerrisk <[EMAIL PROTECTED]>
*/
+/*
*/
+/* Licensed under the GNU GPLv2 or later.
*/
+/* This program is free software; you can redistribute it and/or
modify */
+/* it under the terms of the GNU General Public License as published by
*/
+/* the Free Software Foundation; either version 2 of the License, or
*/
+/* (at your option) any later version.
*/
+/*
*/
+/* This program is distributed in the hope that it will be useful,
*/
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
*/
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
*/
+/* the GNU General Public License for more details.
*/
+/*
*/
+/* You should have received a copy of the GNU General Public License
*/
+/* along with this program; if not, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA */
+/*
*/
+/******************************************************************************/
+
+/******************************************************************************/
+/*
*/
+/* File: accept4_01.c
*/
+/*
*/
+/* Description: This will test the newly introduced syscall accept4()
*/
+/*
*/
+/* Total Tests: 4
*/
+/*
*/
+/* Test Name: accept4_01
*/
+/*
*/
+/* Author: Michael Kerrisk <[EMAIL PROTECTED]>
*/
+/*
*/
+/* History: Created - Nov 17 2008 - Michael
<[EMAIL PROTECTED]> */
+/* Initial Porting to LTP
*/
+/* - Nov 17 2008 - Subrata
<[EMAIL PROTECTED]> */
+/*
*/
+/******************************************************************************/
+
+#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>
+
+#include "test.h"
+#include "usctest.h"
+
+#define PORT_NUM 33333
+
+#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 O_CLOEXEC
+# define O_CLOEXEC 02000000
+#endif
+
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC O_CLOEXEC
+#endif
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK O_NONBLOCK
+#endif
+
+#ifdef __x86_64__
+#define SYS_ACCEPT4 288
+#elif __i386__
+#define USE_SOCKETCALL 1
+#define SYS_ACCEPT4 18
+#else
+#error "Sorry -- don't know the syscall # on this architecture"
+#endif
+
+/* Extern Global Variables */
+extern int Tst_count; /* counter for tst_xxx routines.
*/
+extern char *TESTDIR; /* temporary dir created by
tst_tmpdir() */
+
+/* Global Variables */
+char *TCID = "accept04_01"; /* test program identifier. */
+int TST_TOTAL = 1; /* total number of tests in this
file. */
+
+/* Extern Global Functions */
+/******************************************************************************/
+/*
*/
+/* Function: cleanup
*/
+/*
*/
+/* Description: Performs all one time clean up for this test on
successful */
+/* completion, premature exit or failure. Closes all
temporary */
+/* files, removes all temporary directories exits the test
with */
+/* appropriate return code by calling tst_exit() function.
*/
+/*
*/
+/* Input: None.
*/
+/*
*/
+/* Output: None.
*/
+/*
*/
+/* Return: On failure - Exits calling tst_exit(). Non '0' return
code. */
+/* On success - Exits calling tst_exit(). With '0' return
code. */
+/*
*/
+/******************************************************************************/
+/* We would need this for many more reasons in future
*/
+extern void
+cleanup()
+{
+ /* Remove tmp dir and all files in it */
+ TEST_CLEANUP;
+ tst_rmdir();
+
+ /* Exit with appropriate return code. */
+ tst_exit();
+}
+
+
+/* Local Functions */
+/******************************************************************************/
+/*
*/
+/* Function: setup
*/
+/*
*/
+/* Description: Performs all one time setup for this test. This
function is */
+/* typically used to capture signals, create temporary
dirs */
+/* and temporary files that may be used in the course of
this */
+/* test.
*/
+/*
*/
+/* Input: None.
*/
+/*
*/
+/* Output: None.
*/
+/*
*/
+/* Return: On failure - Exits by calling cleanup().
*/
+/* On success - returns 0.
*/
+/*
*/
+/******************************************************************************/
+void
+setup()
+{
+ /* Capture signals if any */
+ /* Create temporary directories */
+ TEST_PAUSE;
+ tst_tmpdir();
+}
+
+
+static int
+accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int
flags)
+{
+ tst_resm(TINFO, "Calling accept4(): flags = %x", flags);
+ if (flags != 0) {
+ tst_resm(TINFO," (");
+ if (flags & SOCK_CLOEXEC)
+ tst_resm(TINFO,"SOCK_CLOEXEC");
+ if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK))
+ tst_resm(TINFO," ");
+ if (flags & SOCK_NONBLOCK)
+ tst_resm(TINFO,"SOCK_NONBLOCK");
+ tst_resm(TINFO,")");
+ }
+ tst_resm(TINFO,"\n");
+
+#if USE_SOCKETCALL
+ long args[6];
+
+ args[0] = fd;
+ args[1] = (long) sockaddr;
+ args[2] = (long) addrlen;
+ args[3] = flags;
+
+ return syscall(SYS_socketcall, SYS_ACCEPT4, args);
+#else
+ return syscall(SYS_accept4, fd, sockaddr, addrlen, flags);
+#endif
+}
+
+/**********************************************************************/
+
+
+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;
+
+ tst_resm(TINFO,"=======================================\n");
+
+ connfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (connfd == -1)
+ tst_brkm(TBROK, cleanup, "Socket Error");
+ if (connect(connfd, (struct sockaddr *) conn_addr,
+ sizeof(struct sockaddr_in)) == -1)
+ tst_brkm(TBROK, cleanup, "Connect Error");
+
+ addrlen = sizeof(struct sockaddr_in);
+ acceptfd = accept4(lfd, (struct sockaddr *) &claddr, &addrlen,
+ closeonexec_flag | nonblock_flag);
+ if (acceptfd == -1) {
+ tst_brkm(TBROK, cleanup, "accept4() Error");
+ close(connfd);
+ return 0;
+ }
+
+ fdf = fcntl(acceptfd, F_GETFD);
+ if (fdf == -1)
+ tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
+ fdf_pass = ((fdf & FD_CLOEXEC) != 0) ==
+ ((closeonexec_flag & SOCK_CLOEXEC) != 0);
+ tst_resm(TINFO, "Close-on-exec flag is %sset (%s); ", (fdf &
FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed");
+
+ flf = fcntl(acceptfd, F_GETFL);
+ if (flf == -1)
+ tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
+ flf_pass = ((flf & O_NONBLOCK) != 0) ==
+ ((nonblock_flag & SOCK_NONBLOCK) !=0);
+ tst_resm(TINFO, "nonblock flag is %sset (%s)\n", (flf &
O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed");
+
+ close(acceptfd);
+ close(connfd);
+
+ tst_resm(TINFO, "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)
+ tst_brkm(TBROK, cleanup, "Socket Error");
+
+ optval = 1;
+ if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(optval)) == -1)
+ tst_brkm(TBROK, cleanup, "Setsockopt Error");
+
+ if (bind(lfd, (struct sockaddr *) &svaddr,
+ sizeof(struct sockaddr_in)) == -1)
+ tst_brkm(TBROK, cleanup, "Bind Error");
+
+ if (listen(lfd, 5) == -1)
+ tst_brkm(TBROK, cleanup, "Listen Error");
+
+ return lfd;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ struct sockaddr_in conn_addr;
+ int lfd;
+ int port_num;
+ int passed=1;
+
+ setup();
+ 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);
+}
diff -uprN
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile
---
ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile
1970-01-01 05:30:00.000000000 +0530
+++ ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile
2008-11-17 16:32:49.000000000 +0530
@@ -0,0 +1,31 @@
+#
+# Copyright (c) International Business Machines Corp., 2008
+#
+# This program is free software; you can redistribute it and/or
modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
+#
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp
+
+SRCS = $(wildcard *.c)
+TARGETS = $(patsubst %.c,%,$(SRCS))
+
+all: $(TARGETS)
+
+install:
+ @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
+
+clean:
+ rm -f $(TARGETS)
--- ltp-intermediate-20081117/runtest/syscalls.orig 2008-11-17
16:38:43.000000000 +0530
+++ ltp-intermediate-20081117/runtest/syscalls 2008-11-17
16:39:10.000000000 +0530
@@ -2,6 +2,7 @@
abort01 ulimit -c 1024;abort01
accept01 accept01
+accept4_01 accept4_01
access01 access01
access02 access02
Regards--
Subrata
>
> ===
> From: Ulrich Drepper <[EMAIL PROTECTED]>
>
> Introduce a new accept4() system call. The addition of this system call
> matches analogous changes in 2.6.27 (dup3(), evenfd2(), signalfd4(),
> inotify_init1(), epoll_create1(), pipe2()) which added new system calls
> that differed from analogous traditional system calls in adding a flags
> argument that can be used to access additional functionality.
>
> The accept4() system call is exactly the same as accept(), except that
> it adds a flags bit-mask argument. Two flags are initially implemented.
> (Most of the new system calls in 2.6.27 also had both of these flags.)
>
> SOCK_CLOEXEC causes the close-on-exec (FD_CLOEXEC) flag to be enabled
> for the new file descriptor returned by accept4(). This is a useful
> security feature to avoid leaking information in a multithreaded
> program where one thread is doing an accept() at the same time as
> another thread is doing a fork() plus exec(). More details here:
> http://udrepper.livejournal.com/20407.html "Secure File Descriptor Handling",
> Ulrich Drepper).
>
> The other flag is SOCK_NONBLOCK, which causes the O_NONBLOCK flag
> to be enabled on the new open file description created by accept4().
> (This flag is merely a convenience, saving the use of additional calls
> fcntl(F_GETFL) and fcntl (F_SETFL) to achieve the same result.
>
> Here's a test program. Works on x86-32. Should work on x86-64, but
> I (mtk) don't have a system to hand to test with.
>
> It tests accept4() with each of the four possible combinations of
> SOCK_CLOEXEC and SOCK_NONBLOCK set/clear in 'flags', and verifies
> that the appropriate flags are set on the file descriptor/open file
> description returned by accept4().
>
> I tested Ulrich's patch in this thread by applying against 2.6.28-rc2,
> and it passes according to my test program.
>
> /* test_accept4.c
>
> Copyright (C) 2008, Linux Foundation, written by Michael Kerrisk
> <[EMAIL PROTECTED]>
>
> 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 33333
>
> #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_CLOEXEC O_CLOEXEC
> #endif
> #ifndef SOCK_NONBLOCK
> #define SOCK_NONBLOCK O_NONBLOCK
> #endif
>
> #ifdef __x86_64__
> #define SYS_accept4 288
> #elif __i386__
> #define USE_SOCKETCALL 1
> #define SYS_ACCEPT4 18
> #else
> #error "Sorry -- don't know the syscall # on this architecture"
> #endif
>
> 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");
>
> #if USE_SOCKETCALL
> long args[6];
>
> args[0] = fd;
> args[1] = (long) sockaddr;
> args[2] = (long) addrlen;
> args[3] = flags;
>
> return syscall(SYS_socketcall, SYS_ACCEPT4, args);
> #else
> return syscall(SYS_accept4, fd, sockaddr, addrlen, flags);
> #endif
> }
>
> /**********************************************************************/
>
>
> 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);
> }
>
> [EMAIL PROTECTED]: rewrote changelog and test program]
> Signed-off-by: Ulrich Drepper <[EMAIL PROTECTED]>
> Tested-by: Michael Kerrisk <[EMAIL PROTECTED]>
> Acked-by: Michael Kerrisk <[EMAIL PROTECTED]>
> Cc: <[EMAIL PROTECTED]>
> Cc: <[EMAIL PROTECTED]>
> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
diff -uprN ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c
--- ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c 1970-01-01 05:30:00.000000000 +0530
+++ ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c 2008-11-17 16:42:25.000000000 +0530
@@ -0,0 +1,293 @@
+/******************************************************************************/
+/* */
+/* Copyright (C) 2008, Linux Foundation, */
+/* written by Michael Kerrisk <[EMAIL PROTECTED]> */
+/* */
+/* Licensed under the GNU GPLv2 or later. */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
+/* the GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/******************************************************************************/
+
+/******************************************************************************/
+/* */
+/* File: accept4_01.c */
+/* */
+/* Description: This will test the newly introduced syscall accept4() */
+/* */
+/* Total Tests: 4 */
+/* */
+/* Test Name: accept4_01 */
+/* */
+/* Author: Michael Kerrisk <[EMAIL PROTECTED]> */
+/* */
+/* History: Created - Nov 17 2008 - Michael <[EMAIL PROTECTED]> */
+/* Initial Porting to LTP */
+/* - Nov 17 2008 - Subrata <[EMAIL PROTECTED]> */
+/* */
+/******************************************************************************/
+
+#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>
+
+#include "test.h"
+#include "usctest.h"
+
+#define PORT_NUM 33333
+
+#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 O_CLOEXEC
+# define O_CLOEXEC 02000000
+#endif
+
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC O_CLOEXEC
+#endif
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK O_NONBLOCK
+#endif
+
+#ifdef __x86_64__
+#define SYS_ACCEPT4 288
+#elif __i386__
+#define USE_SOCKETCALL 1
+#define SYS_ACCEPT4 18
+#else
+#error "Sorry -- don't know the syscall # on this architecture"
+#endif
+
+/* Extern Global Variables */
+extern int Tst_count; /* counter for tst_xxx routines. */
+extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */
+
+/* Global Variables */
+char *TCID = "accept04_01"; /* test program identifier. */
+int TST_TOTAL = 1; /* total number of tests in this file. */
+
+/* Extern Global Functions */
+/******************************************************************************/
+/* */
+/* Function: cleanup */
+/* */
+/* Description: Performs all one time clean up for this test on successful */
+/* completion, premature exit or failure. Closes all temporary */
+/* files, removes all temporary directories exits the test with */
+/* appropriate return code by calling tst_exit() function. */
+/* */
+/* Input: None. */
+/* */
+/* Output: None. */
+/* */
+/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */
+/* On success - Exits calling tst_exit(). With '0' return code. */
+/* */
+/******************************************************************************/
+/* We would need this for many more reasons in future */
+extern void
+cleanup()
+{
+ /* Remove tmp dir and all files in it */
+ TEST_CLEANUP;
+ tst_rmdir();
+
+ /* Exit with appropriate return code. */
+ tst_exit();
+}
+
+
+/* Local Functions */
+/******************************************************************************/
+/* */
+/* Function: setup */
+/* */
+/* Description: Performs all one time setup for this test. This function is */
+/* typically used to capture signals, create temporary dirs */
+/* and temporary files that may be used in the course of this */
+/* test. */
+/* */
+/* Input: None. */
+/* */
+/* Output: None. */
+/* */
+/* Return: On failure - Exits by calling cleanup(). */
+/* On success - returns 0. */
+/* */
+/******************************************************************************/
+void
+setup()
+{
+ /* Capture signals if any */
+ /* Create temporary directories */
+ TEST_PAUSE;
+ tst_tmpdir();
+}
+
+
+static int
+accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int flags)
+{
+ tst_resm(TINFO, "Calling accept4(): flags = %x", flags);
+ if (flags != 0) {
+ tst_resm(TINFO," (");
+ if (flags & SOCK_CLOEXEC)
+ tst_resm(TINFO,"SOCK_CLOEXEC");
+ if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK))
+ tst_resm(TINFO," ");
+ if (flags & SOCK_NONBLOCK)
+ tst_resm(TINFO,"SOCK_NONBLOCK");
+ tst_resm(TINFO,")");
+ }
+ tst_resm(TINFO,"\n");
+
+#if USE_SOCKETCALL
+ long args[6];
+
+ args[0] = fd;
+ args[1] = (long) sockaddr;
+ args[2] = (long) addrlen;
+ args[3] = flags;
+
+ return syscall(SYS_socketcall, SYS_ACCEPT4, args);
+#else
+ return syscall(SYS_accept4, fd, sockaddr, addrlen, flags);
+#endif
+}
+
+/**********************************************************************/
+
+
+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;
+
+ tst_resm(TINFO,"=======================================\n");
+
+ connfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (connfd == -1)
+ tst_brkm(TBROK, cleanup, "Socket Error");
+ if (connect(connfd, (struct sockaddr *) conn_addr,
+ sizeof(struct sockaddr_in)) == -1)
+ tst_brkm(TBROK, cleanup, "Connect Error");
+
+ addrlen = sizeof(struct sockaddr_in);
+ acceptfd = accept4(lfd, (struct sockaddr *) &claddr, &addrlen,
+ closeonexec_flag | nonblock_flag);
+ if (acceptfd == -1) {
+ tst_brkm(TBROK, cleanup, "accept4() Error");
+ close(connfd);
+ return 0;
+ }
+
+ fdf = fcntl(acceptfd, F_GETFD);
+ if (fdf == -1)
+ tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
+ fdf_pass = ((fdf & FD_CLOEXEC) != 0) ==
+ ((closeonexec_flag & SOCK_CLOEXEC) != 0);
+ tst_resm(TINFO, "Close-on-exec flag is %sset (%s); ", (fdf & FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed");
+
+ flf = fcntl(acceptfd, F_GETFL);
+ if (flf == -1)
+ tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
+ flf_pass = ((flf & O_NONBLOCK) != 0) ==
+ ((nonblock_flag & SOCK_NONBLOCK) !=0);
+ tst_resm(TINFO, "nonblock flag is %sset (%s)\n", (flf & O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed");
+
+ close(acceptfd);
+ close(connfd);
+
+ tst_resm(TINFO, "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)
+ tst_brkm(TBROK, cleanup, "Socket Error");
+
+ optval = 1;
+ if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(optval)) == -1)
+ tst_brkm(TBROK, cleanup, "Setsockopt Error");
+
+ if (bind(lfd, (struct sockaddr *) &svaddr,
+ sizeof(struct sockaddr_in)) == -1)
+ tst_brkm(TBROK, cleanup, "Bind Error");
+
+ if (listen(lfd, 5) == -1)
+ tst_brkm(TBROK, cleanup, "Listen Error");
+
+ return lfd;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ struct sockaddr_in conn_addr;
+ int lfd;
+ int port_num;
+ int passed=1;
+
+ setup();
+ 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);
+}
diff -uprN ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile
--- ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile 1970-01-01 05:30:00.000000000 +0530
+++ ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile 2008-11-17 16:32:49.000000000 +0530
@@ -0,0 +1,31 @@
+#
+# Copyright (c) International Business Machines Corp., 2008
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp
+
+SRCS = $(wildcard *.c)
+TARGETS = $(patsubst %.c,%,$(SRCS))
+
+all: $(TARGETS)
+
+install:
+ @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
+
+clean:
+ rm -f $(TARGETS)
--- ltp-intermediate-20081117/runtest/syscalls.orig 2008-11-17 16:38:43.000000000 +0530
+++ ltp-intermediate-20081117/runtest/syscalls 2008-11-17 16:39:10.000000000 +0530
@@ -2,6 +2,7 @@
abort01 ulimit -c 1024;abort01
accept01 accept01
+accept4_01 accept4_01
access01 access01
access02 access02
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list