aboutsummaryrefslogtreecommitdiffstats
path: root/src/dired.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dired.c')
-rw-r--r--src/dired.c205
1 files changed, 90 insertions, 115 deletions
diff --git a/src/dired.c b/src/dired.c
index 4986f845101..3530b74ecb4 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -31,44 +31,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31#include <errno.h> 31#include <errno.h>
32#include <unistd.h> 32#include <unistd.h>
33 33
34/* The d_nameln member of a struct dirent includes the '\0' character
35 on some systems, but not on others. What's worse, you can't tell
36 at compile-time which one it will be, since it really depends on
37 the sort of system providing the filesystem you're reading from,
38 not the system you are running on. Paul Eggert
39 <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
40 SunOS 4.1.2 host, reading a directory that is remote-mounted from a
41 Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
42
43 Since applying strlen to the name always works, we'll just do that. */
44#define NAMLEN(p) strlen (p->d_name)
45
46#ifdef HAVE_DIRENT_H
47
48#include <dirent.h> 34#include <dirent.h>
49#define DIRENTRY struct dirent
50
51#else /* not HAVE_DIRENT_H */
52
53#include <sys/dir.h>
54#include <sys/stat.h>
55
56#define DIRENTRY struct direct
57
58extern DIR *opendir (char *);
59extern struct direct *readdir (DIR *);
60
61#endif /* HAVE_DIRENT_H */
62
63#include <filemode.h> 35#include <filemode.h>
64#include <stat-time.h> 36#include <stat-time.h>
65 37
66#ifdef MSDOS
67#define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
68#else
69#define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
70#endif
71
72#include "lisp.h" 38#include "lisp.h"
73#include "systime.h" 39#include "systime.h"
74#include "character.h" 40#include "character.h"
@@ -88,6 +54,17 @@ static Lisp_Object Qfile_attributes_lessp;
88 54
89static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); 55static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
90 56
57/* Return the number of bytes in DP's name. */
58static ptrdiff_t
59dirent_namelen (struct dirent *dp)
60{
61#ifdef _D_EXACT_NAMLEN
62 return _D_EXACT_NAMLEN (dp);
63#else
64 return strlen (dp->d_name);
65#endif
66}
67
91#ifdef WINDOWSNT 68#ifdef WINDOWSNT
92Lisp_Object 69Lisp_Object
93directory_files_internal_w32_unwind (Lisp_Object arg) 70directory_files_internal_w32_unwind (Lisp_Object arg)
@@ -124,7 +101,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
124 bool needsep = 0; 101 bool needsep = 0;
125 ptrdiff_t count = SPECPDL_INDEX (); 102 ptrdiff_t count = SPECPDL_INDEX ();
126 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 103 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
127 DIRENTRY *dp; 104 struct dirent *dp;
128#ifdef WINDOWSNT 105#ifdef WINDOWSNT
129 Lisp_Object w32_save = Qnil; 106 Lisp_Object w32_save = Qnil;
130#endif 107#endif
@@ -209,6 +186,11 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
209 /* Loop reading blocks until EOF or error. */ 186 /* Loop reading blocks until EOF or error. */
210 for (;;) 187 for (;;)
211 { 188 {
189 ptrdiff_t len;
190 bool wanted = 0;
191 Lisp_Object name, finalname;
192 struct gcpro gcpro1, gcpro2;
193
212 errno = 0; 194 errno = 0;
213 dp = readdir (d); 195 dp = readdir (d);
214 196
@@ -225,89 +207,81 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
225 if (dp == NULL) 207 if (dp == NULL)
226 break; 208 break;
227 209
228 if (DIRENTRY_NONEMPTY (dp)) 210 len = dirent_namelen (dp);
211 name = finalname = make_unibyte_string (dp->d_name, len);
212 GCPRO2 (finalname, name);
213
214 /* Note: DECODE_FILE can GC; it should protect its argument,
215 though. */
216 name = DECODE_FILE (name);
217 len = SBYTES (name);
218
219 /* Now that we have unwind_protect in place, we might as well
220 allow matching to be interrupted. */
221 immediate_quit = 1;
222 QUIT;
223
224 if (NILP (match)
225 || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0)))
226 wanted = 1;
227
228 immediate_quit = 0;
229
230 if (wanted)
229 { 231 {
230 ptrdiff_t len; 232 if (!NILP (full))
231 bool wanted = 0; 233 {
232 Lisp_Object name, finalname; 234 Lisp_Object fullname;
233 struct gcpro gcpro1, gcpro2; 235 ptrdiff_t nbytes = len + directory_nbytes + needsep;
236 ptrdiff_t nchars;
234 237
235 len = NAMLEN (dp); 238 fullname = make_uninit_multibyte_string (nbytes, nbytes);
236 name = finalname = make_unibyte_string (dp->d_name, len); 239 memcpy (SDATA (fullname), SDATA (directory),
237 GCPRO2 (finalname, name); 240 directory_nbytes);
238 241
239 /* Note: DECODE_FILE can GC; it should protect its argument, 242 if (needsep)
240 though. */ 243 SSET (fullname, directory_nbytes, DIRECTORY_SEP);
241 name = DECODE_FILE (name);
242 len = SBYTES (name);
243 244
244 /* Now that we have unwind_protect in place, we might as well 245 memcpy (SDATA (fullname) + directory_nbytes + needsep,
245 allow matching to be interrupted. */ 246 SDATA (name), len);
246 immediate_quit = 1;
247 QUIT;
248 247
249 if (NILP (match) 248 nchars = chars_in_text (SDATA (fullname), nbytes);
250 || (0 <= re_search (bufp, SSDATA (name), len, 0, len, 0)))
251 wanted = 1;
252 249
253 immediate_quit = 0; 250 /* Some bug somewhere. */
251 if (nchars > nbytes)
252 emacs_abort ();
254 253
255 if (wanted) 254 STRING_SET_CHARS (fullname, nchars);
256 { 255 if (nchars == nbytes)
257 if (!NILP (full)) 256 STRING_SET_UNIBYTE (fullname);
258 { 257
259 Lisp_Object fullname; 258 finalname = fullname;
260 ptrdiff_t nbytes = len + directory_nbytes + needsep;
261 ptrdiff_t nchars;
262
263 fullname = make_uninit_multibyte_string (nbytes, nbytes);
264 memcpy (SDATA (fullname), SDATA (directory),
265 directory_nbytes);
266
267 if (needsep)
268 SSET (fullname, directory_nbytes, DIRECTORY_SEP);
269
270 memcpy (SDATA (fullname) + directory_nbytes + needsep,
271 SDATA (name), len);
272
273 nchars = chars_in_text (SDATA (fullname), nbytes);
274
275 /* Some bug somewhere. */
276 if (nchars > nbytes)
277 emacs_abort ();
278
279 STRING_SET_CHARS (fullname, nchars);
280 if (nchars == nbytes)
281 STRING_SET_UNIBYTE (fullname);
282
283 finalname = fullname;
284 }
285 else
286 finalname = name;
287
288 if (attrs)
289 {
290 /* Construct an expanded filename for the directory entry.
291 Use the decoded names for input to Ffile_attributes. */
292 Lisp_Object decoded_fullname, fileattrs;
293 struct gcpro gcpro1, gcpro2;
294
295 decoded_fullname = fileattrs = Qnil;
296 GCPRO2 (decoded_fullname, fileattrs);
297
298 /* Both Fexpand_file_name and Ffile_attributes can GC. */
299 decoded_fullname = Fexpand_file_name (name, directory);
300 fileattrs = Ffile_attributes (decoded_fullname, id_format);
301
302 list = Fcons (Fcons (finalname, fileattrs), list);
303 UNGCPRO;
304 }
305 else
306 list = Fcons (finalname, list);
307 } 259 }
260 else
261 finalname = name;
308 262
309 UNGCPRO; 263 if (attrs)
264 {
265 /* Construct an expanded filename for the directory entry.
266 Use the decoded names for input to Ffile_attributes. */
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);
278 UNGCPRO;
279 }
280 else
281 list = Fcons (finalname, list);
310 } 282 }
283
284 UNGCPRO;
311 } 285 }
312 286
313 block_input (); 287 block_input ();
@@ -442,7 +416,8 @@ These are all file names in directory DIRECTORY which begin with FILE. */)
442 return file_name_completion (file, directory, 1, Qnil); 416 return file_name_completion (file, directory, 1, Qnil);
443} 417}
444 418
445static int file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr); 419static int file_name_completion_stat (Lisp_Object dirname, struct dirent *dp,
420 struct stat *st_addr);
446static Lisp_Object Qdefault_directory; 421static Lisp_Object Qdefault_directory;
447 422
448static Lisp_Object 423static Lisp_Object
@@ -499,7 +474,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
499 /* (att3b compiler bug requires do a null comparison this way) */ 474 /* (att3b compiler bug requires do a null comparison this way) */
500 while (1) 475 while (1)
501 { 476 {
502 DIRENTRY *dp; 477 struct dirent *dp;
503 ptrdiff_t len; 478 ptrdiff_t len;
504 bool canexclude = 0; 479 bool canexclude = 0;
505 480
@@ -517,11 +492,10 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
517 492
518 if (!dp) break; 493 if (!dp) break;
519 494
520 len = NAMLEN (dp); 495 len = dirent_namelen (dp);
521 496
522 QUIT; 497 QUIT;
523 if (! DIRENTRY_NONEMPTY (dp) 498 if (len < SCHARS (encoded_file)
524 || len < SCHARS (encoded_file)
525 || 0 <= scmp (dp->d_name, SSDATA (encoded_file), 499 || 0 <= scmp (dp->d_name, SSDATA (encoded_file),
526 SCHARS (encoded_file))) 500 SCHARS (encoded_file)))
527 continue; 501 continue;
@@ -806,9 +780,10 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
806} 780}
807 781
808static int 782static int
809file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr) 783file_name_completion_stat (Lisp_Object dirname, struct dirent *dp,
784 struct stat *st_addr)
810{ 785{
811 ptrdiff_t len = NAMLEN (dp); 786 ptrdiff_t len = dirent_namelen (dp);
812 ptrdiff_t pos = SCHARS (dirname); 787 ptrdiff_t pos = SCHARS (dirname);
813 int value; 788 int value;
814 USE_SAFE_ALLOCA; 789 USE_SAFE_ALLOCA;