1 /* Lisp functions for making directory listings.
2 Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include <sys/types.h>
33 /* The d_nameln member of a struct dirent includes the '\0' character
34 on some systems, but not on others. What's worse, you can't tell
35 at compile-time which one it will be, since it really depends on
36 the sort of system providing the filesystem you're reading from,
37 not the system you are running on. Paul Eggert
38 <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
39 SunOS 4.1.2 host, reading a directory that is remote-mounted from a
40 Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
42 Since applying strlen to the name always works, we'll just do that. */
43 #define NAMLEN(p) strlen (p->d_name)
45 #ifdef SYSV_SYSTEM_DIR
48 #define DIRENTRY struct dirent
52 #ifdef NONSYSTEM_DIR_LIBRARY
54 #else /* not NONSYSTEM_DIR_LIBRARY */
56 #endif /* not NONSYSTEM_DIR_LIBRARY */
58 #define DIRENTRY struct direct
60 extern DIR *opendir ();
61 extern struct direct
*readdir ();
71 /* A search buffer, with a fastmap allocated and ready to go. */
72 extern struct re_pattern_buffer searchbuf
;
74 #define min(a, b) ((a) < (b) ? (a) : (b))
76 /* if system does not have symbolic links, it does not have lstat.
77 In that case, use ordinary stat instead. */
83 extern Lisp_Object
Ffind_file_name_handler ();
85 Lisp_Object Vcompletion_ignored_extensions
;
87 Lisp_Object Qcompletion_ignore_case
;
89 Lisp_Object Qdirectory_files
;
90 Lisp_Object Qfile_name_completion
;
91 Lisp_Object Qfile_name_all_completions
;
92 Lisp_Object Qfile_attributes
;
94 DEFUN ("directory-files", Fdirectory_files
, Sdirectory_files
, 1, 4, 0,
95 "Return a list of names of files in DIRECTORY.\n\
96 There are three optional arguments:\n\
97 If FULL is non-nil, absolute pathnames of the files are returned.\n\
98 If MATCH is non-nil, only pathnames containing that regexp are returned.\n\
99 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
100 NOSORT is useful if you plan to sort the result yourself.")
101 (dirname
, full
, match
, nosort
)
102 Lisp_Object dirname
, full
, match
, nosort
;
106 Lisp_Object list
, name
, dirfilename
;
109 /* If the file name has special constructs in it,
110 call the corresponding file handler. */
111 handler
= Ffind_file_name_handler (dirname
);
117 args
[1] = Qdirectory_files
;
122 return Ffuncall (6, args
);
126 struct gcpro gcpro1
, gcpro2
;
128 /* Because of file name handlers, these functions might call
129 Ffuncall, and cause a GC. */
131 dirname
= Fexpand_file_name (dirname
, Qnil
);
133 GCPRO2 (match
, dirname
);
134 dirfilename
= Fdirectory_file_name (dirname
);
140 CHECK_STRING (match
, 3);
142 /* MATCH might be a flawed regular expression. Rather than
143 catching and signalling our own errors, we just call
144 compile_pattern to do the work for us. */
146 compile_pattern (match
, &searchbuf
, 0,
147 buffer_defaults
.downcase_table
->contents
);
149 compile_pattern (match
, &searchbuf
, 0, 0);
153 /* Now searchbuf is the compiled form of MATCH; don't call anything
154 which might compile a new regexp until we're done with the loop! */
156 /* Do this opendir after anything which might signal an error; if
157 an error is signalled while the directory stream is open, we
158 have to make sure it gets closed, and setting up an
159 unwind_protect to do so would be a pain. */
160 d
= opendir (XSTRING (dirfilename
)->data
);
162 report_file_error ("Opening directory", Fcons (dirname
, Qnil
));
165 length
= XSTRING (dirname
)->size
;
167 /* Loop reading blocks */
170 DIRENTRY
*dp
= readdir (d
);
178 || (0 <= re_search (&searchbuf
, dp
->d_name
, len
, 0, len
, 0)))
182 int index
= XSTRING (dirname
)->size
;
183 int total
= len
+ index
;
186 || XSTRING (dirname
)->data
[length
- 1] != '/')
190 name
= make_uninit_string (total
);
191 bcopy (XSTRING (dirname
)->data
, XSTRING (name
)->data
,
195 || XSTRING (dirname
)->data
[length
- 1] != '/')
196 XSTRING (name
)->data
[index
++] = '/';
198 bcopy (dp
->d_name
, XSTRING (name
)->data
+ index
, len
);
201 name
= make_string (dp
->d_name
, len
);
202 list
= Fcons (name
, list
);
209 return Fsort (Fnreverse (list
), Qstring_lessp
);
212 Lisp_Object
file_name_completion ();
214 DEFUN ("file-name-completion", Ffile_name_completion
, Sfile_name_completion
,
216 "Complete file name FILE in directory DIR.\n\
217 Returns the longest string\n\
218 common to all filenames in DIR that start with FILE.\n\
219 If there is only one and FILE matches it exactly, returns t.\n\
220 Returns nil if DIR contains no name starting with FILE.")
222 Lisp_Object file
, dirname
;
225 /* Don't waste time trying to complete a null string.
226 Besides, this case happens when user is being asked for
227 a directory name and has supplied one ending in a /.
228 We would not want to add anything in that case
229 even if there are some unique characters in that directory. */
230 if (XTYPE (file
) == Lisp_String
&& XSTRING (file
)->size
== 0)
233 /* If the file name has special constructs in it,
234 call the corresponding file handler. */
235 handler
= Ffind_file_name_handler (dirname
);
237 return call3 (handler
, Qfile_name_completion
, file
, dirname
);
239 return file_name_completion (file
, dirname
, 0, 0);
242 DEFUN ("file-name-all-completions", Ffile_name_all_completions
,
243 Sfile_name_all_completions
, 2, 2, 0,
244 "Return a list of all completions of file name FILE in directory DIR.\n\
245 These are all file names in directory DIR which begin with FILE.")
247 Lisp_Object file
, dirname
;
251 /* If the file name has special constructs in it,
252 call the corresponding file handler. */
253 handler
= Ffind_file_name_handler (dirname
);
255 return call3 (handler
, Qfile_name_all_completions
, file
, dirname
);
257 return file_name_completion (file
, dirname
, 1, 0);
261 file_name_completion (file
, dirname
, all_flag
, ver_flag
)
262 Lisp_Object file
, dirname
;
263 int all_flag
, ver_flag
;
267 int bestmatchsize
, skip
;
268 register int compare
, matchsize
;
269 unsigned char *p1
, *p2
;
271 Lisp_Object bestmatch
, tem
, elt
, name
;
275 int count
= specpdl_ptr
- specpdl
;
277 extern DIRENTRY
* readdirver ();
279 DIRENTRY
*((* readfunc
) ());
281 /* Filename completion on VMS ignores case, since VMS filesys does. */
282 specbind (Qcompletion_ignore_case
, Qt
);
286 readfunc
= readdirver
;
287 file
= Fupcase (file
);
289 CHECK_STRING (file
, 0);
292 dirname
= Fexpand_file_name (dirname
, Qnil
);
295 /* With passcount = 0, ignore files that end in an ignored extension.
296 If nothing found then try again with passcount = 1, don't ignore them.
297 If looking for all completions, start with passcount = 1,
298 so always take even the ignored ones.
300 ** It would not actually be helpful to the user to ignore any possible
301 completions when making a list of them.** */
303 for (passcount
= !!all_flag
; NILP (bestmatch
) && passcount
< 2; passcount
++)
305 if (!(d
= opendir (XSTRING (Fdirectory_file_name (dirname
))->data
)))
306 report_file_error ("Opening directory", Fcons (dirname
, Qnil
));
308 /* Loop reading blocks */
309 /* (att3b compiler bug requires do a null comparison this way) */
316 dp
= (*readfunc
) (d
);
324 if (!NILP (Vquit_flag
) && NILP (Vinhibit_quit
))
327 || len
< XSTRING (file
)->size
328 || 0 <= scmp (dp
->d_name
, XSTRING (file
)->data
,
329 XSTRING (file
)->size
))
332 if (file_name_completion_stat (dirname
, dp
, &st
) < 0)
335 directoryp
= ((st
.st_mode
& S_IFMT
) == S_IFDIR
);
339 /* Compare extensions-to-be-ignored against end of this file name */
340 /* if name is not an exact match against specified string */
341 if (!passcount
&& len
> XSTRING (file
)->size
)
342 /* and exit this for loop if a match is found */
343 for (tem
= Vcompletion_ignored_extensions
;
344 CONSP (tem
); tem
= XCONS (tem
)->cdr
)
346 elt
= XCONS (tem
)->car
;
347 if (XTYPE (elt
) != Lisp_String
) continue;
348 skip
= len
- XSTRING (elt
)->size
;
349 if (skip
< 0) continue;
351 if (0 <= scmp (dp
->d_name
+ skip
,
353 XSTRING (elt
)->size
))
359 /* Unless an ignored-extensions match was found,
360 process this name as a completion */
361 if (passcount
|| !CONSP (tem
))
363 /* Update computation of how much all possible completions match */
367 if (all_flag
|| NILP (bestmatch
))
369 /* This is a possible completion */
372 /* This completion is a directory; make it end with '/' */
373 name
= Ffile_name_as_directory (make_string (dp
->d_name
, len
));
376 name
= make_string (dp
->d_name
, len
);
379 bestmatch
= Fcons (name
, bestmatch
);
384 bestmatchsize
= XSTRING (name
)->size
;
389 compare
= min (bestmatchsize
, len
);
390 p1
= XSTRING (bestmatch
)->data
;
391 p2
= (unsigned char *) dp
->d_name
;
392 matchsize
= scmp(p1
, p2
, compare
);
395 /* If this dirname all matches,
396 see if implicit following slash does too. */
398 && compare
== matchsize
399 && bestmatchsize
> matchsize
400 && p1
[matchsize
] == '/')
402 bestmatchsize
= min (matchsize
, bestmatchsize
);
409 unbind_to (count
, Qnil
);
411 if (all_flag
|| NILP (bestmatch
))
413 if (matchcount
== 1 && bestmatchsize
== XSTRING (file
)->size
)
415 return Fsubstring (bestmatch
, make_number (0), make_number (bestmatchsize
));
419 return Fsignal (Qquit
, Qnil
);
422 file_name_completion_stat (dirname
, dp
, st_addr
)
425 struct stat
*st_addr
;
427 int len
= NAMLEN (dp
);
428 int pos
= XSTRING (dirname
)->size
;
429 char *fullname
= (char *) alloca (len
+ pos
+ 2);
431 bcopy (XSTRING (dirname
)->data
, fullname
, pos
);
433 if (fullname
[pos
- 1] != '/')
434 fullname
[pos
++] = '/';
437 bcopy (dp
->d_name
, fullname
+ pos
, len
);
438 fullname
[pos
+ len
] = 0;
440 return stat (fullname
, st_addr
);
445 DEFUN ("file-name-all-versions", Ffile_name_all_versions
,
446 Sfile_name_all_versions
, 2, 2, 0,
447 "Return a list of all versions of file name FILE in directory DIR.")
449 Lisp_Object file
, dirname
;
451 return file_name_completion (file
, dirname
, 1, 1);
454 DEFUN ("file-version-limit", Ffile_version_limit
, Sfile_version_limit
, 1, 1, 0,
455 "Return the maximum number of versions allowed for FILE.\n\
456 Returns nil if the file cannot be opened or if there is no version limit.")
458 Lisp_Object filename
;
463 struct XABFHC xabfhc
;
466 filename
= Fexpand_file_name (filename
, Qnil
);
468 xabfhc
= cc$rms_xabfhc
;
469 fab
.fab$l_fna
= XSTRING (filename
)->data
;
470 fab
.fab$b_fns
= strlen (fab
.fab$l_fna
);
471 fab
.fab$l_xab
= (char *) &xabfhc
;
472 status
= sys$
open (&fab
, 0, 0);
473 if (status
!= RMS$_NORMAL
) /* Probably non-existent file */
475 sys$
close (&fab
, 0, 0);
476 if (xabfhc
.xab$w_verlimit
== 32767)
477 return Qnil
; /* No version limit */
479 return make_number (xabfhc
.xab$w_verlimit
);
488 return Fcons (make_number (time
>> 16),
489 Fcons (make_number (time
& 0177777), Qnil
));
492 DEFUN ("file-attributes", Ffile_attributes
, Sfile_attributes
, 1, 1, 0,
493 "Return a list of attributes of file FILENAME.\n\
494 Value is nil if specified file cannot be opened.\n\
495 Otherwise, list elements are:\n\
496 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
497 1. Number of links to file.\n\
500 4. Last access time, as a list of two integers.\n\
501 First integer has high-order 16 bits of time, second has low 16 bits.\n\
502 5. Last modification time, likewise.\n\
503 6. Last status change time, likewise.\n\
505 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
506 9. t iff file's gid would change if file were deleted and recreated.\n\
508 11. Device number.\n\
510 If file does not exist, returns nil.")
512 Lisp_Object filename
;
514 Lisp_Object values
[12];
521 filename
= Fexpand_file_name (filename
, Qnil
);
523 /* If the file name has special constructs in it,
524 call the corresponding file handler. */
525 handler
= Ffind_file_name_handler (filename
);
527 return call2 (handler
, Qfile_attributes
, filename
);
529 if (lstat (XSTRING (filename
)->data
, &s
) < 0)
532 switch (s
.st_mode
& S_IFMT
)
535 values
[0] = Qnil
; break;
537 values
[0] = Qt
; break;
540 values
[0] = Ffile_symlink_p (filename
); break;
543 values
[1] = make_number (s
.st_nlink
);
544 values
[2] = make_number (s
.st_uid
);
545 values
[3] = make_number (s
.st_gid
);
546 values
[4] = make_time (s
.st_atime
);
547 values
[5] = make_time (s
.st_mtime
);
548 values
[6] = make_time (s
.st_ctime
);
549 /* perhaps we should set this to most-positive-fixnum if it is too large? */
550 values
[7] = make_number (s
.st_size
);
551 filemodestring (&s
, modes
);
552 values
[8] = make_string (modes
, 10);
553 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
554 #define BSD4_2 /* A new meaning to the term `backwards compatability' */
556 #ifdef BSD4_2 /* file gid will be dir gid */
557 dirname
= Ffile_name_directory (filename
);
558 if (! NILP (dirname
) && stat (XSTRING (dirname
)->data
, &sdir
) == 0)
559 values
[9] = (sdir
.st_gid
!= s
.st_gid
) ? Qt
: Qnil
;
560 else /* if we can't tell, assume worst */
562 #else /* file gid will be egid */
563 values
[9] = (s
.st_gid
!= getegid ()) ? Qt
: Qnil
;
564 #endif /* BSD4_2 (or BSD4_3) */
566 #undef BSD4_2 /* ok, you can look again without throwing up */
568 values
[10] = make_number (s
.st_ino
);
569 values
[11] = make_number (s
.st_dev
);
570 return Flist (sizeof(values
) / sizeof(values
[0]), values
);
575 Qdirectory_files
= intern ("directory-files");
576 Qfile_name_completion
= intern ("file-name-completion");
577 Qfile_name_all_completions
= intern ("file-name-all-completions");
578 Qfile_attributes
= intern ("file-attributes");
580 defsubr (&Sdirectory_files
);
581 defsubr (&Sfile_name_completion
);
583 defsubr (&Sfile_name_all_versions
);
584 defsubr (&Sfile_version_limit
);
586 defsubr (&Sfile_name_all_completions
);
587 defsubr (&Sfile_attributes
);
590 Qcompletion_ignore_case
= intern ("completion-ignore-case");
591 staticpro (&Qcompletion_ignore_case
);
594 DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions
,
595 "*Completion ignores filenames ending in any string in this list.\n\
596 This variable does not affect lists of possible completions,\n\
597 but does affect the commands that actually do completions.");
598 Vcompletion_ignored_extensions
= Qnil
;