1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-07-25 10:16:53 +02:00

(__getcwd): Don't assume that system calls after readdir

leave errno alone.  Problem reported by Dmitry V. Levin.
This commit is contained in:
Paul Eggert
2005-10-30 01:31:32 +00:00
parent 5648577df0
commit b90c07efd8
2 changed files with 48 additions and 42 deletions
+5
View File
@@ -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
+43 -42
View File
@@ -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;
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;
}
__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;
/* 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;