aboutsummaryrefslogtreecommitdiffstats
path: root/src/dired.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dired.c')
-rw-r--r--src/dired.c226
1 files changed, 117 insertions, 109 deletions
diff --git a/src/dired.c b/src/dired.c
index 3530b74ecb4..ab48488966b 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -1,5 +1,6 @@
1/* Lisp functions for making directory listings. 1/* Lisp functions for making directory listings.
2 Copyright (C) 1985-1986, 1993-1994, 1999-2012 Free Software Foundation, Inc. 2 Copyright (C) 1985-1986, 1993-1994, 1999-2013 Free Software
3 Foundation, Inc.
3 4
4This file is part of GNU Emacs. 5This file is part of GNU Emacs.
5 6
@@ -29,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29#include <grp.h> 30#include <grp.h>
30 31
31#include <errno.h> 32#include <errno.h>
33#include <fcntl.h>
32#include <unistd.h> 34#include <unistd.h>
33 35
34#include <dirent.h> 36#include <dirent.h>
@@ -53,6 +55,7 @@ static Lisp_Object Qfile_attributes;
53static Lisp_Object Qfile_attributes_lessp; 55static Lisp_Object Qfile_attributes_lessp;
54 56
55static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); 57static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
58static Lisp_Object file_attributes (int, char const *, Lisp_Object);
56 59
57/* Return the number of bytes in DP's name. */ 60/* Return the number of bytes in DP's name. */
58static ptrdiff_t 61static ptrdiff_t
@@ -65,6 +68,44 @@ dirent_namelen (struct dirent *dp)
65#endif 68#endif
66} 69}
67 70
71static DIR *
72open_directory (char const *name, int *fdp)
73{
74 DIR *d;
75 int fd, opendir_errno;
76
77 block_input ();
78
79#ifdef DOS_NT
80 /* Directories cannot be opened. The emulation assumes that any
81 file descriptor other than AT_FDCWD corresponds to the most
82 recently opened directory. This hack is good enough for Emacs. */
83 fd = 0;
84 d = opendir (name);
85 opendir_errno = errno;
86#else
87 fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0);
88 if (fd < 0)
89 {
90 opendir_errno = errno;
91 d = 0;
92 }
93 else
94 {
95 d = fdopendir (fd);
96 opendir_errno = errno;
97 if (! d)
98 close (fd);
99 }
100#endif
101
102 unblock_input ();
103
104 *fdp = fd;
105 errno = opendir_errno;
106 return d;
107}
108
68#ifdef WINDOWSNT 109#ifdef WINDOWSNT
69Lisp_Object 110Lisp_Object
70directory_files_internal_w32_unwind (Lisp_Object arg) 111directory_files_internal_w32_unwind (Lisp_Object arg)
@@ -77,7 +118,7 @@ directory_files_internal_w32_unwind (Lisp_Object arg)
77static Lisp_Object 118static Lisp_Object
78directory_files_internal_unwind (Lisp_Object dh) 119directory_files_internal_unwind (Lisp_Object dh)
79{ 120{
80 DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer; 121 DIR *d = XSAVE_POINTER (dh, 0);
81 block_input (); 122 block_input ();
82 closedir (d); 123 closedir (d);
83 unblock_input (); 124 unblock_input ();
@@ -95,6 +136,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
95 Lisp_Object id_format) 136 Lisp_Object id_format)
96{ 137{
97 DIR *d; 138 DIR *d;
139 int fd;
98 ptrdiff_t directory_nbytes; 140 ptrdiff_t directory_nbytes;
99 Lisp_Object list, dirfilename, encoded_directory; 141 Lisp_Object list, dirfilename, encoded_directory;
100 struct re_pattern_buffer *bufp = NULL; 142 struct re_pattern_buffer *bufp = NULL;
@@ -141,9 +183,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
141 /* Now *bufp is the compiled form of MATCH; don't call anything 183 /* Now *bufp is the compiled form of MATCH; don't call anything
142 which might compile a new regexp until we're done with the loop! */ 184 which might compile a new regexp until we're done with the loop! */
143 185
144 block_input (); 186 d = open_directory (SSDATA (dirfilename), &fd);
145 d = opendir (SSDATA (dirfilename));
146 unblock_input ();
147 if (d == NULL) 187 if (d == NULL)
148 report_file_error ("Opening directory", Fcons (directory, Qnil)); 188 report_file_error ("Opening directory", Fcons (directory, Qnil));
149 189
@@ -151,7 +191,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
151 file-attributes on filenames, both of which can throw, so we must 191 file-attributes on filenames, both of which can throw, so we must
152 do a proper unwind-protect. */ 192 do a proper unwind-protect. */
153 record_unwind_protect (directory_files_internal_unwind, 193 record_unwind_protect (directory_files_internal_unwind,
154 make_save_value (d, 0)); 194 make_save_pointer (d));
155 195
156#ifdef WINDOWSNT 196#ifdef WINDOWSNT
157 if (attrs) 197 if (attrs)
@@ -193,19 +233,15 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
193 233
194 errno = 0; 234 errno = 0;
195 dp = readdir (d); 235 dp = readdir (d);
196 236 if (!dp)
197 if (dp == NULL && (0 237 {
198#ifdef EAGAIN 238 if (errno == EAGAIN || errno == EINTR)
199 || errno == EAGAIN 239 {
200#endif 240 QUIT;
201#ifdef EINTR 241 continue;
202 || errno == EINTR 242 }
203#endif 243 break;
204 )) 244 }
205 { QUIT; continue; }
206
207 if (dp == NULL)
208 break;
209 245
210 len = dirent_namelen (dp); 246 len = dirent_namelen (dp);
211 name = finalname = make_unibyte_string (dp->d_name, len); 247 name = finalname = make_unibyte_string (dp->d_name, len);
@@ -222,7 +258,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
222 QUIT; 258 QUIT;
223 259
224 if (NILP (match) 260 if (NILP (match)
225 || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0))) 261 || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0)
226 wanted = 1; 262 wanted = 1;
227 263
228 immediate_quit = 0; 264 immediate_quit = 0;
@@ -262,20 +298,9 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
262 298
263 if (attrs) 299 if (attrs)
264 { 300 {
265 /* Construct an expanded filename for the directory entry. 301 Lisp_Object fileattrs
266 Use the decoded names for input to Ffile_attributes. */ 302 = file_attributes (fd, dp->d_name, id_format);
267 Lisp_Object decoded_fullname, fileattrs;
268 struct gcpro gcpro1, gcpro2;
269
270 decoded_fullname = fileattrs = Qnil;
271 GCPRO2 (decoded_fullname, fileattrs);
272
273 /* Both Fexpand_file_name and Ffile_attributes can GC. */
274 decoded_fullname = Fexpand_file_name (name, directory);
275 fileattrs = Ffile_attributes (decoded_fullname, id_format);
276
277 list = Fcons (Fcons (finalname, fileattrs), list); 303 list = Fcons (Fcons (finalname, fileattrs), list);
278 UNGCPRO;
279 } 304 }
280 else 305 else
281 list = Fcons (finalname, list); 306 list = Fcons (finalname, list);
@@ -416,8 +441,7 @@ These are all file names in directory DIRECTORY which begin with FILE. */)
416 return file_name_completion (file, directory, 1, Qnil); 441 return file_name_completion (file, directory, 1, Qnil);
417} 442}
418 443
419static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 444static int file_name_completion_stat (int, struct dirent *, struct stat *);
420 struct stat *st_addr);
421static Lisp_Object Qdefault_directory; 445static Lisp_Object Qdefault_directory;
422 446
423static Lisp_Object 447static Lisp_Object
@@ -425,6 +449,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
425 Lisp_Object predicate) 449 Lisp_Object predicate)
426{ 450{
427 DIR *d; 451 DIR *d;
452 int fd;
428 ptrdiff_t bestmatchsize = 0; 453 ptrdiff_t bestmatchsize = 0;
429 int matchcount = 0; 454 int matchcount = 0;
430 /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. 455 /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
@@ -459,16 +484,14 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
459 on the encoded file name. */ 484 on the encoded file name. */
460 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; 485 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
461 486
462 encoded_dir = ENCODE_FILE (dirname); 487 encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
463 488
464 block_input (); 489 d = open_directory (SSDATA (encoded_dir), &fd);
465 d = opendir (SSDATA (Fdirectory_file_name (encoded_dir)));
466 unblock_input ();
467 if (!d) 490 if (!d)
468 report_file_error ("Opening directory", Fcons (dirname, Qnil)); 491 report_file_error ("Opening directory", Fcons (dirname, Qnil));
469 492
470 record_unwind_protect (directory_files_internal_unwind, 493 record_unwind_protect (directory_files_internal_unwind,
471 make_save_value (d, 0)); 494 make_save_pointer (d));
472 495
473 /* Loop reading blocks */ 496 /* Loop reading blocks */
474 /* (att3b compiler bug requires do a null comparison this way) */ 497 /* (att3b compiler bug requires do a null comparison this way) */
@@ -480,27 +503,25 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
480 503
481 errno = 0; 504 errno = 0;
482 dp = readdir (d); 505 dp = readdir (d);
483 if (dp == NULL && (0 506 if (!dp)
484# ifdef EAGAIN 507 {
485 || errno == EAGAIN 508 if (errno == EAGAIN || errno == EINTR)
486# endif 509 {
487# ifdef EINTR 510 QUIT;
488 || errno == EINTR 511 continue;
489# endif 512 }
490 )) 513 break;
491 { QUIT; continue; } 514 }
492
493 if (!dp) break;
494 515
495 len = dirent_namelen (dp); 516 len = dirent_namelen (dp);
496 517
497 QUIT; 518 QUIT;
498 if (len < SCHARS (encoded_file) 519 if (len < SCHARS (encoded_file)
499 || 0 <= scmp (dp->d_name, SSDATA (encoded_file), 520 || scmp (dp->d_name, SSDATA (encoded_file),
500 SCHARS (encoded_file))) 521 SCHARS (encoded_file)) >= 0)
501 continue; 522 continue;
502 523
503 if (file_name_completion_stat (encoded_dir, dp, &st) < 0) 524 if (file_name_completion_stat (fd, dp, &st) < 0)
504 continue; 525 continue;
505 526
506 directoryp = S_ISDIR (st.st_mode) != 0; 527 directoryp = S_ISDIR (st.st_mode) != 0;
@@ -559,7 +580,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
559 if (skip < 0) 580 if (skip < 0)
560 continue; 581 continue;
561 582
562 if (0 <= scmp (dp->d_name + skip, p1, elt_len)) 583 if (scmp (dp->d_name + skip, p1, elt_len) >= 0)
563 continue; 584 continue;
564 break; 585 break;
565 } 586 }
@@ -581,9 +602,8 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
581 skip = len - SCHARS (elt); 602 skip = len - SCHARS (elt);
582 if (skip < 0) continue; 603 if (skip < 0) continue;
583 604
584 if (0 <= scmp (dp->d_name + skip, 605 if (scmp (dp->d_name + skip, SSDATA (elt), SCHARS (elt))
585 SSDATA (elt), 606 >= 0)
586 SCHARS (elt)))
587 continue; 607 continue;
588 break; 608 break;
589 } 609 }
@@ -677,10 +697,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
677 name, zero, 697 name, zero,
678 make_number (compare), 698 make_number (compare),
679 completion_ignore_case ? Qt : Qnil); 699 completion_ignore_case ? Qt : Qnil);
680 ptrdiff_t matchsize 700 ptrdiff_t matchsize = EQ (cmp, Qt) ? compare : eabs (XINT (cmp)) - 1;
681 = (EQ (cmp, Qt) ? compare
682 : XINT (cmp) < 0 ? - XINT (cmp) - 1
683 : XINT (cmp) - 1);
684 701
685 if (completion_ignore_case) 702 if (completion_ignore_case)
686 { 703 {
@@ -780,14 +797,9 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
780} 797}
781 798
782static int 799static int
783file_name_completion_stat (Lisp_Object dirname, struct dirent *dp, 800file_name_completion_stat (int fd, struct dirent *dp, struct stat *st_addr)
784 struct stat *st_addr)
785{ 801{
786 ptrdiff_t len = dirent_namelen (dp);
787 ptrdiff_t pos = SCHARS (dirname);
788 int value; 802 int value;
789 USE_SAFE_ALLOCA;
790 char *fullname = SAFE_ALLOCA (len + pos + 2);
791 803
792#ifdef MSDOS 804#ifdef MSDOS
793 /* Some fields of struct stat are *very* expensive to compute on MS-DOS, 805 /* Some fields of struct stat are *very* expensive to compute on MS-DOS,
@@ -800,23 +812,15 @@ file_name_completion_stat (Lisp_Object dirname, struct dirent *dp,
800 _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; 812 _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
801#endif /* MSDOS */ 813#endif /* MSDOS */
802 814
803 memcpy (fullname, SDATA (dirname), pos);
804 if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
805 fullname[pos++] = DIRECTORY_SEP;
806
807 memcpy (fullname + pos, dp->d_name, len);
808 fullname[pos + len] = 0;
809
810 /* We want to return success if a link points to a nonexistent file, 815 /* We want to return success if a link points to a nonexistent file,
811 but we want to return the status for what the link points to, 816 but we want to return the status for what the link points to,
812 in case it is a directory. */ 817 in case it is a directory. */
813 value = lstat (fullname, st_addr); 818 value = fstatat (fd, dp->d_name, st_addr, AT_SYMLINK_NOFOLLOW);
814 if (value == 0 && S_ISLNK (st_addr->st_mode)) 819 if (value == 0 && S_ISLNK (st_addr->st_mode))
815 stat (fullname, st_addr); 820 fstatat (fd, dp->d_name, st_addr, 0);
816#ifdef MSDOS 821#ifdef MSDOS
817 _djstat_flags = save_djstat_flags; 822 _djstat_flags = save_djstat_flags;
818#endif /* MSDOS */ 823#endif /* MSDOS */
819 SAFE_FREE ();
820 return value; 824 return value;
821} 825}
822 826
@@ -826,7 +830,7 @@ stat_uname (struct stat *st)
826#ifdef WINDOWSNT 830#ifdef WINDOWSNT
827 return st->st_uname; 831 return st->st_uname;
828#else 832#else
829 struct passwd *pw = (struct passwd *) getpwuid (st->st_uid); 833 struct passwd *pw = getpwuid (st->st_uid);
830 834
831 if (pw) 835 if (pw)
832 return pw->pw_name; 836 return pw->pw_name;
@@ -841,7 +845,7 @@ stat_gname (struct stat *st)
841#ifdef WINDOWSNT 845#ifdef WINDOWSNT
842 return st->st_gname; 846 return st->st_gname;
843#else 847#else
844 struct group *gr = (struct group *) getgrgid (st->st_gid); 848 struct group *gr = getgrgid (st->st_gid);
845 849
846 if (gr) 850 if (gr)
847 return gr->gr_name; 851 return gr->gr_name;
@@ -875,7 +879,7 @@ Elements of the attribute list are:
875 7. Size in bytes. 879 7. Size in bytes.
876 This is a floating point number if the size is too large for an integer. 880 This is a floating point number if the size is too large for an integer.
877 8. File modes, as a string of ten letters or dashes as in ls -l. 881 8. File modes, as a string of ten letters or dashes as in ls -l.
878 9. t if file's gid would change if file were deleted and recreated. 882 9. An unspecified value, present only for backward compatibility.
87910. inode number. If it is larger than what an Emacs integer can hold, 88310. inode number. If it is larger than what an Emacs integer can hold,
880 this is of the form (HIGH . LOW): first the high bits, then the low 16 bits. 884 this is of the form (HIGH . LOW): first the high bits, then the low 16 bits.
881 If even HIGH is too large for an Emacs integer, this is instead of the form 885 If even HIGH is too large for an Emacs integer, this is instead of the form
@@ -894,21 +898,8 @@ On some FAT-based filesystems, only the date of last access is recorded,
894so last access time will always be midnight of that day. */) 898so last access time will always be midnight of that day. */)
895 (Lisp_Object filename, Lisp_Object id_format) 899 (Lisp_Object filename, Lisp_Object id_format)
896{ 900{
897 Lisp_Object values[12];
898 Lisp_Object encoded; 901 Lisp_Object encoded;
899 struct stat s;
900#ifdef BSD4_2
901 Lisp_Object dirname;
902 struct stat sdir;
903#endif /* BSD4_2 */
904
905 /* An array to hold the mode string generated by filemodestring,
906 including its terminating space and null byte. */
907 char modes[sizeof "-rwxr-xr-x "];
908
909 Lisp_Object handler; 902 Lisp_Object handler;
910 struct gcpro gcpro1;
911 char *uname = NULL, *gname = NULL;
912 903
913 filename = Fexpand_file_name (filename, Qnil); 904 filename = Fexpand_file_name (filename, Qnil);
914 905
@@ -924,14 +915,41 @@ so last access time will always be midnight of that day. */)
924 return call3 (handler, Qfile_attributes, filename, id_format); 915 return call3 (handler, Qfile_attributes, filename, id_format);
925 } 916 }
926 917
927 GCPRO1 (filename);
928 encoded = ENCODE_FILE (filename); 918 encoded = ENCODE_FILE (filename);
929 UNGCPRO; 919 return file_attributes (AT_FDCWD, SSDATA (encoded), id_format);
920}
921
922static Lisp_Object
923file_attributes (int fd, char const *name, Lisp_Object id_format)
924{
925 Lisp_Object values[12];
926 struct stat s;
927 int lstat_result;
928
929 /* An array to hold the mode string generated by filemodestring,
930 including its terminating space and null byte. */
931 char modes[sizeof "-rwxr-xr-x "];
932
933 char *uname = NULL, *gname = NULL;
934
935#ifdef WINDOWSNT
936 /* We usually don't request accurate owner and group info, because
937 it can be very expensive on Windows to get that, and most callers
938 of 'lstat' don't need that. But here we do want that information
939 to be accurate. */
940 w32_stat_get_owner_group = 1;
941#endif
942
943 lstat_result = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW);
944
945#ifdef WINDOWSNT
946 w32_stat_get_owner_group = 0;
947#endif
930 948
931 if (lstat (SSDATA (encoded), &s) < 0) 949 if (lstat_result < 0)
932 return Qnil; 950 return Qnil;
933 951
934 values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename) 952 values[0] = (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name)
935 : S_ISDIR (s.st_mode) ? Qt : Qnil); 953 : S_ISDIR (s.st_mode) ? Qt : Qnil);
936 values[1] = make_number (s.st_nlink); 954 values[1] = make_number (s.st_nlink);
937 955
@@ -965,17 +983,7 @@ so last access time will always be midnight of that day. */)
965 983
966 filemodestring (&s, modes); 984 filemodestring (&s, modes);
967 values[8] = make_string (modes, 10); 985 values[8] = make_string (modes, 10);
968#ifdef BSD4_2 /* file gid will be dir gid */ 986 values[9] = Qt;
969 dirname = Ffile_name_directory (filename);
970 if (! NILP (dirname))
971 encoded = ENCODE_FILE (dirname);
972 if (! NILP (dirname) && stat (SDATA (encoded), &sdir) == 0)
973 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
974 else /* if we can't tell, assume worst */
975 values[9] = Qt;
976#else /* file gid will be egid */
977 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
978#endif /* not BSD4_2 */
979 values[10] = INTEGER_TO_CONS (s.st_ino); 987 values[10] = INTEGER_TO_CONS (s.st_ino);
980 values[11] = INTEGER_TO_CONS (s.st_dev); 988 values[11] = INTEGER_TO_CONS (s.st_dev);
981 989