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