diff src/dired.c @ 267:966663fcf606 r20-5b32

Import from CVS: tag r20-5b32
author cvs
date Mon, 13 Aug 2007 10:26:29 +0200
parents 727739f917cb
children c5d627a313b1
line wrap: on
line diff
--- a/src/dired.c	Mon Aug 13 10:25:39 2007 +0200
+++ b/src/dired.c	Mon Aug 13 10:26:29 2007 +0200
@@ -63,43 +63,41 @@
 */
        (dirname, full, match, nosort, files_only))
 {
-  /* This function can GC.  GC checked 1997.04.06. */
+  /* This function can GC */
   DIR *d;
-  Bytecount name_as_dir_length;
-  Lisp_Object list = Qnil, name, dirfilename = Qnil;
+  Lisp_Object list = Qnil;
+  Bytecount dirnamelen;
   Lisp_Object handler;
   struct re_pattern_buffer *bufp = NULL;
-  Lisp_Object name_as_dir = Qnil;
   int speccount = specpdl_depth ();
   char *statbuf, *statbuf_tail;
 
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  GCPRO4 (dirname, name_as_dir, dirfilename, list);
+  struct gcpro gcpro1, gcpro2;
+  GCPRO2 (dirname, list);
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
   handler = Ffind_file_name_handler (dirname, Qdirectory_files);
   if (!NILP (handler))
-  {
-    UNGCPRO;
-    if (!NILP (files_only))
-      return call6 (handler, Qdirectory_files, dirname, full, match, nosort,
-                    files_only);
-    else
-      return call5 (handler, Qdirectory_files, dirname, full, match,
-		    nosort);
-  }
+    {
+      UNGCPRO;
+      if (!NILP (files_only))
+	return call6 (handler, Qdirectory_files, dirname, full, match, nosort,
+		      files_only);
+      else
+	return call5 (handler, Qdirectory_files, dirname, full, match,
+		      nosort);
+    }
 
   /* #### why do we do Fexpand_file_name after file handlers here,
      but earlier everywhere else? */
   dirname = Fexpand_file_name (dirname, Qnil);
-  dirfilename = Fdirectory_file_name (dirname);
-  name_as_dir = Ffile_name_as_directory (dirname);
+  dirname = Ffile_name_as_directory (dirname);
+  dirnamelen = XSTRING_LENGTH (dirname);
 
-  name_as_dir_length = XSTRING_LENGTH (name_as_dir);
-  statbuf = (char *) alloca (name_as_dir_length + MAXNAMLEN + 1);
-  memcpy (statbuf, XSTRING_DATA (name_as_dir), name_as_dir_length);
-  statbuf_tail = statbuf + name_as_dir_length;
+  statbuf = (char *)alloca (dirnamelen + MAXNAMLEN + 1);
+  memcpy (statbuf, XSTRING_DATA (dirname), dirnamelen);
+  statbuf_tail = statbuf + dirnamelen;
 
   /* XEmacs: this should come after Ffile_name_as_directory() to avoid
      potential regexp cache smashage.  It comes before the opendir()
@@ -117,81 +115,82 @@
   /* Now *bufp is the compiled form of MATCH; don't call anything
      which might compile a new regexp until we're done with the loop!  */
 
-  /* Do this opendir after anything which might signal an error;
-     previosly, there was no unwind-protection in case of error, but
-     now there is.  */
-  d = opendir ((char *) XSTRING_DATA (dirfilename));
-  if (! d)
+  /* Do this opendir after anything which might signal an error.
+     NOTE: the above comment is old; previosly, there was no
+     unwind-protection in case of error, but now there is.  */
+  d = opendir ((char *) XSTRING_DATA (dirname));
+  if (!d)
     report_file_error ("Opening directory", list1 (dirname));
 
   record_unwind_protect (close_directory_unwind, make_opaque_ptr ((void *)d));
 
-  list = Qnil;
-
   /* Loop reading blocks */
   while (1)
     {
       DIRENTRY *dp = readdir (d);
+      Lisp_Object name;
       int len;
 
-      if (!dp) break;
+      if (!dp)
+	break;
       len = NAMLEN (dp);
-      if (DIRENTRY_NONEMPTY (dp))
+      if (DIRENTRY_NONEMPTY (dp)
+	  && (NILP (match)
+	      || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0))))
 	{
-	  int result;
-	  result = (NILP (match)
-	      || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)));
-          if (result)
+	  if (!NILP (files_only))
 	    {
-	      if (!NILP (files_only))
-		{
-		  int dir_p;
-		  struct stat st;
-		  char *cur_statbuf = statbuf;
-		  char *cur_statbuf_tail = statbuf_tail;
+	      int dir_p;
+	      struct stat st;
+	      char *cur_statbuf = statbuf;
+	      char *cur_statbuf_tail = statbuf_tail;
+
+	      /* #### I don't think the code under `if' is necessary
+		 anymore.  The crashes in this function were reported
+		 because MAXNAMLEN was used to remember the *whole*
+		 statbuf, instead of using MAXPATHLEN.  This should be
+		 tested after 20.5 is released.  */
 
-		  /* A trick: we normally use the buffer created by
-		     alloca.  However, if the filename is too big
-		     (meaning MAXNAMLEN is wrong or useless on the
-		     system), we'll use a malloced buffer, and free
-		     it. */
-		  if (len > MAXNAMLEN)
-		    {
-		      cur_statbuf = (char *) xmalloc (name_as_dir_length
-						      + len + 1);
-		      memcpy (cur_statbuf, statbuf, name_as_dir_length);
-		      cur_statbuf_tail = cur_statbuf + name_as_dir_length;
-		    }
-		  memcpy (cur_statbuf_tail, dp->d_name, len);
-		  cur_statbuf_tail [len] = 0;
-
-		  if (stat (cur_statbuf, &st) < 0)
-		    dir_p = 0;
-		  else
-		    dir_p = ((st.st_mode & S_IFMT) == S_IFDIR);
+	      /* We normally use the buffer created by alloca.
+		 However, if the file name we get too big, we'll use a
+		 malloced buffer, and free it.  It is undefined how
+		 stat() will react to this, but we avoid a buffer
+		 overrun.  */
+	      if (len > MAXNAMLEN)
+		{
+		  cur_statbuf = (char *)xmalloc (dirnamelen + len + 1);
+		  memcpy (cur_statbuf, statbuf, dirnamelen);
+		  cur_statbuf_tail = cur_statbuf + dirnamelen;
+		}
+	      memcpy (cur_statbuf_tail, dp->d_name, len);
+	      cur_statbuf_tail[len] = 0;
 
-		  if (cur_statbuf != statbuf)
-		    xfree (cur_statbuf);
+	      if (stat (cur_statbuf, &st) < 0)
+		dir_p = 0;
+	      else
+		dir_p = ((st.st_mode & S_IFMT) == S_IFDIR);
 
-		  if (EQ (files_only, Qt) && dir_p)
-		    continue;
-		  else if (!EQ (files_only, Qt) && !dir_p)
-		    continue;
-		}
+	      if (cur_statbuf != statbuf)
+		xfree (cur_statbuf);
 
-	      if (!NILP (full))
-		name = concat2 (name_as_dir,
-				make_ext_string ((Bufbyte *)dp->d_name,
-						 len, FORMAT_FILENAME));
-	      else
-		name = make_ext_string ((Bufbyte *)dp->d_name,
-					len, FORMAT_FILENAME);
+	      if (EQ (files_only, Qt) && dir_p)
+		continue;
+	      else if (!EQ (files_only, Qt) && !dir_p)
+		continue;
+	    }
 
