mschorm / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone
Blob Blame History Raw
--- 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 <misiek@pld.ORG.PL>
 - added Native Language Support
 
+2006-12-15 Karel Zak <kzak@redhat.com> 
+- 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 <stdio.h>
@@ -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: