Subject: Re: bug#4673: Not the same as 4674

From: Eli Zaretskii <[email-masked]>
Date: Sat, 04 Feb 2012 11:05:50 +0200

> Date: Fri, 3 Feb 2012 12:17:31 +0000
> From: Richard Copley <[email-masked]>
> Cc: [email-masked]
> 
> >> Visiting a Windows DFS share when ".." is not accessible still crashes
> >> in `ls-lisp-insert-directory' in the trunk of Emacs, as the attribute
> >> list for ".." in the `file-alist' returned for by
> >> `directory-files-and-attributes' is empty.
> >
> > What does the following yield for a DFS share?
> >
> >  M-: (file-attributes "//root/share/.." 'string) RET
> 
> nil.
> 
> > For that matter, what does the following cmd command display?
> >
> >  dir /n/q/a:d \\root\share
> 
> 
>  Volume in drive \\root\share is Data
>  Volume Serial Number is 0123-4567
> 
>  Directory of \\root\share
> 
> 11/11/2011  12:34    <DIR>          BUILTIN\Administrators .
> 11/11/2011  12:34    <DIR>          BUILTIN\Administrators ..
>                0 File(s)              0 bytes
>                2 Dir(s)  123,456,789,000 bytes free

Can you test the patch below?  I don't have access to such shares, so
I cannot test it myself.  TIA.

Since ls-lisp.el is preloaded, you will either need to rebuild Emacs
(if you have the development environment and the Emacs sources), or
manually load the patched ls-lisp.el before invoking Dired.

=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog	2012-02-04 02:10:22 +0000
+++ lisp/ChangeLog	2012-02-04 09:00:52 +0000
@@ -1,3 +1,9 @@
+2012-02-04  Eli Zaretskii  <[email-masked]>
+
+	* ls-lisp.el (ls-lisp-sanitize): New function.
+	(ls-lisp-insert-directory): Use it to fix or remove any elements
+	in file-alist with missing attributes.  (Bug#4673)
+
 2012-02-04  Glenn Morris  <[email-masked]>
 
 	* image.el (image-extension-data): Add obsolete alias.

=== modified file 'lisp/ls-lisp.el'
--- lisp/ls-lisp.el	2012-01-19 07:21:25 +0000
+++ lisp/ls-lisp.el	2012-02-04 08:55:21 +0000
@@ -331,6 +331,7 @@ not contain `d', so that a full listing 
 	     ;; do all bindings here for speed
 	     total-line files elt short file-size attr
 	     fuid fgid uid-len gid-len)
+	(setq file-alist (ls-lisp-sanitize file-alist))
 	(cond ((memq ?A switches)
 	       (setq file-alist
 		     (ls-lisp-delete-matching "^\\.\\.?$" file-alist)))
@@ -437,6 +438,22 @@ not contain `d', so that a full listing 
 	(message "%s: doesn't exist or is inaccessible" file)
 	(ding) (sit-for 2)))))		; to show user the message!
 
+(defun ls-lisp-sanitize (file-alist)
+  "Sanitize the elements in FILE-ALIST.
+Fixes any elements in the alist for directory entries whose file
+attributes are nil (meaning that `file-attributes' failed for
+them).  This is known to happen for some network shares, in
+particular for the \"..\" directory entry.
+
+If the \"..\" directory entry has nil attributes, the attributes
+are copied from the \".\" entry, if they are non-nil.  Otherwise,
+the offending element is removed from the list, as are any
+elements for other directory entries with nil attributes."
+  (if (and (null (cdr (assoc ".." file-alist)))
+	   (cdr (assoc "." file-alist)))
+      (setcdr (assoc ".." file-alist) (cdr (assoc "." file-alist))))
+  (rassq-delete-all nil file-alist))
+
 (defun ls-lisp-column-format (file-alist)
   "Insert the file names (only) in FILE-ALIST into the current buffer.
 Format in columns, sorted vertically, following GNU ls -C.