static void check_realpath_recurse(const char *path, int depth) { DIR *dir; struct dirent *dirent; char pathsub[PATH_MAX + 1]; struct stat st; /* check with the path itself */ check_realpath_step_by_step(path, 0); /* don't go too deep */ if (depth < 1) return; /* don't bother with non-directories. Due to timeouts in drivers we * might not get expected results and takes way too long */ if (stat(path, &st) != 0) { /* dangling symlinks may cause legitimate failures here */ if (lstat(path, &st) != 0) ERR; return; } if (!S_ISDIR(st.st_mode)) return; /* loop through subdirectories (including . and ..) */ if (!(dir = opendir(path))) { /* Opening some special files might result in errors when the * corresponding hardware is not present, or simply when access * rights prohibit access (e.g., /dev/log). */ if (errno != ENOTDIR && errno != ENXIO && errno != EIO && errno != EACCES) { ERR; } return; } while ((dirent = readdir(dir)) != NULL) { /* build path */ if (!pathncat(pathsub, sizeof(pathsub), path, dirent->d_name)) { ERR; continue; } /* check path */ check_realpath_recurse(pathsub, depth - 1); } if (closedir(dir) < 0) ERR; }
static void check_realpath_recurse(const char *path, int depth) { DIR *dir; struct dirent *dirent; char pathsub[PATH_MAX + 1]; /* check with the path itself */ check_realpath_step_by_step(path, 0); /* don't go too deep */ if (depth < 1) return; /* loop through subdirectories (including . and ..) */ if (!(dir = opendir(path))) { /* Opening some special files might result in errors when the * corresponding hardware is not present, or simply when access * rights prohibit access (e.g., /dev/log). */ if (errno != ENOTDIR && errno != ENXIO && errno != EIO && errno != EACCES) { ERR; } return; } while ((dirent = readdir(dir)) != NULL) { /* build path */ if (!pathncat(pathsub, sizeof(pathsub), path, dirent->d_name)) { ERR; continue; } /* check path */ check_realpath_recurse(pathsub, depth - 1); } if (closedir(dir) < 0) ERR; }
int main(int argc, char **argv) { char buffer1[PATH_MAX + 1], buffer2[PATH_MAX + 1]; subtest = 1; /* initialize */ start(43); executable = argv[0]; getcwd(basepath, sizeof(basepath)); /* prepare some symlinks to make it more difficult */ if (symlink("/", addbasepath(buffer1, L(1))) < 0) ERR; if (symlink(basepath, addbasepath(buffer1, L(2))) < 0) ERR; /* perform some tests */ check_realpath_recurse(basepath, PATH_DEPTH); /* now try with recursive symlinks */ if (symlink(addbasepath(buffer1, L(3)), addbasepath(buffer2, L(3))) < 0) ERR; if (symlink(addbasepath(buffer1, L(5)), addbasepath(buffer2, L(4))) < 0) ERR; if (symlink(addbasepath(buffer1, L(4)), addbasepath(buffer2, L(5))) < 0) ERR; check_realpath_step_by_step(addbasepath(buffer1, L(3)), ELOOP); check_realpath_step_by_step(addbasepath(buffer1, L(4)), ELOOP); check_realpath_step_by_step(addbasepath(buffer1, L(5)), ELOOP); /* delete the symlinks */ cleanup(); /* also test dirname */ test_dirname("", "."); test_dirname(".", "."); test_dirname("..", "."); test_dirname("x", "."); test_dirname("xy", "."); test_dirname("x/y", "x"); test_dirname("xy/z", "xy"); test_dirname("x/yz", "x"); test_dirname("ab/cd", "ab"); test_dirname("x//y", "x"); test_dirname("xy//z", "xy"); test_dirname("x//yz", "x"); test_dirname("ab//cd", "ab"); test_dirname("/", "/"); test_dirname("/x", "/"); test_dirname("/xy", "/"); test_dirname("/x/y", "/x"); test_dirname("/xy/z", "/xy"); test_dirname("/x/yz", "/x"); test_dirname("/ab/cd", "/ab"); test_dirname("/x//y", "/x"); test_dirname("/xy//z", "/xy"); test_dirname("/x//yz", "/x"); test_dirname("/ab//cd", "/ab"); test_dirname("/usr/src", "/usr"); test_dirname("/usr/src/test", "/usr/src"); test_dirname("usr/src", "usr"); test_dirname("usr/src/test", "usr/src"); /* done */ quit(); return(-1); /* impossible */ }