On Sat, 2007-12-22 at 10:13 -0500, Chet Ramey wrote:
> Michael Haubenwallner wrote:
> >> It is because readdir() returns 0 (zero) for (struct dirent).(d_ino),
> >> while stat() returns useful values for (struct stat).(st_ino), so their 
> >> equal-comparison never succeeds.
> > 
> > Attached patch should fix this issue, not relying on readdir() returning
> > valid d_ino, but doing stat() always instead.
> 
> You didn't attach one.

Uh oh, indeed, sorry. Here it is.

/haubi/
-- 
Michael Haubenwallner
Gentoo on a different level
--- lib/sh/getcwd.c.orig	Fri Dec 21 11:34:00 2007
+++ lib/sh/getcwd.c	Fri Dec 21 14:37:57 2007
@@ -58,6 +58,24 @@
 #  define NULL 0
 #endif
 
+static int concat_path_and_stat(char *dotp, size_t dotlen,
+	char *nam, size_t namlen,
+	struct stat *st, char mount_point, ino_t thisino,
+	int *saved_errno)
+{
+  char *name;
+  name = alloca(dotlen + 1 + namlen + 1);
+  memcpy(name, dotp, dotlen);
+  name[dotlen] = '/';
+  memcpy(&name[dotlen+1], nam, namlen+1);
+  if (stat(name, st) < 0)
+    return -1;
+  if (mount_point || st->st_ino == thisino)
+      if (lstat(name, st) < 0)
+	  *saved_errno = errno;
+  return 0;
+}
+
 /* Get the pathname of the current working directory,
    and put it in SIZE bytes of BUF.  Returns NULL if the
    directory couldn't be determined or SIZE was too small.
@@ -169,31 +187,15 @@
 	      (d->d_name[1] == '\0' ||
 		(d->d_name[1] == '.' && d->d_name[2] == '\0')))
 	    continue;
-	  if (mount_point || d->d_fileno == thisino)
-	    {
-	      char *name;
-
-	      namlen = D_NAMLEN(d);
-	      name = (char *)
-		alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
-	      memcpy (name, dotp, dotlist + dotsize - dotp);
-	      name[dotlist + dotsize - dotp] = '/';
-	      memcpy (&name[dotlist + dotsize - dotp + 1],
-		      d->d_name, namlen + 1);
-	      if (lstat (name, &st) < 0)
-		{
-#if 0
-		  int save = errno;
-		  (void) closedir (dirstream);
-		  errno = save;
-		  goto lose;
-#else
-		  saved_errno = errno;
-#endif
-		}
-	      if (st.st_dev == thisdev && st.st_ino == thisino)
-		break;
-	    }
+	    namlen = D_NAMLEN(d);
+	    if (concat_path_and_stat(dotp, dotlist + dotsize - dotp,
+		    d->d_name, namlen,
+		    &st, mount_point, thisino,
+		    &saved_errno
+	    ) < 0)
+		goto lose;
+	    if (st.st_dev == thisdev && st.st_ino == thisino)
+	      break;
 	}
       if (d == NULL)
 	{

Reply via email to