--- util-linux-2.13-pre7/misc-utils/namei.1.nodir 2006-12-15 10:58:38.000000000 +0100 +++ util-linux-2.13-pre7/misc-utils/namei.1 2006-12-15 10:58:51.000000000 +0100 @@ -52,9 +52,5 @@ Roger Southwick (rogers@amadeus.wr.tek.com) .SH BUGS To be discovered. -.SH CAVEATS -.I Namei -will follow an infinite loop of symbolic links forever. To escape, use -SIGINT (usually ^C). .SH "SEE ALSO" ls(1), stat(1) --- util-linux-2.13-pre7/misc-utils/namei.c.nodir 2006-12-14 21:38:41.000000000 +0100 +++ util-linux-2.13-pre7/misc-utils/namei.c 2006-12-15 10:58:31.000000000 +0100 @@ -42,6 +42,10 @@ 1999-02-22 Arkadiusz Mi¶kiewicz - added Native Language Support +2006-12-15 Karel Zak +- fixed logic; don't follow the path if a component is not directory +- fixed infinite loop of symbolic links; stack size is very limited + -------------------------------------------------------------*/ #include @@ -66,7 +70,7 @@ #endif static char *pperm(unsigned short); -static void namei(char *, int); +static void namei(char *, int, mode_t *); static void usage(void); int @@ -107,9 +111,10 @@ for(; optind < argc; optind++){ + mode_t lastmode = 0; (void)printf("f: %s\n", argv[optind]); symcount = 1; - namei(argv[optind], 0); + namei(argv[optind], 0, &lastmode); if(chdir(curdir) == -1){ (void)fprintf(stderr, @@ -131,8 +136,10 @@ #define NODEV (dev_t)(-1) #endif +int kzak; + static void -namei(char *file, int lev) { +namei(char *file, int lev, mode_t *lastmode) { char *cp; char buf[BUFSIZ], sym[BUFSIZ]; struct stat stb; @@ -143,7 +150,7 @@ * See if the file has a leading /, and if so cd to root */ - if(*file == '/'){ + if(file && *file == '/'){ while(*file == '/') file++; @@ -166,7 +173,7 @@ (void)printf(" d /\n"); } - for(;;){ + for(; file && *file;){ if (strlen(file) >= BUFSIZ) { fprintf(stderr,_("namei: buf overflow\n")); @@ -198,6 +205,20 @@ for(i = 0; i < lev; i++) (void)printf(" "); + + /* + * Previous element in the path wasn't directory, it means + * we cannot walk on *path* and check the actual element by lstat(), because + * there could be a component with same name. Try: + * + * $ touch a b + * $ namei a/b <-- "a" is not directory so namei shouldn't check for "b" + */ + if (*lastmode && S_ISDIR(*lastmode)==0 && S_ISLNK(*lastmode)==0){ + (void)printf(" ? %s - %s (%d)\n", buf, strerror(ENOENT), ENOENT); + return; + } + /* * See what type of critter this file is */ @@ -207,6 +228,8 @@ return; } + *lastmode = stb.st_mode; + switch(stb.st_mode & S_IFMT){ case S_IFDIR: @@ -241,7 +264,6 @@ * Sigh, another symlink. Read its contents and * call namei() */ - bzero(sym, BUFSIZ); if(readlink(buf, sym, BUFSIZ) == -1){ (void)printf(_(" ? problems reading symlink %s - %s (%d)\n"), buf, ERR); @@ -255,11 +277,12 @@ if(symcount > 0 && symcount++ > MAXSYMLINKS){ (void)printf(_(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***\n")); - symcount = -1; } else { (void)printf("\n"); - namei(sym, lev + 1); + namei(sym, lev + 1, lastmode); } + if (symcount > MAXSYMLINKS) + return; break; case S_IFCHR: