This source file includes following definitions.
- dirent_namelen
- dirent_type
- open_directory
- directory_files_internal_w32_unwind
- directory_files_internal_unwind
- read_dirent
- directory_files_internal
- file_name_completion
- scmp
- file_name_completion_dirp
- stat_uname
- stat_gname
- file_attributes
- DEFUN
- DEFUN
- syms_of_dired
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include <sys/stat.h>
24
25 #ifdef HAVE_PWD_H
26 #include <pwd.h>
27 #endif
28 #include <grp.h>
29
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include <dirent.h>
35 #include <filemode.h>
36 #include <stat-time.h>
37
38 #include "lisp.h"
39 #include "systime.h"
40 #include "buffer.h"
41 #include "coding.h"
42
43 #ifdef MSDOS
44 #include "msdos.h"
45 #endif
46
47 #ifdef WINDOWSNT
48 extern int is_slow_fs (const char *);
49 #endif
50
51 static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
52 static Lisp_Object file_attributes (int, char const *, Lisp_Object,
53 Lisp_Object, Lisp_Object);
54
55
56 static ptrdiff_t
57 dirent_namelen (struct dirent *dp)
58 {
59 #ifdef _D_EXACT_NAMLEN
60 return _D_EXACT_NAMLEN (dp);
61 #else
62 return strlen (dp->d_name);
63 #endif
64 }
65
66 #ifndef HAVE_STRUCT_DIRENT_D_TYPE
67 enum { DT_UNKNOWN, DT_DIR, DT_LNK };
68 #endif
69
70
71 static int
72 dirent_type (struct dirent *dp)
73 {
74 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
75 return dp->d_type;
76 #else
77 return DT_UNKNOWN;
78 #endif
79 }
80
81 static DIR *
82 open_directory (Lisp_Object dirname, Lisp_Object encoded_dirname, int *fdp)
83 {
84 char *name = SSDATA (encoded_dirname);
85 DIR *d;
86 int fd, opendir_errno;
87
88 #ifdef DOS_NT
89
90
91
92 fd = 0;
93 d = opendir (name);
94 opendir_errno = errno;
95 #else
96 fd = emacs_open (name, O_RDONLY | O_DIRECTORY, 0);
97 if (fd < 0)
98 {
99 opendir_errno = errno;
100 d = 0;
101 }
102 else
103 {
104 d = fdopendir (fd);
105 opendir_errno = errno;
106 if (! d)
107 emacs_close (fd);
108 }
109 #endif
110
111 if (!d)
112 report_file_errno ("Opening directory", dirname, opendir_errno);
113 *fdp = fd;
114 return d;
115 }
116
117 #ifdef WINDOWSNT
118 static void
119 directory_files_internal_w32_unwind (Lisp_Object arg)
120 {
121 Vw32_get_true_file_attributes = arg;
122 }
123 #endif
124
125 static void
126 directory_files_internal_unwind (void *d)
127 {
128 closedir (d);
129 }
130
131
132
133
134
135 static struct dirent *
136 read_dirent (DIR *dir, Lisp_Object dirname)
137 {
138 while (true)
139 {
140 errno = 0;
141 struct dirent *dp = readdir (dir);
142 if (dp || errno == 0)
143 return dp;
144 if (! (errno == EAGAIN || errno == EINTR))
145 {
146 #ifdef WINDOWSNT
147
148
149
150
151 if (errno == ENOENT || errno == EACCES)
152 report_file_error ("Opening directory", dirname);
153 #endif
154 report_file_error ("Reading directory", dirname);
155 }
156 maybe_quit ();
157 }
158 }
159
160
161
162
163
164
165 Lisp_Object
166 directory_files_internal (Lisp_Object directory, Lisp_Object full,
167 Lisp_Object match, Lisp_Object nosort, bool attrs,
168 Lisp_Object id_format, Lisp_Object return_count)
169 {
170 EMACS_INT ind = 0, last = MOST_POSITIVE_FIXNUM;
171
172 if (!NILP (return_count))
173 {
174 CHECK_FIXNAT (return_count);
175 last = XFIXNAT (return_count);
176 }
177
178 if (!NILP (match))
179 CHECK_STRING (match);
180
181
182
183 Lisp_Object volatile directory_volatile = directory;
184
185 Lisp_Object dirfilename = Fdirectory_file_name (directory);
186
187
188
189
190 Lisp_Object encoded_dirfilename = ENCODE_FILE (dirfilename);
191
192 int fd;
193 DIR *d = open_directory (dirfilename, encoded_dirfilename, &fd);
194
195
196
197
198 specpdl_ref count = SPECPDL_INDEX ();
199 record_unwind_protect_ptr (directory_files_internal_unwind, d);
200
201 #ifdef WINDOWSNT
202 Lisp_Object w32_save = Qnil;
203 if (attrs)
204 {
205
206
207 record_unwind_protect (directory_files_internal_w32_unwind,
208 Vw32_get_true_file_attributes);
209 w32_save = Vw32_get_true_file_attributes;
210 if (EQ (Vw32_get_true_file_attributes, Qlocal))
211 {
212
213
214 if (is_slow_fs (SSDATA (encoded_dirfilename)))
215 Vw32_get_true_file_attributes = Qnil;
216 else
217 Vw32_get_true_file_attributes = Qt;
218 }
219 }
220 #endif
221
222 if (!NILP (full) && !STRING_MULTIBYTE (directory))
223 {
224
225
226 directory = DECODE_FILE (directory);
227 }
228
229 ptrdiff_t directory_nbytes = SBYTES (directory);
230 re_match_object = Qt;
231
232
233 bool needsep = (directory_nbytes == 0
234 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)));
235
236
237 Lisp_Object case_table = Qnil;
238 #ifdef WINDOWSNT
239 case_table = BVAR (&buffer_defaults, case_canon_table);
240 #endif
241
242
243 Lisp_Object list = Qnil;
244 for (struct dirent *dp; (dp = read_dirent (d, directory)); )
245 {
246 ptrdiff_t len = dirent_namelen (dp);
247 Lisp_Object name = make_unibyte_string (dp->d_name, len);
248 Lisp_Object finalname = name;
249
250
251 name = DECODE_FILE (name);
252
253 maybe_quit ();
254
255 if (!NILP (match)
256 && fast_string_match_internal (match, name, case_table) < 0)
257 continue;
258
259 Lisp_Object fileattrs UNINIT;
260 if (attrs)
261 {
262 fileattrs = file_attributes (fd, dp->d_name, directory, name,
263 id_format);
264 if (NILP (fileattrs))
265 continue;
266 }
267
268 if (!NILP (full))
269 {
270 ptrdiff_t name_nbytes = SBYTES (name);
271 ptrdiff_t nbytes = directory_nbytes + needsep + name_nbytes;
272 ptrdiff_t nchars = SCHARS (directory) + needsep + SCHARS (name);
273
274
275
276
277
278
279
280
281
282
283
284 finalname = (nchars == nbytes)
285 ? make_uninit_string (nbytes)
286 : make_uninit_multibyte_string (nchars, nbytes);
287 memcpy (SDATA (finalname), SDATA (directory), directory_nbytes);
288 if (needsep)
289 SSET (finalname, directory_nbytes, DIRECTORY_SEP);
290 memcpy (SDATA (finalname) + directory_nbytes + needsep,
291 SDATA (name), name_nbytes);
292 }
293 else
294 finalname = name;
295
296 if (ind == last)
297 break;
298 ind ++;
299
300 list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
301 }
302
303 closedir (d);
304 #ifdef WINDOWSNT
305 if (attrs)
306 Vw32_get_true_file_attributes = w32_save;
307 #endif
308
309
310 specpdl_ptr = specpdl_ref_to_ptr (count);
311
312 if (NILP (nosort))
313 list = Fsort (Fnreverse (list),
314 attrs ? Qfile_attributes_lessp : Qstring_lessp);
315
316 (void) directory_volatile;
317 return list;
318 }
319
320
321 DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
322 doc:
323
324
325
326
327
328
329
330
331
332 )
333 (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
334 Lisp_Object nosort, Lisp_Object count)
335 {
336 directory = Fexpand_file_name (directory, Qnil);
337
338
339
340 Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
341 if (!NILP (handler))
342 return call6 (handler, Qdirectory_files, directory,
343 full, match, nosort, count);
344
345 return directory_files_internal (directory, full, match, nosort,
346 false, Qnil, count);
347 }
348
349 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
350 Sdirectory_files_and_attributes, 1, 6, 0,
351 doc:
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371 )
372 (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
373 Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
374 {
375 directory = Fexpand_file_name (directory, Qnil);
376
377
378
379 Lisp_Object handler
380 = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
381 if (!NILP (handler))
382 return call7 (handler, Qdirectory_files_and_attributes,
383 directory, full, match, nosort, id_format, count);
384
385 return directory_files_internal (directory, full, match, nosort,
386 true, id_format, count);
387 }
388
389
390 static Lisp_Object file_name_completion (Lisp_Object, Lisp_Object, bool,
391 Lisp_Object);
392
393 DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
394 2, 3, 0,
395 doc:
396
397
398
399
400
401
402
403
404
405
406
407 )
408 (Lisp_Object file, Lisp_Object directory, Lisp_Object predicate)
409 {
410 Lisp_Object handler;
411 directory = Fexpand_file_name (directory, Qnil);
412
413
414
415 handler = Ffind_file_name_handler (directory, Qfile_name_completion);
416 if (!NILP (handler))
417 return call4 (handler, Qfile_name_completion, file, directory, predicate);
418
419
420
421 handler = Ffind_file_name_handler (file, Qfile_name_completion);
422 if (!NILP (handler))
423 return call4 (handler, Qfile_name_completion, file, directory, predicate);
424
425 return file_name_completion (file, directory, 0, predicate);
426 }
427
428 DEFUN ("file-name-all-completions", Ffile_name_all_completions,
429 Sfile_name_all_completions, 2, 2, 0,
430 doc:
431
432
433
434
435 )
436 (Lisp_Object file, Lisp_Object directory)
437 {
438 Lisp_Object handler;
439 directory = Fexpand_file_name (directory, Qnil);
440
441
442
443 handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
444 if (!NILP (handler))
445 return call3 (handler, Qfile_name_all_completions, file, directory);
446
447
448
449 handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
450 if (!NILP (handler))
451 return call3 (handler, Qfile_name_all_completions, file, directory);
452
453 return file_name_completion (file, directory, 1, Qnil);
454 }
455
456 static bool file_name_completion_dirp (int, struct dirent *, ptrdiff_t);
457
458 static Lisp_Object
459 file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
460 Lisp_Object predicate)
461 {
462 ptrdiff_t bestmatchsize = 0;
463 int matchcount = 0;
464
465
466
467 Lisp_Object bestmatch, tem, elt, name;
468 Lisp_Object encoded_file;
469 Lisp_Object encoded_dir;
470 bool directoryp;
471
472
473
474 bool includeall = 1;
475 bool check_decoded = false;
476 specpdl_ref count = SPECPDL_INDEX ();
477
478 elt = Qnil;
479
480 CHECK_STRING (file);
481
482 bestmatch = Qnil;
483 encoded_file = encoded_dir = Qnil;
484 specbind (Qdefault_directory, dirname);
485
486
487
488
489
490
491
492 encoded_file = ENCODE_FILE (file);
493 encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname));
494
495 Lisp_Object file_encoding = Vfile_name_coding_system;
496 if (NILP (Vfile_name_coding_system))
497 file_encoding = Vdefault_file_name_coding_system;
498
499
500
501
502 if (!NILP (file_encoding)
503 && !NILP (plist_get (Fcoding_system_plist (file_encoding),
504 Qdecomposed_characters)))
505 {
506 check_decoded = true;
507 if (STRING_MULTIBYTE (file))
508 {
509
510
511
512
513 file = DECODE_FILE (encoded_file);
514 }
515 }
516 int fd;
517 DIR *d = open_directory (dirname, encoded_dir, &fd);
518 record_unwind_protect_ptr (directory_files_internal_unwind, d);
519
520
521 Lisp_Object zero = make_fixnum (0);
522 ptrdiff_t enc_file_len = SCHARS (encoded_file);
523 Lisp_Object file_len = make_fixnum (SCHARS (file));
524 for (struct dirent *dp; (dp = read_dirent (d, dirname)); )
525 {
526 ptrdiff_t len = dirent_namelen (dp);
527 bool canexclude = 0;
528
529 maybe_quit ();
530
531 if (len < enc_file_len
532
533
534 || (!completion_ignore_case
535 && scmp (dp->d_name, SSDATA (encoded_file), enc_file_len) >= 0))
536 continue;
537
538 name = make_unibyte_string (dp->d_name, len);
539 name = DECODE_FILE (name);
540 ptrdiff_t name_blen = SBYTES (name), name_len = SCHARS (name);
541 if (completion_ignore_case
542 && !BASE_EQ (Fcompare_strings (name, zero, file_len, file, zero,
543 file_len, Qt),
544 Qt))
545 continue;
546
547 switch (dirent_type (dp))
548 {
549 case DT_DIR:
550 directoryp = true;
551 break;
552
553 case DT_LNK: case DT_UNKNOWN:
554 directoryp = file_name_completion_dirp (fd, dp, len);
555 break;
556
557 default:
558 directoryp = false;
559 break;
560 }
561
562 tem = Qnil;
563
564
565
566 if (!all_flag)
567 {
568 ptrdiff_t skip;
569 Lisp_Object cmp_len = make_fixnum (name_len);
570
571 #if 0
572
573
574
575 if (!completion_ignore_case
576
577 && matchcount > 1
578 && !includeall
579 && len >= bestmatchsize
580 && 0 > scmp (dp->d_name, SSDATA (bestmatch), bestmatchsize))
581 continue;
582 #endif
583
584 if (directoryp)
585 {
586 #ifndef TRIVIAL_DIRECTORY_ENTRY
587 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
588 #endif
589
590
591 if (TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
592 canexclude = 1;
593 else if (len > enc_file_len)
594
595
596 for (tem = Vcompletion_ignored_extensions;
597 CONSP (tem); tem = XCDR (tem))
598 {
599 ptrdiff_t elt_len;
600 char *p1;
601
602 elt = XCAR (tem);
603 if (!STRINGP (elt))
604 continue;
605 elt_len = SBYTES (elt) - 1;
606 if (elt_len <= 0)
607 continue;
608 p1 = SSDATA (elt);
609 if (p1[elt_len] != '/')
610 continue;
611 skip = name_blen - elt_len;
612 if (skip < 0)
613 continue;
614
615 if (!completion_ignore_case
616 && scmp (SSDATA (name) + skip, p1, elt_len) >= 0)
617 continue;
618 if (completion_ignore_case)
619 {
620 elt_len = SCHARS (elt) - 1;
621 skip = name_len - elt_len;
622 cmp_len = make_fixnum (elt_len);
623 if (skip < 0
624 || !BASE_EQ (Fcompare_strings (name,
625 make_fixnum (skip),
626 Qnil,
627 elt, zero, cmp_len,
628 Qt),
629 Qt))
630 continue;
631 }
632 break;
633 }
634 }
635 else
636 {
637
638
639 if (len > enc_file_len)
640
641 for (tem = Vcompletion_ignored_extensions;
642 CONSP (tem); tem = XCDR (tem))
643 {
644 elt = XCAR (tem);
645 if (!STRINGP (elt)) continue;
646 ptrdiff_t elt_len = SBYTES (elt);
647 skip = len - elt_len;
648 if (skip < 0) continue;
649
650 if (!completion_ignore_case
651 && (scmp (SSDATA (name) + skip, SSDATA (elt), elt_len)
652 >= 0))
653 continue;
654 if (completion_ignore_case)
655 {
656 elt_len = SCHARS (elt);
657 skip = name_len - elt_len;
658 cmp_len = make_fixnum (elt_len);
659 if (skip < 0
660 || !BASE_EQ (Fcompare_strings (name,
661 make_fixnum (skip),
662 Qnil,
663 elt, zero, cmp_len,
664 Qt),
665 Qt))
666 continue;
667 }
668 break;
669 }
670 }
671
672
673
674 if (CONSP (tem))
675 canexclude = 1;
676
677 if (!includeall && canexclude)
678
679 continue;
680
681 if (includeall && !canexclude)
682 {
683
684 includeall = 0;
685
686 bestmatch = Qnil;
687 bestmatchsize = 0;
688 matchcount = 0;
689 }
690 }
691
692 Lisp_Object regexps, table = (completion_ignore_case
693 ? Vascii_canon_table : Qnil);
694
695
696 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
697 regexps = XCDR (regexps))
698 if (fast_string_match_internal (XCAR (regexps), name, table) < 0)
699 break;
700
701 if (CONSP (regexps))
702 continue;
703
704
705 if (directoryp)
706
707 name = Ffile_name_as_directory (name);
708
709
710 if (!NILP (predicate) && NILP (call1 (predicate, name)))
711 continue;
712
713
714
715
716 if (check_decoded && SCHARS (file) <= SCHARS (name))
717 {
718
719 ptrdiff_t compare = SCHARS (file);
720 Lisp_Object cmp
721 = Fcompare_strings (name, zero, make_fixnum (compare),
722 file, zero, make_fixnum (compare),
723 completion_ignore_case ? Qt : Qnil);
724 if (!BASE_EQ (cmp, Qt))
725 continue;
726 }
727
728
729
730 matchcount += matchcount <= 1;
731
732 if (all_flag)
733 bestmatch = Fcons (name, bestmatch);
734 else if (NILP (bestmatch))
735 {
736 bestmatch = name;
737 bestmatchsize = SCHARS (name);
738 }
739 else
740 {
741
742 ptrdiff_t compare = min (bestmatchsize, SCHARS (name));
743 Lisp_Object cmp
744 = Fcompare_strings (bestmatch, zero, make_fixnum (compare),
745 name, zero, make_fixnum (compare),
746 completion_ignore_case ? Qt : Qnil);
747 ptrdiff_t matchsize = BASE_EQ (cmp, Qt)
748 ? compare : eabs (XFIXNUM (cmp)) - 1;
749
750 if (completion_ignore_case)
751 {
752
753
754
755
756
757
758 if ((matchsize == SCHARS (name)
759 && matchsize + directoryp < SCHARS (bestmatch))
760 ||
761
762
763
764
765
766
767
768
769 (((matchsize == SCHARS (name))
770 ==
771 (matchsize + directoryp == SCHARS (bestmatch)))
772 && (cmp = Fcompare_strings (name, zero,
773 make_fixnum (SCHARS (file)),
774 file, zero,
775 Qnil,
776 Qnil),
777 BASE_EQ (Qt, cmp))
778 && (cmp = Fcompare_strings (bestmatch, zero,
779 make_fixnum (SCHARS (file)),
780 file, zero,
781 Qnil,
782 Qnil),
783 ! BASE_EQ (Qt, cmp))))
784 bestmatch = name;
785 }
786 bestmatchsize = matchsize;
787
788
789
790
791 if (matchsize <= SCHARS (file)
792 && !includeall
793
794
795
796 && (!completion_ignore_case || matchsize == 0)
797
798 && matchcount > 1)
799 break;
800
801 }
802 }
803
804
805 bestmatch = unbind_to (count, bestmatch);
806
807 if (all_flag || NILP (bestmatch))
808 return bestmatch;
809
810
811 if (matchcount == 1 && !NILP (Fequal (bestmatch, file)))
812 return Qt;
813 bestmatch = Fsubstring (bestmatch, make_fixnum (0),
814 make_fixnum (bestmatchsize));
815 return bestmatch;
816 }
817
818
819
820
821
822
823 static ptrdiff_t
824 scmp (const char *s1, const char *s2, ptrdiff_t len)
825 {
826 register ptrdiff_t l = len;
827
828 if (completion_ignore_case)
829 {
830
831
832
833 while (l
834 && (downcase ((unsigned char) *s1++)
835 == downcase ((unsigned char) *s2++)))
836 l--;
837 }
838 else
839 {
840 while (l && *s1++ == *s2++)
841 l--;
842 }
843 if (l == 0)
844 return -1;
845 else
846 return len - l;
847 }
848
849
850
851 static bool
852 file_name_completion_dirp (int fd, struct dirent *dp, ptrdiff_t len)
853 {
854 USE_SAFE_ALLOCA;
855 char *subdir_name = SAFE_ALLOCA (len + 2);
856 memcpy (subdir_name, dp->d_name, len);
857 strcpy (subdir_name + len, "/");
858 bool dirp = faccessat (fd, subdir_name, F_OK, AT_EACCESS) == 0;
859 SAFE_FREE ();
860 return dirp;
861 }
862
863 static char *
864 stat_uname (struct stat *st)
865 {
866 #ifdef WINDOWSNT
867 return st->st_uname;
868 #else
869 struct passwd *pw = getpwuid (st->st_uid);
870
871 if (pw)
872 return pw->pw_name;
873 else
874 return NULL;
875 #endif
876 }
877
878 static char *
879 stat_gname (struct stat *st)
880 {
881 #ifdef WINDOWSNT
882 return st->st_gname;
883 #else
884 struct group *gr = getgrgid (st->st_gid);
885
886 if (gr)
887 return gr->gr_name;
888 else
889 return NULL;
890 #endif
891 }
892
893 DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0,
894 doc:
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937 )
938 (Lisp_Object filename, Lisp_Object id_format)
939 {
940 Lisp_Object encoded;
941 Lisp_Object handler;
942
943 filename = internal_condition_case_2 (Fexpand_file_name, filename, Qnil,
944 Qt, Fidentity);
945 if (!STRINGP (filename))
946 return Qnil;
947
948
949
950 handler = Ffind_file_name_handler (filename, Qfile_attributes);
951 if (!NILP (handler))
952 {
953
954
955 if (NILP (id_format))
956 return call2 (handler, Qfile_attributes, filename);
957 else
958 return call3 (handler, Qfile_attributes, filename, id_format);
959 }
960
961 encoded = ENCODE_FILE (filename);
962 return file_attributes (AT_FDCWD, SSDATA (encoded), Qnil, filename,
963 id_format);
964 }
965
966 static Lisp_Object
967 file_attributes (int fd, char const *name,
968 Lisp_Object dirname, Lisp_Object filename,
969 Lisp_Object id_format)
970 {
971 specpdl_ref count = SPECPDL_INDEX ();
972 struct stat s;
973
974
975
976 char modes[sizeof "-rwxr-xr-x "];
977
978 char *uname = NULL, *gname = NULL;
979
980 int err = EINVAL;
981
982 #if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG
983 int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0);
984 if (namefd < 0)
985 err = errno;
986 else
987 {
988 record_unwind_protect_int (close_file_unwind, namefd);
989 if (fstat (namefd, &s) != 0)
990 {
991 err = errno;
992
993
994
995 if (err == EBADF)
996 err = EINVAL;
997 }
998 else
999 {
1000 err = 0;
1001 fd = namefd;
1002 name = "";
1003 }
1004 }
1005 #endif
1006
1007 if (err == EINVAL)
1008 {
1009 #ifdef WINDOWSNT
1010
1011
1012
1013
1014 w32_stat_get_owner_group = 1;
1015 #endif
1016 err = emacs_fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
1017 #ifdef WINDOWSNT
1018 w32_stat_get_owner_group = 0;
1019 #endif
1020 }
1021
1022 if (err != 0)
1023 return unbind_to (count, file_attribute_errno (filename, err));
1024
1025 Lisp_Object file_type;
1026 if (S_ISLNK (s.st_mode))
1027 {
1028
1029
1030
1031
1032 file_type = check_emacs_readlinkat (fd, filename, name);
1033 if (NILP (file_type))
1034 return unbind_to (count, Qnil);
1035 }
1036 else
1037 file_type = S_ISDIR (s.st_mode) ? Qt : Qnil;
1038
1039 unbind_to (count, Qnil);
1040
1041 if (!(NILP (id_format) || EQ (id_format, Qinteger)))
1042 {
1043 uname = stat_uname (&s);
1044 gname = stat_gname (&s);
1045 }
1046
1047 filemodestring (&s, modes);
1048
1049 return CALLN (Flist,
1050 file_type,
1051 make_fixnum (s.st_nlink),
1052 (uname
1053 ? DECODE_SYSTEM (build_unibyte_string (uname))
1054 : INT_TO_INTEGER (s.st_uid)),
1055 (gname
1056 ? DECODE_SYSTEM (build_unibyte_string (gname))
1057 : INT_TO_INTEGER (s.st_gid)),
1058 make_lisp_time (get_stat_atime (&s)),
1059 make_lisp_time (get_stat_mtime (&s)),
1060 make_lisp_time (get_stat_ctime (&s)),
1061
1062
1063
1064
1065
1066 INT_TO_INTEGER (sizeof (s.st_size) == 4
1067 ? s.st_size & 0xffffffffu
1068 : s.st_size),
1069
1070 make_string (modes, 10),
1071 Qt,
1072 INT_TO_INTEGER (s.st_ino),
1073 INT_TO_INTEGER (s.st_dev));
1074 }
1075
1076 DEFUN ("file-attributes-lessp", Ffile_attributes_lessp,
1077 Sfile_attributes_lessp, 2, 2, 0,
1078 doc:
1079 )
1080 (Lisp_Object f1, Lisp_Object f2)
1081 {
1082 return Fstring_lessp (Fcar (f1), Fcar (f2));
1083 }
1084
1085
1086 DEFUN ("system-users", Fsystem_users, Ssystem_users, 0, 0, 0,
1087 doc:
1088
1089 )
1090 (void)
1091 {
1092 Lisp_Object users = Qnil;
1093 #if defined HAVE_GETPWENT && defined HAVE_ENDPWENT
1094 struct passwd *pw;
1095
1096 while ((pw = getpwent ()))
1097 users = Fcons (DECODE_SYSTEM (build_string (pw->pw_name)), users);
1098
1099 endpwent ();
1100 #endif
1101 if (NILP (users))
1102
1103 users = list1 (Vuser_real_login_name);
1104 return users;
1105 }
1106
1107 DEFUN ("system-groups", Fsystem_groups, Ssystem_groups, 0, 0, 0,
1108 doc:
1109 )
1110 (void)
1111 {
1112 Lisp_Object groups = Qnil;
1113 #if defined HAVE_GETGRENT && defined HAVE_ENDGRENT
1114 struct group *gr;
1115
1116 while ((gr = getgrent ()))
1117 groups = Fcons (DECODE_SYSTEM (build_string (gr->gr_name)), groups);
1118
1119 endgrent ();
1120 #endif
1121 return groups;
1122 }
1123
1124 void
1125 syms_of_dired (void)
1126 {
1127 DEFSYM (Qdirectory_files, "directory-files");
1128 DEFSYM (Qdirectory_files_and_attributes, "directory-files-and-attributes");
1129 DEFSYM (Qfile_name_completion, "file-name-completion");
1130 DEFSYM (Qfile_name_all_completions, "file-name-all-completions");
1131 DEFSYM (Qfile_attributes, "file-attributes");
1132 DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp");
1133 DEFSYM (Qdefault_directory, "default-directory");
1134 DEFSYM (Qdecomposed_characters, "decomposed-characters");
1135
1136 defsubr (&Sdirectory_files);
1137 defsubr (&Sdirectory_files_and_attributes);
1138 defsubr (&Sfile_name_completion);
1139 defsubr (&Sfile_name_all_completions);
1140 defsubr (&Sfile_attributes);
1141 defsubr (&Sfile_attributes_lessp);
1142 defsubr (&Ssystem_users);
1143 defsubr (&Ssystem_groups);
1144
1145 DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
1146 doc:
1147
1148
1149
1150 );
1151 Vcompletion_ignored_extensions = Qnil;
1152 }