/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (1); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { de = readdir(t->d); if (de == NULL) { closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (1); } } /* If the current dir needs to be traversed, set it up. */ if (t->stack->flags & needsTraversal) { tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsTraversal; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { t->stack->fd = open(".", O_RDONLY); t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } if (chdir(t->stack->name) == 0) { t->depth++; t->dirname_length = t->path_length; t->d = opendir("."); } else tree_pop(t); continue; } /* We've done everything necessary for the top stack entry. */ tree_ascend(t); tree_pop(t); } return (0); }
/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; int r; /* If we're called again after a fatal error, that's an API * violation. Just crash now. */ if (t->visit_type == TREE_ERROR_FATAL) { const char *msg = "Unable to continue traversing" " directory hierarchy after a fatal error.\n"; errmsg(msg); *(volatile int *)0 = 1; /* Deliberate SEGV; NULL pointer dereference. */ exit(1); /* In case the SEGV didn't work. */ } /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (t->visit_type = TREE_REGULAR); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { errno = 0; de = readdir(t->d); if (de == NULL) { if (errno) { /* If readdir fails, we're screwed. */ closedir(t->d); t->d = NULL; t->visit_type = TREE_ERROR_FATAL; return (t->visit_type); } /* Reached end of directory. */ closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_REGULAR); } } /* If the current dir needs to be visited, set it up. */ if (t->stack->flags & needsPreVisit) { t->current = t->stack; tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsPreVisit; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { #ifdef HAVE_FCHDIR t->stack->fd = open(".", O_RDONLY); #elif defined(_WIN32) && !defined(__CYGWIN__) t->stack->fullpath = getcwd(NULL, 0); #endif t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } t->dirname_length = t->path_length; if (chdir(t->stack->name) != 0) { /* chdir() failed; return error */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->depth++; t->d = opendir("."); if (t->d == NULL) { r = tree_ascend(t); /* Undo "chdir" */ tree_pop(t); t->tree_errno = errno; t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } t->flags &= ~hasLstat; t->flags &= ~hasStat; t->basename = "."; /* Figure out where we are. */ if (getcwd(t->realpath, PATH_MAX) != NULL) { t->realpath_dirname_length = strlen(t->realpath); if (t->realpath[0] == '/' && t->realpath[1] == '\0') t->realpath_dirname_length = 0; t->realpath_valid = 1; } else { t->realpath_valid = 0; } return (t->visit_type = TREE_POSTDESCENT); } /* We've done everything necessary for the top stack entry. */ if (t->stack->flags & needsPostVisit) { r = tree_ascend(t); tree_pop(t); t->flags &= ~hasLstat; t->flags &= ~hasStat; t->visit_type = r != 0 ? r : TREE_POSTASCENT; return (t->visit_type); } } return (t->visit_type = 0); }
/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (t->visit_type = TREE_REGULAR); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { de = readdir(t->d); if (de == NULL) { closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_REGULAR); } } /* If the current dir needs to be visited, set it up. */ if (t->stack->flags & needsPreVisit) { t->current = t->stack; tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsPreVisit; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { t->stack->fd = open(".", O_RDONLY); t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } t->dirname_length = t->path_length; if (chdir(t->stack->name) != 0) { /* chdir() failed; return error */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->depth++; t->d = opendir("."); if (t->d == NULL) { tree_ascend(t); /* Undo "chdir" */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->flags &= ~hasLstat; t->flags &= ~hasStat; t->basename = "."; return (t->visit_type = TREE_POSTDESCENT); } /* We've done everything necessary for the top stack entry. */ if (t->stack->flags & needsPostVisit) { tree_ascend(t); tree_pop(t); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_POSTASCENT); } } return (t->visit_type = 0); }