[LTP] [PATCH v3] recvmsg01: Refactor using new LTP API

Wei Gao wegao@suse.com
Sun Apr 30 08:04:19 CEST 2023


---
 testcases/kernel/syscalls/recvmsg/recvmsg01.c | 717 +++++++++---------
 1 file changed, 345 insertions(+), 372 deletions(-)

diff --git a/testcases/kernel/syscalls/recvmsg/recvmsg01.c b/testcases/kernel/syscalls/recvmsg/recvmsg01.c
index 3ce7ab027..e77a12400 100644
--- a/testcases/kernel/syscalls/recvmsg/recvmsg01.c
+++ b/testcases/kernel/syscalls/recvmsg/recvmsg01.c
@@ -1,364 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) 2001 Wayne Boyer International Business Machines
+ * Copyright (c) Linux Test Project, 2002-2022
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
  */
 
-/*
- * Test Name: recvmsg01
- *
- * Test Description:
- *  Verify that recvmsg() returns the proper errno for various failure cases
- *
- * Usage:  <for command-line>
- *  recvmsg01 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *     where,  -c n : Run n copies concurrently.
- *             -e   : Turn on errno logging.
- *	       -i n : Execute test n times.
- *	       -I x : Execute test for x seconds.
- *	       -P x : Pause for x seconds between iterations.
- *	       -t   : Turn on syscall timing.
- *
- * HISTORY
- *	07/2001 Ported by Wayne Boyer
- *
- * RESTRICTIONS:
- *  None.
+/*\
+ * [Description]
  *
+ * Verify that recvmsg() returns the proper errno for various failure cases.
  */
 
 #include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-
+#include <stdlib.h>
 #include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/signal.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <sys/file.h>
-
-#include <netinet/in.h>
-
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "recvmsg01";
-int testno;
-
-char buf[1024], cbuf[1024];
-int s;				/* socket descriptor */
-int passed_fd = -1;		/* rights-passing test descriptor */
-struct sockaddr_in sin1, from;
-struct sockaddr_un sun1;
-struct msghdr msgdat;
-struct cmsghdr *control = 0;
-int controllen = 0;
-struct iovec iov[1];
+#include "tst_test.h"
+
+#define MSG "from recvmsg01 server"
+#define BUF_SIZE 1024
+#define CONTROL_LEN (128 * 1024)
+
+static char recv_buf[BUF_SIZE], cbuf[BUF_SIZE];
+static int sock;
+static struct sockaddr_in sin1, from;
+static struct sockaddr_un sun1;
+static struct msghdr msgdat;
+static struct cmsghdr *control;
+static int controllen;
+static struct iovec iov[1];
 static int sfd;			/* shared between do_child and start_server */
 static int ufd;			/* shared between do_child and start_server */
