(Ffile_attributes): Return inode number as a cons only if necessary.
[bpt/emacs.git] / src / dired.c
1 /* Lisp functions for making directory listings.
2 Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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)
9 any later version.
10
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.
15
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. */
20
21
22 #include <config.h>
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 #ifdef VMS
29 #include <string.h>
30 #include <rms.h>
31 #include <rmsdef.h>
32 #endif
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 SYSV_SYSTEM_DIR
47
48 #include <dirent.h>
49 #define DIRENTRY struct dirent
50
51 #else /* not SYSV_SYSTEM_DIR */
52
53 #ifdef NONSYSTEM_DIR_LIBRARY
54 #include "ndir.h"
55 #else /* not NONSYSTEM_DIR_LIBRARY */
56 #ifdef MSDOS
57 #include <dirent.h>
58 #else
59 #include <sys/dir.h>
60 #endif
61 #endif /* not NONSYSTEM_DIR_LIBRARY */
62
63 #ifndef MSDOS
64 #define DIRENTRY struct direct
65
66 extern DIR *opendir ();
67 extern struct direct *readdir ();
68
69 #endif /* not MSDOS */
70 #endif /* not SYSV_SYSTEM_DIR */
71
72 #ifdef MSDOS
73 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
74 #else
75 #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
76 #endif
77
78 #include "lisp.h"
79 #include "buffer.h"
80 #include "commands.h"
81
82 #include "regex.h"
83
84 /* Returns a search buffer, with a fastmap allocated and ready to go. */
85 extern struct re_pattern_buffer *compile_pattern ();
86
87 #define min(a, b) ((a) < (b) ? (a) : (b))
88
89 /* if system does not have symbolic links, it does not have lstat.
90 In that case, use ordinary stat instead. */
91
92 #ifndef S_IFLNK
93 #define lstat stat
94 #endif
95
96 extern int completion_ignore_case;
97 extern Lisp_Object Vcompletion_regexp_list;
98
99 Lisp_Object Vcompletion_ignored_extensions;
100 Lisp_Object Qcompletion_ignore_case;
101 Lisp_Object Qdirectory_files;
102 Lisp_Object Qfile_name_completion;
103 Lisp_Object Qfile_name_all_completions;
104 Lisp_Object Qfile_attributes;
105 \f
106 DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
107 "Return a list of names of files in DIRECTORY.\n\
108 There are three optional arguments:\n\
109 If FULL is non-nil, return absolute file names. Otherwise return names\n\
110 that are relative to the specified directory.\n\
111 If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
112 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
113 NOSORT is useful if you plan to sort the result yourself.")
114 (directory, full, match, nosort)
115 Lisp_Object directory, full, match, nosort;
116 {
117 DIR *d;
118 int dirnamelen;
119 Lisp_Object list, name, dirfilename;
120 Lisp_Object handler;
121 struct re_pattern_buffer *bufp;
122
123 /* If the file name has special constructs in it,
124 call the corresponding file handler. */
125 handler = Ffind_file_name_handler (directory, Qdirectory_files);
126 if (!NILP (handler))
127 {
128 Lisp_Object args[6];
129
130 args[0] = handler;
131 args[1] = Qdirectory_files;
132 args[2] = directory;
133 args[3] = full;
134 args[4] = match;
135 args[5] = nosort;
136 return Ffuncall (6, args);
137 }
138
139 {
140 struct gcpro gcpro1, gcpro2;
141
142 /* Because of file name handlers, these functions might call
143 Ffuncall, and cause a GC. */
144 GCPRO1 (match);
145 directory = Fexpand_file_name (directory, Qnil);
146 UNGCPRO;
147 GCPRO2 (match, directory);
148 dirfilename = Fdirectory_file_name (directory);
149 UNGCPRO;
150 }
151
152 if (!NILP (match))
153 {
154 CHECK_STRING (match, 3);
155
156 /* MATCH might be a flawed regular expression. Rather than
157 catching and signaling our own errors, we just call
158 compile_pattern to do the work for us. */
159 #ifdef VMS
160 bufp = compile_pattern (match, 0,
161 buffer_defaults.downcase_table->contents, 0);
162 #else
163 bufp = compile_pattern (match, 0, 0, 0);
164 #endif
165 }
166
167 /* Now *bufp is the compiled form of MATCH; don't call anything
168 which might compile a new regexp until we're done with the loop! */
169
170 /* Do this opendir after anything which might signal an error; if
171 an error is signaled while the directory stream is open, we
172 have to make sure it gets closed, and setting up an
173 unwind_protect to do so would be a pain. */
174 d = opendir (XSTRING (dirfilename)->data);
175 if (! d)
176 report_file_error ("Opening directory", Fcons (directory, Qnil));
177
178 list = Qnil;
179 dirnamelen = XSTRING (directory)->size;
180 re_match_object = Qt;
181
182 /* Loop reading blocks */
183 while (1)
184 {
185 DIRENTRY *dp = readdir (d);
186 int len;
187
188 if (!dp) break;
189 len = NAMLEN (dp);
190 if (DIRENTRY_NONEMPTY (dp))
191 {
192 if (NILP (match)
193 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))
194 {
195 if (!NILP (full))
196 {
197 int afterdirindex = dirnamelen;
198 int total = len + dirnamelen;
199 int needsep = 0;
200
201 /* Decide whether we need to add a directory separator. */
202 #ifndef VMS
203 if (dirnamelen == 0
204 || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
205 needsep = 1;
206 #endif /* VMS */
207
208 name = make_uninit_string (total + needsep);
209 bcopy (XSTRING (directory)->data, XSTRING (name)->data,
210 dirnamelen);
211 if (needsep)
212 XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
213 bcopy (dp->d_name,
214 XSTRING (name)->data + afterdirindex, len);
215 }
216 else
217 name = make_string (dp->d_name, len);
218 list = Fcons (name, list);
219 }
220 }
221 }
222 closedir (d);
223 if (!NILP (nosort))
224 return list;
225 return Fsort (Fnreverse (list), Qstring_lessp);
226 }
227 \f
228 Lisp_Object file_name_completion ();
229
230 DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
231 2, 2, 0,
232 "Complete file name FILE in directory DIRECTORY.\n\
233 Returns the longest string\n\
234 common to all file names in DIRECTORY that start with FILE.\n\
235 If there is only one and FILE matches it exactly, returns t.\n\
236 Returns nil if DIR contains no name starting with FILE.")
237 (file, directory)
238 Lisp_Object file, directory;
239 {
240 Lisp_Object handler;
241
242 /* If the directory name has special constructs in it,
243 call the corresponding file handler. */
244 handler = Ffind_file_name_handler (directory, Qfile_name_completion);
245 if (!NILP (handler))
246 return call3 (handler, Qfile_name_completion, file, directory);
247
248 /* If the file name has special constructs in it,
249 call the corresponding file handler. */
250 handler = Ffind_file_name_handler (file, Qfile_name_completion);
251 if (!NILP (handler))
252 return call3 (handler, Qfile_name_completion, file, directory);
253
254 return file_name_completion (file, directory, 0, 0);
255 }
256
257 DEFUN ("file-name-all-completions", Ffile_name_all_completions,
258 Sfile_name_all_completions, 2, 2, 0,
259 "Return a list of all completions of file name FILE in directory DIRECTORY.\n\
260 These are all file names in directory DIRECTORY which begin with FILE.")
261 (file, directory)
262 Lisp_Object file, directory;
263 {
264 Lisp_Object handler;
265
266 /* If the directory name has special constructs in it,
267 call the corresponding file handler. */
268 handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
269 if (!NILP (handler))
270 return call3 (handler, Qfile_name_all_completions, file, directory);
271
272 /* If the file name has special constructs in it,
273 call the corresponding file handler. */
274 handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
275 if (!NILP (handler))
276 return call3 (handler, Qfile_name_all_completions, file, directory);
277
278 return file_name_completion (file, directory, 1, 0);
279 }
280
281 Lisp_Object
282 file_name_completion (file, dirname, all_flag, ver_flag)
283 Lisp_Object file, dirname;
284 int all_flag, ver_flag;
285 {
286 DIR *d;
287 DIRENTRY *dp;
288 int bestmatchsize, skip;
289 register int compare, matchsize;
290 unsigned char *p1, *p2;
291 int matchcount = 0;
292 Lisp_Object bestmatch, tem, elt, name;
293 struct stat st;
294 int directoryp;
295 int passcount;
296 int count = specpdl_ptr - specpdl;
297 struct gcpro gcpro1, gcpro2, gcpro3;
298
299 #ifdef VMS
300 extern DIRENTRY * readdirver ();
301
302 DIRENTRY *((* readfunc) ());
303
304 /* Filename completion on VMS ignores case, since VMS filesys does. */
305 specbind (Qcompletion_ignore_case, Qt);
306
307 readfunc = readdir;
308 if (ver_flag)
309 readfunc = readdirver;
310 file = Fupcase (file);
311 #else /* not VMS */
312 CHECK_STRING (file, 0);
313 #endif /* not VMS */
314
315 #ifdef FILE_SYSTEM_CASE
316 file = FILE_SYSTEM_CASE (file);
317 #endif
318 bestmatch = Qnil;
319 GCPRO3 (file, dirname, bestmatch);
320 dirname = Fexpand_file_name (dirname, Qnil);
321
322 /* With passcount = 0, ignore files that end in an ignored extension.
323 If nothing found then try again with passcount = 1, don't ignore them.
324 If looking for all completions, start with passcount = 1,
325 so always take even the ignored ones.
326
327 ** It would not actually be helpful to the user to ignore any possible
328 completions when making a list of them.** */
329
330 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
331 {
332 if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
333 report_file_error ("Opening directory", Fcons (dirname, Qnil));
334
335 /* Loop reading blocks */
336 /* (att3b compiler bug requires do a null comparison this way) */
337 while (1)
338 {
339 DIRENTRY *dp;
340 int len;
341
342 #ifdef VMS
343 dp = (*readfunc) (d);
344 #else
345 dp = readdir (d);
346 #endif
347 if (!dp) break;
348
349 len = NAMLEN (dp);
350
351 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
352 goto quit;
353 if (! DIRENTRY_NONEMPTY (dp)
354 || len < XSTRING (file)->size
355 || 0 <= scmp (dp->d_name, XSTRING (file)->data,
356 XSTRING (file)->size))
357 continue;
358
359 if (file_name_completion_stat (dirname, dp, &st) < 0)
360 continue;
361
362 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
363 tem = Qnil;
364 if (directoryp)
365 {
366 #ifndef TRIVIAL_DIRECTORY_ENTRY
367 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
368 #endif
369 /* "." and ".." are never interesting as completions, but are
370 actually in the way in a directory contains only one file. */
371 if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
372 continue;
373 }
374 else
375 {
376 /* Compare extensions-to-be-ignored against end of this file name */
377 /* if name is not an exact match against specified string */
378 if (!passcount && len > XSTRING (file)->size)
379 /* and exit this for loop if a match is found */
380 for (tem = Vcompletion_ignored_extensions;
381 CONSP (tem); tem = XCONS (tem)->cdr)
382 {
383 elt = XCONS (tem)->car;
384 if (!STRINGP (elt)) continue;
385 skip = len - XSTRING (elt)->size;
386 if (skip < 0) continue;
387
388 if (0 <= scmp (dp->d_name + skip,
389 XSTRING (elt)->data,
390 XSTRING (elt)->size))
391 continue;
392 break;
393 }
394 }
395
396 /* If an ignored-extensions match was found,
397 don't process this name as a completion. */
398 if (!passcount && CONSP (tem))
399 continue;
400
401 if (!passcount)
402 {
403 Lisp_Object regexps;
404 Lisp_Object zero;
405 XSETFASTINT (zero, 0);
406
407 /* Ignore this element if it fails to match all the regexps. */
408 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
409 regexps = XCONS (regexps)->cdr)
410 {
411 tem = Fstring_match (XCONS (regexps)->car, elt, zero);
412 if (NILP (tem))
413 break;
414 }
415 if (CONSP (regexps))
416 continue;
417 }
418
419 /* Update computation of how much all possible completions match */
420
421 matchcount++;
422
423 if (all_flag || NILP (bestmatch))
424 {
425 /* This is a possible completion */
426 if (directoryp)
427 {
428 /* This completion is a directory; make it end with '/' */
429 name = Ffile_name_as_directory (make_string (dp->d_name, len));
430 }
431 else
432 name = make_string (dp->d_name, len);
433 if (all_flag)
434 {
435 bestmatch = Fcons (name, bestmatch);
436 }
437 else
438 {
439 bestmatch = name;
440 bestmatchsize = XSTRING (name)->size;
441 }
442 }
443 else
444 {
445 compare = min (bestmatchsize, len);
446 p1 = XSTRING (bestmatch)->data;
447 p2 = (unsigned char *) dp->d_name;
448 matchsize = scmp(p1, p2, compare);
449 if (matchsize < 0)
450 matchsize = compare;
451 if (completion_ignore_case)
452 {
453 /* If this is an exact match except for case,
454 use it as the best match rather than one that is not
455 an exact match. This way, we get the case pattern
456 of the actual match. */
457 /* This tests that the current file is an exact match
458 but BESTMATCH is not (it is too long). */
459 if ((matchsize == len
460 && matchsize + !!directoryp
461 < XSTRING (bestmatch)->size)
462 ||
463 /* If there is no exact match ignoring case,
464 prefer a match that does not change the case
465 of the input. */
466 /* If there is more than one exact match aside from
467 case, and one of them is exact including case,
468 prefer that one. */
469 /* This == checks that, of current file and BESTMATCH,
470 either both or neither are exact. */
471 (((matchsize == len)
472 ==
473 (matchsize + !!directoryp
474 == XSTRING (bestmatch)->size))
475 && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size)
476 && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size)))
477 {
478 bestmatch = make_string (dp->d_name, len);
479 if (directoryp)
480 bestmatch = Ffile_name_as_directory (bestmatch);
481 }
482 }
483
484 /* If this dirname all matches, see if implicit following
485 slash does too. */
486 if (directoryp
487 && compare == matchsize
488 && bestmatchsize > matchsize
489 && IS_ANY_SEP (p1[matchsize]))
490 matchsize++;
491 bestmatchsize = matchsize;
492 }
493 }
494 closedir (d);
495 }
496
497 UNGCPRO;
498 bestmatch = unbind_to (count, bestmatch);
499
500 if (all_flag || NILP (bestmatch))
501 return bestmatch;
502 if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
503 return Qt;
504 return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
505 quit:
506 if (d) closedir (d);
507 Vquit_flag = Qnil;
508 return Fsignal (Qquit, Qnil);
509 }
510
511 file_name_completion_stat (dirname, dp, st_addr)
512 Lisp_Object dirname;
513 DIRENTRY *dp;
514 struct stat *st_addr;
515 {
516 int len = NAMLEN (dp);
517 int pos = XSTRING (dirname)->size;
518 int value;
519 char *fullname = (char *) alloca (len + pos + 2);
520
521 #ifdef MSDOS
522 #if __DJGPP__ > 1
523 /* Some fields of struct stat are *very* expensive to compute on MS-DOS,
524 but aren't required here. Avoid computing the following fields:
525 st_inode, st_size and st_nlink for directories, and the execute bits
526 in st_mode for non-directory files with non-standard extensions. */
527
528 unsigned short save_djstat_flags = _djstat_flags;
529
530 _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
531 #endif /* __DJGPP__ > 1 */
532 #endif /* MSDOS */
533
534 bcopy (XSTRING (dirname)->data, fullname, pos);
535 #ifndef VMS
536 if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
537 fullname[pos++] = DIRECTORY_SEP;
538 #endif
539
540 bcopy (dp->d_name, fullname + pos, len);
541 fullname[pos + len] = 0;
542
543 #ifdef S_IFLNK
544 /* We want to return success if a link points to a nonexistent file,
545 but we want to return the status for what the link points to,
546 in case it is a directory. */
547 value = lstat (fullname, st_addr);
548 stat (fullname, st_addr);
549 return value;
550 #else
551 value = stat (fullname, st_addr);
552 #ifdef MSDOS
553 #if __DJGPP__ > 1
554 _djstat_flags = save_djstat_flags;
555 #endif /* __DJGPP__ > 1 */
556 #endif /* MSDOS */
557 return value;
558 #endif /* S_IFLNK */
559 }
560 \f
561 #ifdef VMS
562
563 DEFUN ("file-name-all-versions", Ffile_name_all_versions,
564 Sfile_name_all_versions, 2, 2, 0,
565 "Return a list of all versions of file name FILE in directory DIRECTORY.")
566 (file, directory)
567 Lisp_Object file, directory;
568 {
569 return file_name_completion (file, directory, 1, 1);
570 }
571
572 DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
573 "Return the maximum number of versions allowed for FILE.\n\
574 Returns nil if the file cannot be opened or if there is no version limit.")
575 (filename)
576 Lisp_Object filename;
577 {
578 Lisp_Object retval;
579 struct FAB fab;
580 struct RAB rab;
581 struct XABFHC xabfhc;
582 int status;
583
584 filename = Fexpand_file_name (filename, Qnil);
585 fab = cc$rms_fab;
586 xabfhc = cc$rms_xabfhc;
587 fab.fab$l_fna = XSTRING (filename)->data;
588 fab.fab$b_fns = strlen (fab.fab$l_fna);
589 fab.fab$l_xab = (char *) &xabfhc;
590 status = sys$open (&fab, 0, 0);
591 if (status != RMS$_NORMAL) /* Probably non-existent file */
592 return Qnil;
593 sys$close (&fab, 0, 0);
594 if (xabfhc.xab$w_verlimit == 32767)
595 return Qnil; /* No version limit */
596 else
597 return make_number (xabfhc.xab$w_verlimit);
598 }
599
600 #endif /* VMS */
601 \f
602 Lisp_Object
603 make_time (time)
604 int time;
605 {
606 return Fcons (make_number (time >> 16),
607 Fcons (make_number (time & 0177777), Qnil));
608 }
609
610 DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
611 "Return a list of attributes of file FILENAME.\n\
612 Value is nil if specified file cannot be opened.\n\
613 Otherwise, list elements are:\n\
614 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
615 1. Number of links to file.\n\
616 2. File uid.\n\
617 3. File gid.\n\
618 4. Last access time, as a list of two integers.\n\
619 First integer has high-order 16 bits of time, second has low 16 bits.\n\
620 5. Last modification time, likewise.\n\
621 6. Last status change time, likewise.\n\
622 7. Size in bytes (-1, if number is out of range).\n\
623 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
624 9. t iff file's gid would change if file were deleted and recreated.\n\
625 10. inode number.\n\
626 11. Device number.\n\
627 \n\
628 If file does not exist, returns nil.")
629 (filename)
630 Lisp_Object filename;
631 {
632 Lisp_Object values[12];
633 Lisp_Object dirname;
634 struct stat s;
635 struct stat sdir;
636 char modes[10];
637 Lisp_Object handler;
638
639 filename = Fexpand_file_name (filename, Qnil);
640
641 /* If the file name has special constructs in it,
642 call the corresponding file handler. */
643 handler = Ffind_file_name_handler (filename, Qfile_attributes);
644 if (!NILP (handler))
645 return call2 (handler, Qfile_attributes, filename);
646
647 if (lstat (XSTRING (filename)->data, &s) < 0)
648 return Qnil;
649
650 switch (s.st_mode & S_IFMT)
651 {
652 default:
653 values[0] = Qnil; break;
654 case S_IFDIR:
655 values[0] = Qt; break;
656 #ifdef S_IFLNK
657 case S_IFLNK:
658 values[0] = Ffile_symlink_p (filename); break;
659 #endif
660 }
661 values[1] = make_number (s.st_nlink);
662 values[2] = make_number (s.st_uid);
663 values[3] = make_number (s.st_gid);
664 values[4] = make_time (s.st_atime);
665 values[5] = make_time (s.st_mtime);
666 values[6] = make_time (s.st_ctime);
667 values[7] = make_number ((int) s.st_size);
668 /* If the size is out of range, give back -1. */
669 if (XINT (values[7]) != s.st_size)
670 XSETINT (values[7], -1);
671 filemodestring (&s, modes);
672 values[8] = make_string (modes, 10);
673 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
674 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */
675 #endif
676 #ifdef BSD4_2 /* file gid will be dir gid */
677 dirname = Ffile_name_directory (filename);
678 if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0)
679 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
680 else /* if we can't tell, assume worst */
681 values[9] = Qt;
682 #else /* file gid will be egid */
683 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
684 #endif /* BSD4_2 (or BSD4_3) */
685 #ifdef BSD4_3
686 #undef BSD4_2 /* ok, you can look again without throwing up */
687 #endif
688 if (s.st_ino & ((-1) << VALBITS))
689 /* To allow inode numbers larger than VALBITS, separate the bottom
690 16 bits. */
691 values[10] = Fcons (make_number (s.st_ino >> 16),
692 make_number (s.st_ino & 0xffff));
693 else
694 /* But keep the most common cases as integers. */
695 values[10] = make_number (s.st_ino);
696 values[11] = make_number (s.st_dev);
697 return Flist (sizeof(values) / sizeof(values[0]), values);
698 }
699 \f
700 syms_of_dired ()
701 {
702 Qdirectory_files = intern ("directory-files");
703 Qfile_name_completion = intern ("file-name-completion");
704 Qfile_name_all_completions = intern ("file-name-all-completions");
705 Qfile_attributes = intern ("file-attributes");
706
707 staticpro (&Qdirectory_files);
708 staticpro (&Qfile_name_completion);
709 staticpro (&Qfile_name_all_completions);
710 staticpro (&Qfile_attributes);
711
712 defsubr (&Sdirectory_files);
713 defsubr (&Sfile_name_completion);
714 #ifdef VMS
715 defsubr (&Sfile_name_all_versions);
716 defsubr (&Sfile_version_limit);
717 #endif /* VMS */
718 defsubr (&Sfile_name_all_completions);
719 defsubr (&Sfile_attributes);
720
721 #ifdef VMS
722 Qcompletion_ignore_case = intern ("completion-ignore-case");
723 staticpro (&Qcompletion_ignore_case);
724 #endif /* VMS */
725
726 DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
727 "*Completion ignores filenames ending in any string in this list.\n\
728 This variable does not affect lists of possible completions,\n\
729 but does affect the commands that actually do completions.");
730 Vcompletion_ignored_extensions = Qnil;
731 }