1/*
2 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like.  Any license provided herein, whether implied or
15 * otherwise, applies only to this software file.  Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA  94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
33/* $Id: readdir01.c,v 1.7 2009/03/23 13:36:01 subrata_modak Exp $ */
34/**********************************************************
35 *
36 *    OS Test - Silicon Graphics, Inc.
37 *
38 *    TEST IDENTIFIER	: readdir01
39 *
40 *    EXECUTED BY	: anyone
41 *
42 *    TEST TITLE	: write multiple files and try to find them with readdir
43 *
44 *    TEST CASE TOTAL	:
45 *
46 *    WALL CLOCK TIME	:
47 *
48 *    CPU TYPES		: ALL
49 *
50 *    AUTHOR		: Nate Straz
51 *
52 *    CO-PILOT		:
53 *
54 *    DATE STARTED	: 02/16/2001
55 *
56 *    INITIAL RELEASE	: Linux 2.4.x
57 *
58 *    TEST CASES
59 *
60 * 	1.) Create n files and check that readdir() finds n files
61 *
62 *    INPUT SPECIFICATIONS
63 * 	The standard options for system call tests are accepted.
64 *	(See the parse_opts(3) man page).
65 *
66 *    OUTPUT SPECIFICATIONS
67 *$
68 *    DURATION
69 * 	Terminates - with frequency and infinite modes.
70 *
71 *    SIGNALS
72 * 	Uses SIGUSR1 to pause before test if option set.
73 * 	(See the parse_opts(3) man page).
74 *
75 *    RESOURCES
76 * 	None
77 *
78 *    ENVIRONMENTAL NEEDS
79 *      No run-time environmental needs.
80 *
81 *    SPECIAL PROCEDURAL REQUIREMENTS
82 * 	None
83 *
84 *    INTERCASE DEPENDENCIES
85 * 	None
86 *
87 *    DETAILED DESCRIPTION
88 *	This is a Phase I test for the readdir(2) system call.  It is intended
89 *	to provide a limited exposure of the system call, for now.  It
90 *	should/will be extended when full functional tests are written for
91 *	readdir(2).
92 *
93 * 	Setup:
94 * 	  Setup signal handling.
95 *	  Pause for SIGUSR1 if option specified.
96 *
97 * 	Test:
98 *	 Loop if the proper options are given.
99 * 	  Execute system call
100 *	  Check return code, if system call failed (return=-1)
101 *		Log the errno and Issue a FAIL message.
102 *	  Otherwise, Issue a PASS message.
103 *
104 * 	Cleanup:
105 * 	  Print errno log and/or timing stats if options given
106 *
107 *
108 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
109
110#include <sys/types.h>
111#include <sys/stat.h>
112#include <fcntl.h>
113#include <dirent.h>
114#include <unistd.h>
115#include <errno.h>
116#include <string.h>
117#include <signal.h>
118#include "test.h"
119
120 /* The setup and cleanup functions are basic parts of a test case.  These
121  * steps are usually put in separate functions for clarity.  The help function
122  * is only needed when you are adding new command line options.
123  */
124void setup();
125void help();
126void cleanup();
127
128char *TCID = "readdir01";
129int TST_TOTAL = 2;
130
131#define BASENAME	"readdirfile"
132
133char Basename[255];
134char Fname[255];
135int Nfiles = 0;
136
137char *Nfilearg;
138int Nflag = 0;
139
140option_t options[] = {
141	{"N:", &Nflag, &Nfilearg},	/* -N #files */
142	{NULL, NULL, NULL}
143};
144
145/***********************************************************************
146 * Main
147 ***********************************************************************/
148int main(int ac, char **av)
149{
150	int lc;
151	int cnt;
152	int nfiles, fd;
153	char fname[255];
154	DIR *test_dir;
155	struct dirent *dptr;
156
157	tst_parse_opts(ac, av, options, &help);
158
159	if (Nflag) {
160		if (sscanf(Nfilearg, "%i", &Nfiles) != 1) {
161			tst_brkm(TBROK, NULL, "--N option arg is not a number");
162		}
163	}
164
165    /***************************************************************
166     * perform global setup for test
167     ***************************************************************/
168	/* Next you should run a setup routine to make sure your environment is
169	 * sane.
170	 */
171	setup();
172
173    /***************************************************************
174     * check looping state
175     ***************************************************************/
176	/* TEST_LOOPING() is a macro that will make sure the test continues
177	 * looping according to the standard command line args.
178	 */
179	for (lc = 0; TEST_LOOPING(lc); lc++) {
180
181		tst_count = 0;
182
183		if (Nfiles)
184			nfiles = Nfiles;
185		else
186			/* min of 10 links and max of a 100 links */
187			nfiles = (lc % 90) + 10;
188
189		/* create a bunch of files to look at */
190		for (cnt = 0; cnt < nfiles; cnt++) {
191
192			sprintf(fname, "%s%d", Basename, cnt);
193			if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
194				tst_brkm(TBROK, cleanup,
195					 "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s",
196					 fname, errno, strerror(errno));
197			} else if (write(fd, "hello\n", 6) < 0) {
198				tst_brkm(TBROK, cleanup,
199					 "write(%s, \"hello\\n\", 6) Failed, errno=%d : %s",
200					 fname, errno, strerror(errno));
201			} else if (close(fd) < 0) {
202				tst_resm(TWARN,
203					"close(%s) Failed, errno=%d : %s",
204					fname, errno, strerror(errno));
205			}
206		}
207
208		if ((test_dir = opendir(".")) == NULL) {
209			tst_resm(TFAIL, "opendir(\".\") Failed, errno=%d : %s",
210				 errno, strerror(errno));
211		} else {
212			/* count the entries we find to see if any are missing */
213			cnt = 0;
214			errno = 0;
215			while ((dptr = readdir(test_dir)) != 0) {
216				if (strcmp(dptr->d_name, ".")
217				    && strcmp(dptr->d_name, ".."))
218					cnt++;
219			}
220
221			if (errno != 0) {
222				tst_resm(TFAIL,
223					 "readir(test_dir) Failed on try %d, errno=%d : %s",
224					 cnt + 1, errno, strerror(errno));
225			}
226			if (cnt == nfiles) {
227				tst_resm(TPASS,
228					 "found all %d that were created",
229					 nfiles);
230			} else if (cnt > nfiles) {
231				tst_resm(TFAIL,
232					 "found more files than were created");
233				tst_resm(TINFO, "created: %d, found: %d",
234					 nfiles, cnt);
235			} else {
236				tst_resm(TFAIL,
237					 "found less files than were created");
238				tst_resm(TINFO, "created: %d, found: %d",
239					 nfiles, cnt);
240			}
241		}
242
243		/* Here we clean up after the test case so we can do another iteration.
244		 */
245		for (cnt = 0; cnt < nfiles; cnt++) {
246
247			sprintf(fname, "%s%d", Basename, cnt);
248
249			if (unlink(fname) == -1) {
250				tst_resm(TWARN,
251					"unlink(%s) Failed, errno=%d : %s",
252					Fname, errno, strerror(errno));
253			}
254		}
255
256	}
257
258    /***************************************************************
259     * cleanup and exit
260     ***************************************************************/
261	cleanup();
262
263	tst_exit();
264}
265
266/***************************************************************
267 * help
268 ***************************************************************/
269/* The custom help() function is really simple.  Just write your help message to
270 * standard out.  Your help function will be called after the standard options
271 * have been printed
272 */
273void help(void)
274{
275	printf("  -N #files : create #files files every iteration\n");
276}
277
278/***************************************************************
279 * setup() - performs all ONE TIME setup for this test.
280 ***************************************************************/
281void setup(void)
282{
283	/* You will want to enable some signal handling so you can capture
284	 * unexpected signals like SIGSEGV.
285	 */
286	tst_sig(NOFORK, DEF_HANDLER, cleanup);
287
288	/* One cavet that hasn't been fixed yet.  TEST_PAUSE contains the code to
289	 * fork the test with the -c option.  You want to make sure you do this
290	 * before you create your temporary directory.
291	 */
292	TEST_PAUSE;
293
294	/* If you are doing any file work, you should use a temporary directory.  We
295	 * provide tst_tmpdir() which will create a uniquely named temporary
296	 * directory and cd into it.  You can now create files in the current
297	 * directory without worrying.
298	 */
299	tst_tmpdir();
300
301	sprintf(Basename, "%s_%d.", BASENAME, getpid());
302}
303
304/***************************************************************
305 * cleanup() - performs all ONE TIME cleanup for this test at
306 *		completion or premature exit.
307 ***************************************************************/
308void cleanup(void)
309{
310
311	/* If you use a temporary directory, you need to be sure you remove it. Use
312	 * tst_rmdir() to do it automatically.$
313	 */
314	tst_rmdir();
315
316}
317