-
-void setup(void);
-void setup0(void);
-void setup1(void);
-void setup2(void);
-void setup3(void);
-void setup4(void);
-void cleanup(void);
-void cleanup0(void);
-void cleanup1(void);
-void cleanup2(void);
-void do_child(void);
-
-void sender(int);
-pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
-
-struct test_case_t {		/* test case structure */
-	int domain;		/* PF_INET, PF_UNIX, ... */
-	int type;		/* SOCK_STREAM, SOCK_DGRAM ... */
-	int proto;		/* protocol number (usually 0 = default) */
+static pid_t pid;
+static char tmpsunpath[BUF_SIZE];
+
+static void setup_all(void);
+static void setup_invalid_sock(int);
+static void setup_valid_sock(int);
+static void setup_valid_msg_control(int);
+static void setup_large_msg_control(int);
+static void cleanup_all(void);
+static void cleanup_invalid_sock(int);
+static void cleanup_close_sock(int);
+static void cleanup_reset_all(int);
+static void do_child(void);
+static pid_t start_server(struct sockaddr_in *, struct sockaddr_un *);
+
+static struct tcase {
+	int domain;
+	int type;
+	int protocol;
 	struct iovec *iov;
 	int iovcnt;
-	void *buf;		/* recv data buffer */
-	int buflen;		/* recv buffer length */
+	void *recv_buf;
+	int buflen;
 	struct msghdr *msg;
-	unsigned flags;
-	struct sockaddr *from;	/* from address */
-	int fromlen;		/* from address value/result buffer length */
-	int retval;		/* syscall return value */
-	int experrno;		/* expected errno */
-	void (*setup) (void);
-	void (*cleanup) (void);
+	unsigned int flags;
+	struct sockaddr *from;
+	int fromlen;
+	int ret;
+	int exp_errno;
+	void (*setup)(int n);
+	void (*cleanup)(int n);
 	char *desc;
-} tdat[] = {
-/* 1 */
-	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, buf, sizeof(buf), &msgdat, 0,
-		    (struct sockaddr *)&from, sizeof(from),
-		    -1, EBADF, setup0, cleanup0, "bad file descriptor"}
-	,
-/* 2 */
+} tcases[] = {
 	{
-	0, 0, 0, iov, 1, (void *)buf, sizeof(buf), &msgdat, 0,
-		    (struct sockaddr *)&from, sizeof(from),
-		    -1, ENOTSOCK, setup0, cleanup0, "invalid socket"}
-	,
-/* 3 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EBADF,
+		.setup = setup_invalid_sock,
+		.cleanup = cleanup_invalid_sock,
+		.desc = "bad file descriptor",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)-1, sizeof(from), 0,
-		    ENOTSOCK, setup1, cleanup1, "invalid socket buffer"}
-	,
-/* 4 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = (void *)recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = ENOTSOCK,
+		.setup = setup_invalid_sock,
+		.cleanup = cleanup_invalid_sock,
+		.desc = "invalid socket",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, -1, (struct sockaddr *)&from, -1, -1,
-		    EINVAL, setup1, cleanup1, "invalid socket length"},
-/* 5 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = (void *)recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.flags = -1,
+		.from = (struct sockaddr *)&from,
+		.fromlen = -1,
+		.ret = -1,
+		.exp_errno = EINVAL,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid socket length",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, (void *)-1, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    -1, EFAULT, setup1, cleanup1, "invalid recv buffer"}
-	,
-/* 6 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = (void *)-1,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EFAULT,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid recv buffer",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, 0, 1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    -1, EFAULT, setup1, cleanup1, "invalid iovec buffer"}
-	,
-/* 7 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EFAULT,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid iovec buffer",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, -1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    -1, EMSGSIZE, setup1, cleanup1, "invalid iovec count"}
-	,
-/* 8 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = -1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EMSGSIZE,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid iovec count",
+	},
 	{
-	PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    0, 0, setup2, cleanup2, "rights reception"}
-	,
-/* 9 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.setup = setup_valid_msg_control,
+		.cleanup = cleanup_reset_all,
+		.desc = "rights reception",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, MSG_OOB, (struct sockaddr *)&from,
-		    sizeof(from), -1, EINVAL, setup1, cleanup1,
-		    "invalid MSG_OOB flag set"}
-	,
-/* 10 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.flags = MSG_OOB,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EINVAL,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid MSG_OOB flag set",
+	},
 	{
-	PF_INET, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, MSG_ERRQUEUE, (struct sockaddr *)&from,
-		    sizeof(from), -1, EAGAIN, setup1, cleanup1,
-		    "invalid MSG_ERRQUEUE flag set"}
-	,
-/* 11 */
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.flags = MSG_ERRQUEUE,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.ret = -1,
+		.exp_errno = EAGAIN,
+		.setup = setup_valid_sock,
+		.cleanup = cleanup_close_sock,
+		.desc = "invalid MSG_ERRQUEUE flag set",
+	},
 	{
-	PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    0, EINVAL, setup3, cleanup2, "invalid cmsg length"}
-	,
-/* 12 */
-	{
-	PF_UNIX, SOCK_STREAM, 0, iov, 1, (void *)buf, sizeof(buf),
-		    &msgdat, 0, (struct sockaddr *)&from, sizeof(from),
-		    0, 0, setup4, cleanup2, "large cmesg length"}
-,};
-
-int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
+		.domain = PF_INET,
+		.type = SOCK_STREAM,
+		.iov = iov,
+		.iovcnt = 1,
+		.recv_buf = recv_buf,
+		.buflen = sizeof(recv_buf),
+		.msg = &msgdat,
+		.from = (struct sockaddr *)&from,
+		.fromlen = sizeof(from),
+		.setup = setup_large_msg_control,
+		.cleanup = cleanup_reset_all,
+		.desc = "large cmesg length",
+	},
+
+};
+
+static void run(unsigned int n)
+{
+	setup_all();
 
-#ifdef UCLINUX
-static char *argv0;
-#endif
+	struct tcase *tc = &tcases[n];
 
-int main(int argc, char *argv[])
-{
-	int lc;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-#ifdef UCLINUX
-	argv0 = argv[0];
-	maybe_run_child(&do_child, "dd", &sfd, &ufd);
-#endif
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); ++lc) {
-		tst_count = 0;
-		for (testno = 0; testno < TST_TOTAL; ++testno) {
-			if ((tst_kvercmp(3, 17, 0) < 0)
-			    && (tdat[testno].flags & MSG_ERRQUEUE)
-			    && (tdat[testno].type & SOCK_STREAM)) {
-				tst_resm(TCONF, "skip MSG_ERRQUEUE test, "
-						"it's supported from 3.17");
-				continue;
-			}
+	if ((tst_kvercmp(3, 17, 0) < 0)
+			&& (tc->flags & MSG_ERRQUEUE)
+			&& (tc->type & SOCK_STREAM)) {
+		tst_res(TCONF, "MSG_ERRQUEUE requires kernel >= 3.17");
+	}
 
-			tdat[testno].setup();
-
-			/* setup common to all tests */
-			iov[0].iov_base = tdat[testno].buf;
-			iov[0].iov_len = tdat[testno].buflen;
-			msgdat.msg_name = tdat[testno].from;
-			msgdat.msg_namelen = tdat[testno].fromlen;
-			msgdat.msg_iov = tdat[testno].iov;
-			msgdat.msg_iovlen = tdat[testno].iovcnt;
-			msgdat.msg_control = control;
-			msgdat.msg_controllen = controllen;
-			msgdat.msg_flags = 0;
-
-			TEST(recvmsg(s, tdat[testno].msg, tdat[testno].flags));
-			if (TEST_RETURN >= 0)
-				TEST_RETURN = 0;	/* all nonzero equal here */
-			if (TEST_RETURN != tdat[testno].retval ||
-			    (TEST_RETURN < 0 &&
-			     TEST_ERRNO != tdat[testno].experrno)) {
-				tst_resm(TFAIL, "%s ; returned"
-					 " %ld (expected %d), errno %d (expected"
-					 " %d)", tdat[testno].desc,
-					 TEST_RETURN, tdat[testno].retval,
-					 TEST_ERRNO, tdat[testno].experrno);
-			} else {
-				tst_resm(TPASS, "%s successful",
-					 tdat[testno].desc);
-			}
-			tdat[testno].cleanup();
-		}
+	tc->setup(n);
+
+	iov[0].iov_base = tc->recv_buf;
+	iov[0].iov_len = tc->buflen;
+	msgdat.msg_name = tc->from;
+	msgdat.msg_namelen = tc->fromlen;
+	msgdat.msg_iov = tc->iov;
+	msgdat.msg_iovlen = tc->iovcnt;
+	msgdat.msg_control = control;
+	msgdat.msg_controllen = controllen;
+	msgdat.msg_flags = 0;
+
+	TEST(recvmsg(sock, tc->msg, tc->flags));
+	if (TST_RET >= 0)
+		TST_RET = 0;
+
+	if (TST_RET != tc->ret) {
+		tst_res(TFAIL | TTERRNO, "%s: expected %d, returned %ld",
+			tc->desc, tc->ret, TST_RET);
+	} else if (TST_ERR != tc->exp_errno) {
+		tst_res(TFAIL | TTERRNO,
+			"%s: expected %s",
+			tc->desc, tst_strerrno(tc->exp_errno));
+	} else {
+		tst_res(TPASS, "%s passed", tc->desc);
 	}
-	cleanup();
 
-	tst_exit();
+	tc->cleanup(n);
+	cleanup_all();
 }
 
