openat: don’t close (-1)
[gnulib.git] / tests / test-passfd.c
blob72dcd83b71f163ad65a63c9c7b13d958bed72f8e
1 /* Test of passing file descriptors.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #include <config.h>
19 #include "passfd.h"
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/wait.h>
32 #include "macros.h"
34 int
35 main ()
37 #if defined __CYGWIN__
38 /* Cygwin does not support file-descriptor passing: As on Cygwin 3.5.3,
39 the only cmsg_type that winsup/cygwin/fhandler/socket_unix.cc handles
40 is SCM_CREDENTIALS. Not SCM_RIGHTS. */
41 return 90;
42 #elif HAVE_SOCKETPAIR
43 int pair[2];
44 int ret;
45 pid_t pid;
46 int status;
47 int fdnull;
48 int fd;
49 struct stat st;
51 # if HAVE_DECL_ALARM
52 /* Avoid hanging on failure. */
53 int alarm_value = 5;
54 signal (SIGALRM, SIG_DFL);
55 alarm (alarm_value);
56 # endif
58 fdnull = open ("/dev/null", O_RDWR);
59 if (fdnull < 0)
61 perror ("Could not open /dev/null");
62 return 1;
65 ret = socketpair (AF_UNIX, SOCK_STREAM, 0, pair);
66 if (ret < 0)
68 perror ("socket pair failed");
69 return 2;
72 pid = fork ();
73 if (pid == -1)
75 perror ("fork");
76 return 3;
78 if (pid == 0)
80 ret = sendfd (pair[1], fdnull);
81 if (ret == -1)
83 perror ("sendfd");
84 return 64;
86 return 0;
88 /* father */
89 else
91 ASSERT (close (pair[1]) == 0);
92 fd = recvfd (pair[0], 0);
93 if (fd == -1)
95 perror ("recvfd");
96 return 16;
98 ret = waitpid (pid, &status, 0);
99 if (ret == -1)
101 perror ("waitpid");
102 return 17;
104 ASSERT (ret == pid);
106 if (!WIFEXITED (status))
108 fprintf (stderr, "Child does not normally exit\n");
109 return 65;
111 ret = WEXITSTATUS (status);
112 if (ret != 0)
114 fprintf (stderr, "Send fd fail\n");
115 return ret;
118 /* try to stat new fd */
119 ret = fstat (fd, &st);
120 if (ret < 0)
122 perror ("fstat");
123 return 80;
126 /* Check behavior when sender no longer around */
127 errno = 0;
128 fd = recvfd (pair[0], 0);
129 ASSERT (fd == -1);
130 ASSERT (errno == ENOTCONN);
132 return test_exit_status;
134 #else
135 errno = 0;
136 ASSERT(sendfd (0, 0) == -1);
137 ASSERT(errno == ENOSYS);
139 errno = 0;
140 ASSERT(recvfd (0, 0) == -1);
141 ASSERT(errno == ENOSYS);
143 if (test_exit_status != EXIT_SUCCESS)
144 return test_exit_status;
145 fputs ("skipping test: socketpair not supported on this system\n",
146 stderr);
147 return 77;
148 #endif