1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <config.h>
24:
25: #include <stdio.h>
26: #include <sys/types.h>
27: #include <sys/stat.h>
28:
29: #ifdef HAVE_PWD_H
30: #include <pwd.h>
31: #endif
32: #ifndef VMS
33: #include <grp.h>
34: #endif
35:
36: #include <errno.h>
37:
38: #ifdef VMS
39: #include <string.h>
40: #include <rms.h>
41: #include <rmsdef.h>
42: #endif
43:
44: #ifdef HAVE_UNISTD_H
45: #include <unistd.h>
46: #endif
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58: #define NAMLEN(p) strlen (p->d_name)
59:
60: #ifdef SYSV_SYSTEM_DIR
61:
62: #include <dirent.h>
63: #define DIRENTRY struct dirent
64:
65: #else
66:
67: #ifdef NONSYSTEM_DIR_LIBRARY
68: #include "ndir.h"
69: #else
70: #ifdef MSDOS
71: #include <dirent.h>
72: #else
73: #include <sys/dir.h>
74: #endif
75: #endif
76:
77: #include <sys/stat.h>
78:
79: #ifndef MSDOS
80: #define DIRENTRY struct direct
81:
82: extern DIR *opendir ();
83: extern struct direct *readdir ();
84:
85: #endif
86: #endif
87:
88:
89: #if defined(MSDOS) || defined(__CYGWIN__)
90: #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
91: #else
92: #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
93: #endif
94:
95: #include "lisp.h"
96: #include "systime.h"
97: #include "buffer.h"
98: #include "commands.h"
99: #include "charset.h"
100: #include "coding.h"
101: #include "regex.h"
102: #include "blockinput.h"
103:
104:
105: extern struct re_pattern_buffer *compile_pattern ();
106:
107:
108: extern void filemodestring P_ ((struct stat *, char *));
109:
110:
111:
112:
113: #ifndef S_IFLNK
114: #define lstat stat
115: #endif
116:
117: extern int completion_ignore_case;
118: extern Lisp_Object Vcompletion_regexp_list;
119:
120: Lisp_Object Vcompletion_ignored_extensions;
121: Lisp_Object Qcompletion_ignore_case;
122: Lisp_Object Qdirectory_files;
123: Lisp_Object Qdirectory_files_and_attributes;
124: Lisp_Object Qfile_name_completion;
125: Lisp_Object Qfile_name_all_completions;
126: Lisp_Object Qfile_attributes;
127: Lisp_Object Qfile_attributes_lessp;
128:
129: static int scmp P_ ((unsigned char *, unsigned char *, int));
130: ^L
131:
132: Lisp_Object
133: directory_files_internal_unwind (dh)
134: Lisp_Object dh;
135: {
136: DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer;
137: BLOCK_INPUT;
138: closedir (d);
139: UNBLOCK_INPUT;
140: return Qnil;
141: }
142:
143:
144:
145:
146:
147:
148: Lisp_Object
149: directory_files_internal (directory, full, match, nosort, attrs, id_format)
150: Lisp_Object directory, full, match, nosort;
151: int attrs;
152: Lisp_Object id_format;
153: {
154: DIR *d;
155: int directory_nbytes;
156: Lisp_Object list, dirfilename, encoded_directory;
157: struct re_pattern_buffer *bufp = NULL;
158: int needsep = 0;
159: int count = SPECPDL_INDEX ();
160: struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
161: DIRENTRY *dp;
162:
163:
164:
165: list = encoded_directory = dirfilename = Qnil;
166: GCPRO5 (match, directory, list, dirfilename, encoded_directory);
167: dirfilename = Fdirectory_file_name (directory);
168:
169: if (!NILP (match))
170: {
171: CHECK_STRING (match);
172:
173:
174:
175:
176:
177:
178: #ifdef VMS
179: bufp = compile_pattern (match, 0,
180: buffer_defaults.downcase_table, 0, 1);
181: #else
182: # ifdef WINDOWSNT
183:
184: bufp = compile_pattern (match, 0,
185: buffer_defaults.case_canon_table, 0, 1);
186: # else
187: bufp = compile_pattern (match, 0, Qnil, 0, 1);
188: # endif
189: #endif
190: }
191:
192:
193:
194:
195: dirfilename = ENCODE_FILE (dirfilename);
196: encoded_directory = ENCODE_FILE (directory);
197:
198:
199:
200:
201: BLOCK_INPUT;
202: d = opendir (SDATA (dirfilename));
203: UNBLOCK_INPUT;
204: if (d == NULL)
205: report_file_error ("Opening directory", Fcons (directory, Qnil));
206:
207:
208:
209:
210: record_unwind_protect (directory_files_internal_unwind,
211: make_save_value (d, 0));
212:
213: directory_nbytes = SBYTES (directory);
214: re_match_object = Qt;
215:
216:
217: #ifndef VMS
218: if (directory_nbytes == 0
219: || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
220: needsep = 1;
221: #endif
222:
223:
224: for (;;)
225: {
226: errno = 0;
227: dp = readdir (d);
228:
229: if (dp == NULL && (0
230: #ifdef EAGAIN
231: || errno == EAGAIN
232: #endif
233: #ifdef EINTR
234: || errno == EINTR
235: #endif
236: ))
237: { QUIT; continue; }
238:
239: if (dp == NULL)
240: break;
241:
242: if (DIRENTRY_NONEMPTY (dp))
243: {
244: int len;
245: int wanted = 0;
246: Lisp_Object name, finalname;
247: struct gcpro gcpro1, gcpro2;
248:
249: len = NAMLEN (dp);
250: name = finalname = make_unibyte_string (dp->d_name, len);
251: GCPRO2 (finalname, name);
252:
253:
254:
255: name = DECODE_FILE (name);
256: len = SBYTES (name);
257:
258:
259:
260: immediate_quit = 1;
261: QUIT;
262:
263: if (NILP (match)
264: || (0 <= re_search (bufp, SDATA (name), len, 0, len, 0)))
265: wanted = 1;
266:
267: immediate_quit = 0;
268:
269: if (wanted)
270: {
271: if (!NILP (full))
272: {
273: Lisp_Object fullname;
274: int nbytes = len + directory_nbytes + needsep;
275: int nchars;
276:
277: fullname = make_uninit_multibyte_string (nbytes, nbytes);
278: bcopy (SDATA (directory), SDATA (fullname),
279: directory_nbytes);
280:
281: if (needsep)
282: SSET (fullname, directory_nbytes, DIRECTORY_SEP);
283:
284: bcopy (SDATA (name),
285: SDATA (fullname) + directory_nbytes + needsep,
286: len);
287:
288: nchars = chars_in_text (SDATA (fullname), nbytes);
289:
290:
291: if (nchars > nbytes)
292: abort ();
293:
294: STRING_SET_CHARS (fullname, nchars);
295: if (nchars == nbytes)
296: STRING_SET_UNIBYTE (fullname);
297:
298: finalname = fullname;
299: }
300: else
301: finalname = name;
302:
303: if (attrs)
304: {
305:
306:
307: Lisp_Object decoded_fullname, fileattrs;
308: struct gcpro gcpro1, gcpro2;
309:
310: decoded_fullname = fileattrs = Qnil;
311: GCPRO2 (decoded_fullname, fileattrs);
312:
313:
314: decoded_fullname = Fexpand_file_name (name, directory);
315: fileattrs = Ffile_attributes (decoded_fullname, id_format);
316:
317: list = Fcons (Fcons (finalname, fileattrs), list);
318: UNGCPRO;
319: }
320: else
321: list = Fcons (finalname, list);
322: }
323:
324: UNGCPRO;
325: }
326: }
327:
328: BLOCK_INPUT;
329: closedir (d);
330: UNBLOCK_INPUT;
331:
332:
333: specpdl_ptr = specpdl + count;
334:
335: if (NILP (nosort))
336: list = Fsort (Fnreverse (list),
337: attrs ? Qfile_attributes_lessp : Qstring_lessp);
338:
339: RETURN_UNGCPRO (list);
340: }
341:
342:
343: DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
344: doc:
345:
346:
347:
348:
349:
350: )
351: (directory, full, match, nosort)
352: Lisp_Object directory, full, match, nosort;
353: {
354: Lisp_Object handler;
355: directory = Fexpand_file_name (directory, Qnil);
356:
357:
358:
359: handler = Ffind_file_name_handler (directory, Qdirectory_files);
360: if (!NILP (handler))
361: return call5 (handler, Qdirectory_files, directory,
362: full, match, nosort);
363:
364: return directory_files_internal (directory, full, match, nosort, 0, Qnil);
365: }
366:
367: DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
368: Sdirectory_files_and_attributes, 1, 5, 0,
369: doc:
370:
371:
372:
373:
374:
375:
376:
377: )
378: (directory, full, match, nosort, id_format)
379: Lisp_Object directory, full, match, nosort, id_format;
380: {
381: Lisp_Object handler;
382: directory = Fexpand_file_name (directory, Qnil);
383:
384:
385:
386: handler = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
387: if (!NILP (handler))
388: return call6 (handler, Qdirectory_files_and_attributes,
389: directory, full, match, nosort, id_format);
390:
391: return directory_files_internal (directory, full, match, nosort, 1, id_format);
392: }
393:
394: ^L
395: Lisp_Object file_name_completion ();
396:
397: DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
398: 2, 3, 0,
399: doc:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409: )
410: (file, directory, predicate)
411: Lisp_Object file, directory, predicate;
412: {
413: Lisp_Object handler;
414:
415:
416:
417: handler = Ffind_file_name_handler (directory, Qfile_name_completion);
418: if (!NILP (handler))
419: return call4 (handler, Qfile_name_completion, file, directory, predicate);
420:
421:
422:
423: handler = Ffind_file_name_handler (file, Qfile_name_completion);
424: if (!NILP (handler))
425: return call4 (handler, Qfile_name_completion, file, directory, predicate);
426:
427: return file_name_completion (file, directory, 0, 0, predicate);
428: }
429:
430: DEFUN ("file-name-all-completions", Ffile_name_all_completions,
431: Sfile_name_all_completions, 2, 2, 0,
432: doc:
433: )
434: (file, directory)
435: Lisp_Object file, directory;
436: {
437: Lisp_Object handler;
438:
439:
440:
441: handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
442: if (!NILP (handler))
443: return call3 (handler, Qfile_name_all_completions, file, directory);
444:
445:
446:
447: handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
448: if (!NILP (handler))
449: return call3 (handler, Qfile_name_all_completions, file, directory);
450:
451: return file_name_completion (file, directory, 1, 0, Qnil);
452: }
453:
454: static int file_name_completion_stat ();
455:
456: Lisp_Object
457: file_name_completion (file, dirname, all_flag, ver_flag, predicate)
458: Lisp_Object file, dirname;
459: int all_flag, ver_flag;
460: Lisp_Object predicate;
461: {
462: DIR *d;
463: int bestmatchsize = 0, skip;
464: register int compare, matchsize;
465: unsigned char *p1, *p2;
466: int matchcount = 0;
467:
468:
469:
470: Lisp_Object bestmatch, tem, elt, name;
471: Lisp_Object encoded_file;
472: Lisp_Object encoded_dir;
473: struct stat st;
474: int directoryp;
475: int passcount;
476: int count = SPECPDL_INDEX ();
477: struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
478:
479: elt = Qnil;
480:
481: #ifdef VMS
482: extern DIRENTRY * readdirver ();
483:
484: DIRENTRY *((* readfunc) ());
485:
486:
487: specbind (Qcompletion_ignore_case, Qt);
488:
489: readfunc = readdir;
490: if (ver_flag)
491: readfunc = readdirver;
492: file = Fupcase (file);
493: #else
494: CHECK_STRING (file);
495: #endif
496:
497: #ifdef FILE_SYSTEM_CASE
498: file = FILE_SYSTEM_CASE (file);
499: #endif
500: bestmatch = Qnil;
501: encoded_file = encoded_dir = Qnil;
502: GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir);
503: dirname = Fexpand_file_name (dirname, Qnil);
504:
505:
506:
507:
508: encoded_file = ENCODE_FILE (file);
509:
510: encoded_dir = ENCODE_FILE (dirname);
511:
512:
513:
514:
515:
516:
517:
518:
519:
520: for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
521: {
522: int inner_count = SPECPDL_INDEX ();
523:
524: BLOCK_INPUT;
525: d = opendir (SDATA (Fdirectory_file_name (encoded_dir)));
526: UNBLOCK_INPUT;
527: if (!d)
528: report_file_error ("Opening directory", Fcons (dirname, Qnil));
529:
530: record_unwind_protect (directory_files_internal_unwind,
531: make_save_value (d, 0));
532:
533:
534:
535: while (1)
536: {
537: DIRENTRY *dp;
538: int len;
539:
540: #ifdef VMS
541: dp = (*readfunc) (d);
542: #else
543: errno = 0;
544: dp = readdir (d);
545: if (dp == NULL && (0
546: # ifdef EAGAIN
547: || errno == EAGAIN
548: # endif
549: # ifdef EINTR
550: || errno == EINTR
551: # endif
552: ))
553: { QUIT; continue; }
554: #endif
555:
556: if (!dp) break;
557:
558: len = NAMLEN (dp);
559:
560: QUIT;
561: if (! DIRENTRY_NONEMPTY (dp)
562: || len < SCHARS (encoded_file)
563: || 0 <= scmp (dp->d_name, SDATA (encoded_file),
564: SCHARS (encoded_file)))
565: continue;
566:
567: if (file_name_completion_stat (encoded_dir, dp, &st) < 0)
568: continue;
569:
570: directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
571: tem = Qnil;
572: if (directoryp)
573: {
574: #ifndef TRIVIAL_DIRECTORY_ENTRY
575: #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
576: #endif
577:
578:
579: if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
580: continue;
581: if (!passcount && len > SCHARS (encoded_file))
582:
583:
584: for (tem = Vcompletion_ignored_extensions;
585: CONSP (