-pid_t pid;
-char tmpsunpath[1024];
 
-void setup(void)
+static void setup_all(void)
 {
 	int tfd;
-	TEST_PAUSE;
 
-	tst_tmpdir();
+	sun1.sun_family = AF_UNIX;
+
 	(void)strcpy(tmpsunpath, "udsockXXXXXX");
 	tfd = mkstemp(tmpsunpath);
-	close(tfd);
-	unlink(tmpsunpath);
-	sun1.sun_family = AF_UNIX;
+	SAFE_CLOSE(tfd);
+	SAFE_UNLINK(tmpsunpath);
 	(void)strcpy(sun1.sun_path, tmpsunpath);
-
-	signal(SIGPIPE, SIG_IGN);
-
+	SAFE_SIGNAL(SIGPIPE, SIG_IGN);
 	pid = start_server(&sin1, &sun1);
 }
 
-void cleanup(void)
+static void cleanup_all(void)
 {
 	if (pid > 0) {
 		(void)kill(pid, SIGKILL);	/* kill server */
 		wait(NULL);
 	}
 	if (tmpsunpath[0] != '\0')
-		(void)unlink(tmpsunpath);
-	tst_rmdir();
-
+		(void)SAFE_UNLINK(tmpsunpath);
 }
 
-void setup0(void)
+static void setup_invalid_sock(int n)
 {
-	if (tdat[testno].experrno == EBADF)
-		s = 400;	/* anything not an open file */
-	else if ((s = open("/dev/null", O_WRONLY)) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "open(/dev/null) failed");
+	if (tcases[n].exp_errno == EBADF)
+		sock = 400;	/* anything not an open file */
+	else
+		sock = SAFE_OPEN("/dev/null", O_WRONLY);
 }
 
