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)
{