1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2002
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with this program;  if not, write to the Free Software
17 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/* 10/31/2002   Port to LTP     robbiew@us.ibm.com */
21/* 06/30/2001   Port to Linux   nsharoff@us.ibm.com */
22
23/*
24 * NAME
25 *      test.c - Test functions for nftw()
26 */
27
28#include "nftw.h"
29
30extern int callback(const char *path);
31
32extern pathdata pathdat[];
33extern struct list mnem[], badlist[];
34extern char *dirlist[NDIRLISTENTS], *goodlist[];
35extern int npathdats, ngoods, nbads, nmnem, visit, s2, next_fd[4];
36
37extern FILE *temp;
38/*
39 *    void test1A()     - tests the assertion:
40 *      A call to int nftw(const char *path, int (*fn)(const char *, const
41 *      struct stat *, int, struct FTW *), int depth, int flags) shall
42 *      recursively descend the directory hierarchy rooted in path until it
43 *      has traversed the whole tree, calling the function fn for each object
44 *      in the directory tree, and return 0.
45 */
46
47void test1A(void)
48{
49	int i, j, ret;
50
51	temp = stderr;
52#ifdef DEBUG
53	fprintf(temp, "TEST: nftw() succeeds\n");
54#endif
55
56	visit = 0;
57	if ((ret = nftw("./tmp/data/dirh", test_func1, MAX_FD, 0)) == -1) {
58		perror("ERROR: nftw failed");
59		cleanup_function();
60		fail_exit();
61	}
62
63	if (ret == 999) {
64		cleanup_function();
65		fail_exit();
66	}
67#ifdef DEBUG
68	fprintf(temp, "TEST: Whole tree traversed\n");
69#endif
70
71	if (visit != ngoods) {
72		fprintf(temp, "ERROR: Count of objects visited incorrect\n");
73		fprintf(temp, "       Expected %d, Received %d\n", ngoods,
74			visit);
75		cleanup_function();
76		fail_exit();
77	}
78
79	for (i = 0; i < visit; i++) {
80		for (j = 0; j < ngoods; j++) {
81			if (strcmp(dirlist[i], goodlist[j]) == 0) {
82				free(dirlist[i]);
83				dirlist[i] = NULL;
84				break;
85			}
86		}
87	}
88
89	for (i = 0; i < visit; i++) {
90		if (dirlist[i] != NULL) {
91			free(dirlist[i]);
92			fprintf(temp, "ERROR: Unexpected visit to %s\n",
93				dirlist[i]);
94			cleanup_function();
95			fail_exit();
96		}
97	}
98}
99
100/*
101 *    void test2A()     - tests the assertion:
102 *      A call to int nftw(const char *path, int (*fn)(const char *, const
103 *      struct stat *, int, struct FTW *), int depth, int flags) when flags
104 *      contains FTW_PHYS shall not traverse symbolic links.
105 */
106
107void test2A(void)
108{
109	int i, ret;
110
111	temp = stderr;
112#ifdef DEBUG
113	fprintf(temp,
114		"TEST: nftw with FTW_PHYS does not follow symbolic links\n");
115#endif
116
117	visit = 0;
118	if ((ret = nftw("./tmp/data/dirl", test_func1, MAX_FD, FTW_PHYS))
119	    == -1) {
120		perror("nftw");
121		cleanup_function();
122		fail_exit();
123	}
124
125	if (ret == 999) {
126		cleanup_function();
127		fail_exit();
128	}
129
130	if (visit != NO_LINK_CNT) {
131		fprintf(temp,
132			"ERROR: Expected %d files to be visited.  nftw() visited %d\n",
133			NO_LINK_CNT, visit);
134		cleanup_function();
135		fail_exit();
136	}
137
138	for (i = 0; i < visit; i++) {
139		if (dirlist[i] != NULL)
140			free(dirlist[i]);
141	}
142}
143
144/*
145 *    void test3A()     - tests the assertion:
146 *      A call to int nftw(const char *path, int (*fn)(const char *, const
147 *      struct stat *, int, struct FTW *), int depth, int flags) when flags
148 *      does not contain FTW_PHYS shall follow links instead of reporting
149 *      them and shall not report the same file twice.
150 */
151
152void test3A(void)
153{
154	int ret;
155
156#ifdef DEBUG
157	fprintf(temp, "TEST: nftw without FTW_PHYS follows symbolic links\n");
158#endif
159
160	visit = 0;
161
162	if ((ret = nftw("./tmp/data/dirl", test_func3, MAX_FD, 0)) == -1) {
163		perror("nftw");
164		cleanup_function();
165		fail_exit();
166	}
167	if (ret == 999) {
168		cleanup_function();
169		fail_exit();
170	}
171
172	if (visit != LINK_CNT - 1) {
173		fprintf(temp,
174			"ERROR: Expected %d files to be visited.  nftw() visited %d\n",
175			LINK_CNT - 1, visit);
176		cleanup_function();
177		fail_exit();
178	}
179}
180
181/*
182 *    void test4A()     - tests the assertion:
183 *      A call to int nftw(const char *path, int (*fn)(const char *, const
184 *      struct stat *, int, struct FTW *), int depth, int flags) when flags
185 *      contains FTW_DEPTH shall report all files in a directory before
186 *      reporting the directory.
187 */
188
189void test4A(void)
190{
191	char path[] = "./tmp/data/d777";
192	int ret_val;
193
194#ifdef DEBUG
195	fprintf(temp, "TEST: Verify traversal with FTW_DEPTH set\n");
196#endif
197
198	visit = 0;
199	if ((ret_val = nftw(path, test_func4, MAX_FD, FTW_DEPTH)) == -1) {
200		perror("nftw");
201		cleanup_function();
202		fail_exit();
203	}
204	if (ret_val != 999) {
205		fprintf(temp, "ERROR: %s never visited\n", path);
206		cleanup_function();
207		fail_exit();
208	}
209
210	if (visit != 2) {
211		fprintf(temp, "ERROR: Visited directory before contents\n");
212		cleanup_function();
213		fail_exit();
214	}
215}
216
217/*
218 *    void test5A()     - tests the assertion:
219 *      A call to int nftw(const char *path, int (*fn)(const char *, const
220 *      struct stat *, int, struct FTW *), int depth, int flags) when flags
221 *      does not contain FTW_DEPTH shall report a directory before reporting
222 *      the files in that directory.
223 */
224
225void test5A(void)
226{
227	char path[] = "./tmp/data/d777";
228	int ret_val;
229
230#ifdef DEBUG
231	fprintf(temp, "TEST: Verify traversal without FTW_DEPTH set\n");
232#endif
233
234	visit = 0;
235	if ((ret_val = nftw(path, test_func4, MAX_FD, 0)) == -1) {
236		perror("nftw");
237		cleanup_function();
238		fail_exit();
239	}
240	if (ret_val != 999) {
241		fprintf(temp, "ERROR: %s never visited\n", path);
242		cleanup_function();
243		fail_exit();
244	}
245
246	if (visit != 1) {
247		fprintf(temp, "ERROR: Visited contents before directory\n");
248		cleanup_function();
249		fail_exit();
250	}
251}
252
253/*
254 *    void test6A()     - tests the assertion:
255 *      A call to int nftw(const char *path, int (*fn)(const char *, const
256 *      struct stat *, int, struct FTW *), int depth, int flags) when flags
257 *      contains FTW_CHDIR shall change the current working directory to each
258 *      directory as it reports files in that directory.
259 */
260
261void test6A(void)
262{
263	char path[PATH_MAX + NAME_MAX];
264	int ret_val;
265
266	if (getcwd(path, sizeof(path)) == NULL) {
267		perror("getcwd");
268		cleanup_function();
269		fail_exit();
270	}
271	(void)strcat(path, "/tmp/data/dirh");
272
273#ifdef DEBUG
274	fprintf(temp,
275		"TEST: nftw with FTW_CHDIR changes to each dir before reporting files in it\n");
276#endif
277
278	ret_val = nftw(path, test_func5, MAX_FD, FTW_CHDIR);
279	if (ret_val == -1) {
280		perror("nftw");
281		cleanup_function();
282		fail_exit();
283	}
284	if ((ret_val == 998) || (ret_val == 999)) {
285		cleanup_function();
286		fail_exit();
287	}
288}
289
290/*
291 *    void test7A()     - tests the assertion:
292 *      A call to int nftw(const char *path, int (*fn)(const char *, const
293 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
294 *      the path-name of the current object as the first argument of the
295 *      function fn.
296 */
297
298void test7A(void)
299{
300	int ret;
301
302#ifdef DEBUG
303	fprintf(temp, "TEST: nftw passes pathname as first argument to fn()\n");
304#endif
305
306	if ((ret = nftw("./tmp/data/dirg", test_func7, MAX_FD, 0)) == -1) {
307		perror("nftw");
308		cleanup_function();
309		fail_exit();
310	}
311
312	if (ret == 999) {
313		cleanup_function();
314		fail_exit();
315	}
316}
317
318/*
319 *    void test8A()    - tests the assertion:
320 *      A call to int nftw(const char *path, int (*fn)(const char *, const
321 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass a
322 *      pointer to a stat structure containing information about the current
323 *      object as the second argument to fn.
324 */
325
326void test8A(void)
327{
328	int ret;
329
330#ifdef DEBUG
331	fprintf(temp,
332		"TEST: nftw passes stat struct as second argument to fn()\n");
333#endif
334
335	if ((ret = nftw("./tmp/data/dirg", test_func8, MAX_FD, 0)) == -1) {
336		perror("nftw");
337		cleanup_function();
338		fail_exit();
339	}
340
341	if (ret == 999) {
342		cleanup_function();
343		fail_exit();
344	}
345}
346
347/*
348 *    void test9A()    - tests the assertion:
349 *      A call to int nftw(const char *path, int (*fn)(const char *, const
350 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
351 *      FTW_F as the third argument of the function fn when the object is a
352 *      file
353 */
354
355void test9A(void)
356{
357	int ret;
358
359#ifdef DEBUG
360	fprintf(temp,
361		"TEST: nftw passes FTW_F as third arg to fn() for files\n");
362#endif
363
364	if ((ret = nftw("./tmp/data/dirg", test_func9, MAX_FD, FTW_PHYS)) == -1) {
365		perror("nftw");
366		cleanup_function();
367		fail_exit();
368	}
369
370	if (ret == 999) {
371		cleanup_function();
372		fail_exit();
373	}
374}
375
376/*
377 *    void test10A()    - tests the assertion:
378 *      A call to int nftw(const char *path, int (*fn)(const char *, const
379 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
380 *      FTW_D as the third argument of the function fn when the object is a
381 *      directory.
382 */
383
384void test10A(void)
385{
386	int ret;
387
388#ifdef DEBUG
389	fprintf(temp,
390		"TEST: nftw passes FTW_D as third arg to fn() when file is directory\n");
391#endif
392
393	if ((ret = nftw("./tmp/data/dirg", test_func10, MAX_FD,
394			FTW_PHYS)) == -1) {
395		perror("nftw");
396		cleanup_function();
397		fail_exit();
398	}
399
400	if (ret == 999) {
401		cleanup_function();
402		fail_exit();
403	}
404}
405
406/*
407 *    void test11A()    - tests the assertion:
408 *      A call to int nftw(const char *path, int (*fn)(const char *, const
409 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
410 *      FTW_DP as the third argument of the function fn when the object is a
411 *      directory and subdirectories have been visited.
412 */
413
414void test11A(void)
415{
416	int i, ret;
417
418	for (i = 0; i < nbads; i++)
419		if (badlist[i].i == FTW_D)
420			badlist[i].i = FTW_DP;
421
422#ifdef DEBUG
423	fprintf(temp,
424		"TEST: nftw passes FTW_DP when file is directory and subdirs already visited\n");
425#endif
426
427	if ((ret = nftw("./tmp/data/dirg", test_func11, MAX_FD, FTW_DEPTH |
428			FTW_PHYS)) == -1) {
429		perror("nftw");
430		cleanup_function();
431		fail_exit();
432	}
433
434	if (ret == 999) {
435		cleanup_function();
436		fail_exit();
437	}
438}
439
440/*
441 *    void test12A()    - tests the assertion:
442 *      A call to int nftw(const char *path, int (*fn)(const char *, const
443 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
444 *      FTW_SL as the third argument of the function fn when the object is a
445 *      symbolic link.
446 */
447
448void test12A(void)
449{
450	int ret;
451
452#ifdef DEBUG
453	fprintf(temp,
454		"TEST: nftw wth FTW_PHYS passes FTW_SL when file is symlink\n");
455#endif
456
457	if ((ret = nftw("./tmp/data/dirg", test_func12, MAX_FD,
458			FTW_PHYS)) == -1) {
459		perror("nftw");
460		cleanup_function();
461		fail_exit();
462	}
463
464	if (ret == 999) {
465		cleanup_function();
466		fail_exit();
467	}
468}
469
470/*
471 *    void test13A()    - tests the assertion:
472 *      A call to int nftw(const char *path, int (*fn)(const char *, const
473 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
474 *      FTW_SLN as the third argument of the function fn when the object is a
475 *      symbolic link that does not name an existing file.
476 */
477
478void test13A(void)
479{
480	int i, ret;
481
482	if (unlink("./tmp/byebye") == -1) {
483		perror("unlink");
484		cleanup_function();
485		fail_exit();
486	}
487
488	for (i = 0; i < nbads; i++)
489		if (badlist[i].i == FTW_SL)
490			badlist[i].i = FTW_SLN;
491
492#ifdef DEBUG
493	fprintf(temp, "TEST: nftw with FTW_PHYS passes FTW_SLN when file");
494	fprintf(temp, " is symlink pointing \n to non-existent file\n");
495#endif
496
497	if ((ret = nftw("./tmp/data/dirg", test_func13, MAX_FD,
498			FTW_PHYS)) == -1) {
499		perror("nftw");
500		cleanup_function();
501		fail_exit();
502	}
503
504	if (ret == 999) {
505		cleanup_function();
506		fail_exit();
507	}
508}
509
510/*
511 *    void test14A()    - tests the assertion:
512 *      A call to int nftw(const char *path, int (*fn)(const char *, const
513 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
514 *      FTW_DNR as the third argument of the function fn when the object is a
515 *      directory that cannot be read.
516 */
517
518void test14A(void)
519{
520	int ret;
521
522#ifdef DEBUG
523	fprintf(temp,
524		"TEST: nftw passes FTW_DNR when file is directory that cannot be read\n");
525#endif
526
527	if ((ret = nftw("./tmp/data/d333", test_func14, MAX_FD, 0)) == -1) {
528		perror("nftw");
529		cleanup_function();
530		fail_exit();
531	}
532
533	if (ret == 999) {
534		cleanup_function();
535		fail_exit();
536	}
537}
538
539/*
540 *    void test15A()    - tests the assertion:
541 *      A call to int nftw(const char *path, int (*fn)(const char *, const
542 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
543 *      FTW_NS as the third argument of the function fn when stat() failed on
544 *      the object because of lack of appropriate permission.
545 */
546
547void test15A(void)
548{
549	int ret;
550
551#ifdef DEBUG
552	fprintf(temp,
553		"TEST: nftw(path, fn, depth, FTW_PHYS) passes FTW_NS when dir unsearchable\n");
554#endif
555
556	if ((ret =
557	     nftw("./tmp/data/d666", test_func15, MAX_FD, FTW_PHYS)) == -1) {
558		perror("nftw");
559		cleanup_function();
560		fail_exit();
561	}
562
563	if (ret == 999) {
564		cleanup_function();
565		fail_exit();
566	}
567}
568
569/*
570 *    void test16A()    - tests the assertion:
571 *      A call to int nftw(const char *path, int (*fn)(const char *, const
572 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass a
573 *      structure which contains the offset into the pathname of the object
574 *      and the depth relative to the root of the walk starting from 0 as the
575 *      fourth argument of the function fn.
576 */
577
578void test16A(void)
579{
580	char path[PATH_MAX + NAME_MAX];
581	char orig[PATH_MAX];
582
583	if (getcwd(orig, sizeof(orig)) == NULL) {
584		perror("getcwd on original wd");
585		cleanup_function();
586		fail_exit();
587	}
588
589	strcpy(path, orig);
590	(void)strcat(path, "/tmp/data/dirg");
591
592#ifdef DEBUG
593	fprintf(temp, "TEST: nftw with absolute pathname %s\n", path);
594#endif
595
596	if ((s2 = nftw(path, test_func16, MAX_FD, 0)) == -1) {
597		perror("nftw");
598		cleanup_function();
599		fail_exit();
600	}
601	if (s2 == 999) {
602		cleanup_function();
603		fail_exit();
604	}
605
606	(void)strcpy(path, "./tmp/data/dirg");
607
608#ifdef DEBUG
609	fprintf(temp, "TEST: nftw with relative pathname %s\n", path);
610#endif
611
612	if ((s2 = nftw(path, test_func16, MAX_FD, 0)) == -1) {
613		perror("nftw");
614		cleanup_function();
615		fail_exit();
616	}
617
618	if (s2 == 999) {
619		cleanup_function();
620		fail_exit();
621	}
622}
623
624/*
625 *    void test17A()    - tests the assertion:
626 *      A call to int nftw(const char *path, int (*fn)(const char *, const
627 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
628 *      FTW_SL as the third argument to the function fn if and only if the
629 *      FTW_PHYS flag is included in flags.
630 */
631
632void test17A(void)
633{
634	int ret;
635
636	visit = 0;
637
638#ifdef DEBUG
639	fprintf(temp, "TEST: nftw with FTW_PHYS passes FTW_SL for symlink\n");
640#endif
641
642	if ((ret =
643	     nftw("./tmp/data/dirl", test_func17, MAX_FD, FTW_PHYS)) == -1) {
644		perror("nftw");
645		cleanup_function();
646		fail_exit();
647	}
648	if (ret != 999) {
649		fprintf(temp, "ERROR: nftw() failed to find symbolic link\n");
650		cleanup_function();
651		fail_exit();
652	}
653
654	visit = 0;
655
656#ifdef DEBUG
657	fprintf(temp,
658		"TEST: nftw without FTW_PHYS does not pass FTW_SL for symlink\n");
659#endif
660
661	if ((ret = nftw("./tmp/data/dirl", test_func17, MAX_FD, 0)) == -1) {
662		perror("nftw");
663		cleanup_function();
664		fail_exit();
665	}
666	if (ret == 999) {
667		fprintf(temp, "ERROR: nftw() found symbolic link\n");
668		cleanup_function();
669		fail_exit();
670	}
671}
672
673/*
674 *    void test18A()    - tests the assertion:
675 *      A call to int nftw(const char *path, int (*fn)(const char *, const
676 *      struct stat *, int, struct FTW *), int depth, int flags) shall pass
677 *      FTW_SLN as the third argument to the function fn if and only if the
678 *      FTW_PHYS flag is not included in flags.
679 */
680
681void test18A(void)
682{
683	int ret;
684
685	unlink("./tmp/byebye");
686
687	visit = 0;
688
689#ifdef DEBUG
690	fprintf(temp, "TEST: nftw with FTW_PHYS does not pass FTW_SLN\n");
691#endif
692
693	if ((ret = nftw("./tmp/data/dirg", test_func18, MAX_FD,
694			FTW_PHYS)) == -1) {
695		perror("nftw");
696		cleanup_function();
697		fail_exit();
698	}
699	if (ret == 999) {
700		fprintf(temp, "ERROR: nftw() passed FTW_SLN\n");
701		cleanup_function();
702		fail_exit();
703	}
704
705	visit = 0;
706
707#ifdef DEBUG
708	fprintf(temp, "TEST: nftw without FTW_PHYS passes FTW_SLN\n");
709#endif
710
711	if ((ret = nftw("./tmp/data/dirg", test_func18, MAX_FD, 0)) == -1) {
712		perror("nftw");
713		cleanup_function();
714		fail_exit();
715	}
716
717	if (visit == 1) {
718		if (ret == 999) {
719			/* Test is passed */
720			return;
721		} else {
722			fprintf(temp, "ERROR: nftw passed FTW_SLN but did");
723			fprintf(temp, "not return value returned by fn()\n");
724			cleanup_function();
725			fail_exit();
726		}
727	} else {
728		fprintf(temp, "ERROR: nftw() did not pass FTW_SLN\n");
729		cleanup_function();
730		fail_exit();
731	}
732}
733
734/*
735 *    void test19A()    - tests the assertion:
736 *      On a call to int nftw(const char *path, int (*fn)(const char *, const
737 *      struct stat *, int, struct FTW *), int depth, int flags) when the
738 *      third argument passed to the function fn is FTW_DNR then the
739 *      descendants of the directory shall not be processed.
740 */
741
742void test19A(void)
743{
744	int ret_val;
745
746#ifdef DEBUG
747	fprintf(temp,
748		"TEST: Can not traverse directory with no read permission\n");
749#endif
750
751	visit = 0;
752
753	ret_val = nftw("./tmp/data/d333", test_func19, MAX_FD, 0);
754	if (ret_val == -1) {
755		perror("nftw");
756		cleanup_function();
757		fail_exit();
758	}
759
760	if (ret_val == 999) {
761		cleanup_function();
762		fail_exit();
763	}
764#ifdef DEBUG
765	fprintf(temp, "TEST: fn only be called once\n");
766#endif
767
768	if (visit != 1) {
769		fprintf(temp, "ERROR: %s",
770			"Directory without read permission allows traversing\n");
771		fprintf(temp, "       Visited %d files\n", visit);
772		cleanup_function();
773		fail_exit();
774	}
775}
776
777/*
778 *    void test20A()    - tests the assertion:
779 *      A call to int nftw(const char *path, int (*fn)(const char *, const
780 *      struct stat *, int, struct FTW *), int depth, int flags) shall close
781 *      any file descriptors or directory streams used to traverse the
782 *      directory tree.
783 */
784
785void test20A(void)
786{
787	int fd, nfd;
788
789#ifdef DEBUG
790	fprintf(temp, "TEST: File descriptors used in traversal are closed\n");
791#endif
792
793	if ((fd = open("./tmp/data/dirh", O_RDONLY)) == -1) {
794		perror("close");
795		cleanup_function();
796		fail_exit();
797	}
798
799	if (close(fd) == -1) {
800		perror("close");
801		cleanup_function();
802		fail_exit();
803	}
804
805	if (nftw("./tmp/data/dirh", test_func20, 1, 0) == -1) {
806		perror("nftw");
807		cleanup_function();
808		fail_exit();
809	}
810
811	if ((nfd = open("./tmp/data/dirh", O_RDONLY)) == -1) {
812		perror("open");
813		cleanup_function();
814		fail_exit();
815	}
816
817	if (nfd != fd) {
818		fprintf(temp, "ERROR: %s,fd == %d ofd = %d",
819			"nftw did not close all file descriptors used in traversal\n",
820			nfd, fd);
821		cleanup_function();
822		fail_exit();
823	}
824
825	if (close(nfd) == -1) {
826		perror("close");
827		cleanup_function();
828		fail_exit();
829	}
830}
831
832/*
833 *    void test21A()    - tests the assertion:
834 *      On a call to int nftw(const char *path, int (*fn)(const char *, const
835 *      struct stat *, int, struct FTW *), int depth, int flags) shall
836 *      be the maximum number of file descriptors used for the search.
837 */
838
839void test21A(void)
840{
841	char path[] = "./tmp/data/dirh";
842	int ret_val;
843
844#ifdef DEBUG
845	fprintf(temp,
846		"TEST: No more than depth file descriptors used in traversal\n");
847#endif
848
849	/*this is the fd we expect if 0 are used */
850	if ((next_fd[0] = open(path, O_RDONLY)) == -1) {
851		perror("open next_fd[0]");
852		cleanup_function();
853		fail_exit();
854	}
855
856	/*this is the fd we expect if 1 is used */
857	if ((next_fd[1] = open(path, O_RDONLY)) == -1) {
858		perror("open next_fd[1]");
859		cleanup_function();
860		fail_exit();
861	}
862
863	if (close(next_fd[0]) == -1) {
864		perror("close next_fd[0]");
865		cleanup_function();
866		fail_exit();
867	}
868
869	if (close(next_fd[1]) == -1) {
870		perror("close next_fd[1]");
871		cleanup_function();
872		fail_exit();
873	}
874
875	visit = 0;
876	ret_val = nftw(path, test_func21, 1, 0);
877	if (ret_val == -1) {
878		perror("nftw");
879		cleanup_function();
880		fail_exit();
881	}
882
883	if (ret_val == 999) {
884		cleanup_function();
885		fail_exit();
886	}
887}
888
889/*
890 *    void test22A()    - tests the assertion:
891 *      A call to int nftw(const char *path, int (*fn)(const char *, const
892 *      struct stat *, int, struct FTW *), int depth, int flags) shall use at
893 *      most one file descriptor for each directory level.
894 */
895
896void test22A(void)
897{
898	char path[] = "./tmp/data/dirh";
899	int ret_val, i;
900
901	for (i = 0; i < 4; i++) {
902		if ((next_fd[i] = open(path, O_RDONLY)) == -1) {
903			perror("open");
904			cleanup_function();
905			fail_exit();
906		}
907	}
908
909	for (i = 0; i < 4; i++) {
910		if (close(next_fd[i]) == -1) {
911			perror("close");
912			cleanup_function();
913			fail_exit();
914		}
915	}
916
917	visit = 0;
918
919#ifdef DEBUG
920	fprintf(temp,
921		"TEST: No more than 1 fd per level is used in traversal\n");
922#endif
923
924	ret_val = nftw(path, test_func22, MAX_FD, 0);
925
926	if (ret_val == -1) {
927		perror("nftw");
928		cleanup_function();
929		fail_exit();
930	}
931
932	if (ret_val == 999) {
933		cleanup_function();
934		fail_exit();
935	}
936}
937
938/*
939 *    void test23A()    - tests the assertion:
940 *      A call to int nftw(const char *path, int (*fn)(const char *, const
941 *      struct stat *, int, struct FTW *), int depth, int flags) when the
942 *      function fn returns a non-zero value shall stop and return the value
943 *      returned by fn.
944 */
945
946void test23A(void)
947{
948	int ret;
949
950	visit = 0;
951
952#ifdef DEBUG
953	fprintf(temp,
954		"TEST: The function nftw should return with value set by fn\n");
955#endif
956
957	if ((ret =
958	     nftw("./tmp/data/dirh", test_func23, MAX_FD, FTW_PHYS)) == -1) {
959		perror("nftw");
960		cleanup_function();
961		fail_exit();
962	}
963
964	if (ret != 999) {
965		fprintf(temp,
966			"ERROR: nftw did not return value returned by fn()\n");
967		cleanup_function();
968		fail_exit();
969	}
970	if (visit != 4) {
971		fprintf(temp,
972			"ERROR: nftw() did not return immediately on non-zero fn() return\n");
973		cleanup_function();
974		fail_exit();
975	}
976}
977
978/*
979 *    void test24A()    - tests the assertion:
980 *      ENAMETOOLONG in errno and return -1 on a call to int nftw(const char
981 *      *path, int (*fn)(const char *, const struct stat *, int, struct FTW
982 *      *), int depth, int flags) when the length of path exceeds PATH_MAX.
983 */
984
985void test24A(void)
986{
987	test_ENAMETOOLONG_path("nftw", callback, -1);
988}
989
990/*
991 *    void test25A()    - tests the assertion:
992 *      ENAMETOOLONG in errno and return -1 on a call to int nftw(const char
993 *      *path, int (*fn)(const char *, const struct stat *, int, struct FTW
994 *      *), int depth, int flags) when a component of path exceeds NAME_MAX.
995 */
996
997void test25A(void)
998{
999	test_ENAMETOOLONG_name("nftw", callback, -1);
1000}
1001
1002/*
1003 *    void test26A()    - tests the assertion:
1004 *      ENOENT in errno and return -1 on a call to int nftw(const char *path,
1005 *      int (*fn)(const char *, const struct stat *, int, struct FTW *), int
1006 *      depth, int flags) when path points to a file which does not exist.
1007 */
1008
1009void test26A(void)
1010{
1011#ifdef DEBUG
1012	fprintf(temp, "TEST: [ENOENT] && -1 returned by nftw\n");
1013#endif
1014
1015	test_ENOENT_nofile("nftw", callback, -1);
1016}
1017
1018/*
1019 *    void test27A()    - tests the assertion:
1020 *      ENOENT in errno and return -1 on a call to int nftw(const char *path,
1021 *      int (*fn)(const char *, const struct stat *, int, struct FTW *), int
1022 *      depth, int flags) when path points to an empty string.
1023 */
1024
1025void test27A(void)
1026{
1027#ifdef DEBUG
1028	fprintf(temp, "TEST: The function nftw should return with a -1\n");
1029#endif
1030
1031	test_ENOENT_empty("nftw", callback, -1);
1032}
1033
1034/*
1035 *    void test28A()    - tests the assertion:
1036 *      ENOTDIR in errno and return -1 on a call to int nftw(const char
1037 *      *path, int (*fn)(const char *, const struct stat *, int, struct FTW
1038 *      *), int depth, int flags) when path is not a directory.
1039 */
1040
1041void test28A(void)
1042{
1043#ifdef DEBUG
1044	fprintf(temp, "TEST: [ENOTDIR] && -1 returned by nftw\n");
1045#endif
1046
1047	test_ENOTDIR("nftw", callback, -1);
1048}
1049
1050/*
1051 *    void test29A()    - tests the assertion:
1052 *      EACCES in errno and return -1 on a call to int nftw(const char *path,
1053 *      int (*fn)(const char *, const struct stat *, int, struct FTW *), int
1054 *      depth, int flags) when search permission is denied for any component
1055 *      of path.
1056 */
1057
1058void test29A(void)
1059{
1060	if (chmod("./tmp/data/d333", (mode_t) S_IRUSR) == -1) {
1061		perror("chmod");
1062		cleanup_function();
1063		fail_exit();
1064	}
1065#ifdef DEBUG
1066	fprintf(temp, "TEST: [EACCES] && -1 returned by nftw\n");
1067#endif
1068
1069	test_ENOTDIR("nftw", callback, -1);
1070}
1071
1072/*
1073 *    void test30A()    - tests the assertion:
1074 *      EACCES in errno and return -1 on a call to int nftw(const char *path,
1075 *      int (*fn)(const char *, const struct stat *, int, struct FTW *), int
1076 *      depth, int flags) when read permission is denied for path.
1077 */
1078
1079void test30A(void)
1080{
1081	if (chmod("./tmp/data/d333", (mode_t) S_IXUSR) == -1) {
1082		perror("chmod");
1083		cleanup_function();
1084		fail_exit();
1085	}
1086#ifdef DEBUG
1087	fprintf(temp, "TEST: [EACCES] && -1 returned by nftw\n");
1088#endif
1089	test_ENOTDIR("nftw", callback, -1);
1090}
1091