-void cleanup0(void)
+static void cleanup_invalid_sock(int n)
 {
-	s = -1;
+	if (tcases[n].exp_errno == EBADF)
+		sock = -1;
+	else
+		SAFE_CLOSE(sock);
 }
 
-void setup1(void)
+static void setup_valid_sock(int n)
 {
 	fd_set rdfds;
 	struct timeval timeout;
-	int n;
 
-	s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type,
-			tdat[testno].proto);
-	if (tdat[testno].type == SOCK_STREAM) {
-		if (tdat[testno].domain == PF_INET) {
-			SAFE_CONNECT(cleanup, s, (struct sockaddr *)&sin1,
+	sock = SAFE_SOCKET(tcases[n].domain, tcases[n].type,
+			tcases[n].protocol);
+	if (tcases[n].type == SOCK_STREAM) {
+		if (tcases[n].domain == PF_INET) {
+			SAFE_CONNECT(sock, (struct sockaddr *)&sin1,
 				     sizeof(sin1));
 			/* Wait for something to be readable, else we won't detect EFAULT on recv */
 			FD_ZERO(&rdfds);
-			FD_SET(s, &rdfds);
+			FD_SET(sock, &rdfds);
 			timeout.tv_sec = 2;
 			timeout.tv_usec = 0;
-			n = select(s + 1, &rdfds, 0, 0, &timeout);
-			if (n != 1 || !FD_ISSET(s, &rdfds))
-				tst_brkm(TBROK, cleanup,
-					 "client setup1 failed - no message ready in 2 sec");
-		} else if (tdat[testno].domain == PF_UNIX) {
-			SAFE_CONNECT(cleanup, s, (struct sockaddr *)&sun1,
+			n = select(sock + 1, &rdfds, 0, 0, &timeout);
+			if (n != 1 || !FD_ISSET(sock, &rdfds))
+				tst_brk(TBROK, "no message ready in 2 sec");
+		} else if (tcases[n].domain == PF_UNIX) {
+			SAFE_CONNECT(sock, (struct sockaddr *)&sun1,
 				     sizeof(sun1));
 		}
 	}
 }
 
-void setup2(void)
+static void setup_valid_msg_control(int n)
 {
-	setup1();
-	if (write(s, "R", 1) < 0)
-		tst_brkm(TBROK | TERRNO, cleanup, "test setup failed: write:");
+	setup_valid_sock(n);
+	SAFE_SEND(1, sock, "R", 1, 0);
 	control = (struct cmsghdr *)cbuf;
 	controllen = control->cmsg_len = sizeof(cbuf);
 }
 
-void setup3(void)
+static void setup_large_msg_control(int n)
 {
-	setup2();
-	controllen = sizeof(struct cmsghdr) - 1;
+	setup_valid_msg_control(n);
+	controllen = CONTROL_LEN;
 }
 
-void setup4(void)
+static void cleanup_close_sock(int n)
 {
-	setup2();
-	controllen = 128 * 1024;
+	SAFE_CLOSE(sock);
 }
 
-void cleanup1(void)
+static void cleanup_reset_all(int n)
 {
-	(void)close(s);
-	close(ufd);
-	close(sfd);
-	s = -1;
-}
+	SAFE_CLOSE(sock);
 
-void cleanup2(void)
-{
-	close(ufd);
-	close(sfd);
-	(void)close(s);
-	s = -1;
-
-	if (passed_fd >= 0)
-		(void)close(passed_fd);
-	passed_fd = -1;
 	control = 0;
 	controllen = 0;
 }
@@ -373,63 +372,70 @@ pid_t start_server(struct sockaddr_in *ssin, struct sockaddr_un *ssun)
 	ssin->sin_addr.s_addr = INADDR_ANY;
 
 	/* set up inet socket */
-	sfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (sfd < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server socket failed");
-		return -1;
-	}
-	if (bind(sfd, (struct sockaddr *)ssin, sizeof(*ssin)) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server bind failed");
-		return -1;
-	}
-	if (listen(sfd, 10) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server listen failed");
-		return -1;
-	}
-	SAFE_GETSOCKNAME(cleanup, sfd, (struct sockaddr *)ssin, &slen);
+	sfd = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
+	SAFE_BIND(sfd, (struct sockaddr *)ssin, sizeof(*ssin));
+	SAFE_LISTEN(sfd, 10);
+	SAFE_GETSOCKNAME(sfd, (struct sockaddr *)ssin, &slen);
 
 	/* set up UNIX-domain socket */
-	ufd = socket(PF_UNIX, SOCK_STREAM, 0);
-	if (ufd < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server UD socket failed");
-		return -1;
-	}
-	if (bind(ufd, (struct sockaddr *)ssun, sizeof(*ssun))) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server UD bind failed");
-		return -1;
-	}
-	if (listen(ufd, 10) < 0) {
-		tst_brkm(TBROK | TERRNO, cleanup, "server UD listen failed");
-		return -1;
-	}
+	ufd = SAFE_SOCKET(PF_UNIX, SOCK_STREAM, 0);
+	SAFE_BIND(ufd, (struct sockaddr *)ssun, sizeof(*ssun));
+	SAFE_LISTEN(ufd, 10);
 
-	switch ((pid = FORK_OR_VFORK())) {
-	case 0:		/* child */
-#ifdef UCLINUX
-		if (self_exec(argv0, "dd", sfd, ufd) < 0)
-			tst_brkm(TBROK | TERRNO, cleanup,
-				 "server self_exec failed");
-#else
+	pid = SAFE_FORK();
+	if (!pid) {
 		do_child();
-#endif
-		break;
-	case -1:
-		tst_brkm(TBROK | TERRNO, cleanup, "server fork failed");
-		/* fall through */
-	default:		/* parent */
-		(void)close(sfd);
-		(void)close(ufd);
-		return pid;
+		exit(1);
 	}
-	exit(1);
+
+	SAFE_CLOSE(sfd);
+	SAFE_CLOSE(ufd);
+
+	return pid;
 }
 
-void do_child(void)
+/* special for rights-passing test */
+static void sender(int fd)
+{
+	struct msghdr mh = {};
+	struct cmsghdr *control;
+	char tmpfn[BUF_SIZE] = "";
+	char snd_cbuf[BUF_SIZE] = "";
+	int tfd;
+
+	(void)strcpy(tmpfn, "smtXXXXXX");
+	tfd = mkstemp(tmpfn);
+	if (tfd < 0)
+		return;
+
+	/* set up cmsghdr */
+	control = (struct cmsghdr *)snd_cbuf;
+	control->cmsg_len = sizeof(struct cmsghdr) + 4;
+	control->cmsg_level = SOL_SOCKET;
+	control->cmsg_type = SCM_RIGHTS;
+	*(int *)CMSG_DATA(control) = tfd;
+
+	/* set up msghdr */
+	iov[0].iov_base = MSG;
+	iov[0].iov_len = sizeof(MSG);
+	mh.msg_iov = iov;
+	mh.msg_iovlen = 1;
+	mh.msg_flags = 0;
+	mh.msg_control = control;
+	mh.msg_controllen = control->cmsg_len;
+
+	/* do it */
+	SAFE_SENDMSG(sizeof(MSG), fd, &mh, 0);
+	SAFE_CLOSE(tfd);
+	(void)SAFE_UNLINK(tmpfn);
+}
+
+static void do_child(void)
 {
 	struct sockaddr_in fsin;
 	struct sockaddr_un fsun;
 	fd_set afds, rfds;
-	int nfds, cc, fd;
+	int nfds, fd;
 
 	FD_ZERO(&afds);
 	FD_SET(sfd, &afds);
@@ -455,19 +461,19 @@ void do_child(void)
 			int newfd;
 
 			fromlen = sizeof(fsin);
-			newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen);
+			newfd = SAFE_ACCEPT(sfd, (struct sockaddr *)&fsin, &fromlen);
 			if (newfd >= 0) {
 				FD_SET(newfd, &afds);
 				nfds = MAX(nfds, newfd + 1);
 				/* send something back */
-				(void)write(newfd, "hoser\n", 6);
+				SAFE_SEND(1, newfd, "hi", 2, 0);
 			}
 		}
 		if (FD_ISSET(ufd, &rfds)) {
 			int newfd;
 
 			fromlen = sizeof(fsun);
-			newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen);
+			newfd = SAFE_ACCEPT(ufd, (struct sockaddr *)&fsun, &fromlen);
 			if (newfd >= 0) {
 				FD_SET(newfd, &afds);
 				nfds = MAX(nfds, newfd + 1);
@@ -475,55 +481,22 @@ void do_child(void)
 		}
 		for (fd = 0; fd < nfds; ++fd)
 			if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) {
-				char rbuf[1024];
+				char rbuf[BUF_SIZE];
 
-				cc = read(fd, rbuf, sizeof(rbuf));
-				if (cc && rbuf[0] == 'R')
+				TEST(read(fd, rbuf, sizeof(rbuf)));
+				if (TST_RET > 0 && rbuf[0] == 'R')
 					sender(fd);
-				if (cc == 0 || (cc < 0 && errno != EINTR)) {
-					(void)close(fd);
+				if (TST_RET == 0 || (TST_RET < 0 && TST_ERR != EINTR)) {
+					close(fd);
 					FD_CLR(fd, &afds);
 				}
 			}
 	}
 }
 
