From: Sami Kerola Date: Thu, 30 Sep 2010 22:33:44 +0000 (+0200) Subject: namei: parse all path arguments when an optarg path will fail X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c49e31f4ee7c35946f91335a8a3179f503bd9cf0;p=util-linux namei: parse all path arguments when an optarg path will fail Old implementation of namei listed path all the way to non-existing file or directory, something like: f: /usr/bin/nxdir/file d / d usr d bin ? nxdir - No such file or directory (2) whiles the current implementation prints: namei: failed to stat: /usr/bin/nxdir/file: No such file or directory The new output it's not helpful. I am especially interested see where the path is broken when a path is symlink to other path with symlink, and few more like that, and something somewhere is broken. [kzak@redhat.com: - coding style changes] Signed-off-by: Sami Kerola Signed-off-by: Karel Zak --- diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 6853e1ec..9873cda9 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -60,6 +60,7 @@ struct namei { struct namei *next; /* next item */ int level; int mountpoint; /* is mount point */ + int noent; /* is this item not existing */ }; struct idcache { @@ -250,8 +251,10 @@ new_namei(struct namei *parent, const char *path, const char *fname, int lev) nm->name = strdup(fname); if (!nm->name) err(EXIT_FAILURE, _("out of memory?")); - if (lstat(path, &nm->st) == -1) - err(EXIT_FAILURE, _("could not stat '%s'"), path); + + nm->noent = (lstat(path, &nm->st) == -1); + if (nm->noent) + return nm; if (S_ISLNK(nm->st.st_mode)) readlink_to_namei(nm, path); @@ -331,7 +334,6 @@ add_namei(struct namei *parent, const char *orgpath, int start, struct namei **l return first; } - static int follow_symlinks(struct namei *nm) { @@ -340,6 +342,8 @@ follow_symlinks(struct namei *nm) for (; nm; nm = nm->next) { struct namei *next, *last; + if (nm->noent) + continue; if (!S_ISLNK(nm->st.st_mode)) continue; if (++symcount > MAXSYMLINKS) { @@ -394,7 +398,7 @@ strmode(mode_t mode, char *str) str[10] = '\0'; } -static void +static int print_namei(struct namei *nm, char *path) { struct namei *prev = NULL; @@ -406,6 +410,11 @@ print_namei(struct namei *nm, char *path) for (; nm; prev = nm, nm = nm->next) { char md[11]; + if (nm->noent) { + printf(_("%s - No such file or directory\n"), nm->name); + return -1; + } + strmode(nm->st.st_mode, md); if (nm->mountpoint) @@ -439,6 +448,7 @@ print_namei(struct namei *nm, char *path) else printf(" %s\n", nm->name); } + return 0; } static void @@ -482,6 +492,7 @@ main(int argc, char **argv) { extern int optind; int c; + int rc = EXIT_SUCCESS; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -522,25 +533,29 @@ main(int argc, char **argv) struct stat st; if (stat(path, &st) != 0) - err(EXIT_FAILURE, _("failed to stat: %s"), path); + rc = EXIT_FAILURE; nm = add_namei(NULL, path, 0, NULL); if (nm) { int sml = 0; if (!(flags & NAMEI_NOLINKS)) sml = follow_symlinks(nm); - print_namei(nm, path); + if (print_namei(nm, path)) { + rc = EXIT_FAILURE; + continue; + } free_namei(nm); - if (sml == -1) - errx(EXIT_FAILURE, - _("%s: exceeded limit of symlinks"), - path); + if (sml == -1) { + rc = EXIT_FAILURE; + warnx(_("%s: exceeded limit of symlinks"), path); + continue; + } } } free_idcache(ucache); free_idcache(gcache); - return EXIT_SUCCESS; + return rc; }