diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2005-10-30 01:32:04 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2005-10-30 01:32:04 +0000 |
commit | 0b78641d85af3b72e3b9d94cb7b94e45f3c08ee5 (patch) | |
tree | b971536e2bb1f5809a20ffb2d3a5e50da2e47c7a /lib | |
parent | e8a9707b9127a0c83a9711b9b909c1e23fc51bd5 (diff) | |
download | gnulib-0b78641d85af3b72e3b9d94cb7b94e45f3c08ee5.tar.gz |
* getcwd.c (__getcwd): Don't assume that system calls after readdir
leave errno alone.
Diffstat (limited to 'lib')
-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 9ad3c38863..87bf2c246a 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 3bc6e9a52e..ec1771b83d 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; |