]> git.eshelyaron.com Git - emacs.git/commitdiff
Report readdir failures
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 29 Jan 2015 23:32:15 +0000 (15:32 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 29 Jan 2015 23:33:20 +0000 (15:33 -0800)
Previously, on non-MS-Windows platforms the code treated most
readdir failures as EOF.  This was incorrect, e.g., when readdir
fails with errno == EOVERFLOW.  Signal an error instead.
* dired.c (read_dirent):
New function, which signals an error when readdir fails.
(directory_files_internal, file_name_completion): Use it.

src/ChangeLog
src/dired.c

index 96e6aa25d5e24bb7f5d3cefc7ff13a7a7ad666c0..029ac88a28f035977379382cb259ea78010526fa 100644 (file)
@@ -1,3 +1,13 @@
+2015-01-29  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Report readdir failures
+       Previously, on non-MS-Windows platforms the code treated most
+       readdir failures as EOF.  This was incorrect, e.g., when readdir
+       fails with errno == EOVERFLOW.  Signal an error instead.
+       * dired.c (read_dirent):
+       New function, which signals an error when readdir fails.
+       (directory_files_internal, file_name_completion): Use it.
+
 2015-01-29  Eli Zaretskii  <eliz@gnu.org>
 
        * dired.c (directory_files_internal, file_name_completion)
index f0e81b612787a8d98bd6f8c0629f4fe49ecec349..23a867463f4c265ca527265683d51963e86f8496 100644 (file)
@@ -120,6 +120,25 @@ directory_files_internal_unwind (void *dh)
   unblock_input ();
 }
 
+/* Return the next directory entry from DIR; DIR's name is DIRNAME.
+   If there are no more directory entries, return a null pointer.
+   Signal any unrecoverable errors.  */
+
+static struct dirent *
+read_dirent (DIR *dir, Lisp_Object dirname)
+{
+  while (true)
+    {
+      errno = 0;
+      struct dirent *dp = readdir (dir);
+      if (dp || errno == 0)
+       return dp;
+      if (! (errno == EAGAIN || errno == EINTR))
+       report_file_error ("Reading directory", dirname);
+      QUIT;
+    }
+}
+
 /* Function shared by Fdirectory_files and Fdirectory_files_and_attributes.
    If not ATTRS, return a list of directory filenames;
    if ATTRS, return a list of directory filenames and their attributes.
@@ -138,7 +157,6 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
   bool needsep = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-  struct dirent *dp;
 #ifdef WINDOWSNT
   Lisp_Object w32_save = Qnil;
 #endif
@@ -221,36 +239,13 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
       || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
     needsep = 1;
 
-  /* Loop reading blocks until EOF or error.  */
-  for (;;)
+  /* Loop reading directory entries.  */
+  for (struct dirent *dp; (dp = read_dirent (d, directory)); )
     {
-      ptrdiff_t len;
-      bool wanted = 0;
-      Lisp_Object name, finalname;
+      ptrdiff_t len = dirent_namelen (dp);
+      Lisp_Object name = make_unibyte_string (dp->d_name, len);
+      Lisp_Object finalname = name;
       struct gcpro gcpro1, gcpro2;
-
-      errno = 0;
-      dp = readdir (d);
-      if (!dp)
-       {
-         if (errno == EAGAIN || errno == EINTR)
-           {
-             QUIT;
-             continue;
-           }
-#ifdef WINDOWSNT
-         /* The MS-Windows implementation of 'opendir' doesn't
-            actually open a directory until the first call to
-            'readdir'.  If 'readdir' fails to open the directory, it
-            sets errno to ENOENT or EACCES, see w32.c.  */
-         if (errno)
-           report_file_error ("Opening directory", directory);
-#endif
-         break;
-       }
-
-      len = dirent_namelen (dp);
-      name = finalname = make_unibyte_string (dp->d_name, len);
       GCPRO2 (finalname, name);
 
       /* Note: DECODE_FILE can GC; it should protect its argument,
@@ -263,9 +258,8 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
       immediate_quit = 1;
       QUIT;
 
-      if (NILP (match)
-         || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0)
-       wanted = 1;
+      bool wanted = (NILP (match)
+                    || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0);
 
       immediate_quit = 0;
 
@@ -498,32 +492,12 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
 
   record_unwind_protect_ptr (directory_files_internal_unwind, d);
 
-  /* Loop reading blocks */
-  /* (att3b compiler bug requires do a null comparison this way) */
-  while (1)
+  /* Loop reading directory entries.  */
+  for (struct dirent *dp; (dp = read_dirent (d, dirname)); )
     {
-      struct dirent *dp;
-      ptrdiff_t len;
+      ptrdiff_t len = dirent_namelen (dp);
       bool canexclude = 0;
 
-      errno = 0;
-      dp = readdir (d);
-      if (!dp)
-       {
-         if (errno == EAGAIN || errno == EINTR)
-           {
-             QUIT;
-             continue;
-           }
-#ifdef WINDOWSNT
-         if (errno)
-           report_file_error ("Opening directory", dirname);
-#endif
-         break;
-       }
-
-      len = dirent_namelen (dp);
-
       QUIT;
       if (len < SCHARS (encoded_file)
          || (scmp (dp->d_name, SSDATA (encoded_file),