1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Fujitsu Ltd.
4  * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
5  */
6 
7 /*
8  * Test Name: epoll_ctl02.c
9  *
10  * Description:
11  * 1) epoll_ctl(2) fails if epfd is a invalid file descriptor.
12  * 2) epoll_ctl(2) fails if fd is a invalid file descriptor.
13  * 3) epoll_ctl(2) fails if op is not supported by this interface.
14  * 4) epoll_ctl(2) fails if fd is the same as epfd.
15  * 5) epoll_ctl(2) fails with EPOLL_CTL_DEL if fd is not registered
16  *    with this epoll instance.
17  * 6) epoll_ctl(2) fails with EPOLL_CTL_MOD if fd is not registered
18  *    with this epoll instance.
19  * 7) epoll_ctl(2) fails with EPOLL_CTL_ADD if fd is already registered
20  *    with this epoll instance.
21  *
22  * Expected Result:
23  * 1) epoll_ctl(2) should return -1 and set errno to EBADF.
24  * 2) epoll_ctl(2) should return -1 and set errno to EBADF.
25  * 3) epoll_ctl(2) should return -1 and set errno to EINVAL.
26  * 4) epoll_ctl(2) should return -1 and set errno to EINVAL.
27  * 5) epoll_ctl(2) should return -1 and set errno to ENOENT.
28  * 6) epoll_ctl(2) should return -1 and set errno to ENOENT.
29  * 7) epoll_ctl(2) should return -1 and set errno to EEXIST.
30  *
31  */
32 #include <sys/epoll.h>
33 #include <poll.h>
34 #include <errno.h>
35 #include "tst_test.h"
36 
37 static int epfd;
38 static int fd[2];
39 static int inv = -1;
40 
41 static struct epoll_event events[2] = {
42 	{.events = EPOLLIN},
43 	{.events = EPOLLOUT},
44 };
45 
46 static struct testcase {
47 	int *epfds;
48 	int opt;
49 	int *fds;
50 	struct epoll_event *ts_event;
51 	int exp_err;
52 } tcases[] = {
53 	{&inv, EPOLL_CTL_ADD, &fd[1], &events[1], EBADF},
54 	{&epfd, EPOLL_CTL_ADD, &inv, &events[1], EBADF},
55 	{&epfd, -1, &fd[1], &events[1], EINVAL},
56 	{&epfd, EPOLL_CTL_ADD, &epfd, &events[1], EINVAL},
57 	{&epfd, EPOLL_CTL_DEL, &fd[1], &events[1], ENOENT},
58 	{&epfd, EPOLL_CTL_MOD, &fd[1], &events[1], ENOENT},
59 	{&epfd, EPOLL_CTL_ADD, &fd[0], &events[0], EEXIST}
60 };
61 
setup(void)62 static void setup(void)
63 {
64 	epfd = epoll_create(2);
65 	if (epfd == -1)
66 		tst_brk(TBROK | TERRNO, "fail to create epoll instance");
67 
68 	SAFE_PIPE(fd);
69 
70 	events[0].data.fd = fd[0];
71 	events[1].data.fd = fd[1];
72 
73 	TEST(epoll_ctl(epfd, EPOLL_CTL_ADD, fd[0], &events[0]));
74 	if (TST_RET == -1)
75 		tst_brk(TFAIL | TTERRNO, "epoll_ctl() fails to init");
76 }
77 
cleanup(void)78 static void cleanup(void)
79 {
80 	if (epfd)
81 		SAFE_CLOSE(epfd);
82 
83 	if (fd[0])
84 		SAFE_CLOSE(fd[0]);
85 
86 	if (fd[1])
87 		SAFE_CLOSE(fd[1]);
88 }
89 
verify_epoll_ctl(unsigned int n)90 static void verify_epoll_ctl(unsigned int n)
91 {
92 	struct testcase *tc = &tcases[n];
93 
94 	TEST(epoll_ctl(*tc->epfds, tc->opt, *tc->fds,  tc->ts_event));
95 	if (TST_RET != -1) {
96 		tst_res(TFAIL, "epoll_ctl() succeeds unexpectedly");
97 		return;
98 	}
99 
100 	if (tc->exp_err == TST_ERR) {
101 		tst_res(TPASS | TTERRNO, "epoll_ctl() fails as expected");
102 	} else {
103 		tst_res(TFAIL | TTERRNO,
104 			"epoll_ctl() fails unexpectedly, expected %i: %s",
105 			tc->exp_err, tst_strerrno(tc->exp_err));
106 	}
107 }
108 
109 static struct tst_test test = {
110 	.tcnt = ARRAY_SIZE(tcases),
111 	.setup = setup,
112 	.cleanup = cleanup,
113 	.test = verify_epoll_ctl,
114 };
115