-#define TM	"from recvmsg01 server"
-
-/* special for rights-passing test */
-void sender(int fd)
-{
-	struct msghdr mh;
-	struct cmsghdr *control;
-	char tmpfn[1024], snd_cbuf[1024];
-	int tfd;
-
-	(void)strcpy(tmpfn, "smtXXXXXX");
-	tfd = mkstemp(tmpfn);
-	if (tfd < 0)
-		return;
-
-	memset(&mh, 0x00, sizeof(mh));
-
-	/* set up cmsghdr */
-	control = (struct cmsghdr *)snd_cbuf;
-	memset(control, 0x00, sizeof(struct cmsghdr));
-	control->cmsg_len = sizeof(struct cmsghdr) + 4;
-	control->cmsg_level = SOL_SOCKET;
-	control->cmsg_type = SCM_RIGHTS;
-	*(int *)CMSG_DATA(control) = tfd;
-
-	/* set up msghdr */
-	iov[0].iov_base = TM;
-	iov[0].iov_len = sizeof(TM);
-	mh.msg_iov = iov;
-	mh.msg_iovlen = 1;
-	mh.msg_flags = 0;
-	mh.msg_control = control;
-	mh.msg_controllen = control->cmsg_len;
-
-	/* do it */
-	(void)sendmsg(fd, &mh, 0);
-	(void)close(tfd);
-	(void)unlink(tmpfn);
-}
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.forks_child = 1,
+	.needs_tmpdir = 1,
+};
-- 
2.35.3



More information about the ltp mailing list