Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
266:18d185df8c54 | 267:966663fcf606 |
---|---|
61 if FILES-ONLY is nil (the default) then both files and subdirectories will | 61 if FILES-ONLY is nil (the default) then both files and subdirectories will |
62 be returned. | 62 be returned. |
63 */ | 63 */ |
64 (dirname, full, match, nosort, files_only)) | 64 (dirname, full, match, nosort, files_only)) |
65 { | 65 { |
66 /* This function can GC. GC checked 1997.04.06. */ | 66 /* This function can GC */ |
67 DIR *d; | 67 DIR *d; |
68 Bytecount name_as_dir_length; | 68 Lisp_Object list = Qnil; |
69 Lisp_Object list = Qnil, name, dirfilename = Qnil; | 69 Bytecount dirnamelen; |
70 Lisp_Object handler; | 70 Lisp_Object handler; |
71 struct re_pattern_buffer *bufp = NULL; | 71 struct re_pattern_buffer *bufp = NULL; |
72 Lisp_Object name_as_dir = Qnil; | |
73 int speccount = specpdl_depth (); | 72 int speccount = specpdl_depth (); |
74 char *statbuf, *statbuf_tail; | 73 char *statbuf, *statbuf_tail; |
75 | 74 |
76 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 75 struct gcpro gcpro1, gcpro2; |
77 GCPRO4 (dirname, name_as_dir, dirfilename, list); | 76 GCPRO2 (dirname, list); |
78 | 77 |
79 /* If the file name has special constructs in it, | 78 /* If the file name has special constructs in it, |
80 call the corresponding file handler. */ | 79 call the corresponding file handler. */ |
81 handler = Ffind_file_name_handler (dirname, Qdirectory_files); | 80 handler = Ffind_file_name_handler (dirname, Qdirectory_files); |
82 if (!NILP (handler)) | 81 if (!NILP (handler)) |
83 { | 82 { |
84 UNGCPRO; | 83 UNGCPRO; |
85 if (!NILP (files_only)) | 84 if (!NILP (files_only)) |
86 return call6 (handler, Qdirectory_files, dirname, full, match, nosort, | 85 return call6 (handler, Qdirectory_files, dirname, full, match, nosort, |
87 files_only); | 86 files_only); |
88 else | 87 else |
89 return call5 (handler, Qdirectory_files, dirname, full, match, | 88 return call5 (handler, Qdirectory_files, dirname, full, match, |
90 nosort); | 89 nosort); |
91 } | 90 } |
92 | 91 |
93 /* #### why do we do Fexpand_file_name after file handlers here, | 92 /* #### why do we do Fexpand_file_name after file handlers here, |
94 but earlier everywhere else? */ | 93 but earlier everywhere else? */ |
95 dirname = Fexpand_file_name (dirname, Qnil); | 94 dirname = Fexpand_file_name (dirname, Qnil); |
96 dirfilename = Fdirectory_file_name (dirname); | 95 dirname = Ffile_name_as_directory (dirname); |
97 name_as_dir = Ffile_name_as_directory (dirname); | 96 dirnamelen = XSTRING_LENGTH (dirname); |
98 | 97 |
99 name_as_dir_length = XSTRING_LENGTH (name_as_dir); | 98 statbuf = (char *)alloca (dirnamelen + MAXNAMLEN + 1); |
100 statbuf = (char *) alloca (name_as_dir_length + MAXNAMLEN + 1); | 99 memcpy (statbuf, XSTRING_DATA (dirname), dirnamelen); |
101 memcpy (statbuf, XSTRING_DATA (name_as_dir), name_as_dir_length); | 100 statbuf_tail = statbuf + dirnamelen; |
102 statbuf_tail = statbuf + name_as_dir_length; | |
103 | 101 |
104 /* XEmacs: this should come after Ffile_name_as_directory() to avoid | 102 /* XEmacs: this should come after Ffile_name_as_directory() to avoid |
105 potential regexp cache smashage. It comes before the opendir() | 103 potential regexp cache smashage. It comes before the opendir() |
106 because it might signal an error. */ | 104 because it might signal an error. */ |
107 if (!NILP (match)) | 105 if (!NILP (match)) |
115 } | 113 } |
116 | 114 |
117 /* Now *bufp is the compiled form of MATCH; don't call anything | 115 /* Now *bufp is the compiled form of MATCH; don't call anything |
118 which might compile a new regexp until we're done with the loop! */ | 116 which might compile a new regexp until we're done with the loop! */ |
119 | 117 |
120 /* Do this opendir after anything which might signal an error; | 118 /* Do this opendir after anything which might signal an error. |
121 previosly, there was no unwind-protection in case of error, but | 119 NOTE: the above comment is old; previosly, there was no |
122 now there is. */ | 120 unwind-protection in case of error, but now there is. */ |
123 d = opendir ((char *) XSTRING_DATA (dirfilename)); | 121 d = opendir ((char *) XSTRING_DATA (dirname)); |
124 if (! d) | 122 if (!d) |
125 report_file_error ("Opening directory", list1 (dirname)); | 123 report_file_error ("Opening directory", list1 (dirname)); |
126 | 124 |
127 record_unwind_protect (close_directory_unwind, make_opaque_ptr ((void *)d)); | 125 record_unwind_protect (close_directory_unwind, make_opaque_ptr ((void *)d)); |
128 | |
129 list = Qnil; | |
130 | 126 |
131 /* Loop reading blocks */ | 127 /* Loop reading blocks */ |
132 while (1) | 128 while (1) |
133 { | 129 { |
134 DIRENTRY *dp = readdir (d); | 130 DIRENTRY *dp = readdir (d); |
131 Lisp_Object name; | |
135 int len; | 132 int len; |
136 | 133 |
137 if (!dp) break; | 134 if (!dp) |
135 break; | |
138 len = NAMLEN (dp); | 136 len = NAMLEN (dp); |
139 if (DIRENTRY_NONEMPTY (dp)) | 137 if (DIRENTRY_NONEMPTY (dp) |
138 && (NILP (match) | |
139 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))) | |
140 { | 140 { |
141 int result; | 141 if (!NILP (files_only)) |
142 result = (NILP (match) | |
143 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0))); | |
144 if (result) | |
145 { | 142 { |
146 if (!NILP (files_only)) | 143 int dir_p; |
144 struct stat st; | |
145 char *cur_statbuf = statbuf; | |
146 char *cur_statbuf_tail = statbuf_tail; | |
147 | |
148 /* #### I don't think the code under `if' is necessary | |
149 anymore. The crashes in this function were reported | |
150 because MAXNAMLEN was used to remember the *whole* | |
151 statbuf, instead of using MAXPATHLEN. This should be | |
152 tested after 20.5 is released. */ | |
153 | |
154 /* We normally use the buffer created by alloca. | |
155 However, if the file name we get too big, we'll use a | |
156 malloced buffer, and free it. It is undefined how | |
157 stat() will react to this, but we avoid a buffer | |
158 overrun. */ | |
159 if (len > MAXNAMLEN) | |
147 { | 160 { |
148 int dir_p; | 161 cur_statbuf = (char *)xmalloc (dirnamelen + len + 1); |
149 struct stat st; | 162 memcpy (cur_statbuf, statbuf, dirnamelen); |
150 char *cur_statbuf = statbuf; | 163 cur_statbuf_tail = cur_statbuf + dirnamelen; |
151 char *cur_statbuf_tail = statbuf_tail; | |
152 | |
153 /* A trick: we normally use the buffer created by | |
154 alloca. However, if the filename is too big | |
155 (meaning MAXNAMLEN is wrong or useless on the | |
156 system), we'll use a malloced buffer, and free | |
157 it. */ | |
158 if (len > MAXNAMLEN) | |
159 { | |
160 cur_statbuf = (char *) xmalloc (name_as_dir_length | |
161 + len + 1); | |
162 memcpy (cur_statbuf, statbuf, name_as_dir_length); | |
163 cur_statbuf_tail = cur_statbuf + name_as_dir_length; | |
164 } | |
165 memcpy (cur_statbuf_tail, dp->d_name, len); | |
166 cur_statbuf_tail [len] = 0; | |
167 | |
168 if (stat (cur_statbuf, &st) < 0) | |
169 dir_p = 0; | |
170 else | |
171 dir_p = ((st.st_mode & S_IFMT) == S_IFDIR); | |
172 | |
173 if (cur_statbuf != statbuf) | |
174 xfree (cur_statbuf); | |
175 | |
176 if (EQ (files_only, Qt) && dir_p) | |
177 continue; | |
178 else if (!EQ (files_only, Qt) && !dir_p) | |
179 continue; | |
180 } | 164 } |
181 | 165 memcpy (cur_statbuf_tail, dp->d_name, len); |
182 if (!NILP (full)) | 166 cur_statbuf_tail[len] = 0; |
183 name = concat2 (name_as_dir, | 167 |
184 make_ext_string ((Bufbyte *)dp->d_name, | 168 if (stat (cur_statbuf, &st) < 0) |
185 len, FORMAT_FILENAME)); | 169 dir_p = 0; |
186 else | 170 else |
187 name = make_ext_string ((Bufbyte *)dp->d_name, | 171 dir_p = ((st.st_mode & S_IFMT) == S_IFDIR); |
188 len, FORMAT_FILENAME); | 172 |
189 | 173 if (cur_statbuf != statbuf) |
190 list = Fcons (name, list); | 174 xfree (cur_statbuf); |
175 | |
176 if (EQ (files_only, Qt) && dir_p) | |
177 continue; | |
178 else if (!EQ (files_only, Qt) && !dir_p) | |
179 continue; | |
191 } | 180 } |
181 | |
182 if (!NILP (full)) | |
183 name = concat2 (dirname, make_ext_string ((Bufbyte *)dp->d_name, | |
184 len, FORMAT_FILENAME)); | |
185 else | |
186 name = make_ext_string ((Bufbyte *)dp->d_name, | |
187 len, FORMAT_FILENAME); | |
188 | |
189 list = Fcons (name, list); | |
192 } | 190 } |
193 } | 191 } |
194 unbind_to (speccount, Qnil); /* This will close the dir */ | 192 unbind_to (speccount, Qnil); /* This will close the dir */ |
193 | |
195 if (!NILP (nosort)) | 194 if (!NILP (nosort)) |
196 RETURN_UNGCPRO (list); | 195 RETURN_UNGCPRO (list); |
197 else | 196 else |
198 RETURN_UNGCPRO (Fsort (Fnreverse (list), Qstring_lessp)); | 197 RETURN_UNGCPRO (Fsort (Fnreverse (list), Qstring_lessp)); |
199 } | 198 } |
290 #endif | 289 #endif |
291 return value; | 290 return value; |
292 } | 291 } |
293 | 292 |
294 static Lisp_Object | 293 static Lisp_Object |
295 file_name_completion_unwind (Lisp_Object unwind_obj) | 294 file_name_completion_unwind (Lisp_Object locative) |
296 { | 295 { |
297 DIR *d; | 296 DIR *d; |
298 Lisp_Object obj = XCAR (unwind_obj); | 297 Lisp_Object obj = XCAR (locative); |
299 | 298 |
300 if (NILP (obj)) | 299 if (NILP (obj)) |
301 return Qnil; | 300 return Qnil; |
302 d = (DIR *)get_opaque_ptr (obj); | 301 d = (DIR *)get_opaque_ptr (obj); |
303 closedir (d); | 302 closedir (d); |
304 free_opaque_ptr (obj); | 303 free_opaque_ptr (obj); |
305 free_cons (XCONS (unwind_obj)); | 304 free_cons (XCONS (locative)); |
306 return Qnil; | 305 return Qnil; |
307 } | 306 } |
308 | 307 |
309 static Lisp_Object | 308 static Lisp_Object |
310 file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag, | 309 file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag, |
317 Charcount bestmatchsize = 0; | 316 Charcount bestmatchsize = 0; |
318 struct stat st; | 317 struct stat st; |
319 int passcount; | 318 int passcount; |
320 int speccount = specpdl_depth (); | 319 int speccount = specpdl_depth (); |
321 Charcount file_name_length; | 320 Charcount file_name_length; |
322 DIRENTRY *((*readfunc) (DIR *)) = readdir; | 321 Lisp_Object locative; |
323 Lisp_Object unwind_closure; | |
324 struct gcpro gcpro1, gcpro2, gcpro3; | 322 struct gcpro gcpro1, gcpro2, gcpro3; |
325 | 323 |
326 GCPRO3 (file, dirname, bestmatch); | 324 GCPRO3 (file, dirname, bestmatch); |
327 | 325 |
328 CHECK_STRING (file); | 326 CHECK_STRING (file); |
329 | 327 |
330 #ifdef WINDOWSNT | 328 #ifdef WINDOWSNT |
331 /* Filename completion on Windows ignores case, since Windows | 329 /* Filename completion on Windows ignores case, since Windows |
332 filesystems do. */ | 330 filesystems do. */ |
333 specbind (Qcompletion_ignore_case, Qt); | 331 specbind (Qcompletion_ignore_case, Qt); |
334 #endif /* HAVE_WINDOWS */ | 332 #endif /* WINDOWSNT */ |
335 | 333 |
336 #ifdef FILE_SYSTEM_CASE | 334 #ifdef FILE_SYSTEM_CASE |
337 file = FILE_SYSTEM_CASE (file); | 335 file = FILE_SYSTEM_CASE (file); |
338 #endif | 336 #endif |
339 dirname = Fexpand_file_name (dirname, Qnil); | 337 dirname = Fexpand_file_name (dirname, Qnil); |
350 /* We cannot use close_directory_unwind() because we change the | 348 /* We cannot use close_directory_unwind() because we change the |
351 directory. The old code used to just avoid signaling errors, and | 349 directory. The old code used to just avoid signaling errors, and |
352 call closedir, but it was wrong, because it made sane handling of | 350 call closedir, but it was wrong, because it made sane handling of |
353 QUIT impossible and, besides, various utility functions like | 351 QUIT impossible and, besides, various utility functions like |
354 regexp_ignore_completion_p can signal errors. */ | 352 regexp_ignore_completion_p can signal errors. */ |
355 unwind_closure = noseeum_cons (Qnil, Qnil); | 353 locative = noseeum_cons (Qnil, Qnil); |
356 record_unwind_protect (file_name_completion_unwind, unwind_closure); | 354 record_unwind_protect (file_name_completion_unwind, locative); |
357 | 355 |
358 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++) | 356 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++) |
359 { | 357 { |
360 d = opendir ((char *) XSTRING_DATA (Fdirectory_file_name (dirname))); | 358 d = opendir ((char *) XSTRING_DATA (Fdirectory_file_name (dirname))); |
361 if (!d) | 359 if (!d) |
362 report_file_error ("Opening directory", list1 (dirname)); | 360 report_file_error ("Opening directory", list1 (dirname)); |
363 XCAR (unwind_closure) = make_opaque_ptr ((void *)d); | 361 XCAR (locative) = make_opaque_ptr ((void *)d); |
364 | 362 |
365 /* Loop reading blocks */ | 363 /* Loop reading blocks */ |
366 while (1) | 364 while (1) |
367 { | 365 { |
368 DIRENTRY *dp; | 366 DIRENTRY *dp; |
372 Charcount cclen; | 370 Charcount cclen; |
373 int directoryp; | 371 int directoryp; |
374 int ignored_extension_p = 0; | 372 int ignored_extension_p = 0; |
375 Bufbyte *d_name; | 373 Bufbyte *d_name; |
376 | 374 |
377 dp = (*readfunc) (d); | 375 dp = readdir (d); |
378 if (!dp) break; | 376 if (!dp) break; |
379 | 377 |
380 /* #### This is a bad idea, because d_name can contain | 378 /* #### This is a bad idea, because d_name can contain |
381 control characters, which can make XEmacs crash. This | 379 control characters, which can make XEmacs crash. This |
382 should be handled properly with FORMAT_FILENAME. */ | 380 should be handled properly with FORMAT_FILENAME. */ |
514 matchsize++; | 512 matchsize++; |
515 bestmatchsize = matchsize; | 513 bestmatchsize = matchsize; |
516 } | 514 } |
517 } | 515 } |
518 closedir (d); | 516 closedir (d); |
519 free_opaque_ptr (XCAR (unwind_closure)); | 517 free_opaque_ptr (XCAR (locative)); |
520 XCAR (unwind_closure) = Qnil; | 518 XCAR (locative) = Qnil; |
521 } | 519 } |
522 | 520 |
523 unbind_to (speccount, Qnil); | 521 unbind_to (speccount, Qnil); |
524 | 522 |
525 UNGCPRO; | 523 UNGCPRO; |