From 8d95074b7d034188af8542aaea0306d3670d71be Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 7 Mar 2016 16:02:47 -0600 Subject: Cleanup pass on the dirtree infrastructure, in preparation for making rm -r handle infinite depth. Fix docs, tweak dirtree_handle_callback() semantics, remove dirtree_start() and don't export dirtree_handle_callback(), instead offer dirtree_flagread(). (dirtree_read() is a wrapper around dirtree_flagread passing 0 for flags.) --- lib/dirtree.c | 39 +++++++++++++++++++-------------------- lib/lib.h | 7 ++++--- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/dirtree.c b/lib/dirtree.c index 8b9f2993..cc1ab90c 100644 --- a/lib/dirtree.c +++ b/lib/dirtree.c @@ -17,7 +17,7 @@ static int notdotdot(char *name) int dirtree_notdotdot(struct dirtree *catch) { // Should we skip "." and ".."? - return notdotdot(catch->name) ? DIRTREE_SAVE|DIRTREE_RECURSE : 0; + return notdotdot(catch->name)*(DIRTREE_SAVE|DIRTREE_RECURSE); } // Create a dirtree node from a path, with stat and symlink info. @@ -96,21 +96,18 @@ int dirtree_parentfd(struct dirtree *node) return node->parent ? node->parent->dirfd : AT_FDCWD; } -// Handle callback for a node in the tree. Returns saved node(s) or NULL. -// -// By default, allocates a tree of struct dirtree, not following symlinks -// If callback==NULL, or callback always returns 0, allocate tree of struct -// dirtree and return root of tree. Otherwise call callback(node) on each -// hit, free structures after use, and return NULL. -// +// Handle callback for a node in the tree. Returns saved node(s) if +// callback returns DIRTREE_SAVE, otherwise frees consumed nodes and +// returns NULL. If !callback return top node unchanged. +// If !new return DIRTREE_ABORTVAL struct dirtree *dirtree_handle_callback(struct dirtree *new, int (*callback)(struct dirtree *node)) { int flags; - if (!new) return 0; - if (!callback) callback = dirtree_notdotdot; + if (!new) return DIRTREE_ABORTVAL; + if (!callback) return new; flags = callback(new); if (S_ISDIR(new->st.st_mode)) { @@ -176,19 +173,21 @@ int dirtree_recurse(struct dirtree *node, return flags; } -// Create dirtree root -struct dirtree *dirtree_start(char *name, int symfollow) +// Create dirtree from path, using callback to filter nodes. If !callback +// return just the top node. Use dirtree_notdotdot callback to allocate a +// tree of struct dirtree nodes and return pointer to root node for later +// processing. +// Returns DIRTREE_ABORTVAL if path didn't exist (use DIRTREE_SHUTUP to handle +// error message yourself). + +struct dirtree *dirtree_flagread(char *path, int flags, + int (*callback)(struct dirtree *node)) { - return dirtree_add_node(0, name, DIRTREE_SYMFOLLOW*!!symfollow); + return dirtree_handle_callback(dirtree_add_node(0, path, flags), callback); } -// Create dirtree from path, using callback to filter nodes. -// If callback == NULL allocate a tree of struct dirtree nodes and return -// pointer to root node. - +// Common case struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) { - struct dirtree *root = dirtree_start(path, 0); - - return root ? dirtree_handle_callback(root, callback) : DIRTREE_ABORTVAL; + return dirtree_flagread(path, 0, callback); } diff --git a/lib/lib.h b/lib/lib.h index c8cff6ef..917be0c1 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -62,6 +62,8 @@ void get_optflags(void); #define DIRTREE_SYMFOLLOW 8 // Don't warn about failure to stat #define DIRTREE_SHUTUP 16 +// Breadth first traversal, conserves filehandles at the expense of memory +#define DIRTREE_BREADTH 32 // Don't look at any more files in this directory. #define DIRTREE_ABORT 256 @@ -77,15 +79,14 @@ struct dirtree { char name[]; }; -struct dirtree *dirtree_start(char *name, int symfollow); struct dirtree *dirtree_add_node(struct dirtree *p, char *name, int flags); char *dirtree_path(struct dirtree *node, int *plen); int dirtree_notdotdot(struct dirtree *catch); int dirtree_parentfd(struct dirtree *node); -struct dirtree *dirtree_handle_callback(struct dirtree *new, - int (*callback)(struct dirtree *node)); int dirtree_recurse(struct dirtree *node, int (*callback)(struct dirtree *node), int symfollow); +struct dirtree *dirtree_flagread(char *path, int flags, + int (*callback)(struct dirtree *node)); struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)); // help.c -- cgit v1.2.3