Home | History | Annotate | Download | only in nftw
      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 (at) us.ibm.com */
     21 /* 06/30/2001   Port to Linux   nsharoff (at) us.ibm.com */
     22 
     23 /*
     24  * NAME
     25  *      test.c - Test functions for nftw()
     26  */
     27 
     28 #include "nftw.h"
     29 
     30 extern int callback(const char *path);
     31 
     32 extern pathdata pathdat[];
     33 extern struct list mnem[], badlist[];
     34 extern char *dirlist[NDIRLISTENTS], *goodlist[];
     35 extern int npathdats, ngoods, nbads, nmnem, visit, s2, next_fd[4];
     36 
     37 extern 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 
     47 void 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 
    107 void 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 
    152 void 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 
    189 void 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 
    225 void 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 
    261 void 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 
    298 void 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 
    326 void 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 
    355 void 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 
    384 void 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 
    414 void 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 
    448 void 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 
    478 void 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 
    518 void 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 
    547 void 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 
    578 void 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 
    632 void 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 
    681 void 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 
    742 void 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 
    785 void 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 
    839 void 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 
    896 void 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 
    946 void 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 
    985 void 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 
    997 void 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 
   1009 void 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 
   1025 void 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 
   1041 void 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 
   1058 void 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 
   1079 void 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