summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2005-10-30 01:31:32 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2005-10-30 01:31:32 +0000
commitb90c07efd8332e5884900dacc7f34a8d4eb27bfb (patch)
tree9adfe2f54182395617e9602eab0413e205500bbb
parent5648577df01d1f210790aaeec645c767137316eb (diff)
downloadcoreutils-b90c07efd8332e5884900dacc7f34a8d4eb27bfb.tar.xz
(__getcwd): Don't assume that system calls after readdir
leave errno alone. Problem reported by Dmitry V. Levin.
-rw-r--r--lib/ChangeLog5
-rw-r--r--lib/getcwd.c81
2 files changed, 46 insertions, 40 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 1dd26ac7a..ca4aa7462 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,8 @@
+2005-10-29 Paul Eggert <eggert@cs.ucla.edu>
+
+ * getcwd.c (__getcwd): Don't assume that system calls after readdir
+ leave errno alone. Problem reported by Dmitry V. Levin.
+
2005-10-28 Paul Eggert <eggert@cs.ucla.edu>
* savedir.c (savedir): Don't assume that xrealloc etc. leave
diff --git a/lib/getcwd.c b/lib/getcwd.c
index 3bc6e9a52..ec1771b83 100644
--- a/lib/getcwd.c
+++ b/lib/getcwd.c
@@ -201,6 +201,8 @@ __getcwd (char *buf, size_t size)
ino_t dotino;
bool mount_point;
int parent_status;
+ size_t dirroom;
+ size_t namlen;
/* Look at the parent directory. */
#ifdef AT_FDCWD
@@ -241,11 +243,20 @@ __getcwd (char *buf, size_t size)
goto lose;
dotlist[dotlen++] = '/';
#endif
- /* Clear errno to distinguish EOF from error if readdir returns
- NULL. */
- __set_errno (0);
- while ((d = __readdir (dirstream)) != NULL)
+ for (;;)
{
+ /* Clear errno to distinguish EOF from error if readdir returns
+ NULL. */
+ __set_errno (0);
+ d = __readdir (dirstream);
+ if (d == NULL)
+ {
+ if (errno == 0)
+ /* EOF on dirstream, which means that the current directory
+ has been removed. */
+ __set_errno (ENOENT);
+ goto lose;
+ }
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
@@ -303,48 +314,38 @@ __getcwd (char *buf, size_t size)
break;
}
}
- if (d == NULL)
- {
- if (errno == 0)
- /* EOF on dirstream, which means that the current directory
- has been removed. */
- __set_errno (ENOENT);
- goto lose;
- }
- else
- {
- size_t dirroom = dirp - dir;
- size_t namlen = _D_EXACT_NAMLEN (d);
- if (dirroom <= namlen)
+ dirroom = dirp - dir;
+ namlen = _D_EXACT_NAMLEN (d);
+
+ if (dirroom <= namlen)
+ {
+ if (size != 0)
{
- if (size != 0)
- {
- __set_errno (ERANGE);
- goto lose;
- }
- else
- {
- char *tmp;
- size_t oldsize = allocated;
+ __set_errno (ERANGE);
+ goto lose;
+ }
+ else
+ {
+ char *tmp;
+ size_t oldsize = allocated;
- allocated += MAX (allocated, namlen);
- if (allocated < oldsize
- || ! (tmp = realloc (dir, allocated)))
- goto memory_exhausted;
+ allocated += MAX (allocated, namlen);
+ if (allocated < oldsize
+ || ! (tmp = realloc (dir, allocated)))
+ goto memory_exhausted;
- /* Move current contents up to the end of the buffer.
- This is guaranteed to be non-overlapping. */
- dirp = memcpy (tmp + allocated - (oldsize - dirroom),
- tmp + dirroom,
- oldsize - dirroom);
- dir = tmp;
- }
+ /* Move current contents up to the end of the buffer.
+ This is guaranteed to be non-overlapping. */
+ dirp = memcpy (tmp + allocated - (oldsize - dirroom),
+ tmp + dirroom,
+ oldsize - dirroom);
+ dir = tmp;
}
- dirp -= namlen;
- memcpy (dirp, d->d_name, namlen);
- *--dirp = '/';
}
+ dirp -= namlen;
+ memcpy (dirp, d->d_name, namlen);
+ *--dirp = '/';
thisdev = dotdev;
thisino = dotino;