syscalls/pipe07: Rewrite.

* Remove useless comments & usuall stuff.

* Get rid of the ugly system() and use readdir()
  to count number of open files.

  (and remove the ugly hacks to create temp dirs
   that are no longer needed)

* Close the pipes after the test has finished
  so that test looping works

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/testcases/kernel/syscalls/pipe/pipe07.c b/testcases/kernel/syscalls/pipe/pipe07.c
index c774870..7e3b914 100644
--- a/testcases/kernel/syscalls/pipe/pipe07.c
+++ b/testcases/kernel/syscalls/pipe/pipe07.c
@@ -1,112 +1,81 @@
 /*
+ * Copyright (c) International Business Machines  Corp., 2002
+ *               Ported by Paul Larson
+ * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
  *
- *   Copyright (c) International Business Machines  Corp., 2002
+ * 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 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.
  *
- *   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
+ * 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
  */
 
 /*
- * NAME
- *	pipe07.c
- *
- * DESCRIPTION
- * 	Test the ability of pipe to open the maximum even number of file
- * 	descriptors permitted (or (maxfds - 3)/2 pipes)
+ * Test the ability of pipe to open the maximum even number of file
+ * descriptors permitted (or (maxfds - 3)/2 pipes)
  *
  * ALGORITHM
- * 	1. open pipes until EMFILE is returned
- * 	2. check to see that the number of pipes opened is
- * 	   (maxfds - 3) / 2
- *
- * USAGE:  <for command-line>
- *  pipe07 [-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
- *	12/2002 Ported by Paul Larson
- *
- * RESTRICTIONS
- *	None
+ *      1. record file descriptors open prior to test run
+ * 	2. open pipes until EMFILE is returned
+ * 	3. check to see that the number of pipes opened is (maxfds - 3) / 2
+ * 	4. close all fds in range 0, maximal fd that were not open prior to
+ * 	   the test execution
  */
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
 #include "test.h"
 #include "usctest.h"
+#include "safe_macros.h"
 
 char *TCID = "pipe07";
 int TST_TOTAL = 1;
 
-int exp_enos[] = { EMFILE, 0 };
+static int exp_enos[] = { EMFILE, 0 };
 