-	      list = Fcons (name, list);
-	    }
+	  if (!NILP (full))
+	    name = concat2 (dirname, make_ext_string ((Bufbyte *)dp->d_name,
+						      len, FORMAT_FILENAME));
+	  else
+	    name = make_ext_string ((Bufbyte *)dp->d_name,
+				    len, FORMAT_FILENAME);
+
+	  list = Fcons (name, list);
 	}
     }
   unbind_to (speccount, Qnil);	/* This will close the dir */
+
   if (!NILP (nosort))
     RETURN_UNGCPRO (list);
   else
@@ -292,17 +291,17 @@
 }
 
 static Lisp_Object
-file_name_completion_unwind (Lisp_Object unwind_obj)
+file_name_completion_unwind (Lisp_Object locative)
 {
   DIR *d;
-  Lisp_Object obj = XCAR (unwind_obj);
+  Lisp_Object obj = XCAR (locative);
 
   if (NILP (obj))
     return Qnil;
   d = (DIR *)get_opaque_ptr (obj);
   closedir (d);
   free_opaque_ptr (obj);
-  free_cons (XCONS (unwind_obj));
+  free_cons (XCONS (locative));
   return Qnil;
 }
 
@@ -319,8 +318,7 @@
   int passcount;
   int speccount = specpdl_depth ();
   Charcount file_name_length;
-  DIRENTRY *((*readfunc) (DIR *)) = readdir;
-  Lisp_Object unwind_closure;
+  Lisp_Object locative;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   GCPRO3 (file, dirname, bestmatch);
@@ -331,7 +329,7 @@
   /* Filename completion on Windows ignores case, since Windows
      filesystems do.  */
   specbind (Qcompletion_ignore_case, Qt);
-#endif /* HAVE_WINDOWS */
+#endif /* WINDOWSNT */
 
 #ifdef FILE_SYSTEM_CASE
   file = FILE_SYSTEM_CASE (file);
@@ -352,15 +350,15 @@
      call closedir, but it was wrong, because it made sane handling of
      QUIT impossible and, besides, various utility functions like
      regexp_ignore_completion_p can signal errors.  */
-  unwind_closure = noseeum_cons (Qnil, Qnil);
-  record_unwind_protect (file_name_completion_unwind, unwind_closure);
+  locative = noseeum_cons (Qnil, Qnil);
+  record_unwind_protect (file_name_completion_unwind, locative);
 
   for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
     {
       d = opendir ((char *) XSTRING_DATA (Fdirectory_file_name (dirname)));
       if (!d)
 	report_file_error ("Opening directory", list1 (dirname));
-      XCAR (unwind_closure) = make_opaque_ptr ((void *)d);
+      XCAR (locative) = make_opaque_ptr ((void *)d);
 
       /* Loop reading blocks */
       while (1)
@@ -374,7 +372,7 @@
           int ignored_extension_p = 0;
 	  Bufbyte *d_name;
 
-	  dp = (*readfunc) (d);
+	  dp = readdir (d);
 	  if (!dp) break;
 
 	  /* #### This is a bad idea, because d_name can contain
@@ -516,8 +514,8 @@
             }
         }
       closedir (d);
-      free_opaque_ptr (XCAR (unwind_closure));
-      XCAR (unwind_closure) = Qnil;
+      free_opaque_ptr (XCAR (locative));
+      XCAR (locative) = Qnil;
     }
 
   unbind_to (speccount, Qnil);