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;