Mercurial > hg > toybox
comparison lib/dirtree.c @ 607:8bee9c27c219 0.3.1
Unify chown and chgrp, add support for -hHLP flags.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 24 Jun 2012 18:35:49 -0500 |
parents | a6a541b7fc34 |
children | 225262d6e6c7 |
comparison
equal
deleted
inserted
replaced
606:b9ea00fffee5 | 607:8bee9c27c219 |
---|---|
82 int dirtree_parentfd(struct dirtree *node) | 82 int dirtree_parentfd(struct dirtree *node) |
83 { | 83 { |
84 return node->parent ? node->parent->data : AT_FDCWD; | 84 return node->parent ? node->parent->data : AT_FDCWD; |
85 } | 85 } |
86 | 86 |
87 // get open filehandle for node in extra, giving caller the option of | |
88 // using DIRTREE_COMEAGAIN or not. | |
89 int dirtree_opennode(struct dirtree *try) | |
90 { | |
91 if (!dirtree_notdotdot(try)) return 0; | |
92 if (S_ISDIR(try->st.st_mode)) { | |
93 if (!try->extra) { | |
94 try->extra = xdup(try->data); | |
95 return DIRTREE_COMEAGAIN; | |
96 } | |
97 } else try->extra = openat(dirtree_parentfd(try), try->name, 0); | |
98 | |
99 return DIRTREE_SAVE|DIRTREE_RECURSE; | |
100 } | |
101 | |
102 // Handle callback for a node in the tree. Returns saved node(s) or NULL. | 87 // Handle callback for a node in the tree. Returns saved node(s) or NULL. |
103 // | 88 // |
104 // By default, allocates a tree of struct dirtree, not following symlinks | 89 // By default, allocates a tree of struct dirtree, not following symlinks |
105 // If callback==NULL, or callback always returns 0, allocate tree of struct | 90 // If callback==NULL, or callback always returns 0, allocate tree of struct |
106 // dirtree and return root of tree. Otherwise call callback(node) on each | 91 // dirtree and return root of tree. Otherwise call callback(node) on each |
112 { | 97 { |
113 int flags, dir = S_ISDIR(new->st.st_mode); | 98 int flags, dir = S_ISDIR(new->st.st_mode); |
114 | 99 |
115 if (!callback) callback = dirtree_notdotdot; | 100 if (!callback) callback = dirtree_notdotdot; |
116 | 101 |
117 // Directory always has filehandle for examining contents. Whether or | |
118 // not we'll recurse into it gets decided later. | |
119 | |
120 if (dir) new->data = openat(dirtree_parentfd(new), new->name, 0); | |
121 | |
122 flags = callback(new); | 102 flags = callback(new); |
123 | 103 |
124 if (dir) { | 104 if (dir) { |
125 if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { | 105 if (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)) { |
106 new->data = openat(dirtree_parentfd(new), new->name, 0); | |
126 dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW); | 107 dirtree_recurse(new, callback, flags & DIRTREE_SYMFOLLOW); |
127 if (flags & DIRTREE_COMEAGAIN) flags = callback(new); | 108 if (flags & DIRTREE_COMEAGAIN) flags = callback(new); |
128 } else close(new->data); | 109 } |
129 } | 110 } |
130 | 111 |
131 // If this had children, it was callback's job to free them already. | 112 // If this had children, it was callback's job to free them already. |
132 if (!(flags & DIRTREE_SAVE)) { | 113 if (!(flags & DIRTREE_SAVE)) { |
133 free(new); | 114 free(new); |
178 } | 159 } |
179 | 160 |
180 // Create dirtree from path, using callback to filter nodes. | 161 // Create dirtree from path, using callback to filter nodes. |
181 // If callback == NULL allocate a tree of struct dirtree nodes and return | 162 // If callback == NULL allocate a tree of struct dirtree nodes and return |
182 // pointer to root node. | 163 // pointer to root node. |
164 // symfollow is just for the top of tree, callback return code controls children | |
183 | 165 |
184 struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) | 166 struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) |
185 { | 167 { |
186 struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); | 168 struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); |
187 | 169 |