(__getcwd): Don't assume that system calls after readdir
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 30 Oct 2005 01:31:32 +0000 (01:31 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 30 Oct 2005 01:31:32 +0000 (01:31 +0000)
leave errno alone.  Problem reported by Dmitry V. Levin.

lib/ChangeLog
lib/getcwd.c

index 1dd26ac7a47c5d6ffbfeb28dc48b285d36f7ba6d..ca4aa7462cc075aabb080d99d8ee870d887c7c39 100644 (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
index 3bc6e9a52ec498a140671b19a46ed851bbed4bb8..ec1771b83d87ed90d6f0b23cf467f8d539f852ef 100644 (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;
+             __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;