From 3162c27324bb6a26cfb9e47b266d2a3ee451f47b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 6 Dec 2012 15:13:30 -0600 Subject: Have dirtree_add_node() set parent so error message can provide full path. --- lib/dirtree.c | 48 +++++++++++++++++++++++++++++------------------- lib/lib.h | 2 +- toys/posix/chgrp.c | 5 ++--- toys/posix/du.c | 2 +- toys/posix/ls.c | 2 +- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/dirtree.c b/lib/dirtree.c index d1de40ee..33188e1f 100644 --- a/lib/dirtree.c +++ b/lib/dirtree.c @@ -5,11 +5,27 @@ #include "toys.h" +static int notdotdot(char *name) +{ + if (name[0]=='.' && (!name[1] || (name[1]=='.' && !name[2]))) return 0; + + return 1; +} + +// Default callback, filters out "." and "..". + +int dirtree_notdotdot(struct dirtree *catch) +{ + // Should we skip "." and ".."? + return notdotdot(catch->name) ? DIRTREE_SAVE|DIRTREE_RECURSE : 0; +} + // Create a dirtree node from a path, with stat and symlink info. // (This doesn't open directory filehandles yet so as not to exhaust the // filehandle space on large trees. handle_callback() does that instead.) -struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow) +struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, + int symfollow) { struct dirtree *dt = NULL; struct stat st; @@ -17,15 +33,18 @@ struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow) int len = 0, linklen = 0; if (name) { - if (fstatat(dirfd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) - goto error; + // open code this because haven't got node to call dirtree_parentfd() on yet + int fd = parent ? parent->data : AT_FDCWD; + + if (fstatat(fd, name, &st, symfollow ? 0 : AT_SYMLINK_NOFOLLOW)) goto error; if (S_ISLNK(st.st_mode)) { - if (0>(linklen = readlinkat(dirfd, name, buf, 4095))) goto error; + if (0>(linklen = readlinkat(fd, name, buf, 4095))) goto error; buf[linklen++]=0; } len = strlen(name); } dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); + dt->parent = parent; if (name) { memcpy(&(dt->st), &st, sizeof(struct stat)); strcpy(dt->name, name); @@ -39,7 +58,10 @@ struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow) return dt; error: - perror_msg("%s",name); + if (notdotdot(name)) { + char *path = parent ? dirtree_path(parent, 0) : ""; + perror_msg("%s%s%s",path, parent ? "/" : "", name); + } free(dt); return 0; } @@ -66,17 +88,6 @@ char *dirtree_path(struct dirtree *node, int *plen) return path; } -// Default callback, filters out "." and "..". - -int dirtree_notdotdot(struct dirtree *catch) -{ - // Should we skip "." and ".."? - if (catch->name[0]=='.' && (!catch->name[1] || - (catch->name[1]=='.' && !catch->name[2]))) return 0; - - return DIRTREE_SAVE|DIRTREE_RECURSE; -} - int dirtree_parentfd(struct dirtree *node) { return node->parent ? node->parent->data : AT_FDCWD; @@ -140,9 +151,8 @@ void dirtree_recurse(struct dirtree *node, // The extra parentheses are to shut the stupid compiler up. while ((entry = readdir(dir))) { - if (!(new = dirtree_add_node(node->data, entry->d_name, symfollow))) + if (!(new = dirtree_add_node(node, entry->d_name, symfollow))) continue; - new->parent = node; new = handle_callback(new, callback); if (new == DIRTREE_ABORTVAL) break; if (new) { @@ -163,7 +173,7 @@ void dirtree_recurse(struct dirtree *node, struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)) { - struct dirtree *root = dirtree_add_node(AT_FDCWD, path, 0); + struct dirtree *root = dirtree_add_node(0, path, 0); return root ? handle_callback(root, callback) : DIRTREE_ABORTVAL; } diff --git a/lib/lib.h b/lib/lib.h index 3023f0dc..1c0350e0 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -70,7 +70,7 @@ struct dirtree { char name[]; }; -struct dirtree *dirtree_add_node(int dirfd, char *name, int symfollow); +struct dirtree *dirtree_add_node(struct dirtree *p, char *name, int symfollow); char *dirtree_path(struct dirtree *node, int *plen); int dirtree_notdotdot(struct dirtree *catch); int dirtree_parentfd(struct dirtree *node); diff --git a/toys/posix/chgrp.c b/toys/posix/chgrp.c index ed2ff9b2..802d8f8f 100644 --- a/toys/posix/chgrp.c +++ b/toys/posix/chgrp.c @@ -71,7 +71,7 @@ static int do_chgrp(struct dirtree *node) void chgrp_main(void) { - int ischown = toys.which->name[2] == 'o'; + int ischown = toys.which->name[2] == 'o', hl = toys.optflags&(FLAG_H|FLAG_L); char **s, *own; // Distinguish chown from chgrp @@ -103,8 +103,7 @@ void chgrp_main(void) } for (s=toys.optargs+1; *s; s++) { - struct dirtree *new = dirtree_add_node(AT_FDCWD, *s, - toys.optflags&(FLAG_H|FLAG_L)); + struct dirtree *new = dirtree_add_node(0, *s, hl); if (new) handle_callback(new, do_chgrp); else toys.exitval = 1; } diff --git a/toys/posix/du.c b/toys/posix/du.c index 68cf286d..6c09aec6 100644 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -203,7 +203,7 @@ void du_main(void) while(*toys.optargs) { TT.depth = 0; char *path = make_pathproper(*toys.optargs); - struct dirtree *root = dirtree_add_node(AT_FDCWD, path, symfollow); //create a node + struct dirtree *root = dirtree_add_node(0, path, symfollow); if(root) { TT.st_dev = root->st.st_dev; handle_callback(root, do_du); //this will recurse thru the DIR children. diff --git a/toys/posix/ls.c b/toys/posix/ls.c index 6bb41521..cd881b05 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -436,7 +436,7 @@ void ls_main(void) // Non-absolute paths are relative to current directory. TT.files = dirtree_add_node(0, 0, 0); for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { - dt = dirtree_add_node(AT_FDCWD, *s, + dt = dirtree_add_node(0, *s, (toys.optflags & (FLAG_L|FLAG_H|FLAG_l))^FLAG_l); if (!dt) { -- cgit v1.2.3