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: #ifdef HAVE_FCNTL_H
26: #include <fcntl.h>
27: #endif
28:
29: #include <stdio.h>
30: #include <sys/types.h>
31: #include <sys/stat.h>
32:
33: #ifdef HAVE_UNISTD_H
34: #include <unistd.h>
35: #endif
36:
37: #if !defined (S_ISLNK) && defined (S_IFLNK)
38: # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
39: #endif
40:
41: #if !defined (S_ISFIFO) && defined (S_IFIFO)
42: # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
43: #endif
44:
45: #if !defined (S_ISREG) && defined (S_IFREG)
46: # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
47: #endif
48:
49: #ifdef HAVE_PWD_H
50: #include <pwd.h>
51: #endif
52:
53: #include <ctype.h>
54:
55: #ifdef VMS
56: #include "vmsdir.h"
57: #include <perror.h>
58: #include <stddef.h>
59: #include <string.h>
60: #endif
61:
62: #include <errno.h>
63:
64: #ifndef vax11c
65: #ifndef USE_CRT_DLL
66: extern int errno;
67: #endif
68: #endif
69:
70: #ifdef APOLLO
71: #include <sys/time.h>
72: #endif
73:
74: #include "lisp.h"
75: #include "intervals.h"
76: #include "buffer.h"
77: #include "charset.h"
78: #include "coding.h"
79: #include "window.h"
80: #include "blockinput.h"
81:
82: #ifdef WINDOWSNT
83: #define NOMINMAX 1
84: #include <windows.h>
85: #include <stdlib.h>
86: #include <fcntl.h>
87: #endif
88:
89: #ifdef MSDOS
90: #include "msdos.h"
91: #include <sys/param.h>
92: #if __DJGPP__ >= 2
93: #include <fcntl.h>
94: #include <string.h>
95: #endif
96: #endif
97:
98: #ifdef DOS_NT
99: #define CORRECT_DIR_SEPS(s) \
100: do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
101: else unixtodos_filename (s); \
102: } while (0)
103:
104:
105: #ifdef MSDOS
106: #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
107: #endif
108: #ifdef WINDOWSNT
109: #define IS_DRIVE(x) isalpha (x)
110: #endif
111:
112:
113:
114: #define DRIVE_LETTER(x) (tolower (x))
115: #endif
116:
117: #ifdef VMS
118: #include <file.h>
119: #include <rmsdef.h>
120: #include <fab.h>
121: #include <nam.h>
122: #endif
123:
124: #include "systime.h"
125:
126: #ifdef HPUX
127: #include <netio.h>
128: #ifndef HPUX8
129: #ifndef HPUX9
130: #include <errnet.h>
131: #endif
132: #endif
133: #endif
134:
135: #include "commands.h"
136: extern int use_dialog_box;
137: extern int use_file_dialog;
138:
139: #ifndef O_WRONLY
140: #define O_WRONLY 1
141: #endif
142:
143: #ifndef O_RDONLY
144: #define O_RDONLY 0
145: #endif
146:
147: #ifndef S_ISLNK
148: # define lstat stat
149: #endif
150:
151: #ifndef FILE_SYSTEM_CASE
152: #define FILE_SYSTEM_CASE(filename) (filename)
153: #endif
154:
155:
156: int auto_saving;
157:
158:
159:
160: int auto_save_mode_bits;
161:
162:
163:
164:
165:
166:
167: Lisp_Object Qauto_save_coding;
168:
169:
170: Lisp_Object Vfile_name_coding_system;
171:
172:
173:
174: Lisp_Object Vdefault_file_name_coding_system;
175:
176:
177:
178: Lisp_Object Vfile_name_handler_alist;
179:
180:
181:
182: Lisp_Object Qoperations;
183:
184:
185: Lisp_Object Qformat_decode, Qformat_annotate_function;
186:
187:
188: Lisp_Object Vset_auto_coding_function;
189:
190:
191: Lisp_Object Vafter_insert_file_functions;
192:
193:
194:
195: Lisp_Object Qafter_insert_file_set_coding;
196:
197:
198: Lisp_Object Vwrite_region_annotate_functions;
199: Lisp_Object Qwrite_region_annotate_functions;
200:
201:
202:
203: Lisp_Object Vwrite_region_annotations_so_far;
204:
205:
206: Lisp_Object Vauto_save_list_file_name;
207:
208:
209: Lisp_Object Vread_file_name_function;
210:
211:
212: Lisp_Object Vread_file_name_predicate;
213:
214:
215: int read_file_name_completion_ignore_case;
216:
217:
218:
219: int insert_default_directory;
220:
221:
222:
223: int vms_stmlf_recfm;
224:
225:
226:
227: Lisp_Object Vdirectory_sep_char;
228:
229: #ifdef HAVE_FSYNC
230:
231: int write_region_inhibit_fsync;
232: #endif
233:
234: extern Lisp_Object Vuser_login_name;
235:
236: #ifdef WINDOWSNT
237: extern Lisp_Object Vw32_get_true_file_attributes;
238: #endif
239:
240: extern int minibuf_level;
241:
242: extern int minibuffer_auto_raise;
243:
244: extern int history_delete_duplicates;
245:
246:
247:
248:
249:
250:
251:
252:
253: static Lisp_Object Vinhibit_file_name_handlers;
254: static Lisp_Object Vinhibit_file_name_operation;
255:
256: Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
257: Lisp_Object Qexcl;
258: Lisp_Object Qfile_name_history;
259:
260: Lisp_Object Qcar_less_than_car;
261:
262: static int a_write P_ ((int, Lisp_Object, int, int,
263: Lisp_Object *, struct coding_system *));
264: static int e_write P_ ((int, Lisp_Object, int, int, struct coding_system *));
265:
266: ^L
267: void
268: report_file_error (string, data)
269: const char *string;
270: Lisp_Object data;
271: {
272: Lisp_Object errstring;
273: int errorno = errno;
274:
275: synchronize_system_messages_locale ();
276: errstring = code_convert_string_norecord (build_string (strerror (errorno)),
277: Vlocale_coding_system, 0);
278:
279: while (1)
280: switch (errorno)
281: {
282: case EEXIST:
283: xsignal (Qfile_already_exists, Fcons (errstring, data));
284: break;
285: default:
286:
287:
288: if (SREF (errstring, 1) != '/')
289: SSET (errstring, 0, DOWNCASE (SREF (errstring, 0)));
290:
291: xsignal (Qfile_error,
292: Fcons (build_string (string), Fcons (errstring, data)));
293: }
294: }
295:
296: Lisp_Object
297: close_file_unwind (fd)
298: Lisp_Object fd;
299: {
300: emacs_close (XFASTINT (fd));
301: return Qnil;
302: }
303:
304:
305:
306: static Lisp_Object
307: restore_point_unwind (location)
308: Lisp_Object location;
309: {
310: Fgoto_char (location);
311: Fset_marker (location, Qnil, Qnil);
312: return Qnil;
313: }
314: ^L
315: Lisp_Object Qexpand_file_name;
316: Lisp_Object Qsubstitute_in_file_name;
317: Lisp_Object Qdirectory_file_name;
318: Lisp_Object Qfile_name_directory;
319: Lisp_Object Qfile_name_nondirectory;
320: Lisp_Object Qunhandled_file_name_directory;
321: Lisp_Object Qfile_name_as_directory;
322: Lisp_Object Qcopy_file;
323: Lisp_Object Qmake_directory_internal;
324: Lisp_Object Qmake_directory;
325: Lisp_Object Qdelete_directory;
326: Lisp_Object Qdelete_file;
327: Lisp_Object Qrename_file;
328: Lisp_Object Qadd_name_to_file;
329: Lisp_Object Qmake_symbolic_link;
330: Lisp_Object Qfile_exists_p;
331: Lisp_Object Qfile_executable_p;
332: Lisp_Object Qfile_readable_p;
333: Lisp_Object Qfile_writable_p;
334: Lisp_Object Qfile_symlink_p;
335: Lisp_Object Qaccess_file;
336: Lisp_Object Qfile_directory_p;
337: Lisp_Object Qfile_regular_p;
338: Lisp_Object Qfile_accessible_directory_p;
339: Lisp_Object Qfile_modes;
340: Lisp_Object Qset_file_modes;
341: Lisp_Object Qset_file_times;
342: Lisp_Object Qfile_newer_than_file_p;
343: Lisp_Object Qinsert_file_contents;
344: Lisp_Object Qwrite_region;
345: Lisp_Object Qverify_visited_file_modtime;
346: Lisp_Object Qset_visited_file_modtime;
347:
348: DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
349: doc:
350:
351:
352:
353:
354:
355:
356:
357: )
358: (filename, operation)
359: Lisp_Object filename, operation;
360: {
361:
362: Lisp_Object chain, inhibited_handlers, result;
363: int pos = -1;
364:
365: result = Qnil;
366: CHECK_STRING (filename);
367:
368: if (EQ (operation, Vinhibit_file_name_operation))
369: inhibited_handlers = Vinhibit_file_name_handlers;
370: else
371: inhibited_handlers = Qnil;
372:
373: for (chain = Vfile_name_handler_alist; CONSP (chain);
374: chain = XCDR (chain))
375: {
376: Lisp_Object elt;
377: elt = XCAR (chain);
378: if (CONSP (elt))
379: {
380: Lisp_Object string = XCAR (elt);
381: int match_pos;
382: Lisp_Object handler = XCDR (elt);
383: Lisp_Object operations = Qnil;
384:
385: if (SYMBOLP (handler))
386: operations = Fget (handler, Qoperations);
387:
388: if (STRINGP (string)
389: && (match_pos = fast_string_match (string, filename)) > pos
390: && (NILP (operations) || ! NILP (Fmemq (operation, operations))))
391: {
392: Lisp_Object tem;
393:
394: handler = XCDR (elt);
395: tem = Fmemq (handler, inhibited_handlers);
396: if (NILP (tem))
397: {
398: result = handler;
399: pos = match_pos;
400: }
401: }
402: }
403:
404: QUIT;
405: }
406: return result;
407: }
408: ^L
409: DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
410: 1, 1, 0,
411: doc:
412:
413:
414:
415: )
416: (filename)
417: Lisp_Object filename;
418: {
419: #ifndef DOS_NT
420: register const unsigned char *beg;
421: #else
422: register unsigned char *beg;
423: #endif
424: register const unsigned char *p;
425: Lisp_Object handler;
426:
427: CHECK_STRING (filename);
428:
429:
430:
431: handler = Ffind_file_name_handler (filename, Qfile_name_directory);
432: if (!NILP (handler))
433: return call2 (handler, Qfile_name_directory, filename);
434:
435: filename = FILE_SYSTEM_CASE (filename);
436: beg = SDATA (filename);
437: #ifdef DOS_NT
438: beg = strcpy (alloca (strlen (beg) + 1), beg);
439: #endif
440: p = beg + SBYTES (filename);
441:
442: while (p != beg && !IS_DIRECTORY_SEP (p[-1])
443: #ifdef VMS
444: && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
445: #endif
446: #ifdef DOS_NT
447:
448: && !(p[-1] == ':'
449:
450: && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
451: || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
452: #endif
453: ) p--;
454:
455: if (p == beg)
456: return Qnil;
457: #ifdef DOS_NT
458:
459: if (p[-1] == ':')
460: {
461:
462: unsigned char *res = alloca (MAXPATHLEN + 1);
463: unsigned char *r = res;
464:
465: if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
466: {
467: strncpy (res, beg, 2);
468: beg += 2;
469: r += 2;
470: }
471:
472: if (getdefdir (toupper (*beg) - 'A' + 1, r))
473: {
474: if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
475: strcat (res, "/");
476: beg = res;
477: p = beg + strlen (beg);
478: }
479: }
480: CORRECT_DIR_SEPS (beg);
481: #endif
482:
483: return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
484: }
485:
486: DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
487: Sfile_name_nondirectory, 1, 1, 0,
488: doc:
489:
490:
491: )
492: (filename)
493: Lisp_Object filename;
494: {
495: register const unsigned char *beg, *p, *end;
496: Lisp_Object handler;
497:
498: CHECK_STRING (filename);
499:
500:
501:
502: handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory);
503: if (!NILP (handler))
504: return call2 (handler, Qfile_name_nondirectory, filename);
505:
506: beg = SDATA (filename);
507: end = p = beg + SBYTES (filename);
508:
509: while (p != beg && !IS_DIRECTORY_SEP (p[-1])
510: #ifdef VMS
511: && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
512: #endif
513: #ifdef DOS_NT
514:
515: && !(p[-1] == ':'
516:
517: && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
518: #endif
519: )
520: p--;
521:
522: return make_specified_string (p, -1, end - p, STRING_MULTIBYTE (filename));
523: }
524:
525: DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
526: Sunhandled_file_name_directory, 1, 1, 0,
527: doc:
528:
529:
530:
531:
532:
533: )
534: (filename)
535: Lisp_Object filename;
536: {
537: Lisp_Object handler;
538:
539:
540:
541: handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
542: if (!NILP (handler))
543: return call2 (handler, Qunhandled_file_name_directory, filename);
544:
545: return Ffile_name_directory (filename);
546: }
547:
548: ^L
549: char *
550: file_name_as_directory (out, in)
551: char *out, *in;
552: {
553: int size = strlen (in) - 1;
554:
555: strcpy (out, in);
556:
557: if (size < 0)
558: {
559: out[0] = '.';
560: out[1] = '/';
561: out[2] = 0;
562: return out;
563: }
564:
565: #ifdef VMS
566:
567: if (in[size] == ':' || in[size] == ']' || in[size] == '>')
568: return out;
569:
570: else if (! index (in, '/')
571: && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
572: || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
573: || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
574: || ! strncmp (&in[size - 5], ".dir", 4))
575: && (in[size - 1] == '.' || in[size - 1] == ';')
576: && in[size] == '1')))
577: {
578: register char *p, *dot;
579: char brack;
580:
581: