1 /* Lisp functions for making directory listings.
2 Copyright (C) 1985, 1986, 1993, 1994, 1999 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 2, 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include <sys/types.h>
40 /* The d_nameln member of a struct dirent includes the '\0' character
41 on some systems, but not on others. What's worse, you can't tell
42 at compile-time which one it will be, since it really depends on
43 the sort of system providing the filesystem you're reading from,
44 not the system you are running on. Paul Eggert
45 <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
46 SunOS 4.1.2 host, reading a directory that is remote-mounted from a
47 Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
49 Since applying strlen to the name always works, we'll just do that. */
50 #define NAMLEN(p) strlen (p->d_name)
52 #ifdef SYSV_SYSTEM_DIR
55 #define DIRENTRY struct dirent
57 #else /* not SYSV_SYSTEM_DIR */
59 #ifdef NONSYSTEM_DIR_LIBRARY
61 #else /* not NONSYSTEM_DIR_LIBRARY */
67 #endif /* not NONSYSTEM_DIR_LIBRARY */
72 #define DIRENTRY struct direct
74 extern DIR *opendir ();
75 extern struct direct
*readdir ();
77 #endif /* not MSDOS */
78 #endif /* not SYSV_SYSTEM_DIR */
81 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
83 #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
93 /* Returns a search buffer, with a fastmap allocated and ready to go. */
94 extern struct re_pattern_buffer
*compile_pattern ();
96 /* From filemode.c. Can't go in Lisp.h because of `stat'. */
97 extern void filemodestring
P_ ((struct stat
*, char *));
99 #define min(a, b) ((a) < (b) ? (a) : (b))
101 /* if system does not have symbolic links, it does not have lstat.
102 In that case, use ordinary stat instead. */
108 extern int completion_ignore_case
;
109 extern Lisp_Object Vcompletion_regexp_list
;
110 extern Lisp_Object Vfile_name_coding_system
, Vdefault_file_name_coding_system
;
112 Lisp_Object Vcompletion_ignored_extensions
;
113 Lisp_Object Qcompletion_ignore_case
;
114 Lisp_Object Qdirectory_files
;
115 Lisp_Object Qdirectory_files_and_attributes
;
116 Lisp_Object Qfile_name_completion
;
117 Lisp_Object Qfile_name_all_completions
;
118 Lisp_Object Qfile_attributes
;
119 Lisp_Object Qfile_attributes_lessp
;
123 directory_files_internal_unwind (dh
)
126 DIR *d
= (DIR *) ((XINT (XCAR (dh
)) << 16) + XINT (XCDR (dh
)));
131 /* Function shared by Fdirectory_files and Fdirectory_files_and_attributes.
132 When ATTRS is zero, return a list of directory filenames; when
133 non-zero, return a list of directory filenames and their attributes. */
135 directory_files_internal (directory
, full
, match
, nosort
, attrs
)
136 Lisp_Object directory
, full
, match
, nosort
;
140 int directory_nbytes
;
141 Lisp_Object list
, dirfilename
, encoded_directory
;
143 struct re_pattern_buffer
*bufp
= NULL
;
145 int count
= specpdl_ptr
- specpdl
;
146 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
148 /* Because of file name handlers, these functions might call
149 Ffuncall, and cause a GC. */
150 list
= encoded_directory
= dirfilename
= Qnil
;
151 GCPRO5 (match
, directory
, list
, dirfilename
, encoded_directory
);
152 directory
= Fexpand_file_name (directory
, Qnil
);
153 dirfilename
= Fdirectory_file_name (directory
);
157 CHECK_STRING (match
, 3);
159 /* MATCH might be a flawed regular expression. Rather than
160 catching and signaling our own errors, we just call
161 compile_pattern to do the work for us. */
162 /* Pass 1 for the MULTIBYTE arg
163 because we do make multibyte strings if the contents warrant. */
165 bufp
= compile_pattern (match
, 0,
166 buffer_defaults
.downcase_table
, 0, 1);
168 bufp
= compile_pattern (match
, 0, Qnil
, 0, 1);
172 /* Note: ENOCDE_FILE and DECODE_FILE can GC because they can run
173 run_pre_post_conversion_on_str which calls Lisp directly and
175 dirfilename
= ENCODE_FILE (dirfilename
);
176 encoded_directory
= ENCODE_FILE (directory
);
178 /* Now *bufp is the compiled form of MATCH; don't call anything
179 which might compile a new regexp until we're done with the loop! */
181 /* Do this opendir after anything which might signal an error; if
182 an error is signaled while the directory stream is open, we
183 have to make sure it gets closed, and setting up an
184 unwind_protect to do so would be a pain. */
185 d
= opendir (XSTRING (dirfilename
)->data
);
187 report_file_error ("Opening directory", Fcons (directory
, Qnil
));
189 /* Unfortunately, we can now invoke expand-file-name and
190 file-attributes on filenames, both of which can throw, so we must
191 do a proper unwind-protect. */
192 record_unwind_protect (directory_files_internal_unwind
,
193 Fcons (make_number (((unsigned long) d
) >> 16),
194 make_number (((unsigned long) d
) & 0xffff)));
196 directory_nbytes
= STRING_BYTES (XSTRING (directory
));
197 re_match_object
= Qt
;
199 /* Decide whether we need to add a directory separator. */
201 if (directory_nbytes
== 0
202 || !IS_ANY_SEP (XSTRING (directory
)->data
[directory_nbytes
- 1]))
206 /* Loop reading blocks */
209 DIRENTRY
*dp
= readdir (d
);
214 if (DIRENTRY_NONEMPTY (dp
))
218 Lisp_Object name
, finalname
;
219 struct gcpro gcpro1
, gcpro2
;
222 name
= finalname
= make_string (dp
->d_name
, len
);
223 GCPRO2 (finalname
, name
);
225 /* Note: ENCODE_FILE can GC; it should protect its argument,
227 name
= DECODE_FILE (name
);
228 len
= STRING_BYTES (XSTRING (name
));
230 /* Now that we have unwind_protect in place, we might as well
231 allow matching to be interrupted. */
236 || (0 <= re_search (bufp
, XSTRING (name
)->data
, len
, 0, len
, 0)))
245 Lisp_Object fullname
;
246 int nbytes
= len
+ directory_nbytes
+ needsep
;
249 fullname
= make_uninit_multibyte_string (nbytes
, nbytes
);
250 bcopy (XSTRING (directory
)->data
, XSTRING (fullname
)->data
,
254 XSTRING (fullname
)->data
[directory_nbytes
+ 1]
257 bcopy (XSTRING (name
)->data
,
258 XSTRING (fullname
)->data
+ directory_nbytes
+ needsep
,
261 nchars
= chars_in_text (XSTRING (fullname
)->data
, nbytes
);
263 /* Some bug somewhere. */
267 XSTRING (fullname
)->size
= nchars
;
268 if (nchars
== nbytes
)
269 SET_STRING_BYTES (XSTRING (fullname
), -1);
271 finalname
= fullname
;
276 /* Construct an expanded filename for the directory entry.
277 Use the decoded names for input to Ffile_attributes. */
278 Lisp_Object decoded_fullname
, fileattrs
;
279 struct gcpro gcpro1
, gcpro2
;
281 decoded_fullname
= fileattrs
= Qnil
;
282 GCPRO2 (decoded_fullname
, fileattrs
);
284 /* Both Fexpand_file_name and Ffile_attributes can GC. */
285 decoded_fullname
= Fexpand_file_name (name
, directory
);
286 fileattrs
= Ffile_attributes (decoded_fullname
);
288 list
= Fcons (Fcons (finalname
, fileattrs
), list
);
292 list
= Fcons (finalname
, list
);
301 /* Discard the unwind protect. */
302 specpdl_ptr
= specpdl
+ count
;
305 list
= Fsort (Fnreverse (list
),
306 attrs
? Qfile_attributes_lessp
: Qstring_lessp
);
308 RETURN_UNGCPRO (list
);
312 DEFUN ("directory-files", Fdirectory_files
, Sdirectory_files
, 1, 4, 0,
313 "Return a list of names of files in DIRECTORY.\n\
314 There are three optional arguments:\n\
315 If FULL is non-nil, return absolute file names. Otherwise return names\n\
316 that are relative to the specified directory.\n\
317 If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
318 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
319 NOSORT is useful if you plan to sort the result yourself.")
320 (directory
, full
, match
, nosort
)
321 Lisp_Object directory
, full
, match
, nosort
;
325 /* If the file name has special constructs in it,
326 call the corresponding file handler. */
327 handler
= Ffind_file_name_handler (directory
, Qdirectory_files
);
333 args
[1] = Qdirectory_files
;
338 return Ffuncall (6, args
);
341 return directory_files_internal (directory
, full
, match
, nosort
, 0);
344 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes
, Sdirectory_files_and_attributes
, 1, 4, 0,
345 "Return a list of names of files and their attributes in DIRECTORY.\n\
346 There are three optional arguments:\n\
347 If FULL is non-nil, return absolute file names. Otherwise return names\n\
348 that are relative to the specified directory.\n\
349 If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
350 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
351 NOSORT is useful if you plan to sort the result yourself.")
352 (directory
, full
, match
, nosort
)
353 Lisp_Object directory
, full
, match
, nosort
;
357 /* If the file name has special constructs in it,
358 call the corresponding file handler. */
359 handler
= Ffind_file_name_handler (directory
, Qdirectory_files_and_attributes
);
365 args
[1] = Qdirectory_files_and_attributes
;
370 return Ffuncall (6, args
);
373 return directory_files_internal (directory
, full
, match
, nosort
, 1);
377 Lisp_Object
file_name_completion ();
379 DEFUN ("file-name-completion", Ffile_name_completion
, Sfile_name_completion
,
381 "Complete file name FILE in directory DIRECTORY.\n\
382 Returns the longest string\n\
383 common to all file names in DIRECTORY that start with FILE.\n\
384 If there is only one and FILE matches it exactly, returns t.\n\
385 Returns nil if DIR contains no name starting with FILE.")
387 Lisp_Object file
, directory
;
391 /* If the directory name has special constructs in it,
392 call the corresponding file handler. */
393 handler
= Ffind_file_name_handler (directory
, Qfile_name_completion
);
395 return call3 (handler
, Qfile_name_completion
, file
, directory
);
397 /* If the file name has special constructs in it,
398 call the corresponding file handler. */
399 handler
= Ffind_file_name_handler (file
, Qfile_name_completion
);
401 return call3 (handler
, Qfile_name_completion
, file
, directory
);
403 return file_name_completion (file
, directory
, 0, 0);
406 DEFUN ("file-name-all-completions", Ffile_name_all_completions
,
407 Sfile_name_all_completions
, 2, 2, 0,
408 "Return a list of all completions of file name FILE in directory DIRECTORY.\n\
409 These are all file names in directory DIRECTORY which begin with FILE.")
411 Lisp_Object file
, directory
;
415 /* If the directory name has special constructs in it,
416 call the corresponding file handler. */
417 handler
= Ffind_file_name_handler (directory
, Qfile_name_all_completions
);
419 return call3 (handler
, Qfile_name_all_completions
, file
, directory
);
421 /* If the file name has special constructs in it,
422 call the corresponding file handler. */
423 handler
= Ffind_file_name_handler (file
, Qfile_name_all_completions
);
425 return call3 (handler
, Qfile_name_all_completions
, file
, directory
);
427 return file_name_completion (file
, directory
, 1, 0);
430 static int file_name_completion_stat ();
433 file_name_completion (file
, dirname
, all_flag
, ver_flag
)
434 Lisp_Object file
, dirname
;
435 int all_flag
, ver_flag
;
439 int bestmatchsize
= 0, skip
;
440 register int compare
, matchsize
;
441 unsigned char *p1
, *p2
;
443 Lisp_Object bestmatch
, tem
, elt
, name
;
444 Lisp_Object encoded_file
;
445 Lisp_Object encoded_dir
;
449 int count
= specpdl_ptr
- specpdl
;
450 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
455 extern DIRENTRY
* readdirver ();
457 DIRENTRY
*((* readfunc
) ());
459 /* Filename completion on VMS ignores case, since VMS filesys does. */
460 specbind (Qcompletion_ignore_case
, Qt
);
464 readfunc
= readdirver
;
465 file
= Fupcase (file
);
467 CHECK_STRING (file
, 0);
470 #ifdef FILE_SYSTEM_CASE
471 file
= FILE_SYSTEM_CASE (file
);
474 encoded_file
= encoded_dir
= Qnil
;
475 GCPRO5 (file
, dirname
, bestmatch
, encoded_file
, encoded_dir
);
476 dirname
= Fexpand_file_name (dirname
, Qnil
);
478 /* Do completion on the encoded file name
479 because the other names in the directory are (we presume)
480 encoded likewise. We decode the completed string at the end. */
481 encoded_file
= ENCODE_FILE (file
);
483 encoded_dir
= ENCODE_FILE (dirname
);
485 /* With passcount = 0, ignore files that end in an ignored extension.
486 If nothing found then try again with passcount = 1, don't ignore them.
487 If looking for all completions, start with passcount = 1,
488 so always take even the ignored ones.
490 ** It would not actually be helpful to the user to ignore any possible
491 completions when making a list of them.** */
493 for (passcount
= !!all_flag
; NILP (bestmatch
) && passcount
< 2; passcount
++)
495 d
= opendir (XSTRING (Fdirectory_file_name (encoded_dir
))->data
);
497 report_file_error ("Opening directory", Fcons (dirname
, Qnil
));
499 /* Loop reading blocks */
500 /* (att3b compiler bug requires do a null comparison this way) */
507 dp
= (*readfunc
) (d
);
515 if (!NILP (Vquit_flag
) && NILP (Vinhibit_quit
))
517 if (! DIRENTRY_NONEMPTY (dp
)
518 || len
< XSTRING (encoded_file
)->size
519 || 0 <= scmp (dp
->d_name
, XSTRING (encoded_file
)->data
,
520 XSTRING (encoded_file
)->size
))
523 if (file_name_completion_stat (encoded_dir
, dp
, &st
) < 0)
526 directoryp
= ((st
.st_mode
& S_IFMT
) == S_IFDIR
);
530 #ifndef TRIVIAL_DIRECTORY_ENTRY
531 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
533 /* "." and ".." are never interesting as completions, but are
534 actually in the way in a directory contains only one file. */
535 if (!passcount
&& TRIVIAL_DIRECTORY_ENTRY (dp
->d_name
))
540 /* Compare extensions-to-be-ignored against end of this file name */
541 /* if name is not an exact match against specified string */
542 if (!passcount
&& len
> XSTRING (encoded_file
)->size
)
543 /* and exit this for loop if a match is found */
544 for (tem
= Vcompletion_ignored_extensions
;
545 CONSP (tem
); tem
= XCDR (tem
))
548 if (!STRINGP (elt
)) continue;
549 skip
= len
- XSTRING (elt
)->size
;
550 if (skip
< 0) continue;
552 if (0 <= scmp (dp
->d_name
+ skip
,
554 XSTRING (elt
)->size
))
560 /* If an ignored-extensions match was found,
561 don't process this name as a completion. */
562 if (!passcount
&& CONSP (tem
))
569 XSETFASTINT (zero
, 0);
571 /* Ignore this element if it fails to match all the regexps. */
572 for (regexps
= Vcompletion_regexp_list
; CONSP (regexps
);
573 regexps
= XCDR (regexps
))
575 tem
= Fstring_match (XCAR (regexps
), elt
, zero
);
583 /* Update computation of how much all possible completions match */
587 if (all_flag
|| NILP (bestmatch
))
589 /* This is a possible completion */
592 /* This completion is a directory; make it end with '/' */
593 name
= Ffile_name_as_directory (make_string (dp
->d_name
, len
));
596 name
= make_string (dp
->d_name
, len
);
599 name
= DECODE_FILE (name
);
600 bestmatch
= Fcons (name
, bestmatch
);
605 bestmatchsize
= XSTRING (name
)->size
;
610 compare
= min (bestmatchsize
, len
);
611 p1
= XSTRING (bestmatch
)->data
;
612 p2
= (unsigned char *) dp
->d_name
;
613 matchsize
= scmp(p1
, p2
, compare
);
616 if (completion_ignore_case
)
618 /* If this is an exact match except for case,
619 use it as the best match rather than one that is not
620 an exact match. This way, we get the case pattern
621 of the actual match. */
622 /* This tests that the current file is an exact match
623 but BESTMATCH is not (it is too long). */
624 if ((matchsize
== len
625 && matchsize
+ !!directoryp
626 < XSTRING (bestmatch
)->size
)
628 /* If there is no exact match ignoring case,
629 prefer a match that does not change the case
631 /* If there is more than one exact match aside from
632 case, and one of them is exact including case,
634 /* This == checks that, of current file and BESTMATCH,
635 either both or neither are exact. */
638 (matchsize
+ !!directoryp
639 == XSTRING (bestmatch
)->size
))
640 && !bcmp (p2
, XSTRING (encoded_file
)->data
, XSTRING (encoded_file
)->size
)
641 && bcmp (p1
, XSTRING (encoded_file
)->data
, XSTRING (encoded_file
)->size
)))
643 bestmatch
= make_string (dp
->d_name
, len
);
645 bestmatch
= Ffile_name_as_directory (bestmatch
);
649 /* If this dirname all matches, see if implicit following
652 && compare
== matchsize
653 && bestmatchsize
> matchsize
654 && IS_ANY_SEP (p1
[matchsize
]))
656 bestmatchsize
= matchsize
;
663 bestmatch
= unbind_to (count
, bestmatch
);
665 if (all_flag
|| NILP (bestmatch
))
667 if (STRINGP (bestmatch
))
668 bestmatch
= DECODE_FILE (bestmatch
);
671 if (matchcount
== 1 && bestmatchsize
== XSTRING (file
)->size
)
673 bestmatch
= Fsubstring (bestmatch
, make_number (0),
674 make_number (bestmatchsize
));
675 /* Now that we got the right initial segment of BESTMATCH,
676 decode it from the coding system in use. */
677 bestmatch
= DECODE_FILE (bestmatch
);
683 return Fsignal (Qquit
, Qnil
);
687 file_name_completion_stat (dirname
, dp
, st_addr
)
690 struct stat
*st_addr
;
692 int len
= NAMLEN (dp
);
693 int pos
= XSTRING (dirname
)->size
;
695 char *fullname
= (char *) alloca (len
+ pos
+ 2);
699 /* Some fields of struct stat are *very* expensive to compute on MS-DOS,
700 but aren't required here. Avoid computing the following fields:
701 st_inode, st_size and st_nlink for directories, and the execute bits
702 in st_mode for non-directory files with non-standard extensions. */
704 unsigned short save_djstat_flags
= _djstat_flags
;
706 _djstat_flags
= _STAT_INODE
| _STAT_EXEC_MAGIC
| _STAT_DIRSIZE
;
707 #endif /* __DJGPP__ > 1 */
710 bcopy (XSTRING (dirname
)->data
, fullname
, pos
);
712 if (!IS_DIRECTORY_SEP (fullname
[pos
- 1]))
713 fullname
[pos
++] = DIRECTORY_SEP
;
716 bcopy (dp
->d_name
, fullname
+ pos
, len
);
717 fullname
[pos
+ len
] = 0;
720 /* We want to return success if a link points to a nonexistent file,
721 but we want to return the status for what the link points to,
722 in case it is a directory. */
723 value
= lstat (fullname
, st_addr
);
724 stat (fullname
, st_addr
);
727 value
= stat (fullname
, st_addr
);
730 _djstat_flags
= save_djstat_flags
;
731 #endif /* __DJGPP__ > 1 */
739 DEFUN ("file-name-all-versions", Ffile_name_all_versions
,
740 Sfile_name_all_versions
, 2, 2, 0,
741 "Return a list of all versions of file name FILE in directory DIRECTORY.")
743 Lisp_Object file
, directory
;
745 return file_name_completion (file
, directory
, 1, 1);
748 DEFUN ("file-version-limit", Ffile_version_limit
, Sfile_version_limit
, 1, 1, 0,
749 "Return the maximum number of versions allowed for FILE.\n\
750 Returns nil if the file cannot be opened or if there is no version limit.")
752 Lisp_Object filename
;
757 struct XABFHC xabfhc
;
760 filename
= Fexpand_file_name (filename
, Qnil
);
762 xabfhc
= cc$rms_xabfhc
;
763 fab
.fab$l_fna
= XSTRING (filename
)->data
;
764 fab
.fab$b_fns
= strlen (fab
.fab$l_fna
);
765 fab
.fab$l_xab
= (char *) &xabfhc
;
766 status
= sys$
open (&fab
, 0, 0);
767 if (status
!= RMS$_NORMAL
) /* Probably non-existent file */
769 sys$
close (&fab
, 0, 0);
770 if (xabfhc
.xab$w_verlimit
== 32767)
771 return Qnil
; /* No version limit */
773 return make_number (xabfhc
.xab$w_verlimit
);
782 return Fcons (make_number (time
>> 16),
783 Fcons (make_number (time
& 0177777), Qnil
));
786 DEFUN ("file-attributes", Ffile_attributes
, Sfile_attributes
, 1, 1, 0,
787 "Return a list of attributes of file FILENAME.\n\
788 Value is nil if specified file cannot be opened.\n\
789 Otherwise, list elements are:\n\
790 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
791 1. Number of links to file.\n\
794 4. Last access time, as a list of two integers.\n\
795 First integer has high-order 16 bits of time, second has low 16 bits.\n\
796 5. Last modification time, likewise.\n\
797 6. Last status change time, likewise.\n\
799 This is a floating point number if the size is too large for an integer.\n\
800 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
801 9. t iff file's gid would change if file were deleted and recreated.\n\
802 10. inode number. If inode number is larger than the Emacs integer,\n\
803 this is a cons cell containing two integers: first the high part,\n\
804 then the low 16 bits.\n\
805 11. Device number.\n\
807 If file does not exist, returns nil.")
809 Lisp_Object filename
;
811 Lisp_Object values
[12];
819 filename
= Fexpand_file_name (filename
, Qnil
);
821 /* If the file name has special constructs in it,
822 call the corresponding file handler. */
823 handler
= Ffind_file_name_handler (filename
, Qfile_attributes
);
825 return call2 (handler
, Qfile_attributes
, filename
);
827 encoded
= ENCODE_FILE (filename
);
829 if (lstat (XSTRING (encoded
)->data
, &s
) < 0)
832 switch (s
.st_mode
& S_IFMT
)
835 values
[0] = Qnil
; break;
837 values
[0] = Qt
; break;
840 values
[0] = Ffile_symlink_p (filename
); break;
843 values
[1] = make_number (s
.st_nlink
);
844 values
[2] = make_number (s
.st_uid
);
845 values
[3] = make_number (s
.st_gid
);
846 values
[4] = make_time (s
.st_atime
);
847 values
[5] = make_time (s
.st_mtime
);
848 values
[6] = make_time (s
.st_ctime
);
849 values
[7] = make_number (s
.st_size
);
850 /* If the size is out of range for an integer, return a float. */
851 if (XINT (values
[7]) != s
.st_size
)
852 values
[7] = make_float ((double)s
.st_size
);
853 filemodestring (&s
, modes
);
854 values
[8] = make_string (modes
, 10);
855 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
856 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */
858 #ifdef BSD4_2 /* file gid will be dir gid */
859 dirname
= Ffile_name_directory (filename
);
860 if (! NILP (dirname
))
861 encoded
= ENCODE_FILE (dirname
);
862 if (! NILP (dirname
) && stat (XSTRING (encoded
)->data
, &sdir
) == 0)
863 values
[9] = (sdir
.st_gid
!= s
.st_gid
) ? Qt
: Qnil
;
864 else /* if we can't tell, assume worst */
866 #else /* file gid will be egid */
867 values
[9] = (s
.st_gid
!= getegid ()) ? Qt
: Qnil
;
868 #endif /* BSD4_2 (or BSD4_3) */
870 #undef BSD4_2 /* ok, you can look again without throwing up */
872 /* Cast -1 to avoid warning if int is not as wide as VALBITS. */
873 if (s
.st_ino
& (((EMACS_INT
) (-1)) << VALBITS
))
874 /* To allow inode numbers larger than VALBITS, separate the bottom
876 values
[10] = Fcons (make_number (s
.st_ino
>> 16),
877 make_number (s
.st_ino
& 0xffff));
879 /* But keep the most common cases as integers. */
880 values
[10] = make_number (s
.st_ino
);
882 /* Likewise for device. */
883 if (s
.st_dev
& (((EMACS_INT
) (-1)) << VALBITS
))
884 values
[11] = Fcons (make_number (s
.st_dev
>> 16),
885 make_number (s
.st_dev
& 0xffff));
887 values
[11] = make_number (s
.st_dev
);
889 return Flist (sizeof(values
) / sizeof(values
[0]), values
);
892 DEFUN ("file-attributes-lessp", Ffile_attributes_lessp
, Sfile_attributes_lessp
, 2, 2, 0,
893 "Return t if first arg file attributes list is less than second.\n\
894 Comparison is in lexicographic order and case is significant.")
898 return Fstring_lessp (Fcar (f1
), Fcar (f2
));
904 Qdirectory_files
= intern ("directory-files");
905 Qdirectory_files_and_attributes
= intern ("directory-files-and-attributes");
906 Qfile_name_completion
= intern ("file-name-completion");
907 Qfile_name_all_completions
= intern ("file-name-all-completions");
908 Qfile_attributes
= intern ("file-attributes");
909 Qfile_attributes_lessp
= intern ("file-attributes-lessp");
911 staticpro (&Qdirectory_files
);
912 staticpro (&Qdirectory_files_and_attributes
);
913 staticpro (&Qfile_name_completion
);
914 staticpro (&Qfile_name_all_completions
);
915 staticpro (&Qfile_attributes
);
916 staticpro (&Qfile_attributes_lessp
);
918 defsubr (&Sdirectory_files
);
919 defsubr (&Sdirectory_files_and_attributes
);
920 defsubr (&Sfile_name_completion
);
922 defsubr (&Sfile_name_all_versions
);
923 defsubr (&Sfile_version_limit
);
925 defsubr (&Sfile_name_all_completions
);
926 defsubr (&Sfile_attributes
);
927 defsubr (&Sfile_attributes_lessp
);
930 Qcompletion_ignore_case
= intern ("completion-ignore-case");
931 staticpro (&Qcompletion_ignore_case
);
934 DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions
,
935 "*Completion ignores filenames ending in any string in this list.\n\
936 This variable does not affect lists of possible completions,\n\
937 but does affect the commands that actually do completions.");
938 Vcompletion_ignored_extensions
= Qnil
;