1906d4687089fa0f40436d453de38449cb1dd459brobbiew/*
22aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * Copyright (c) International Business Machines  Corp., 2002
32aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis *               Ported by Paul Larson
42aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
5906d4687089fa0f40436d453de38449cb1dd459brobbiew *
62aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * This program is free software;  you can redistribute it and/or modify
72aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * it under the terms of the GNU General Public License as published by
82aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * the Free Software Foundation; either version 2 of the License, or
92aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * (at your option) any later version.
10906d4687089fa0f40436d453de38449cb1dd459brobbiew *
112aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * This program is distributed in the hope that it will be useful,
122aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * but WITHOUT ANY WARRANTY;  without even the implied warranty of
132aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
142aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * the GNU General Public License for more details.
15906d4687089fa0f40436d453de38449cb1dd459brobbiew *
162aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * You should have received a copy of the GNU General Public License
172aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * along with this program;  if not, write to the Free Software
182aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19906d4687089fa0f40436d453de38449cb1dd459brobbiew */
20906d4687089fa0f40436d453de38449cb1dd459brobbiew
21906d4687089fa0f40436d453de38449cb1dd459brobbiew/*
222aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * Test the ability of pipe to open the maximum even number of file
232aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * descriptors permitted (or (maxfds - 3)/2 pipes)
24906d4687089fa0f40436d453de38449cb1dd459brobbiew *
25906d4687089fa0f40436d453de38449cb1dd459brobbiew * ALGORITHM
262aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis *      1. record file descriptors open prior to test run
272aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * 	2. open pipes until EMFILE is returned
282aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * 	3. check to see that the number of pipes opened is (maxfds - 3) / 2
292aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * 	4. close all fds in range 0, maximal fd that were not open prior to
302aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis * 	   the test execution
31906d4687089fa0f40436d453de38449cb1dd459brobbiew */
326617b477babb4933ac65c2db08a94ced22c4b2f1robbiew#include <unistd.h>
33906d4687089fa0f40436d453de38449cb1dd459brobbiew#include <fcntl.h>
34906d4687089fa0f40436d453de38449cb1dd459brobbiew#include <errno.h>
358638910f6ed981998527594ecf8af9879247636frobbiew#include <stdlib.h>
368638910f6ed981998527594ecf8af9879247636frobbiew#include <stdio.h>
372aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis#include <string.h>
382aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis#include <dirent.h>
392aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
40906d4687089fa0f40436d453de38449cb1dd459brobbiew#include "test.h"
412aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis#include "safe_macros.h"
42906d4687089fa0f40436d453de38449cb1dd459brobbiew
43906d4687089fa0f40436d453de38449cb1dd459brobbiewchar *TCID = "pipe07";
44906d4687089fa0f40436d453de38449cb1dd459brobbiewint TST_TOTAL = 1;
45906d4687089fa0f40436d453de38449cb1dd459brobbiew
462aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis/* used to record file descriptors open at the test start */
472aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic int rec_fds[128];
482aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic int rec_fds_max;
492aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void record_open_fds(void);
502aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void close_test_fds(int max_fd);
512aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
522aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void setup(void);
532aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void cleanup(void);
54906d4687089fa0f40436d453de38449cb1dd459brobbiew
55906d4687089fa0f40436d453de38449cb1dd459brobbiewint main(int ac, char **av)
56906d4687089fa0f40436d453de38449cb1dd459brobbiew{
5789af32a63ce8a780ea39337339e14caae244b5a4Cyril Hrubis	int lc;
582aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int min, ret;
592aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int npipes;
602aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int pipes[2], max_fd = 0;
61906d4687089fa0f40436d453de38449cb1dd459brobbiew
62d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis	tst_parse_opts(ac, av, NULL, NULL);
632aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
64906d4687089fa0f40436d453de38449cb1dd459brobbiew	setup();
658638910f6ed981998527594ecf8af9879247636frobbiew
662aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	min = getdtablesize() - rec_fds_max;
67906d4687089fa0f40436d453de38449cb1dd459brobbiew
68906d4687089fa0f40436d453de38449cb1dd459brobbiew	for (lc = 0; TEST_LOOPING(lc); lc++) {
69d59a659cd639ca2780b00049d102acd2a783d585Caspar Zhang		tst_count = 0;
70906d4687089fa0f40436d453de38449cb1dd459brobbiew
7156207cec7732e09c216c751c0b5f88a242bacae6subrata_modak		for (npipes = 0;; npipes++) {
722aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			ret = pipe(pipes);
732aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			if (ret < 0) {
74906d4687089fa0f40436d453de38449cb1dd459brobbiew				if (errno != EMFILE) {
755ef7d2fdd1c7cd6c77c8f17cf74ef243d512cb93vapier					tst_brkm(TFAIL, cleanup,
7656207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 "got unexpected error - %d",
7756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 errno);
78906d4687089fa0f40436d453de38449cb1dd459brobbiew				}
79906d4687089fa0f40436d453de38449cb1dd459brobbiew				break;
80906d4687089fa0f40436d453de38449cb1dd459brobbiew			}
812aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
822aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			max_fd = MAX(pipes[0], max_fd);
832aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			max_fd = MAX(pipes[1], max_fd);
84906d4687089fa0f40436d453de38449cb1dd459brobbiew		}
852aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
86906d4687089fa0f40436d453de38449cb1dd459brobbiew		if (npipes == (min / 2))
8756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak			tst_resm(TPASS, "Opened %d pipes", npipes);
88906d4687089fa0f40436d453de38449cb1dd459brobbiew		else
89906d4687089fa0f40436d453de38449cb1dd459brobbiew			tst_resm(TFAIL, "Unable to open maxfds/2 pipes");
90906d4687089fa0f40436d453de38449cb1dd459brobbiew
912aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		close_test_fds(max_fd);
922aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		max_fd = 0;
93906d4687089fa0f40436d453de38449cb1dd459brobbiew	}
942aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
95906d4687089fa0f40436d453de38449cb1dd459brobbiew	cleanup();
961e6f5a673655551de5734ff31ef48cd63b604e6dGarrett Cooper	tst_exit();
972aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis}
98906d4687089fa0f40436d453de38449cb1dd459brobbiew
992aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void setup(void)
1002aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis{
1012aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	tst_sig(FORK, DEF_HANDLER, cleanup);
1022aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	TEST_PAUSE;
1032aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1042aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	record_open_fds();
105906d4687089fa0f40436d453de38449cb1dd459brobbiew}
106906d4687089fa0f40436d453de38449cb1dd459brobbiew
1072aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void record_open_fds(void)
108906d4687089fa0f40436d453de38449cb1dd459brobbiew{
1092aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	DIR *dir = opendir("/proc/self/fd");
1102aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int dir_fd, fd;
1112aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	struct dirent *file;
1126617b477babb4933ac65c2db08a94ced22c4b2f1robbiew
1132aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	if (dir == NULL)
1142aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		tst_brkm(TBROK | TERRNO, cleanup, "opendir()");
1156617b477babb4933ac65c2db08a94ced22c4b2f1robbiew
1162aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	dir_fd = dirfd(dir);
1176617b477babb4933ac65c2db08a94ced22c4b2f1robbiew
1182aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	if (dir_fd == -1)
1192aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		tst_brkm(TBROK | TERRNO, cleanup, "dirfd()");
1208638910f6ed981998527594ecf8af9879247636frobbiew
1212aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	errno = 0;
122906d4687089fa0f40436d453de38449cb1dd459brobbiew
1232aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	while ((file = readdir(dir))) {
1242aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
1252aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			continue;
1262aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1272aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		fd = atoi(file->d_name);
1282aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1292aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		if (fd == dir_fd)
1302aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			continue;
1312aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1322aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		if (rec_fds_max >= ARRAY_SIZE(rec_fds)) {
1332aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			tst_brkm(TBROK, cleanup,
1342aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			         "Too much file descriptors open");
1352aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		}
136906d4687089fa0f40436d453de38449cb1dd459brobbiew
1372aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		rec_fds[rec_fds_max++] = fd;
1382aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	}
1392aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1402aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	if (errno)
1412aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		tst_brkm(TBROK | TERRNO, cleanup, "readdir()");
1422aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1432aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	closedir(dir);
1442aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1452aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	tst_resm(TINFO, "Found %u files open", rec_fds_max);
146906d4687089fa0f40436d453de38449cb1dd459brobbiew}
147906d4687089fa0f40436d453de38449cb1dd459brobbiew
1482aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic int not_recorded(int fd)
149906d4687089fa0f40436d453de38449cb1dd459brobbiew{
1502aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int i;
151906d4687089fa0f40436d453de38449cb1dd459brobbiew
1522aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	for (i = 0; i < rec_fds_max; i++)
1532aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		if (fd == rec_fds[i])
1542aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			return 0;
1556617b477babb4933ac65c2db08a94ced22c4b2f1robbiew
1562aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	return 1;
1572aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis}
1586617b477babb4933ac65c2db08a94ced22c4b2f1robbiew
1592aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void close_test_fds(int max_fd)
1602aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis{
1612aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	int i;
1622aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1632aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	for (i = 0; i <= max_fd; i++) {
1642aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		if (not_recorded(i)) {
1652aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			if (close(i)) {
1662aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis				if (errno == EBADF)
1672aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis					continue;
1682aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis				tst_resm(TWARN | TERRNO, "close(%i)", i);
1692aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis			}
1702aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis		}
1712aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis	}
1722aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis}
1732aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis
1742aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubisstatic void cleanup(void)
1752aabae101f562a9de0483518b9e0a00cf5a923a7Cyril Hrubis{
176ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
177