comparison src/dired.c @ 195:a2f645c6b9f8 r20-3b24

Import from CVS: tag r20-3b24
author cvs
date Mon, 13 Aug 2007 09:59:05 +0200
parents 3d6bfa290dbd
children 41ff10fd062f
comparison
equal deleted inserted replaced
194:2947057885e5 195:a2f645c6b9f8
25 25
26 #include "buffer.h" 26 #include "buffer.h"
27 #include "commands.h" 27 #include "commands.h"
28 #include "elhash.h" 28 #include "elhash.h"
29 #include "regex.h" 29 #include "regex.h"
30 #include "opaque.h"
30 31
31 #include "sysfile.h" 32 #include "sysfile.h"
32 #include "sysdir.h" 33 #include "sysdir.h"
33 34
34 Lisp_Object Vcompletion_ignored_extensions; 35 Lisp_Object Vcompletion_ignored_extensions;
36 Lisp_Object Qdirectory_files; 37 Lisp_Object Qdirectory_files;
37 Lisp_Object Qfile_name_completion; 38 Lisp_Object Qfile_name_completion;
38 Lisp_Object Qfile_name_all_completions; 39 Lisp_Object Qfile_name_all_completions;
39 Lisp_Object Qfile_attributes; 40 Lisp_Object Qfile_attributes;
40 41
42 static Lisp_Object
43 close_directory_fd (Lisp_Object unwind_obj)
44 {
45 DIR *d = (DIR *)get_opaque_ptr (unwind_obj);
46 closedir (d);
47 free_opaque_ptr (unwind_obj);
48 return Qnil;
49 }
50
41 DEFUN ("directory-files", Fdirectory_files, 1, 5, 0, /* 51 DEFUN ("directory-files", Fdirectory_files, 1, 5, 0, /*
42 Return a list of names of files in DIRECTORY. 52 Return a list of names of files in DIRECTORY.
43 There are four optional arguments: 53 There are four optional arguments:
44 If FULL is non-nil, absolute pathnames of the files are returned. 54 If FULL is non-nil, absolute pathnames of the files are returned.
45 If MATCH is non-nil, only pathnames containing that regexp are returned. 55 If MATCH is non-nil, only pathnames containing that regexp are returned.
53 */ 63 */
54 (dirname, full, match, nosort, files_only)) 64 (dirname, full, match, nosort, files_only))
55 { 65 {
56 /* This function can GC. GC checked 1997.04.06. */ 66 /* This function can GC. GC checked 1997.04.06. */
57 DIR *d; 67 DIR *d;
58 Bytecount dirname_length; 68 Bytecount name_as_dir_length;
59 Lisp_Object list, name, dirfilename = Qnil; 69 Lisp_Object list, name, dirfilename = Qnil;
60 Lisp_Object handler; 70 Lisp_Object handler;
61 struct re_pattern_buffer *bufp = NULL; 71 struct re_pattern_buffer *bufp = NULL;
62 72 Lisp_Object name_as_dir = Qnil;
63 char statbuf [MAXNAMLEN+2]; 73 int speccount = specpdl_depth ();
64 char *statbuf_tail; 74 char *statbuf, *statbuf_tail;
65 Lisp_Object tail_cons = Qnil; 75
66 char slashfilename[MAXNAMLEN+2]; 76 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
67 char *filename = slashfilename; 77 GCPRO4 (dirname, name_as_dir, dirfilename, list);
68
69 struct gcpro gcpro1, gcpro2, gcpro3;
70 GCPRO3 (dirname, dirfilename, tail_cons);
71 78
72 /* If the file name has special constructs in it, 79 /* If the file name has special constructs in it,
73 call the corresponding file handler. */ 80 call the corresponding file handler. */
74 handler = Ffind_file_name_handler (dirname, Qdirectory_files); 81 handler = Ffind_file_name_handler (dirname, Qdirectory_files);
75 if (!NILP (handler)) 82 if (!NILP (handler))
85 92
86 /* #### why do we do Fexpand_file_name after file handlers here, 93 /* #### why do we do Fexpand_file_name after file handlers here,
87 but earlier everywhere else? */ 94 but earlier everywhere else? */
88 dirname = Fexpand_file_name (dirname, Qnil); 95 dirname = Fexpand_file_name (dirname, Qnil);
89 dirfilename = Fdirectory_file_name (dirname); 96 dirfilename = Fdirectory_file_name (dirname);
90 97 name_as_dir = Ffile_name_as_directory (dirname);
91 { 98
92 /* XEmacs: this should come before the opendir() because it might error. */ 99 name_as_dir_length = XSTRING_LENGTH (name_as_dir);
93 Lisp_Object name_as_dir = Ffile_name_as_directory (dirname); 100 statbuf = alloca (name_as_dir_length + MAXNAMLEN + 1);
94 CHECK_STRING (name_as_dir); 101 memcpy (statbuf, XSTRING_DATA (name_as_dir), name_as_dir_length);
95 memcpy (statbuf, ((char *) XSTRING_DATA (name_as_dir)), 102 statbuf_tail = statbuf + name_as_dir_length;
96 XSTRING_LENGTH (name_as_dir));
97 statbuf_tail = statbuf + XSTRING_LENGTH (name_as_dir);
98 }
99 103
100 /* XEmacs: this should come after Ffile_name_as_directory() to avoid 104 /* XEmacs: this should come after Ffile_name_as_directory() to avoid
101 potential regexp cache smashage. This should come before the 105 potential regexp cache smashage. It comes before the opendir()
102 opendir() because it might signal an error. 106 because it might signal an error. */
103 */
104 if (!NILP (match)) 107 if (!NILP (match))
105 { 108 {
106 CHECK_STRING (match); 109 CHECK_STRING (match);
107 110
108 /* MATCH might be a flawed regular expression. Rather than 111 /* MATCH might be a flawed regular expression. Rather than
109 catching and signalling our own errors, we just call 112 catching and signalling our own errors, we just call
110 compile_pattern to do the work for us. */ 113 compile_pattern to do the work for us. */
111 #ifdef VMS
112 bufp =
113 compile_pattern (match, 0,
114 (char *) MIRROR_DOWNCASE_TABLE_AS_STRING
115 (XBUFFER (Vbuffer_defaults)), 0, ERROR_ME);
116 #else
117 bufp = compile_pattern (match, 0, 0, 0, ERROR_ME); 114 bufp = compile_pattern (match, 0, 0, 0, ERROR_ME);
118 #endif
119 } 115 }
120 116
121 /* Now *bufp is the compiled form of MATCH; don't call anything 117 /* Now *bufp is the compiled form of MATCH; don't call anything
122 which might compile a new regexp until we're done with the loop! */ 118 which might compile a new regexp until we're done with the loop! */
123 119
124 /* Do this opendir after anything which might signal an error; if 120 /* Do this opendir after anything which might signal an error;
125 an error is signalled while the directory stream is open, we 121 previosly, there was no unwind-protection in case of error, but
126 have to make sure it gets closed, and setting up an 122 now there is. */
127 unwind_protect to do so would be a pain. */
128 d = opendir ((char *) XSTRING_DATA (dirfilename)); 123 d = opendir ((char *) XSTRING_DATA (dirfilename));
129 if (! d) 124 if (! d)
130 report_file_error ("Opening directory", list1 (dirname)); 125 report_file_error ("Opening directory", list1 (dirname));
131 126
127 record_unwind_protect (close_directory_fd, make_opaque_ptr ((void *)d));
128
132 list = Qnil; 129 list = Qnil;
133 tail_cons = Qnil;
134 dirname_length = XSTRING_LENGTH (dirname);
135 #ifndef VMS
136 if (dirname_length == 0
137 || !IS_ANY_SEP (XSTRING_BYTE (dirname, dirname_length - 1)))
138 {
139 *filename++ = DIRECTORY_SEP;
140 dirname_length++;
141 }
142 #endif /* VMS */
143 130
144 /* Loop reading blocks */ 131 /* Loop reading blocks */
145 while (1) 132 while (1)
146 { 133 {
147 DIRENTRY *dp = readdir (d); 134 DIRENTRY *dp = readdir (d);
150 if (!dp) break; 137 if (!dp) break;
151 len = NAMLEN (dp); 138 len = NAMLEN (dp);
152 if (DIRENTRY_NONEMPTY (dp)) 139 if (DIRENTRY_NONEMPTY (dp))
153 { 140 {
154 int result; 141 int result;
155 Lisp_Object oinhibit_quit = Vinhibit_quit;
156 strncpy (filename, dp->d_name, len);
157 filename[len] = 0;
158 /* re_search can now QUIT, so prevent it to avoid
159 filedesc lossage */
160 Vinhibit_quit = Qt;
161 result = (NILP (match) 142 result = (NILP (match)
162 || (0 <= re_search (bufp, filename, len, 0, len, 0))); 143 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)));
163 Vinhibit_quit = oinhibit_quit;
164 if (result) 144 if (result)
165 { 145 {
166 if (!NILP (files_only)) 146 if (!NILP (files_only))
167 { 147 {
168 int dir_p; 148 int dir_p;
169 struct stat st; 149 struct stat st;
170 150 char *cur_statbuf = statbuf;
171 memcpy (statbuf_tail, filename, len); 151 char *cur_statbuf_tail = statbuf_tail;
172 statbuf_tail [len] = 0; 152
173 153 /* A trick: we normally use the buffer created by
174 if (stat (statbuf, &st) < 0) 154 alloca. However, if the filename is too big
155 (meaning MAXNAMLEN lies on the system), we'll use
156 a malloced buffer, and free it. */
157 if (len > MAXNAMLEN)
158 {
159 cur_statbuf = (char *) xmalloc (name_as_dir_length
160 + len + 1);
161 memcpy (cur_statbuf, statbuf, name_as_dir_length);
162 cur_statbuf_tail = cur_statbuf + name_as_dir_length;
163 }
164 memcpy (cur_statbuf_tail, dp->d_name, len);
165 cur_statbuf_tail [len] = 0;
166
167 if (stat (cur_statbuf, &st) < 0)
175 dir_p = 0; 168 dir_p = 0;
176 else 169 else
177 dir_p = ((st.st_mode & S_IFMT) == S_IFDIR); 170 dir_p = ((st.st_mode & S_IFMT) == S_IFDIR);
171
172 if (cur_statbuf != statbuf)
173 xfree (cur_statbuf);
178 174
179 if (EQ (files_only, Qt) && dir_p) 175 if (EQ (files_only, Qt) && dir_p)
180 continue; 176 continue;
181 else if (!EQ (files_only, Qt) && !dir_p) 177 else if (!EQ (files_only, Qt) && !dir_p)
182 continue; 178 continue;
183 } 179 }
184 180
185 if (!NILP (full)) 181 if (!NILP (full))
186 name = concat2 (dirname, build_string (slashfilename)); 182 name = concat2 (name_as_dir,
183 make_string ((Bufbyte *)dp->d_name, len));
187 else 184 else
188 name = make_string ((Bufbyte *) filename, len); 185 name = make_string ((Bufbyte *)dp->d_name, len);
189 186
190 if (NILP (tail_cons)) 187 list = Fcons (name, list);
191 {
192 list = list1 (name);
193 tail_cons = list;
194 }
195 else
196 {
197 XCDR (tail_cons) = list1 (name);
198 tail_cons = XCDR (tail_cons);
199 }
200 } 188 }
201 } 189 }
202 } 190 }
203 closedir (d); 191 unbind_to (speccount, Qnil); /* This will close the dir */
204 UNGCPRO;
205 if (!NILP (nosort)) 192 if (!NILP (nosort))
206 return list; 193 RETURN_UNGCPRO (list);
207 return Fsort (Fnreverse (list), Qstring_lessp); 194 else
195 RETURN_UNGCPRO (Fsort (Fnreverse (list), Qstring_lessp));
208 } 196 }
209 197
210 static Lisp_Object file_name_completion (Lisp_Object file, 198 static Lisp_Object file_name_completion (Lisp_Object file,
211 Lisp_Object dirname, 199 Lisp_Object dirname,
212 int all_flag, int ver_flag); 200 int all_flag, int ver_flag);