-int pipe_ret, pipes[2];
-char currdir[PATH_MAX];
-char *tempdir = NULL;
-void setup(void);
-void cleanup(void);
+/* used to record file descriptors open at the test start */
+static int rec_fds[128];
+static int rec_fds_max;
+static void record_open_fds(void);
+static void close_test_fds(int max_fd);
+
+static void setup(void);
+static void cleanup(void);
 
 int main(int ac, char **av)
 {
 	int lc;
 	char *msg;
-	int min;		/* number of file descriptors */
-	int usedfds;		/* number of currently used file descriptors */
-	int npipes;		/* number of pipes opened */
-	pid_t mypid;		/* process of id of test */
-	char *cmdstring = NULL;	/* hold command string to execute using system() */
-	FILE *f;		/* used for retrieving the used fds */
+	int min, ret;
+	int npipes;
+	int pipes[2], max_fd = 0;
 
 	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
 		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
-	setup();
-	/* Get the currently used number of file descriptors */
-	mypid = getpid();
-	cmdstring = malloc(BUFSIZ);
-	snprintf(cmdstring, BUFSIZ, "test -d /proc/%d/fd || exit 1 ; "
-		 "ls -A -1 /proc/%d/fd | wc -l | awk {'print $1'} > pipe07.tmp",
-		 mypid, mypid);
-	if (system(cmdstring) == 0) {
-		f = fopen("pipe07.tmp", "r");
-		fscanf(f, "%d", &usedfds);
-		fclose(f);
-	} else
-		usedfds = 3;	/* Could not get processes used fds, so assume 3 */
-	unlink("pipe07.tmp");
 
-	TEST_EXP_ENOS(exp_enos);
+	setup();
+
+	min = getdtablesize() - rec_fds_max;
 
 	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		/* reset tst_count in case we are looping */
 		tst_count = 0;
 
-		min = getdtablesize();
-
-		/* subtract used fds */
-		min -= usedfds;
-
 		for (npipes = 0;; npipes++) {
-			pipe_ret = pipe(pipes);
-			if (pipe_ret < 0) {
+			ret = pipe(pipes);
+			if (ret < 0) {
 				if (errno != EMFILE) {
 					tst_brkm(TFAIL, cleanup,
 						 "got unexpected error - %d",
@@ -114,59 +83,101 @@
 				}
 				break;
 			}
+
+			max_fd = MAX(pipes[0], max_fd);
+			max_fd = MAX(pipes[1], max_fd);
 		}
+
 		if (npipes == (min / 2))
 			tst_resm(TPASS, "Opened %d pipes", npipes);
 		else
 			tst_resm(TFAIL, "Unable to open maxfds/2 pipes");
 
+		close_test_fds(max_fd);
+		max_fd = 0;
 	}
+
 	cleanup();
 	tst_exit();
-
 }
 
-/*
- * setup() - performs all ONE TIME setup for this test.
- */
-void setup()
+static void setup(void)
 {
-	char template[PATH_MAX];
-
-	/* I had to do this, instead of tst_tmpdir() b/c I was receiving      *
-	 * a SIGSEGV for some reason when I tried to use tst_tmpdir/tst_rmdir */
-
-	/* Save current working directory */
-	getcwd(currdir, PATH_MAX);
-
-	/* Create temp directory and cd to it */
-	snprintf(template, PATH_MAX, "%s/%.3sXXXXXX", TEMPDIR, TCID);
-	tempdir = mkdtemp(template);
-	chdir(tempdir);
-
+	TEST_EXP_ENOS(exp_enos);
 	tst_sig(FORK, DEF_HANDLER, cleanup);
-
 	TEST_PAUSE;
 
+	record_open_fds();
 }
 
-/*
- * cleanup() - performs all ONE TIME cleanup for this test at
- *             completion or premature exit.
- */
-void cleanup()
+static void record_open_fds(void)
 {
-	/*
-	 * print timing stats if that option was specified.
-	 * print errno log if that option was specified.
-	 */
+	DIR *dir = opendir("/proc/self/fd");
+	int dir_fd, fd;
+	struct dirent *file;
+
+	if (dir == NULL)
+		tst_brkm(TBROK | TERRNO, cleanup, "opendir()");
+
+	dir_fd = dirfd(dir);
+
+	if (dir_fd == -1)
+		tst_brkm(TBROK | TERRNO, cleanup, "dirfd()");
+
+	errno = 0;
+
+	while ((file = readdir(dir))) {
+		if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
+			continue;
+
+		fd = atoi(file->d_name);
+
+		if (fd == dir_fd)
+			continue;
+
+		if (rec_fds_max >= ARRAY_SIZE(rec_fds)) {
+			tst_brkm(TBROK, cleanup,
+			         "Too much file descriptors open");
+		}
+
+		rec_fds[rec_fds_max++] = fd;
+	}
+
+	if (errno)
+		tst_brkm(TBROK | TERRNO, cleanup, "readdir()");
+
+	closedir(dir);
+
+	tst_resm(TINFO, "Found %u files open", rec_fds_max);
+}
+
+static int not_recorded(int fd)
+{
+	int i;
+
+	for (i = 0; i < rec_fds_max; i++)
+		if (fd == rec_fds[i])
+			return 0;
+
+	return 1;
+}
+
+static void close_test_fds(int max_fd)
+{
+	int i;
+
+	for (i = 0; i <= max_fd; i++) {
+		if (not_recorded(i)) {
+			if (close(i)) {
+				if (errno == EBADF)
+					continue;
+				tst_resm(TWARN | TERRNO, "close(%i)", i);
+			}
+		}
+	}
+}
+
+static void cleanup(void)
+{
 	TEST_CLEANUP;
-
-	/* I had to do this, instead of tst_tmpdir() b/c I was receiving      *
-	 * a SIGSEGV for some reason when I tried to use tst_tmpdir/tst_rmdir */
-
-	/* Chdir back to original working directory */
-	chdir(currdir);
-
-	rmdir(tempdir);
 }