diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2005-10-30 01:31:32 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2005-10-30 01:31:32 +0000 |
commit | b90c07efd8332e5884900dacc7f34a8d4eb27bfb (patch) | |
tree | 9adfe2f54182395617e9602eab0413e205500bbb | |
parent | 5648577df01d1f210790aaeec645c767137316eb (diff) | |
download | coreutils-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/ChangeLog | 5 | ||||
-rw-r--r-- | lib/getcwd.c | 81 |
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; |