(Fdelete_file): Bind completion-ignored-extensions to nil.
[bpt/emacs.git] / src / fileio.c
1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include <config.h>
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28
29 #if !defined (S_ISLNK) && defined (S_IFLNK)
30 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
31 #endif
32
33 #if !defined (S_ISREG) && defined (S_IFREG)
34 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
35 #endif
36
37 #ifdef VMS
38 #include "vms-pwd.h"
39 #else
40 #include <pwd.h>
41 #endif
42
43 #ifdef MSDOS
44 #include "msdos.h"
45 #include <sys/param.h>
46 #endif
47
48 #include <ctype.h>
49
50 #ifdef VMS
51 #include "vmsdir.h"
52 #include <perror.h>
53 #include <stddef.h>
54 #include <string.h>
55 #endif
56
57 #include <errno.h>
58
59 #ifndef vax11c
60 extern int errno;
61 #endif
62
63 extern char *strerror ();
64
65 #ifdef APOLLO
66 #include <sys/time.h>
67 #endif
68
69 #ifndef USG
70 #ifndef VMS
71 #ifndef BSD4_1
72 #define HAVE_FSYNC
73 #endif
74 #endif
75 #endif
76
77 #include "lisp.h"
78 #include "intervals.h"
79 #include "buffer.h"
80 #include "window.h"
81
82 #ifdef VMS
83 #include <file.h>
84 #include <rmsdef.h>
85 #include <fab.h>
86 #include <nam.h>
87 #endif
88
89 #include "systime.h"
90
91 #ifdef HPUX
92 #include <netio.h>
93 #ifndef HPUX8
94 #ifndef HPUX9
95 #include <errnet.h>
96 #endif
97 #endif
98 #endif
99
100 #ifndef O_WRONLY
101 #define O_WRONLY 1
102 #endif
103
104 #ifndef O_RDONLY
105 #define O_RDONLY 0
106 #endif
107
108 #define min(a, b) ((a) < (b) ? (a) : (b))
109 #define max(a, b) ((a) > (b) ? (a) : (b))
110
111 /* Nonzero during writing of auto-save files */
112 int auto_saving;
113
114 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
115 a new file with the same mode as the original */
116 int auto_save_mode_bits;
117
118 /* Alist of elements (REGEXP . HANDLER) for file names
119 whose I/O is done with a special handler. */
120 Lisp_Object Vfile_name_handler_alist;
121
122 /* Functions to be called to process text properties in inserted file. */
123 Lisp_Object Vafter_insert_file_functions;
124
125 /* Functions to be called to create text property annotations for file. */
126 Lisp_Object Vwrite_region_annotate_functions;
127
128 /* During build_annotations, each time an annotation function is called,
129 this holds the annotations made by the previous functions. */
130 Lisp_Object Vwrite_region_annotations_so_far;
131
132 /* File name in which we write a list of all our auto save files. */
133 Lisp_Object Vauto_save_list_file_name;
134
135 /* Nonzero means, when reading a filename in the minibuffer,
136 start out by inserting the default directory into the minibuffer. */
137 int insert_default_directory;
138
139 /* On VMS, nonzero means write new files with record format stmlf.
140 Zero means use var format. */
141 int vms_stmlf_recfm;
142
143 /* These variables describe handlers that have "already" had a chance
144 to handle the current operation.
145
146 Vinhibit_file_name_handlers is a list of file name handlers.
147 Vinhibit_file_name_operation is the operation being handled.
148 If we try to handle that operation, we ignore those handlers. */
149
150 static Lisp_Object Vinhibit_file_name_handlers;
151 static Lisp_Object Vinhibit_file_name_operation;
152
153 extern Lisp_Object Qcompletion_ignored_extensions;
154
155 Lisp_Object Qfile_error, Qfile_already_exists;
156
157 Lisp_Object Qfile_name_history;
158
159 Lisp_Object Qcar_less_than_car;
160
161 report_file_error (string, data)
162 char *string;
163 Lisp_Object data;
164 {
165 Lisp_Object errstring;
166
167 errstring = build_string (strerror (errno));
168
169 /* System error messages are capitalized. Downcase the initial
170 unless it is followed by a slash. */
171 if (XSTRING (errstring)->data[1] != '/')
172 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
173
174 while (1)
175 Fsignal (Qfile_error,
176 Fcons (build_string (string), Fcons (errstring, data)));
177 }
178
179 close_file_unwind (fd)
180 Lisp_Object fd;
181 {
182 close (XFASTINT (fd));
183 }
184
185 /* Restore point, having saved it as a marker. */
186
187 restore_point_unwind (location)
188 Lisp_Object location;
189 {
190 SET_PT (marker_position (location));
191 Fset_marker (location, Qnil, Qnil);
192 }
193 \f
194 Lisp_Object Qexpand_file_name;
195 Lisp_Object Qdirectory_file_name;
196 Lisp_Object Qfile_name_directory;
197 Lisp_Object Qfile_name_nondirectory;
198 Lisp_Object Qunhandled_file_name_directory;
199 Lisp_Object Qfile_name_as_directory;
200 Lisp_Object Qcopy_file;
201 Lisp_Object Qmake_directory_internal;
202 Lisp_Object Qdelete_directory;
203 Lisp_Object Qdelete_file;
204 Lisp_Object Qrename_file;
205 Lisp_Object Qadd_name_to_file;
206 Lisp_Object Qmake_symbolic_link;
207 Lisp_Object Qfile_exists_p;
208 Lisp_Object Qfile_executable_p;
209 Lisp_Object Qfile_readable_p;
210 Lisp_Object Qfile_symlink_p;
211 Lisp_Object Qfile_writable_p;
212 Lisp_Object Qfile_directory_p;
213 Lisp_Object Qfile_accessible_directory_p;
214 Lisp_Object Qfile_modes;
215 Lisp_Object Qset_file_modes;
216 Lisp_Object Qfile_newer_than_file_p;
217 Lisp_Object Qinsert_file_contents;
218 Lisp_Object Qwrite_region;
219 Lisp_Object Qverify_visited_file_modtime;
220 Lisp_Object Qset_visited_file_modtime;
221
222 DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
223 "Return FILENAME's handler function for OPERATION, if it has one.\n\
224 Otherwise, return nil.\n\
225 A file name is handled if one of the regular expressions in\n\
226 `file-name-handler-alist' matches it.\n\n\
227 If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
228 any handlers that are members of `inhibit-file-name-handlers',\n\
229 but we still do run any other handlers. This lets handlers\n\
230 use the standard functions without calling themselves recursively.")
231 (filename, operation)
232 Lisp_Object filename, operation;
233 {
234 /* This function must not munge the match data. */
235 Lisp_Object chain, inhibited_handlers;
236
237 CHECK_STRING (filename, 0);
238
239 if (EQ (operation, Vinhibit_file_name_operation))
240 inhibited_handlers = Vinhibit_file_name_handlers;
241 else
242 inhibited_handlers = Qnil;
243
244 for (chain = Vfile_name_handler_alist; XTYPE (chain) == Lisp_Cons;
245 chain = XCONS (chain)->cdr)
246 {
247 Lisp_Object elt;
248 elt = XCONS (chain)->car;
249 if (XTYPE (elt) == Lisp_Cons)
250 {
251 Lisp_Object string;
252 string = XCONS (elt)->car;
253 if (XTYPE (string) == Lisp_String
254 && fast_string_match (string, filename) >= 0)
255 {
256 Lisp_Object handler, tem;
257
258 handler = XCONS (elt)->cdr;
259 tem = Fmemq (handler, inhibited_handlers);
260 if (NILP (tem))
261 return handler;
262 }
263 }
264
265 QUIT;
266 }
267 return Qnil;
268 }
269 \f
270 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
271 1, 1, 0,
272 "Return the directory component in file name NAME.\n\
273 Return nil if NAME does not include a directory.\n\
274 Otherwise return a directory spec.\n\
275 Given a Unix syntax file name, returns a string ending in slash;\n\
276 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
277 (file)
278 Lisp_Object file;
279 {
280 register unsigned char *beg;
281 register unsigned char *p;
282 Lisp_Object handler;
283
284 CHECK_STRING (file, 0);
285
286 /* If the file name has special constructs in it,
287 call the corresponding file handler. */
288 handler = Ffind_file_name_handler (file, Qfile_name_directory);
289 if (!NILP (handler))
290 return call2 (handler, Qfile_name_directory, file);
291
292 #ifdef FILE_SYSTEM_CASE
293 file = FILE_SYSTEM_CASE (file);
294 #endif
295 beg = XSTRING (file)->data;
296 p = beg + XSTRING (file)->size;
297
298 while (p != beg && p[-1] != '/'
299 #ifdef VMS
300 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
301 #endif /* VMS */
302 #ifdef MSDOS
303 && p[-1] != ':' && p[-1] != '\\'
304 #endif
305 ) p--;
306
307 if (p == beg)
308 return Qnil;
309 #ifdef MSDOS
310 /* Expansion of "c:" to drive and default directory. */
311 if (p == beg + 2 && beg[1] == ':')
312 {
313 int drive = (*beg) - 'a';
314 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
315 unsigned char *res = alloca (MAXPATHLEN + 5);
316 if (getdefdir (drive + 1, res + 2))
317 {
318 res[0] = drive + 'a';
319 res[1] = ':';
320 if (res[strlen (res) - 1] != '/')
321 strcat (res, "/");
322 beg = res;
323 p = beg + strlen (beg);
324 }
325 }
326 #endif
327 return make_string (beg, p - beg);
328 }
329
330 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
331 1, 1, 0,
332 "Return file name NAME sans its directory.\n\
333 For example, in a Unix-syntax file name,\n\
334 this is everything after the last slash,\n\
335 or the entire name if it contains no slash.")
336 (file)
337 Lisp_Object file;
338 {
339 register unsigned char *beg, *p, *end;
340 Lisp_Object handler;
341
342 CHECK_STRING (file, 0);
343
344 /* If the file name has special constructs in it,
345 call the corresponding file handler. */
346 handler = Ffind_file_name_handler (file, Qfile_name_nondirectory);
347 if (!NILP (handler))
348 return call2 (handler, Qfile_name_nondirectory, file);
349
350 beg = XSTRING (file)->data;
351 end = p = beg + XSTRING (file)->size;
352
353 while (p != beg && p[-1] != '/'
354 #ifdef VMS
355 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
356 #endif /* VMS */
357 #ifdef MSDOS
358 && p[-1] != ':' && p[-1] != '\\'
359 #endif
360 ) p--;
361
362 return make_string (p, end - p);
363 }
364
365 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
366 "Return a directly usable directory name somehow associated with FILENAME.\n\
367 A `directly usable' directory name is one that may be used without the\n\
368 intervention of any file handler.\n\
369 If FILENAME is a directly usable file itself, return\n\
370 (file-name-directory FILENAME).\n\
371 The `call-process' and `start-process' functions use this function to\n\
372 get a current directory to run processes in.")
373 (filename)
374 Lisp_Object filename;
375 {
376 Lisp_Object handler;
377
378 /* If the file name has special constructs in it,
379 call the corresponding file handler. */
380 handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
381 if (!NILP (handler))
382 return call2 (handler, Qunhandled_file_name_directory, filename);
383
384 return Ffile_name_directory (filename);
385 }
386
387 \f
388 char *
389 file_name_as_directory (out, in)
390 char *out, *in;
391 {
392 int size = strlen (in) - 1;
393
394 strcpy (out, in);
395
396 #ifdef VMS
397 /* Is it already a directory string? */
398 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
399 return out;
400 /* Is it a VMS directory file name? If so, hack VMS syntax. */
401 else if (! index (in, '/')
402 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
403 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
404 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
405 || ! strncmp (&in[size - 5], ".dir", 4))
406 && (in[size - 1] == '.' || in[size - 1] == ';')
407 && in[size] == '1')))
408 {
409 register char *p, *dot;
410 char brack;
411
412 /* x.dir -> [.x]
413 dir:x.dir --> dir:[x]
414 dir:[x]y.dir --> dir:[x.y] */
415 p = in + size;
416 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
417 if (p != in)
418 {
419 strncpy (out, in, p - in);
420 out[p - in] = '\0';
421 if (*p == ':')
422 {
423 brack = ']';
424 strcat (out, ":[");
425 }
426 else
427 {
428 brack = *p;
429 strcat (out, ".");
430 }
431 p++;
432 }
433 else
434 {
435 brack = ']';
436 strcpy (out, "[.");
437 }
438 dot = index (p, '.');
439 if (dot)
440 {
441 /* blindly remove any extension */
442 size = strlen (out) + (dot - p);
443 strncat (out, p, dot - p);
444 }
445 else
446 {
447 strcat (out, p);
448 size = strlen (out);
449 }
450 out[size++] = brack;
451 out[size] = '\0';
452 }
453 #else /* not VMS */
454 /* For Unix syntax, Append a slash if necessary */
455 #ifdef MSDOS
456 if (out[size] != ':' && out[size] != '/' && out[size] != '\\')
457 #else
458 if (out[size] != '/')
459 #endif
460 strcat (out, "/");
461 #endif /* not VMS */
462 return out;
463 }
464
465 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
466 Sfile_name_as_directory, 1, 1, 0,
467 "Return a string representing file FILENAME interpreted as a directory.\n\
468 This operation exists because a directory is also a file, but its name as\n\
469 a directory is different from its name as a file.\n\
470 The result can be used as the value of `default-directory'\n\
471 or passed as second argument to `expand-file-name'.\n\
472 For a Unix-syntax file name, just appends a slash.\n\
473 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
474 (file)
475 Lisp_Object file;
476 {
477 char *buf;
478 Lisp_Object handler;
479
480 CHECK_STRING (file, 0);
481 if (NILP (file))
482 return Qnil;
483
484 /* If the file name has special constructs in it,
485 call the corresponding file handler. */
486 handler = Ffind_file_name_handler (file, Qfile_name_as_directory);
487 if (!NILP (handler))
488 return call2 (handler, Qfile_name_as_directory, file);
489
490 buf = (char *) alloca (XSTRING (file)->size + 10);
491 return build_string (file_name_as_directory (buf, XSTRING (file)->data));
492 }
493 \f
494 /*
495 * Convert from directory name to filename.
496 * On VMS:
497 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
498 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
499 * On UNIX, it's simple: just make sure there is a terminating /
500
501 * Value is nonzero if the string output is different from the input.
502 */
503
504 directory_file_name (src, dst)
505 char *src, *dst;
506 {
507 long slen;
508 #ifdef VMS
509 long rlen;
510 char * ptr, * rptr;
511 char bracket;
512 struct FAB fab = cc$rms_fab;
513 struct NAM nam = cc$rms_nam;
514 char esa[NAM$C_MAXRSS];
515 #endif /* VMS */
516
517 slen = strlen (src);
518 #ifdef VMS
519 if (! index (src, '/')
520 && (src[slen - 1] == ']'
521 || src[slen - 1] == ':'
522 || src[slen - 1] == '>'))
523 {
524 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
525 fab.fab$l_fna = src;
526 fab.fab$b_fns = slen;
527 fab.fab$l_nam = &nam;
528 fab.fab$l_fop = FAB$M_NAM;
529
530 nam.nam$l_esa = esa;
531 nam.nam$b_ess = sizeof esa;
532 nam.nam$b_nop |= NAM$M_SYNCHK;
533
534 /* We call SYS$PARSE to handle such things as [--] for us. */
535 if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
536 {
537 slen = nam.nam$b_esl;
538 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
539 slen -= 2;
540 esa[slen] = '\0';
541 src = esa;
542 }
543 if (src[slen - 1] != ']' && src[slen - 1] != '>')
544 {
545 /* what about when we have logical_name:???? */
546 if (src[slen - 1] == ':')
547 { /* Xlate logical name and see what we get */
548 ptr = strcpy (dst, src); /* upper case for getenv */
549 while (*ptr)
550 {
551 if ('a' <= *ptr && *ptr <= 'z')
552 *ptr -= 040;
553 ptr++;
554 }
555 dst[slen - 1] = 0; /* remove colon */
556 if (!(src = egetenv (dst)))
557 return 0;
558 /* should we jump to the beginning of this procedure?
559 Good points: allows us to use logical names that xlate
560 to Unix names,
561 Bad points: can be a problem if we just translated to a device
562 name...
563 For now, I'll punt and always expect VMS names, and hope for
564 the best! */
565 slen = strlen (src);
566 if (src[slen - 1] != ']' && src[slen - 1] != '>')
567 { /* no recursion here! */
568 strcpy (dst, src);
569 return 0;
570 }
571 }
572 else
573 { /* not a directory spec */
574 strcpy (dst, src);
575 return 0;
576 }
577 }
578 bracket = src[slen - 1];
579
580 /* If bracket is ']' or '>', bracket - 2 is the corresponding
581 opening bracket. */
582 ptr = index (src, bracket - 2);
583 if (ptr == 0)
584 { /* no opening bracket */
585 strcpy (dst, src);
586 return 0;
587 }
588 if (!(rptr = rindex (src, '.')))
589 rptr = ptr;
590 slen = rptr - src;
591 strncpy (dst, src, slen);
592 dst[slen] = '\0';
593 if (*rptr == '.')
594 {
595 dst[slen++] = bracket;
596 dst[slen] = '\0';
597 }
598 else
599 {
600 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
601 then translate the device and recurse. */
602 if (dst[slen - 1] == ':'
603 && dst[slen - 2] != ':' /* skip decnet nodes */
604 && strcmp(src + slen, "[000000]") == 0)
605 {
606 dst[slen - 1] = '\0';
607 if ((ptr = egetenv (dst))
608 && (rlen = strlen (ptr) - 1) > 0
609 && (ptr[rlen] == ']' || ptr[rlen] == '>')
610 && ptr[rlen - 1] == '.')
611 {
612 char * buf = (char *) alloca (strlen (ptr) + 1);
613 strcpy (buf, ptr);
614 buf[rlen - 1] = ']';
615 buf[rlen] = '\0';
616 return directory_file_name (buf, dst);
617 }
618 else
619 dst[slen - 1] = ':';
620 }
621 strcat (dst, "[000000]");
622 slen += 8;
623 }
624 rptr++;
625 rlen = strlen (rptr) - 1;
626 strncat (dst, rptr, rlen);
627 dst[slen + rlen] = '\0';
628 strcat (dst, ".DIR.1");
629 return 1;
630 }
631 #endif /* VMS */
632 /* Process as Unix format: just remove any final slash.
633 But leave "/" unchanged; do not change it to "". */
634 strcpy (dst, src);
635 if (slen > 1
636 #ifdef MSDOS
637 && (dst[slen - 1] == '/' || dst[slen - 1] == '/')
638 && dst[slen - 2] != ':'
639 #else
640 && dst[slen - 1] == '/'
641 #endif
642 )
643 dst[slen - 1] = 0;
644 return 1;
645 }
646
647 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
648 1, 1, 0,
649 "Returns the file name of the directory named DIR.\n\
650 This is the name of the file that holds the data for the directory DIR.\n\
651 This operation exists because a directory is also a file, but its name as\n\
652 a directory is different from its name as a file.\n\
653 In Unix-syntax, this function just removes the final slash.\n\
654 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
655 it returns a file name such as \"[X]Y.DIR.1\".")
656 (directory)
657 Lisp_Object directory;
658 {
659 char *buf;
660 Lisp_Object handler;
661
662 CHECK_STRING (directory, 0);
663
664 if (NILP (directory))
665 return Qnil;
666
667 /* If the file name has special constructs in it,
668 call the corresponding file handler. */
669 handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
670 if (!NILP (handler))
671 return call2 (handler, Qdirectory_file_name, directory);
672
673 #ifdef VMS
674 /* 20 extra chars is insufficient for VMS, since we might perform a
675 logical name translation. an equivalence string can be up to 255
676 chars long, so grab that much extra space... - sss */
677 buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
678 #else
679 buf = (char *) alloca (XSTRING (directory)->size + 20);
680 #endif
681 directory_file_name (XSTRING (directory)->data, buf);
682 return build_string (buf);
683 }
684
685 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
686 "Generate temporary file name (string) starting with PREFIX (a string).\n\
687 The Emacs process number forms part of the result,\n\
688 so there is no danger of generating a name being used by another process.")
689 (prefix)
690 Lisp_Object prefix;
691 {
692 Lisp_Object val;
693 val = concat2 (prefix, build_string ("XXXXXX"));
694 mktemp (XSTRING (val)->data);
695 return val;
696 }
697 \f
698 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
699 "Convert FILENAME to absolute, and canonicalize it.\n\
700 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
701 (does not start with slash); if DEFAULT is nil or missing,\n\
702 the current buffer's value of default-directory is used.\n\
703 Path components that are `.' are removed, and \n\
704 path components followed by `..' are removed, along with the `..' itself;\n\
705 note that these simplifications are done without checking the resulting\n\
706 paths in the file system.\n\
707 An initial `~/' expands to your home directory.\n\
708 An initial `~USER/' expands to USER's home directory.\n\
709 See also the function `substitute-in-file-name'.")
710 (name, defalt)
711 Lisp_Object name, defalt;
712 {
713 unsigned char *nm;
714
715 register unsigned char *newdir, *p, *o;
716 int tlen;
717 unsigned char *target;
718 struct passwd *pw;
719 #ifdef VMS
720 unsigned char * colon = 0;
721 unsigned char * close = 0;
722 unsigned char * slash = 0;
723 unsigned char * brack = 0;
724 int lbrack = 0, rbrack = 0;
725 int dots = 0;
726 #endif /* VMS */
727 #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
728 int drive = -1;
729 int relpath = 0;
730 unsigned char *tmp, *defdir;
731 #endif
732 Lisp_Object handler;
733
734 CHECK_STRING (name, 0);
735
736 /* If the file name has special constructs in it,
737 call the corresponding file handler. */
738 handler = Ffind_file_name_handler (name, Qexpand_file_name);
739 if (!NILP (handler))
740 return call3 (handler, Qexpand_file_name, name, defalt);
741
742 /* Use the buffer's default-directory if DEFALT is omitted. */
743 if (NILP (defalt))
744 defalt = current_buffer->directory;
745 CHECK_STRING (defalt, 1);
746
747 /* Make sure DEFALT is properly expanded.
748 It would be better to do this down below where we actually use
749 defalt. Unfortunately, calling Fexpand_file_name recursively
750 could invoke GC, and the strings might be relocated. This would
751 be annoying because we have pointers into strings lying around
752 that would need adjusting, and people would add new pointers to
753 the code and forget to adjust them, resulting in intermittent bugs.
754 Putting this call here avoids all that crud.
755
756 The EQ test avoids infinite recursion. */
757 if (! NILP (defalt) && !EQ (defalt, name)
758 /* This saves time in a common case. */
759 && XSTRING (defalt)->data[0] != '/')
760 {
761 struct gcpro gcpro1;
762
763 GCPRO1 (name);
764 defalt = Fexpand_file_name (defalt, Qnil);
765 UNGCPRO;
766 }
767
768 #ifdef VMS
769 /* Filenames on VMS are always upper case. */
770 name = Fupcase (name);
771 #endif
772 #ifdef FILE_SYSTEM_CASE
773 name = FILE_SYSTEM_CASE (name);
774 #endif
775
776 nm = XSTRING (name)->data;
777
778 #ifdef MSDOS
779 /* First map all backslashes to slashes. */
780 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
781
782 /* Now strip drive name. */
783 {
784 unsigned char *colon = rindex (nm, ':');
785 if (colon)
786 if (nm == colon)
787 nm++;
788 else
789 {
790 drive = tolower (colon[-1]) - 'a';
791 nm = colon + 1;
792 if (*nm != '/')
793 {
794 defdir = alloca (MAXPATHLEN + 1);
795 relpath = getdefdir (drive + 1, defdir);
796 }
797 }
798 }
799 #endif
800
801 /* If nm is absolute, flush ...// and detect /./ and /../.
802 If no /./ or /../ we can return right away. */
803 if (
804 nm[0] == '/'
805 #ifdef VMS
806 || index (nm, ':')
807 #endif /* VMS */
808 )
809 {
810 /* If it turns out that the filename we want to return is just a
811 suffix of FILENAME, we don't need to go through and edit
812 things; we just need to construct a new string using data
813 starting at the middle of FILENAME. If we set lose to a
814 non-zero value, that means we've discovered that we can't do
815 that cool trick. */
816 int lose = 0;
817
818 p = nm;
819 while (*p)
820 {
821 /* Since we know the path is absolute, we can assume that each
822 element starts with a "/". */
823
824 /* "//" anywhere isn't necessarily hairy; we just start afresh
825 with the second slash. */
826 if (p[0] == '/' && p[1] == '/'
827 #ifdef APOLLO
828 /* // at start of filename is meaningful on Apollo system */
829 && nm != p
830 #endif /* APOLLO */
831 )
832 nm = p + 1;
833
834 /* "~" is hairy as the start of any path element. */
835 if (p[0] == '/' && p[1] == '~')
836 nm = p + 1, lose = 1;
837
838 /* "." and ".." are hairy. */
839 if (p[0] == '/'
840 && p[1] == '.'
841 && (p[2] == '/'
842 || p[2] == 0
843 || (p[2] == '.' && (p[3] == '/'
844 || p[3] == 0))))
845 lose = 1;
846 #ifdef VMS
847 if (p[0] == '\\')
848 lose = 1;
849 if (p[0] == '/') {
850 /* if dev:[dir]/, move nm to / */
851 if (!slash && p > nm && (brack || colon)) {
852 nm = (brack ? brack + 1 : colon + 1);
853 lbrack = rbrack = 0;
854 brack = 0;
855 colon = 0;
856 }
857 slash = p;
858 }
859 if (p[0] == '-')
860 #ifndef VMS4_4
861 /* VMS pre V4.4,convert '-'s in filenames. */
862 if (lbrack == rbrack)
863 {
864 if (dots < 2) /* this is to allow negative version numbers */
865 p[0] = '_';
866 }
867 else
868 #endif /* VMS4_4 */
869 if (lbrack > rbrack &&
870 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
871 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
872 lose = 1;
873 #ifndef VMS4_4
874 else
875 p[0] = '_';
876 #endif /* VMS4_4 */
877 /* count open brackets, reset close bracket pointer */
878 if (p[0] == '[' || p[0] == '<')
879 lbrack++, brack = 0;
880 /* count close brackets, set close bracket pointer */
881 if (p[0] == ']' || p[0] == '>')
882 rbrack++, brack = p;
883 /* detect ][ or >< */
884 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
885 lose = 1;
886 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
887 nm = p + 1, lose = 1;
888 if (p[0] == ':' && (colon || slash))
889 /* if dev1:[dir]dev2:, move nm to dev2: */
890 if (brack)
891 {
892 nm = brack + 1;
893 brack = 0;
894 }
895 /* if /pathname/dev:, move nm to dev: */
896 else if (slash)
897 nm = slash + 1;
898 /* if node::dev:, move colon following dev */
899 else if (colon && colon[-1] == ':')
900 colon = p;
901 /* if dev1:dev2:, move nm to dev2: */
902 else if (colon && colon[-1] != ':')
903 {
904 nm = colon + 1;
905 colon = 0;
906 }
907 if (p[0] == ':' && !colon)
908 {
909 if (p[1] == ':')
910 p++;
911 colon = p;
912 }
913 if (lbrack == rbrack)
914 if (p[0] == ';')
915 dots = 2;
916 else if (p[0] == '.')
917 dots++;
918 #endif /* VMS */
919 p++;
920 }
921 if (!lose)
922 {
923 #ifdef VMS
924 if (index (nm, '/'))
925 return build_string (sys_translate_unix (nm));
926 #endif /* VMS */
927 #ifndef MSDOS
928 if (nm == XSTRING (name)->data)
929 return name;
930 return build_string (nm);
931 #endif
932 }
933 }
934
935 /* Now determine directory to start with and put it in newdir */
936
937 newdir = 0;
938
939 if (nm[0] == '~') /* prefix ~ */
940 {
941 if (nm[1] == '/'
942 #ifdef VMS
943 || nm[1] == ':'
944 #endif /* VMS */
945 || nm[1] == 0) /* ~ by itself */
946 {
947 if (!(newdir = (unsigned char *) egetenv ("HOME")))
948 newdir = (unsigned char *) "";
949 #ifdef MSDOS
950 dostounix_filename (newdir);
951 #endif
952 nm++;
953 #ifdef VMS
954 nm++; /* Don't leave the slash in nm. */
955 #endif /* VMS */
956 }
957 else /* ~user/filename */
958 {
959 for (p = nm; *p && (*p != '/'
960 #ifdef VMS
961 && *p != ':'
962 #endif /* VMS */
963 ); p++);
964 o = (unsigned char *) alloca (p - nm + 1);
965 bcopy ((char *) nm, o, p - nm);
966 o [p - nm] = 0;
967
968 pw = (struct passwd *) getpwnam (o + 1);
969 if (pw)
970 {
971 newdir = (unsigned char *) pw -> pw_dir;
972 #ifdef VMS
973 nm = p + 1; /* skip the terminator */
974 #else
975 nm = p;
976 #endif /* VMS */
977 }
978
979 /* If we don't find a user of that name, leave the name
980 unchanged; don't move nm forward to p. */
981 }
982 }
983
984 if (nm[0] != '/'
985 #ifdef VMS
986 && !index (nm, ':')
987 #endif /* not VMS */
988 #ifdef MSDOS
989 && drive == -1
990 #endif
991 && !newdir)
992 {
993 newdir = XSTRING (defalt)->data;
994 }
995
996 #ifdef MSDOS
997 if (newdir == 0 && relpath)
998 newdir = defdir;
999 #endif
1000 if (newdir != 0)
1001 {
1002 /* Get rid of any slash at the end of newdir. */
1003 int length = strlen (newdir);
1004 /* Adding `length > 1 &&' makes ~ expand into / when homedir
1005 is the root dir. People disagree about whether that is right.
1006 Anyway, we can't take the risk of this change now. */
1007 #ifdef MSDOS
1008 if (newdir[1] != ':' && length > 1)
1009 #endif
1010 if (newdir[length - 1] == '/')
1011 {
1012 unsigned char *temp = (unsigned char *) alloca (length);
1013 bcopy (newdir, temp, length - 1);
1014 temp[length - 1] = 0;
1015 newdir = temp;
1016 }
1017 tlen = length + 1;
1018 }
1019 else
1020 tlen = 0;
1021
1022 /* Now concatenate the directory and name to new space in the stack frame */
1023 tlen += strlen (nm) + 1;
1024 #ifdef MSDOS
1025 /* Add reserved space for drive name. */
1026 target = (unsigned char *) alloca (tlen + 2) + 2;
1027 #else
1028 target = (unsigned char *) alloca (tlen);
1029 #endif
1030 *target = 0;
1031
1032 if (newdir)
1033 {
1034 #ifndef VMS
1035 if (nm[0] == 0 || nm[0] == '/')
1036 strcpy (target, newdir);
1037 else
1038 #endif
1039 file_name_as_directory (target, newdir);
1040 }
1041
1042 strcat (target, nm);
1043 #ifdef VMS
1044 if (index (target, '/'))
1045 strcpy (target, sys_translate_unix (target));
1046 #endif /* VMS */
1047
1048 /* Now canonicalize by removing /. and /foo/.. if they appear. */
1049
1050 p = target;
1051 o = target;
1052
1053 while (*p)
1054 {
1055 #ifdef VMS
1056 if (*p != ']' && *p != '>' && *p != '-')
1057 {
1058 if (*p == '\\')
1059 p++;
1060 *o++ = *p++;
1061 }
1062 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1063 /* brackets are offset from each other by 2 */
1064 {
1065 p += 2;
1066 if (*p != '.' && *p != '-' && o[-1] != '.')
1067 /* convert [foo][bar] to [bar] */
1068 while (o[-1] != '[' && o[-1] != '<')
1069 o--;
1070 else if (*p == '-' && *o != '.')
1071 *--p = '.';
1072 }
1073 else if (p[0] == '-' && o[-1] == '.' &&
1074 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1075 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1076 {
1077 do
1078 o--;
1079 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1080 if (p[1] == '.') /* foo.-.bar ==> bar*/
1081 p += 2;
1082 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1083 p++, o--;
1084 /* else [foo.-] ==> [-] */
1085 }
1086 else
1087 {
1088 #ifndef VMS4_4
1089 if (*p == '-' &&
1090 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1091 p[1] != ']' && p[1] != '>' && p[1] != '.')
1092 *p = '_';
1093 #endif /* VMS4_4 */
1094 *o++ = *p++;
1095 }
1096 #else /* not VMS */
1097 if (*p != '/')
1098 {
1099 *o++ = *p++;
1100 }
1101 else if (!strncmp (p, "//", 2)
1102 #ifdef APOLLO
1103 /* // at start of filename is meaningful in Apollo system */
1104 && o != target
1105 #endif /* APOLLO */
1106 )
1107 {
1108 o = target;
1109 p++;
1110 }
1111 else if (p[0] == '/'
1112 && p[1] == '.'
1113 && (p[2] == '/'
1114 || p[2] == 0))
1115 {
1116 /* If "/." is the entire filename, keep the "/". Otherwise,
1117 just delete the whole "/.". */
1118 if (o == target && p[2] == '\0')
1119 *o++ = *p;
1120 p += 2;
1121 }
1122 else if (!strncmp (p, "/..", 3)
1123 /* `/../' is the "superroot" on certain file systems. */
1124 && o != target
1125 && (p[3] == '/' || p[3] == 0))
1126 {
1127 while (o != target && *--o != '/')
1128 ;
1129 #ifdef APOLLO
1130 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1131 ++o;
1132 else
1133 #endif /* APOLLO */
1134 if (o == target && *o == '/')
1135 ++o;
1136 p += 3;
1137 }
1138 else
1139 {
1140 *o++ = *p++;
1141 }
1142 #endif /* not VMS */
1143 }
1144
1145 #ifdef MSDOS
1146 /* at last, set drive name. */
1147 if (target[1] != ':')
1148 {
1149 target -= 2;
1150 target[0] = (drive < 0 ? getdisk () : drive) + 'a';
1151 target[1] = ':';
1152 }
1153 #endif
1154
1155 return make_string (target, o - target);
1156 }
1157 #if 0
1158 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'.
1159 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1160 "Convert FILENAME to absolute, and canonicalize it.\n\
1161 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
1162 (does not start with slash); if DEFAULT is nil or missing,\n\
1163 the current buffer's value of default-directory is used.\n\
1164 Filenames containing `.' or `..' as components are simplified;\n\
1165 initial `~/' expands to your home directory.\n\
1166 See also the function `substitute-in-file-name'.")
1167 (name, defalt)
1168 Lisp_Object name, defalt;
1169 {
1170 unsigned char *nm;
1171
1172 register unsigned char *newdir, *p, *o;
1173 int tlen;
1174 unsigned char *target;
1175 struct passwd *pw;
1176 int lose;
1177 #ifdef VMS
1178 unsigned char * colon = 0;
1179 unsigned char * close = 0;
1180 unsigned char * slash = 0;
1181 unsigned char * brack = 0;
1182 int lbrack = 0, rbrack = 0;
1183 int dots = 0;
1184 #endif /* VMS */
1185
1186 CHECK_STRING (name, 0);
1187
1188 #ifdef VMS
1189 /* Filenames on VMS are always upper case. */
1190 name = Fupcase (name);
1191 #endif
1192
1193 nm = XSTRING (name)->data;
1194
1195 /* If nm is absolute, flush ...// and detect /./ and /../.
1196 If no /./ or /../ we can return right away. */
1197 if (
1198 nm[0] == '/'
1199 #ifdef VMS
1200 || index (nm, ':')
1201 #endif /* VMS */
1202 )
1203 {
1204 p = nm;
1205 lose = 0;
1206 while (*p)
1207 {
1208 if (p[0] == '/' && p[1] == '/'
1209 #ifdef APOLLO
1210 /* // at start of filename is meaningful on Apollo system */
1211 && nm != p
1212 #endif /* APOLLO */
1213 )
1214 nm = p + 1;
1215 if (p[0] == '/' && p[1] == '~')
1216 nm = p + 1, lose = 1;
1217 if (p[0] == '/' && p[1] == '.'
1218 && (p[2] == '/' || p[2] == 0
1219 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
1220 lose = 1;
1221 #ifdef VMS
1222 if (p[0] == '\\')
1223 lose = 1;
1224 if (p[0] == '/') {
1225 /* if dev:[dir]/, move nm to / */
1226 if (!slash && p > nm && (brack || colon)) {
1227 nm = (brack ? brack + 1 : colon + 1);
1228 lbrack = rbrack = 0;
1229 brack = 0;
1230 colon = 0;
1231 }
1232 slash = p;
1233 }
1234 if (p[0] == '-')
1235 #ifndef VMS4_4
1236 /* VMS pre V4.4,convert '-'s in filenames. */
1237 if (lbrack == rbrack)
1238 {
1239 if (dots < 2) /* this is to allow negative version numbers */
1240 p[0] = '_';
1241 }
1242 else
1243 #endif /* VMS4_4 */
1244 if (lbrack > rbrack &&
1245 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1246 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1247 lose = 1;
1248 #ifndef VMS4_4
1249 else
1250 p[0] = '_';
1251 #endif /* VMS4_4 */
1252 /* count open brackets, reset close bracket pointer */
1253 if (p[0] == '[' || p[0] == '<')
1254 lbrack++, brack = 0;
1255 /* count close brackets, set close bracket pointer */
1256 if (p[0] == ']' || p[0] == '>')
1257 rbrack++, brack = p;
1258 /* detect ][ or >< */
1259 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1260 lose = 1;
1261 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1262 nm = p + 1, lose = 1;
1263 if (p[0] == ':' && (colon || slash))
1264 /* if dev1:[dir]dev2:, move nm to dev2: */
1265 if (brack)
1266 {
1267 nm = brack + 1;
1268 brack = 0;
1269 }
1270 /* if /pathname/dev:, move nm to dev: */
1271 else if (slash)
1272 nm = slash + 1;
1273 /* if node::dev:, move colon following dev */
1274 else if (colon && colon[-1] == ':')
1275 colon = p;
1276 /* if dev1:dev2:, move nm to dev2: */
1277 else if (colon && colon[-1] != ':')
1278 {
1279 nm = colon + 1;
1280 colon = 0;
1281 }
1282 if (p[0] == ':' && !colon)
1283 {
1284 if (p[1] == ':')
1285 p++;
1286 colon = p;
1287 }
1288 if (lbrack == rbrack)
1289 if (p[0] == ';')
1290 dots = 2;
1291 else if (p[0] == '.')
1292 dots++;
1293 #endif /* VMS */
1294 p++;
1295 }
1296 if (!lose)
1297 {
1298 #ifdef VMS
1299 if (index (nm, '/'))
1300 return build_string (sys_translate_unix (nm));
1301 #endif /* VMS */
1302 if (nm == XSTRING (name)->data)
1303 return name;
1304 return build_string (nm);
1305 }
1306 }
1307
1308 /* Now determine directory to start with and put it in NEWDIR */
1309
1310 newdir = 0;
1311
1312 if (nm[0] == '~') /* prefix ~ */
1313 if (nm[1] == '/'
1314 #ifdef VMS
1315 || nm[1] == ':'
1316 #endif /* VMS */
1317 || nm[1] == 0)/* ~/filename */
1318 {
1319 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1320 newdir = (unsigned char *) "";
1321 nm++;
1322 #ifdef VMS
1323 nm++; /* Don't leave the slash in nm. */
1324 #endif /* VMS */
1325 }
1326 else /* ~user/filename */
1327 {
1328 /* Get past ~ to user */
1329 unsigned char *user = nm + 1;
1330 /* Find end of name. */
1331 unsigned char *ptr = (unsigned char *) index (user, '/');
1332 int len = ptr ? ptr - user : strlen (user);
1333 #ifdef VMS
1334 unsigned char *ptr1 = index (user, ':');
1335 if (ptr1 != 0 && ptr1 - user < len)
1336 len = ptr1 - user;
1337 #endif /* VMS */
1338 /* Copy the user name into temp storage. */
1339 o = (unsigned char *) alloca (len + 1);
1340 bcopy ((char *) user, o, len);
1341 o[len] = 0;
1342
1343 /* Look up the user name. */
1344 pw = (struct passwd *) getpwnam (o + 1);
1345 if (!pw)
1346 error ("\"%s\" isn't a registered user", o + 1);
1347
1348 newdir = (unsigned char *) pw->pw_dir;
1349
1350 /* Discard the user name from NM. */
1351 nm += len;
1352 }
1353
1354 if (nm[0] != '/'
1355 #ifdef VMS
1356 && !index (nm, ':')
1357 #endif /* not VMS */
1358 && !newdir)
1359 {
1360 if (NILP (defalt))
1361 defalt = current_buffer->directory;
1362 CHECK_STRING (defalt, 1);
1363 newdir = XSTRING (defalt)->data;
1364 }
1365
1366 /* Now concatenate the directory and name to new space in the stack frame */
1367
1368 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1369 target = (unsigned char *) alloca (tlen);
1370 *target = 0;
1371
1372 if (newdir)
1373 {
1374 #ifndef VMS
1375 if (nm[0] == 0 || nm[0] == '/')
1376 strcpy (target, newdir);
1377 else
1378 #endif
1379 file_name_as_directory (target, newdir);
1380 }
1381
1382 strcat (target, nm);
1383 #ifdef VMS
1384 if (index (target, '/'))
1385 strcpy (target, sys_translate_unix (target));
1386 #endif /* VMS */
1387
1388 /* Now canonicalize by removing /. and /foo/.. if they appear */
1389
1390 p = target;
1391 o = target;
1392
1393 while (*p)
1394 {
1395 #ifdef VMS
1396 if (*p != ']' && *p != '>' && *p != '-')
1397 {
1398 if (*p == '\\')
1399 p++;
1400 *o++ = *p++;
1401 }
1402 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1403 /* brackets are offset from each other by 2 */
1404 {
1405 p += 2;
1406 if (*p != '.' && *p != '-' && o[-1] != '.')
1407 /* convert [foo][bar] to [bar] */
1408 while (o[-1] != '[' && o[-1] != '<')
1409 o--;
1410 else if (*p == '-' && *o != '.')
1411 *--p = '.';
1412 }
1413 else if (p[0] == '-' && o[-1] == '.' &&
1414 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1415 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1416 {
1417 do
1418 o--;
1419 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1420 if (p[1] == '.') /* foo.-.bar ==> bar*/
1421 p += 2;
1422 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1423 p++, o--;
1424 /* else [foo.-] ==> [-] */
1425 }
1426 else
1427 {
1428 #ifndef VMS4_4
1429 if (*p == '-' &&
1430 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1431 p[1] != ']' && p[1] != '>' && p[1] != '.')
1432 *p = '_';
1433 #endif /* VMS4_4 */
1434 *o++ = *p++;
1435 }
1436 #else /* not VMS */
1437 if (*p != '/')
1438 {
1439 *o++ = *p++;
1440 }
1441 else if (!strncmp (p, "//", 2)
1442 #ifdef APOLLO
1443 /* // at start of filename is meaningful in Apollo system */
1444 && o != target
1445 #endif /* APOLLO */
1446 )
1447 {
1448 o = target;
1449 p++;
1450 }
1451 else if (p[0] == '/' && p[1] == '.' &&
1452 (p[2] == '/' || p[2] == 0))
1453 p += 2;
1454 else if (!strncmp (p, "/..", 3)
1455 /* `/../' is the "superroot" on certain file systems. */
1456 && o != target
1457 && (p[3] == '/' || p[3] == 0))
1458 {
1459 while (o != target && *--o != '/')
1460 ;
1461 #ifdef APOLLO
1462 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1463 ++o;
1464 else
1465 #endif /* APOLLO */
1466 if (o == target && *o == '/')
1467 ++o;
1468 p += 3;
1469 }
1470 else
1471 {
1472 *o++ = *p++;
1473 }
1474 #endif /* not VMS */
1475 }
1476
1477 return make_string (target, o - target);
1478 }
1479 #endif
1480 \f
1481 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
1482 Ssubstitute_in_file_name, 1, 1, 0,
1483 "Substitute environment variables referred to in FILENAME.\n\
1484 `$FOO' where FOO is an environment variable name means to substitute\n\
1485 the value of that variable. The variable name should be terminated\n\
1486 with a character not a letter, digit or underscore; otherwise, enclose\n\
1487 the entire variable name in braces.\n\
1488 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1489 On VMS, `$' substitution is not done; this function does little and only\n\
1490 duplicates what `expand-file-name' does.")
1491 (string)
1492 Lisp_Object string;
1493 {
1494 unsigned char *nm;
1495
1496 register unsigned char *s, *p, *o, *x, *endp;
1497 unsigned char *target;
1498 int total = 0;
1499 int substituted = 0;
1500 unsigned char *xnm;
1501
1502 CHECK_STRING (string, 0);
1503
1504 nm = XSTRING (string)->data;
1505 #ifdef MSDOS
1506 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
1507 substituted = !strcmp (nm, XSTRING (string)->data);
1508 #endif
1509 endp = nm + XSTRING (string)->size;
1510
1511 /* If /~ or // appears, discard everything through first slash. */
1512
1513 for (p = nm; p != endp; p++)
1514 {
1515 if ((p[0] == '~' ||
1516 #ifdef APOLLO
1517 /* // at start of file name is meaningful in Apollo system */
1518 (p[0] == '/' && p - 1 != nm)
1519 #else /* not APOLLO */
1520 p[0] == '/'
1521 #endif /* not APOLLO */
1522 )
1523 && p != nm &&
1524 #ifdef VMS
1525 (p[-1] == ':' || p[-1] == ']' || p[-1] == '>' ||
1526 #endif /* VMS */
1527 p[-1] == '/')
1528 #ifdef VMS
1529 )
1530 #endif /* VMS */
1531 {
1532 nm = p;
1533 substituted = 1;
1534 }
1535 #ifdef MSDOS
1536 if (p[0] && p[1] == ':')
1537 {
1538 nm = p;
1539 substituted = 1;
1540 }
1541 #endif /* MSDOS */
1542 }
1543
1544 #ifdef VMS
1545 return build_string (nm);
1546 #else
1547
1548 /* See if any variables are substituted into the string
1549 and find the total length of their values in `total' */
1550
1551 for (p = nm; p != endp;)
1552 if (*p != '$')
1553 p++;
1554 else
1555 {
1556 p++;
1557 if (p == endp)
1558 goto badsubst;
1559 else if (*p == '$')
1560 {
1561 /* "$$" means a single "$" */
1562 p++;
1563 total -= 1;
1564 substituted = 1;
1565 continue;
1566 }
1567 else if (*p == '{')
1568 {
1569 o = ++p;
1570 while (p != endp && *p != '}') p++;
1571 if (*p != '}') goto missingclose;
1572 s = p;
1573 }
1574 else
1575 {
1576 o = p;
1577 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1578 s = p;
1579 }
1580
1581 /* Copy out the variable name */
1582 target = (unsigned char *) alloca (s - o + 1);
1583 strncpy (target, o, s - o);
1584 target[s - o] = 0;
1585 #ifdef MSDOS
1586 strupr (target); /* $home == $HOME etc. */
1587 #endif
1588
1589 /* Get variable value */
1590 o = (unsigned char *) egetenv (target);
1591 if (!o) goto badvar;
1592 total += strlen (o);
1593 substituted = 1;
1594 }
1595
1596 if (!substituted)
1597 return string;
1598
1599 /* If substitution required, recopy the string and do it */
1600 /* Make space in stack frame for the new copy */
1601 xnm = (unsigned char *) alloca (XSTRING (string)->size + total + 1);
1602 x = xnm;
1603
1604 /* Copy the rest of the name through, replacing $ constructs with values */
1605 for (p = nm; *p;)
1606 if (*p != '$')
1607 *x++ = *p++;
1608 else
1609 {
1610 p++;
1611 if (p == endp)
1612 goto badsubst;
1613 else if (*p == '$')
1614 {
1615 *x++ = *p++;
1616 continue;
1617 }
1618 else if (*p == '{')
1619 {
1620 o = ++p;
1621 while (p != endp && *p != '}') p++;
1622 if (*p != '}') goto missingclose;
1623 s = p++;
1624 }
1625 else
1626 {
1627 o = p;
1628 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1629 s = p;
1630 }
1631
1632 /* Copy out the variable name */
1633 target = (unsigned char *) alloca (s - o + 1);
1634 strncpy (target, o, s - o);
1635 target[s - o] = 0;
1636 #ifdef MSDOS
1637 strupr (target); /* $home == $HOME etc. */
1638 #endif
1639
1640 /* Get variable value */
1641 o = (unsigned char *) egetenv (target);
1642 if (!o)
1643 goto badvar;
1644
1645 strcpy (x, o);
1646 x += strlen (o);
1647 }
1648
1649 *x = 0;
1650
1651 /* If /~ or // appears, discard everything through first slash. */
1652
1653 for (p = xnm; p != x; p++)
1654 if ((p[0] == '~' ||
1655 #ifdef APOLLO
1656 /* // at start of file name is meaningful in Apollo system */
1657 (p[0] == '/' && p - 1 != xnm)
1658 #else /* not APOLLO */
1659 p[0] == '/'
1660 #endif /* not APOLLO */
1661 )
1662 && p != nm && p[-1] == '/')
1663 xnm = p;
1664 #ifdef MSDOS
1665 else if (p[0] && p[1] == ':')
1666 xnm = p;
1667 #endif
1668
1669 return make_string (xnm, x - xnm);
1670
1671 badsubst:
1672 error ("Bad format environment-variable substitution");
1673 missingclose:
1674 error ("Missing \"}\" in environment-variable substitution");
1675 badvar:
1676 error ("Substituting nonexistent environment variable \"%s\"", target);
1677
1678 /* NOTREACHED */
1679 #endif /* not VMS */
1680 }
1681 \f
1682 /* A slightly faster and more convenient way to get
1683 (directory-file-name (expand-file-name FOO)). */
1684
1685 Lisp_Object
1686 expand_and_dir_to_file (filename, defdir)
1687 Lisp_Object filename, defdir;
1688 {
1689 register Lisp_Object abspath;
1690
1691 abspath = Fexpand_file_name (filename, defdir);
1692 #ifdef VMS
1693 {
1694 register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1];
1695 if (c == ':' || c == ']' || c == '>')
1696 abspath = Fdirectory_file_name (abspath);
1697 }
1698 #else
1699 /* Remove final slash, if any (unless path is root).
1700 stat behaves differently depending! */
1701 if (XSTRING (abspath)->size > 1
1702 && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/')
1703 /* We cannot take shortcuts; they might be wrong for magic file names. */
1704 abspath = Fdirectory_file_name (abspath);
1705 #endif
1706 return abspath;
1707 }
1708 \f
1709 barf_or_query_if_file_exists (absname, querystring, interactive)
1710 Lisp_Object absname;
1711 unsigned char *querystring;
1712 int interactive;
1713 {
1714 register Lisp_Object tem;
1715 struct stat statbuf;
1716 struct gcpro gcpro1;
1717
1718 /* stat is a good way to tell whether the file exists,
1719 regardless of what access permissions it has. */
1720 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
1721 {
1722 if (! interactive)
1723 Fsignal (Qfile_already_exists,
1724 Fcons (build_string ("File already exists"),
1725 Fcons (absname, Qnil)));
1726 GCPRO1 (absname);
1727 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1728 XSTRING (absname)->data, querystring));
1729 UNGCPRO;
1730 if (NILP (tem))
1731 Fsignal (Qfile_already_exists,
1732 Fcons (build_string ("File already exists"),
1733 Fcons (absname, Qnil)));
1734 }
1735 return;
1736 }
1737
1738 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
1739 "fCopy file: \nFCopy %s to file: \np\nP",
1740 "Copy FILE to NEWNAME. Both args must be strings.\n\
1741 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1742 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1743 A number as third arg means request confirmation if NEWNAME already exists.\n\
1744 This is what happens in interactive use with M-x.\n\
1745 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1746 last-modified time as the old one. (This works on only some systems.)\n\
1747 A prefix arg makes KEEP-TIME non-nil.")
1748 (filename, newname, ok_if_already_exists, keep_date)
1749 Lisp_Object filename, newname, ok_if_already_exists, keep_date;
1750 {
1751 int ifd, ofd, n;
1752 char buf[16 * 1024];
1753 struct stat st;
1754 Lisp_Object handler;
1755 struct gcpro gcpro1, gcpro2;
1756 int count = specpdl_ptr - specpdl;
1757 int input_file_statable_p;
1758
1759 GCPRO2 (filename, newname);
1760 CHECK_STRING (filename, 0);
1761 CHECK_STRING (newname, 1);
1762 filename = Fexpand_file_name (filename, Qnil);
1763 newname = Fexpand_file_name (newname, Qnil);
1764
1765 /* If the input file name has special constructs in it,
1766 call the corresponding file handler. */
1767 handler = Ffind_file_name_handler (filename, Qcopy_file);
1768 /* Likewise for output file name. */
1769 if (NILP (handler))
1770 handler = Ffind_file_name_handler (newname, Qcopy_file);
1771 if (!NILP (handler))
1772 RETURN_UNGCPRO (call5 (handler, Qcopy_file, filename, newname,
1773 ok_if_already_exists, keep_date));
1774
1775 if (NILP (ok_if_already_exists)
1776 || XTYPE (ok_if_already_exists) == Lisp_Int)
1777 barf_or_query_if_file_exists (newname, "copy to it",
1778 XTYPE (ok_if_already_exists) == Lisp_Int);
1779
1780 ifd = open (XSTRING (filename)->data, O_RDONLY);
1781 if (ifd < 0)
1782 report_file_error ("Opening input file", Fcons (filename, Qnil));
1783
1784 record_unwind_protect (close_file_unwind, make_number (ifd));
1785
1786 /* We can only copy regular files and symbolic links. Other files are not
1787 copyable by us. */
1788 input_file_statable_p = (fstat (ifd, &st) >= 0);
1789
1790 #if defined (S_ISREG) && defined (S_ISLNK)
1791 if (input_file_statable_p)
1792 {
1793 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
1794 {
1795 #if defined (EISDIR)
1796 /* Get a better looking error message. */
1797 errno = EISDIR;
1798 #endif /* EISDIR */
1799 report_file_error ("Non-regular file", Fcons (filename, Qnil));
1800 }
1801 }
1802 #endif /* S_ISREG && S_ISLNK */
1803
1804 #ifdef VMS
1805 /* Create the copy file with the same record format as the input file */
1806 ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
1807 #else
1808 #ifdef MSDOS
1809 /* System's default file type was set to binary by _fmode in emacs.c. */
1810 ofd = creat (XSTRING (newname)->data, S_IREAD | S_IWRITE);
1811 #else /* not MSDOS */
1812 ofd = creat (XSTRING (newname)->data, 0666);
1813 #endif /* not MSDOS */
1814 #endif /* VMS */
1815 if (ofd < 0)
1816 report_file_error ("Opening output file", Fcons (newname, Qnil));
1817
1818 record_unwind_protect (close_file_unwind, make_number (ofd));
1819
1820 immediate_quit = 1;
1821 QUIT;
1822 while ((n = read (ifd, buf, sizeof buf)) > 0)
1823 if (write (ofd, buf, n) != n)
1824 report_file_error ("I/O error", Fcons (newname, Qnil));
1825 immediate_quit = 0;
1826
1827 /* Closing the output clobbers the file times on some systems. */
1828 if (close (ofd) < 0)
1829 report_file_error ("I/O error", Fcons (newname, Qnil));
1830
1831 if (input_file_statable_p)
1832 {
1833 if (!NILP (keep_date))
1834 {
1835 EMACS_TIME atime, mtime;
1836 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
1837 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
1838 EMACS_SET_UTIMES (XSTRING (newname)->data, atime, mtime);
1839 }
1840 #ifdef APOLLO
1841 if (!egetenv ("USE_DOMAIN_ACLS"))
1842 #endif
1843 chmod (XSTRING (newname)->data, st.st_mode & 07777);
1844 }
1845
1846 close (ifd);
1847
1848 /* Discard the unwind protects. */
1849 specpdl_ptr = specpdl + count;
1850
1851 UNGCPRO;
1852 return Qnil;
1853 }
1854
1855 DEFUN ("make-directory-internal", Fmake_directory_internal,
1856 Smake_directory_internal, 1, 1, 0,
1857 "Create a directory. One argument, a file name string.")
1858 (dirname)
1859 Lisp_Object dirname;
1860 {
1861 unsigned char *dir;
1862 Lisp_Object handler;
1863
1864 CHECK_STRING (dirname, 0);
1865 dirname = Fexpand_file_name (dirname, Qnil);
1866
1867 handler = Ffind_file_name_handler (dirname, Qmake_directory_internal);
1868 if (!NILP (handler))
1869 return call2 (handler, Qmake_directory_internal, dirname);
1870
1871 dir = XSTRING (dirname)->data;
1872
1873 if (mkdir (dir, 0777) != 0)
1874 report_file_error ("Creating directory", Flist (1, &dirname));
1875
1876 return Qnil;
1877 }
1878
1879 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
1880 "Delete a directory. One argument, a file name or directory name string.")
1881 (dirname)
1882 Lisp_Object dirname;
1883 {
1884 unsigned char *dir;
1885 Lisp_Object handler;
1886
1887 CHECK_STRING (dirname, 0);
1888 dirname = Fdirectory_file_name (Fexpand_file_name (dirname, Qnil));
1889 dir = XSTRING (dirname)->data;
1890
1891 handler = Ffind_file_name_handler (dirname, Qdelete_directory);
1892 if (!NILP (handler))
1893 return call2 (handler, Qdelete_directory, dirname);
1894
1895 if (rmdir (dir) != 0)
1896 report_file_error ("Removing directory", Flist (1, &dirname));
1897
1898 return Qnil;
1899 }
1900
1901 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
1902 "Delete specified file. One argument, a file name string.\n\
1903 If file has multiple names, it continues to exist with the other names.")
1904 (filename)
1905 Lisp_Object filename;
1906 {
1907 int count = specpdl_ptr - specpdl;
1908 Lisp_Object handler;
1909 CHECK_STRING (filename, 0);
1910 filename = Fexpand_file_name (filename, Qnil);
1911
1912 specbind (Qcompletion_ignored_extensions, Qnil);
1913 handler = Ffind_file_name_handler (filename, Qdelete_file);
1914 if (!NILP (handler))
1915 return unbind_to (count, call2 (handler, Qdelete_file, filename));
1916
1917 if (0 > unlink (XSTRING (filename)->data))
1918 report_file_error ("Removing old name", Flist (1, &filename));
1919 return unbind_to (count, Qnil);
1920 }
1921
1922 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
1923 "fRename file: \nFRename %s to file: \np",
1924 "Rename FILE as NEWNAME. Both args strings.\n\
1925 If file has names other than FILE, it continues to have those names.\n\
1926 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1927 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1928 A number as third arg means request confirmation if NEWNAME already exists.\n\
1929 This is what happens in interactive use with M-x.")
1930 (filename, newname, ok_if_already_exists)
1931 Lisp_Object filename, newname, ok_if_already_exists;
1932 {
1933 #ifdef NO_ARG_ARRAY
1934 Lisp_Object args[2];
1935 #endif
1936 Lisp_Object handler;
1937 struct gcpro gcpro1, gcpro2;
1938
1939 GCPRO2 (filename, newname);
1940 CHECK_STRING (filename, 0);
1941 CHECK_STRING (newname, 1);
1942 filename = Fexpand_file_name (filename, Qnil);
1943 newname = Fexpand_file_name (newname, Qnil);
1944
1945 /* If the file name has special constructs in it,
1946 call the corresponding file handler. */
1947 handler = Ffind_file_name_handler (filename, Qrename_file);
1948 if (NILP (handler))
1949 handler = Ffind_file_name_handler (newname, Qrename_file);
1950 if (!NILP (handler))
1951 RETURN_UNGCPRO (call4 (handler, Qrename_file,
1952 filename, newname, ok_if_already_exists));
1953
1954 if (NILP (ok_if_already_exists)
1955 || XTYPE (ok_if_already_exists) == Lisp_Int)
1956 barf_or_query_if_file_exists (newname, "rename to it",
1957 XTYPE (ok_if_already_exists) == Lisp_Int);
1958 #ifndef BSD4_1
1959 if (0 > rename (XSTRING (filename)->data, XSTRING (newname)->data))
1960 #else
1961 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data)
1962 || 0 > unlink (XSTRING (filename)->data))
1963 #endif
1964 {
1965 if (errno == EXDEV)
1966 {
1967 Fcopy_file (filename, newname,
1968 /* We have already prompted if it was an integer,
1969 so don't have copy-file prompt again. */
1970 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
1971 Fdelete_file (filename);
1972 }
1973 else
1974 #ifdef NO_ARG_ARRAY
1975 {
1976 args[0] = filename;
1977 args[1] = newname;
1978 report_file_error ("Renaming", Flist (2, args));
1979 }
1980 #else
1981 report_file_error ("Renaming", Flist (2, &filename));
1982 #endif
1983 }
1984 UNGCPRO;
1985 return Qnil;
1986 }
1987
1988 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
1989 "fAdd name to file: \nFName to add to %s: \np",
1990 "Give FILE additional name NEWNAME. Both args strings.\n\
1991 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1992 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1993 A number as third arg means request confirmation if NEWNAME already exists.\n\
1994 This is what happens in interactive use with M-x.")
1995 (filename, newname, ok_if_already_exists)
1996 Lisp_Object filename, newname, ok_if_already_exists;
1997 {
1998 #ifdef NO_ARG_ARRAY
1999 Lisp_Object args[2];
2000 #endif
2001 Lisp_Object handler;
2002 struct gcpro gcpro1, gcpro2;
2003
2004 GCPRO2 (filename, newname);
2005 CHECK_STRING (filename, 0);
2006 CHECK_STRING (newname, 1);
2007 filename = Fexpand_file_name (filename, Qnil);
2008 newname = Fexpand_file_name (newname, Qnil);
2009
2010 /* If the file name has special constructs in it,
2011 call the corresponding file handler. */
2012 handler = Ffind_file_name_handler (filename, Qadd_name_to_file);
2013 if (!NILP (handler))
2014 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, filename,
2015 newname, ok_if_already_exists));
2016
2017 if (NILP (ok_if_already_exists)
2018 || XTYPE (ok_if_already_exists) == Lisp_Int)
2019 barf_or_query_if_file_exists (newname, "make it a new name",
2020 XTYPE (ok_if_already_exists) == Lisp_Int);
2021 unlink (XSTRING (newname)->data);
2022 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data))
2023 {
2024 #ifdef NO_ARG_ARRAY
2025 args[0] = filename;
2026 args[1] = newname;
2027 report_file_error ("Adding new name", Flist (2, args));
2028 #else
2029 report_file_error ("Adding new name", Flist (2, &filename));
2030 #endif
2031 }
2032
2033 UNGCPRO;
2034 return Qnil;
2035 }
2036
2037 #ifdef S_IFLNK
2038 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2039 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2040 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
2041 Signals a `file-already-exists' error if a file LINKNAME already exists\n\
2042 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2043 A number as third arg means request confirmation if LINKNAME already exists.\n\
2044 This happens for interactive use with M-x.")
2045 (filename, linkname, ok_if_already_exists)
2046 Lisp_Object filename, linkname, ok_if_already_exists;
2047 {
2048 #ifdef NO_ARG_ARRAY
2049 Lisp_Object args[2];
2050 #endif
2051 Lisp_Object handler;
2052 struct gcpro gcpro1, gcpro2;
2053
2054 GCPRO2 (filename, linkname);
2055 CHECK_STRING (filename, 0);
2056 CHECK_STRING (linkname, 1);
2057 /* If the link target has a ~, we must expand it to get
2058 a truly valid file name. Otherwise, do not expand;
2059 we want to permit links to relative file names. */
2060 if (XSTRING (filename)->data[0] == '~')
2061 filename = Fexpand_file_name (filename, Qnil);
2062 linkname = Fexpand_file_name (linkname, Qnil);
2063
2064 /* If the file name has special constructs in it,
2065 call the corresponding file handler. */
2066 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
2067 if (!NILP (handler))
2068 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2069 linkname, ok_if_already_exists));
2070
2071 if (NILP (ok_if_already_exists)
2072 || XTYPE (ok_if_already_exists) == Lisp_Int)
2073 barf_or_query_if_file_exists (linkname, "make it a link",
2074 XTYPE (ok_if_already_exists) == Lisp_Int);
2075 if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2076 {
2077 /* If we didn't complain already, silently delete existing file. */
2078 if (errno == EEXIST)
2079 {
2080 unlink (XSTRING (linkname)->data);
2081 if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2082 {
2083 UNGCPRO;
2084 return Qnil;
2085 }
2086 }
2087
2088 #ifdef NO_ARG_ARRAY
2089 args[0] = filename;
2090 args[1] = linkname;
2091 report_file_error ("Making symbolic link", Flist (2, args));
2092 #else
2093 report_file_error ("Making symbolic link", Flist (2, &filename));
2094 #endif
2095 }
2096 UNGCPRO;
2097 return Qnil;
2098 }
2099 #endif /* S_IFLNK */
2100
2101 #ifdef VMS
2102
2103 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2104 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
2105 "Define the job-wide logical name NAME to have the value STRING.\n\
2106 If STRING is nil or a null string, the logical name NAME is deleted.")
2107 (varname, string)
2108 Lisp_Object varname;
2109 Lisp_Object string;
2110 {
2111 CHECK_STRING (varname, 0);
2112 if (NILP (string))
2113 delete_logical_name (XSTRING (varname)->data);
2114 else
2115 {
2116 CHECK_STRING (string, 1);
2117
2118 if (XSTRING (string)->size == 0)
2119 delete_logical_name (XSTRING (varname)->data);
2120 else
2121 define_logical_name (XSTRING (varname)->data, XSTRING (string)->data);
2122 }
2123
2124 return string;
2125 }
2126 #endif /* VMS */
2127
2128 #ifdef HPUX_NET
2129
2130 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2131 "Open a network connection to PATH using LOGIN as the login string.")
2132 (path, login)
2133 Lisp_Object path, login;
2134 {
2135 int netresult;
2136
2137 CHECK_STRING (path, 0);
2138 CHECK_STRING (login, 0);
2139
2140 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2141
2142 if (netresult == -1)
2143 return Qnil;
2144 else
2145 return Qt;
2146 }
2147 #endif /* HPUX_NET */
2148 \f
2149 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2150 1, 1, 0,
2151 "Return t if file FILENAME specifies an absolute path name.\n\
2152 On Unix, this is a name starting with a `/' or a `~'.")
2153 (filename)
2154 Lisp_Object filename;
2155 {
2156 unsigned char *ptr;
2157
2158 CHECK_STRING (filename, 0);
2159 ptr = XSTRING (filename)->data;
2160 if (*ptr == '/' || *ptr == '~'
2161 #ifdef VMS
2162 /* ??? This criterion is probably wrong for '<'. */
2163 || index (ptr, ':') || index (ptr, '<')
2164 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2165 && ptr[1] != '.')
2166 #endif /* VMS */
2167 #ifdef MSDOS
2168 || (*ptr != 0 && ptr[1] == ':' && (ptr[2] == '/' || ptr[2] == '\\'))
2169 #endif
2170 )
2171 return Qt;
2172 else
2173 return Qnil;
2174 }
2175
2176 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2177 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
2178 See also `file-readable-p' and `file-attributes'.")
2179 (filename)
2180 Lisp_Object filename;
2181 {
2182 Lisp_Object abspath;
2183 Lisp_Object handler;
2184 struct stat statbuf;
2185
2186 CHECK_STRING (filename, 0);
2187 abspath = Fexpand_file_name (filename, Qnil);
2188
2189 /* If the file name has special constructs in it,
2190 call the corresponding file handler. */
2191 handler = Ffind_file_name_handler (abspath, Qfile_exists_p);
2192 if (!NILP (handler))
2193 return call2 (handler, Qfile_exists_p, abspath);
2194
2195 return (stat (XSTRING (abspath)->data, &statbuf) >= 0) ? Qt : Qnil;
2196 }
2197
2198 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
2199 "Return t if FILENAME can be executed by you.\n\
2200 For a directory, this means you can access files in that directory.")
2201 (filename)
2202 Lisp_Object filename;
2203
2204 {
2205 Lisp_Object abspath;
2206 Lisp_Object handler;
2207
2208 CHECK_STRING (filename, 0);
2209 abspath = Fexpand_file_name (filename, Qnil);
2210
2211 /* If the file name has special constructs in it,
2212 call the corresponding file handler. */
2213 handler = Ffind_file_name_handler (abspath, Qfile_executable_p);
2214 if (!NILP (handler))
2215 return call2 (handler, Qfile_executable_p, abspath);
2216
2217 return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
2218 }
2219
2220 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2221 "Return t if file FILENAME exists and you can read it.\n\
2222 See also `file-exists-p' and `file-attributes'.")
2223 (filename)
2224 Lisp_Object filename;
2225 {
2226 Lisp_Object abspath;
2227 Lisp_Object handler;
2228 int desc;
2229
2230 CHECK_STRING (filename, 0);
2231 abspath = Fexpand_file_name (filename, Qnil);
2232
2233 /* If the file name has special constructs in it,
2234 call the corresponding file handler. */
2235 handler = Ffind_file_name_handler (abspath, Qfile_readable_p);
2236 if (!NILP (handler))
2237 return call2 (handler, Qfile_readable_p, abspath);
2238
2239 desc = open (XSTRING (abspath)->data, O_RDONLY);
2240 if (desc < 0)
2241 return Qnil;
2242 close (desc);
2243 return Qt;
2244 }
2245
2246 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2247 "Return non-nil if file FILENAME is the name of a symbolic link.\n\
2248 The value is the name of the file to which it is linked.\n\
2249 Otherwise returns nil.")
2250 (filename)
2251 Lisp_Object filename;
2252 {
2253 #ifdef S_IFLNK
2254 char *buf;
2255 int bufsize;
2256 int valsize;
2257 Lisp_Object val;
2258 Lisp_Object handler;
2259
2260 CHECK_STRING (filename, 0);
2261 filename = Fexpand_file_name (filename, Qnil);
2262
2263 /* If the file name has special constructs in it,
2264 call the corresponding file handler. */
2265 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
2266 if (!NILP (handler))
2267 return call2 (handler, Qfile_symlink_p, filename);
2268
2269 bufsize = 100;
2270 while (1)
2271 {
2272 buf = (char *) xmalloc (bufsize);
2273 bzero (buf, bufsize);
2274 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
2275 if (valsize < bufsize) break;
2276 /* Buffer was not long enough */
2277 xfree (buf);
2278 bufsize *= 2;
2279 }
2280 if (valsize == -1)
2281 {
2282 xfree (buf);
2283 return Qnil;
2284 }
2285 val = make_string (buf, valsize);
2286 xfree (buf);
2287 return val;
2288 #else /* not S_IFLNK */
2289 return Qnil;
2290 #endif /* not S_IFLNK */
2291 }
2292
2293 #ifdef SOLARIS_BROKEN_ACCESS
2294 /* In Solaris 2.1, the readonly-ness of the filesystem is not
2295 considered by the access system call. This is Sun's bug, but we
2296 still have to make Emacs work. */
2297
2298 #include <sys/statvfs.h>
2299
2300 static int
2301 ro_fsys (path)
2302 char *path;
2303 {
2304 struct statvfs statvfsb;
2305
2306 if (statvfs(path, &statvfsb))
2307 return 1; /* error from statvfs, be conservative and say not wrtable */
2308 else
2309 /* Otherwise, fsys is ro if bit is set. */
2310 return statvfsb.f_flag & ST_RDONLY;
2311 }
2312 #else
2313 /* But on every other os, access has already done the right thing. */
2314 #define ro_fsys(path) 0
2315 #endif
2316
2317 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2318 on the RT/PC. */
2319 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2320 "Return t if file FILENAME can be written or created by you.")
2321 (filename)
2322 Lisp_Object filename;
2323 {
2324 Lisp_Object abspath, dir;
2325 Lisp_Object handler;
2326
2327 CHECK_STRING (filename, 0);
2328 abspath = Fexpand_file_name (filename, Qnil);
2329
2330 /* If the file name has special constructs in it,
2331 call the corresponding file handler. */
2332 handler = Ffind_file_name_handler (abspath, Qfile_writable_p);
2333 if (!NILP (handler))
2334 return call2 (handler, Qfile_writable_p, abspath);
2335
2336 if (access (XSTRING (abspath)->data, 0) >= 0)
2337 return ((access (XSTRING (abspath)->data, 2) >= 0
2338 && ! ro_fsys ((char *) XSTRING (abspath)->data))
2339 ? Qt : Qnil);
2340 dir = Ffile_name_directory (abspath);
2341 #ifdef VMS
2342 if (!NILP (dir))
2343 dir = Fdirectory_file_name (dir);
2344 #endif /* VMS */
2345 #ifdef MSDOS
2346 if (!NILP (dir))
2347 dir = Fdirectory_file_name (dir);
2348 #endif /* MSDOS */
2349 return ((access (!NILP (dir) ? (char *) XSTRING (dir)->data : "", 2) >= 0
2350 && ! ro_fsys ((char *) XSTRING (dir)->data))
2351 ? Qt : Qnil);
2352 }
2353
2354 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2355 "Return t if file FILENAME is the name of a directory as a file.\n\
2356 A directory name spec may be given instead; then the value is t\n\
2357 if the directory so specified exists and really is a directory.")
2358 (filename)
2359 Lisp_Object filename;
2360 {
2361 register Lisp_Object abspath;
2362 struct stat st;
2363 Lisp_Object handler;
2364
2365 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2366
2367 /* If the file name has special constructs in it,
2368 call the corresponding file handler. */
2369 handler = Ffind_file_name_handler (abspath, Qfile_directory_p);
2370 if (!NILP (handler))
2371 return call2 (handler, Qfile_directory_p, abspath);
2372
2373 if (stat (XSTRING (abspath)->data, &st) < 0)
2374 return Qnil;
2375 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2376 }
2377
2378 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
2379 "Return t if file FILENAME is the name of a directory as a file,\n\
2380 and files in that directory can be opened by you. In order to use a\n\
2381 directory as a buffer's current directory, this predicate must return true.\n\
2382 A directory name spec may be given instead; then the value is t\n\
2383 if the directory so specified exists and really is a readable and\n\
2384 searchable directory.")
2385 (filename)
2386 Lisp_Object filename;
2387 {
2388 Lisp_Object handler;
2389 int tem;
2390 struct gcpro gcpro1;
2391
2392 /* If the file name has special constructs in it,
2393 call the corresponding file handler. */
2394 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2395 if (!NILP (handler))
2396 return call2 (handler, Qfile_accessible_directory_p, filename);
2397
2398 /* It's an unlikely combination, but yes we really do need to gcpro:
2399 Suppose that file-accessible-directory-p has no handler, but
2400 file-directory-p does have a handler; this handler causes a GC which
2401 relocates the string in `filename'; and finally file-directory-p
2402 returns non-nil. Then we would end up passing a garbaged string
2403 to file-executable-p. */
2404 GCPRO1 (filename);
2405 tem = (NILP (Ffile_directory_p (filename))
2406 || NILP (Ffile_executable_p (filename)));
2407 UNGCPRO;
2408 return tem ? Qnil : Qt;
2409 }
2410
2411 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2412 "Return mode bits of FILE, as an integer.")
2413 (filename)
2414 Lisp_Object filename;
2415 {
2416 Lisp_Object abspath;
2417 struct stat st;
2418 Lisp_Object handler;
2419
2420 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2421
2422 /* If the file name has special constructs in it,
2423 call the corresponding file handler. */
2424 handler = Ffind_file_name_handler (abspath, Qfile_modes);
2425 if (!NILP (handler))
2426 return call2 (handler, Qfile_modes, abspath);
2427
2428 if (stat (XSTRING (abspath)->data, &st) < 0)
2429 return Qnil;
2430 #ifdef MSDOS
2431 {
2432 int len;
2433 char *suffix;
2434 if (S_ISREG (st.st_mode)
2435 && (len = XSTRING (abspath)->size) >= 5
2436 && (stricmp ((suffix = XSTRING (abspath)->data + len-4), ".com") == 0
2437 || stricmp (suffix, ".exe") == 0
2438 || stricmp (suffix, ".bat") == 0))
2439 st.st_mode |= S_IEXEC;
2440 }
2441 #endif /* MSDOS */
2442
2443 return make_number (st.st_mode & 07777);
2444 }
2445
2446 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
2447 "Set mode bits of FILE to MODE (an integer).\n\
2448 Only the 12 low bits of MODE are used.")
2449 (filename, mode)
2450 Lisp_Object filename, mode;
2451 {
2452 Lisp_Object abspath;
2453 Lisp_Object handler;
2454
2455 abspath = Fexpand_file_name (filename, current_buffer->directory);
2456 CHECK_NUMBER (mode, 1);
2457
2458 /* If the file name has special constructs in it,
2459 call the corresponding file handler. */
2460 handler = Ffind_file_name_handler (abspath, Qset_file_modes);
2461 if (!NILP (handler))
2462 return call3 (handler, Qset_file_modes, abspath, mode);
2463
2464 #ifndef APOLLO
2465 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2466 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2467 #else /* APOLLO */
2468 if (!egetenv ("USE_DOMAIN_ACLS"))
2469 {
2470 struct stat st;
2471 struct timeval tvp[2];
2472
2473 /* chmod on apollo also change the file's modtime; need to save the
2474 modtime and then restore it. */
2475 if (stat (XSTRING (abspath)->data, &st) < 0)
2476 {
2477 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2478 return (Qnil);
2479 }
2480
2481 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2482 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2483
2484 /* reset the old accessed and modified times. */
2485 tvp[0].tv_sec = st.st_atime + 1; /* +1 due to an Apollo roundoff bug */
2486 tvp[0].tv_usec = 0;
2487 tvp[1].tv_sec = st.st_mtime + 1; /* +1 due to an Apollo roundoff bug */
2488 tvp[1].tv_usec = 0;
2489
2490 if (utimes (XSTRING (abspath)->data, tvp) < 0)
2491 report_file_error ("Doing utimes", Fcons (abspath, Qnil));
2492 }
2493 #endif /* APOLLO */
2494
2495 return Qnil;
2496 }
2497
2498 DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
2499 "Set the file permission bits for newly created files.\n\
2500 The argument MODE should be an integer; only the low 9 bits are used.\n\
2501 This setting is inherited by subprocesses.")
2502 (mode)
2503 Lisp_Object mode;
2504 {
2505 CHECK_NUMBER (mode, 0);
2506
2507 umask ((~ XINT (mode)) & 0777);
2508
2509 return Qnil;
2510 }
2511
2512 DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
2513 "Return the default file protection for created files.\n\
2514 The value is an integer.")
2515 ()
2516 {
2517 int realmask;
2518 Lisp_Object value;
2519
2520 realmask = umask (0);
2521 umask (realmask);
2522
2523 XSET (value, Lisp_Int, (~ realmask) & 0777);
2524 return value;
2525 }
2526
2527 #ifdef unix
2528
2529 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
2530 "Tell Unix to finish all pending disk updates.")
2531 ()
2532 {
2533 sync ();
2534 return Qnil;
2535 }
2536
2537 #endif /* unix */
2538
2539 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
2540 "Return t if file FILE1 is newer than file FILE2.\n\
2541 If FILE1 does not exist, the answer is nil;\n\
2542 otherwise, if FILE2 does not exist, the answer is t.")
2543 (file1, file2)
2544 Lisp_Object file1, file2;
2545 {
2546 Lisp_Object abspath1, abspath2;
2547 struct stat st;
2548 int mtime1;
2549 Lisp_Object handler;
2550 struct gcpro gcpro1, gcpro2;
2551
2552 CHECK_STRING (file1, 0);
2553 CHECK_STRING (file2, 0);
2554
2555 abspath1 = Qnil;
2556 GCPRO2 (abspath1, file2);
2557 abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
2558 abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
2559 UNGCPRO;
2560
2561 /* If the file name has special constructs in it,
2562 call the corresponding file handler. */
2563 handler = Ffind_file_name_handler (abspath1, Qfile_newer_than_file_p);
2564 if (NILP (handler))
2565 handler = Ffind_file_name_handler (abspath2, Qfile_newer_than_file_p);
2566 if (!NILP (handler))
2567 return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2);
2568
2569 if (stat (XSTRING (abspath1)->data, &st) < 0)
2570 return Qnil;
2571
2572 mtime1 = st.st_mtime;
2573
2574 if (stat (XSTRING (abspath2)->data, &st) < 0)
2575 return Qt;
2576
2577 return (mtime1 > st.st_mtime) ? Qt : Qnil;
2578 }
2579 \f
2580 #ifdef MSDOS
2581 Lisp_Object Qfind_buffer_file_type;
2582 #endif
2583
2584 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
2585 1, 5, 0,
2586 "Insert contents of file FILENAME after point.\n\
2587 Returns list of absolute file name and length of data inserted.\n\
2588 If second argument VISIT is non-nil, the buffer's visited filename\n\
2589 and last save file modtime are set, and it is marked unmodified.\n\
2590 If visiting and the file does not exist, visiting is completed\n\
2591 before the error is signaled.\n\n\
2592 The optional third and fourth arguments BEG and END\n\
2593 specify what portion of the file to insert.\n\
2594 If VISIT is non-nil, BEG and END must be nil.\n\
2595 If optional fifth argument REPLACE is non-nil,\n\
2596 it means replace the current buffer contents (in the accessible portion)\n\
2597 with the file contents. This is better than simply deleting and inserting\n\
2598 the whole thing because (1) it preserves some marker positions\n\
2599 and (2) it puts less data in the undo list.")
2600 (filename, visit, beg, end, replace)
2601 Lisp_Object filename, visit, beg, end, replace;
2602 {
2603 struct stat st;
2604 register int fd;
2605 register int inserted = 0;
2606 register int how_much;
2607 int count = specpdl_ptr - specpdl;
2608 struct gcpro gcpro1, gcpro2, gcpro3;
2609 Lisp_Object handler, val, insval;
2610 Lisp_Object p;
2611 int total;
2612
2613 val = Qnil;
2614 p = Qnil;
2615
2616 GCPRO3 (filename, val, p);
2617 if (!NILP (current_buffer->read_only))
2618 Fbarf_if_buffer_read_only();
2619
2620 CHECK_STRING (filename, 0);
2621 filename = Fexpand_file_name (filename, Qnil);
2622
2623 /* If the file name has special constructs in it,
2624 call the corresponding file handler. */
2625 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
2626 if (!NILP (handler))
2627 {
2628 val = call6 (handler, Qinsert_file_contents, filename,
2629 visit, beg, end, replace);
2630 goto handled;
2631 }
2632
2633 fd = -1;
2634
2635 #ifndef APOLLO
2636 if (stat (XSTRING (filename)->data, &st) < 0)
2637 #else
2638 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
2639 || fstat (fd, &st) < 0)
2640 #endif /* not APOLLO */
2641 {
2642 if (fd >= 0) close (fd);
2643 badopen:
2644 if (NILP (visit))
2645 report_file_error ("Opening input file", Fcons (filename, Qnil));
2646 st.st_mtime = -1;
2647 how_much = 0;
2648 goto notfound;
2649 }
2650
2651 #ifdef S_IFREG
2652 /* This code will need to be changed in order to work on named
2653 pipes, and it's probably just not worth it. So we should at
2654 least signal an error. */
2655 if (!S_ISREG (st.st_mode))
2656 Fsignal (Qfile_error,
2657 Fcons (build_string ("not a regular file"),
2658 Fcons (filename, Qnil)));
2659 #endif
2660
2661 if (fd < 0)
2662 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
2663 goto badopen;
2664
2665 /* Replacement should preserve point as it preserves markers. */
2666 if (!NILP (replace))
2667 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
2668
2669 record_unwind_protect (close_file_unwind, make_number (fd));
2670
2671 /* Supposedly happens on VMS. */
2672 if (st.st_size < 0)
2673 error ("File size is negative");
2674
2675 if (!NILP (beg) || !NILP (end))
2676 if (!NILP (visit))
2677 error ("Attempt to visit less than an entire file");
2678
2679 if (!NILP (beg))
2680 CHECK_NUMBER (beg, 0);
2681 else
2682 XFASTINT (beg) = 0;
2683
2684 if (!NILP (end))
2685 CHECK_NUMBER (end, 0);
2686 else
2687 {
2688 XSETINT (end, st.st_size);
2689 if (XINT (end) != st.st_size)
2690 error ("maximum buffer size exceeded");
2691 }
2692
2693 /* If requested, replace the accessible part of the buffer
2694 with the file contents. Avoid replacing text at the
2695 beginning or end of the buffer that matches the file contents;
2696 that preserves markers pointing to the unchanged parts. */
2697 #ifdef MSDOS
2698 /* On MSDOS, replace mode doesn't really work, except for binary files,
2699 and it's not worth supporting just for them. */
2700 if (!NILP (replace))
2701 {
2702 replace = Qnil;
2703 XFASTINT (beg) = 0;
2704 XFASTINT (end) = st.st_size;
2705 del_range_1 (BEGV, ZV, 0);
2706 }
2707 #else /* MSDOS */
2708 if (!NILP (replace))
2709 {
2710 unsigned char buffer[1 << 14];
2711 int same_at_start = BEGV;
2712 int same_at_end = ZV;
2713 int overlap;
2714
2715 immediate_quit = 1;
2716 QUIT;
2717 /* Count how many chars at the start of the file
2718 match the text at the beginning of the buffer. */
2719 while (1)
2720 {
2721 int nread, bufpos;
2722
2723 nread = read (fd, buffer, sizeof buffer);
2724 if (nread < 0)
2725 error ("IO error reading %s: %s",
2726 XSTRING (filename)->data, strerror (errno));
2727 else if (nread == 0)
2728 break;
2729 bufpos = 0;
2730 while (bufpos < nread && same_at_start < ZV
2731 && FETCH_CHAR (same_at_start) == buffer[bufpos])
2732 same_at_start++, bufpos++;
2733 /* If we found a discrepancy, stop the scan.
2734 Otherwise loop around and scan the next bufferfull. */
2735 if (bufpos != nread)
2736 break;
2737 }
2738 immediate_quit = 0;
2739 /* If the file matches the buffer completely,
2740 there's no need to replace anything. */
2741 if (same_at_start - BEGV == st.st_size)
2742 {
2743 close (fd);
2744 specpdl_ptr--;
2745 /* Truncate the buffer to the size of the file. */
2746 del_range_1 (same_at_start, same_at_end, 0);
2747 goto handled;
2748 }
2749 immediate_quit = 1;
2750 QUIT;
2751 /* Count how many chars at the end of the file
2752 match the text at the end of the buffer. */
2753 while (1)
2754 {
2755 int total_read, nread, bufpos, curpos, trial;
2756
2757 /* At what file position are we now scanning? */
2758 curpos = st.st_size - (ZV - same_at_end);
2759 /* If the entire file matches the buffer tail, stop the scan. */
2760 if (curpos == 0)
2761 break;
2762 /* How much can we scan in the next step? */
2763 trial = min (curpos, sizeof buffer);
2764 if (lseek (fd, curpos - trial, 0) < 0)
2765 report_file_error ("Setting file position",
2766 Fcons (filename, Qnil));
2767
2768 total_read = 0;
2769 while (total_read < trial)
2770 {
2771 nread = read (fd, buffer + total_read, trial - total_read);
2772 if (nread <= 0)
2773 error ("IO error reading %s: %s",
2774 XSTRING (filename)->data, strerror (errno));
2775 total_read += nread;
2776 }
2777 /* Scan this bufferfull from the end, comparing with
2778 the Emacs buffer. */
2779 bufpos = total_read;
2780 /* Compare with same_at_start to avoid counting some buffer text
2781 as matching both at the file's beginning and at the end. */
2782 while (bufpos > 0 && same_at_end > same_at_start
2783 && FETCH_CHAR (same_at_end - 1) == buffer[bufpos - 1])
2784 same_at_end--, bufpos--;
2785 /* If we found a discrepancy, stop the scan.
2786 Otherwise loop around and scan the preceding bufferfull. */
2787 if (bufpos != 0)
2788 break;
2789 }
2790 immediate_quit = 0;
2791
2792 /* Don't try to reuse the same piece of text twice. */
2793 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV);
2794 if (overlap > 0)
2795 same_at_end += overlap;
2796
2797 /* Arrange to read only the nonmatching middle part of the file. */
2798 XFASTINT (beg) = same_at_start - BEGV;
2799 XFASTINT (end) = st.st_size - (ZV - same_at_end);
2800
2801 del_range_1 (same_at_start, same_at_end, 0);
2802 /* Insert from the file at the proper position. */
2803 SET_PT (same_at_start);
2804 }
2805 #endif /* MSDOS */
2806
2807 total = XINT (end) - XINT (beg);
2808
2809 {
2810 register Lisp_Object temp;
2811
2812 /* Make sure point-max won't overflow after this insertion. */
2813 XSET (temp, Lisp_Int, total);
2814 if (total != XINT (temp))
2815 error ("maximum buffer size exceeded");
2816 }
2817
2818 if (NILP (visit) && total > 0)
2819 prepare_to_modify_buffer (point, point);
2820
2821 move_gap (point);
2822 if (GAP_SIZE < total)
2823 make_gap (total - GAP_SIZE);
2824
2825 if (XINT (beg) != 0 || !NILP (replace))
2826 {
2827 if (lseek (fd, XINT (beg), 0) < 0)
2828 report_file_error ("Setting file position", Fcons (filename, Qnil));
2829 }
2830
2831 how_much = 0;
2832 while (inserted < total)
2833 {
2834 int try = min (total - inserted, 64 << 10);
2835 int this;
2836
2837 /* Allow quitting out of the actual I/O. */
2838 immediate_quit = 1;
2839 QUIT;
2840 this = read (fd, &FETCH_CHAR (point + inserted - 1) + 1, try);
2841 immediate_quit = 0;
2842
2843 if (this <= 0)
2844 {
2845 how_much = this;
2846 break;
2847 }
2848
2849 GPT += this;
2850 GAP_SIZE -= this;
2851 ZV += this;
2852 Z += this;
2853 inserted += this;
2854 }
2855
2856 #ifdef MSDOS
2857 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
2858 /* Determine file type from name and remove LFs from CR-LFs if the file
2859 is deemed to be a text file. */
2860 {
2861 struct gcpro gcpro1;
2862 Lisp_Object code;
2863 code = Qnil;
2864 GCPRO1 (filename);
2865 current_buffer->buffer_file_type
2866 = call1 (Qfind_buffer_file_type, filename);
2867 UNGCPRO;
2868 if (NILP (current_buffer->buffer_file_type))
2869 {
2870 int reduced_size
2871 = inserted - crlf_to_lf (inserted, &FETCH_CHAR (point - 1) + 1);
2872 ZV -= reduced_size;
2873 Z -= reduced_size;
2874 GPT -= reduced_size;
2875 GAP_SIZE += reduced_size;
2876 inserted -= reduced_size;
2877 }
2878 }
2879 #endif
2880
2881 if (inserted > 0)
2882 {
2883 record_insert (point, inserted);
2884
2885 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2886 offset_intervals (current_buffer, point, inserted);
2887 MODIFF++;
2888 }
2889
2890 close (fd);
2891
2892 /* Discard the unwind protect for closing the file. */
2893 specpdl_ptr--;
2894
2895 if (how_much < 0)
2896 error ("IO error reading %s: %s",
2897 XSTRING (filename)->data, strerror (errno));
2898
2899 notfound:
2900 handled:
2901
2902 if (!NILP (visit))
2903 {
2904 if (!EQ (current_buffer->undo_list, Qt))
2905 current_buffer->undo_list = Qnil;
2906 #ifdef APOLLO
2907 stat (XSTRING (filename)->data, &st);
2908 #endif
2909
2910 if (NILP (handler))
2911 {
2912 current_buffer->modtime = st.st_mtime;
2913 current_buffer->filename = filename;
2914 }
2915
2916 current_buffer->save_modified = MODIFF;
2917 current_buffer->auto_save_modified = MODIFF;
2918 XFASTINT (current_buffer->save_length) = Z - BEG;
2919 #ifdef CLASH_DETECTION
2920 if (NILP (handler))
2921 {
2922 if (!NILP (current_buffer->filename))
2923 unlock_file (current_buffer->filename);
2924 unlock_file (filename);
2925 }
2926 #endif /* CLASH_DETECTION */
2927 /* If visiting nonexistent file, return nil. */
2928 if (current_buffer->modtime == -1)
2929 report_file_error ("Opening input file", Fcons (filename, Qnil));
2930 }
2931
2932 if (inserted > 0 && NILP (visit) && total > 0)
2933 signal_after_change (point, 0, inserted);
2934
2935 if (inserted > 0)
2936 {
2937 p = Vafter_insert_file_functions;
2938 while (!NILP (p))
2939 {
2940 insval = call1 (Fcar (p), make_number (inserted));
2941 if (!NILP (insval))
2942 {
2943 CHECK_NUMBER (insval, 0);
2944 inserted = XFASTINT (insval);
2945 }
2946 QUIT;
2947 p = Fcdr (p);
2948 }
2949 }
2950
2951 if (NILP (val))
2952 val = Fcons (filename,
2953 Fcons (make_number (inserted),
2954 Qnil));
2955
2956 RETURN_UNGCPRO (unbind_to (count, val));
2957 }
2958 \f
2959 static Lisp_Object build_annotations ();
2960
2961 /* If build_annotations switched buffers, switch back to BUF.
2962 Kill the temporary buffer that was selected in the meantime. */
2963
2964 static Lisp_Object
2965 build_annotations_unwind (buf)
2966 Lisp_Object buf;
2967 {
2968 Lisp_Object tembuf;
2969
2970 if (XBUFFER (buf) == current_buffer)
2971 return Qnil;
2972 tembuf = Fcurrent_buffer ();
2973 Fset_buffer (buf);
2974 Fkill_buffer (tembuf);
2975 return Qnil;
2976 }
2977
2978 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
2979 "r\nFWrite region to file: ",
2980 "Write current region into specified file.\n\
2981 When called from a program, takes three arguments:\n\
2982 START, END and FILENAME. START and END are buffer positions.\n\
2983 Optional fourth argument APPEND if non-nil means\n\
2984 append to existing file contents (if any).\n\
2985 Optional fifth argument VISIT if t means\n\
2986 set the last-save-file-modtime of buffer to this file's modtime\n\
2987 and mark buffer not modified.\n\
2988 If VISIT is a string, it is a second file name;\n\
2989 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
2990 VISIT is also the file name to lock and unlock for clash detection.\n\
2991 If VISIT is neither t nor nil nor a string,\n\
2992 that means do not print the \"Wrote file\" message.\n\
2993 Kludgy feature: if START is a string, then that string is written\n\
2994 to the file, instead of any buffer contents, and END is ignored.")
2995 (start, end, filename, append, visit)
2996 Lisp_Object start, end, filename, append, visit;
2997 {
2998 register int desc;
2999 int failure;
3000 int save_errno;
3001 unsigned char *fn;
3002 struct stat st;
3003 int tem;
3004 int count = specpdl_ptr - specpdl;
3005 int count1;
3006 #ifdef VMS
3007 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
3008 #endif /* VMS */
3009 Lisp_Object handler;
3010 Lisp_Object visit_file;
3011 Lisp_Object annotations;
3012 int visiting, quietly;
3013 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3014 struct buffer *given_buffer;
3015 #ifdef MSDOS
3016 int buffer_file_type
3017 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
3018 #endif
3019
3020 if (!NILP (start) && !STRINGP (start))
3021 validate_region (&start, &end);
3022
3023 GCPRO2 (filename, visit);
3024 filename = Fexpand_file_name (filename, Qnil);
3025 if (STRINGP (visit))
3026 visit_file = Fexpand_file_name (visit, Qnil);
3027 else
3028 visit_file = filename;
3029 UNGCPRO;
3030
3031 visiting = (EQ (visit, Qt) || STRINGP (visit));
3032 quietly = !NILP (visit);
3033
3034 annotations = Qnil;
3035
3036 GCPRO4 (start, filename, annotations, visit_file);
3037
3038 /* If the file name has special constructs in it,
3039 call the corresponding file handler. */
3040 handler = Ffind_file_name_handler (filename, Qwrite_region);
3041 /* If FILENAME has no handler, see if VISIT has one. */
3042 if (NILP (handler) && XTYPE (visit) == Lisp_String)
3043 handler = Ffind_file_name_handler (visit, Qwrite_region);
3044
3045 if (!NILP (handler))
3046 {
3047 Lisp_Object val;
3048 val = call6 (handler, Qwrite_region, start, end,
3049 filename, append, visit);
3050
3051 if (visiting)
3052 {
3053 current_buffer->save_modified = MODIFF;
3054 XFASTINT (current_buffer->save_length) = Z - BEG;
3055 current_buffer->filename = visit_file;
3056 }
3057 UNGCPRO;
3058 return val;
3059 }
3060
3061 /* Special kludge to simplify auto-saving. */
3062 if (NILP (start))
3063 {
3064 XFASTINT (start) = BEG;
3065 XFASTINT (end) = Z;
3066 }
3067
3068 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
3069 count1 = specpdl_ptr - specpdl;
3070
3071 given_buffer = current_buffer;
3072 annotations = build_annotations (start, end);
3073 if (current_buffer != given_buffer)
3074 {
3075 start = BEGV;
3076 end = ZV;
3077 }
3078
3079 #ifdef CLASH_DETECTION
3080 if (!auto_saving)
3081 lock_file (visit_file);
3082 #endif /* CLASH_DETECTION */
3083
3084 fn = XSTRING (filename)->data;
3085 desc = -1;
3086 if (!NILP (append))
3087 #ifdef MSDOS
3088 desc = open (fn, O_WRONLY | buffer_file_type);
3089 #else
3090 desc = open (fn, O_WRONLY);
3091 #endif
3092
3093 if (desc < 0)
3094 #ifdef VMS
3095 if (auto_saving) /* Overwrite any previous version of autosave file */
3096 {
3097 vms_truncate (fn); /* if fn exists, truncate to zero length */
3098 desc = open (fn, O_RDWR);
3099 if (desc < 0)
3100 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
3101 ? XSTRING (current_buffer->filename)->data : 0,
3102 fn);
3103 }
3104 else /* Write to temporary name and rename if no errors */
3105 {
3106 Lisp_Object temp_name;
3107 temp_name = Ffile_name_directory (filename);
3108
3109 if (!NILP (temp_name))
3110 {
3111 temp_name = Fmake_temp_name (concat2 (temp_name,
3112 build_string ("$$SAVE$$")));
3113 fname = XSTRING (filename)->data;
3114 fn = XSTRING (temp_name)->data;
3115 desc = creat_copy_attrs (fname, fn);
3116 if (desc < 0)
3117 {
3118 /* If we can't open the temporary file, try creating a new
3119 version of the original file. VMS "creat" creates a
3120 new version rather than truncating an existing file. */
3121 fn = fname;
3122 fname = 0;
3123 desc = creat (fn, 0666);
3124 #if 0 /* This can clobber an existing file and fail to replace it,
3125 if the user runs out of space. */
3126 if (desc < 0)
3127 {
3128 /* We can't make a new version;
3129 try to truncate and rewrite existing version if any. */
3130 vms_truncate (fn);
3131 desc = open (fn, O_RDWR);
3132 }
3133 #endif
3134 }
3135 }
3136 else
3137 desc = creat (fn, 0666);
3138 }
3139 #else /* not VMS */
3140 #ifdef MSDOS
3141 desc = open (fn,
3142 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
3143 S_IREAD | S_IWRITE);
3144 #else /* not MSDOS */
3145 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
3146 #endif /* not MSDOS */
3147 #endif /* not VMS */
3148
3149 UNGCPRO;
3150
3151 if (desc < 0)
3152 {
3153 #ifdef CLASH_DETECTION
3154 save_errno = errno;
3155 if (!auto_saving) unlock_file (visit_file);
3156 errno = save_errno;
3157 #endif /* CLASH_DETECTION */
3158 report_file_error ("Opening output file", Fcons (filename, Qnil));
3159 }
3160
3161 record_unwind_protect (close_file_unwind, make_number (desc));
3162
3163 if (!NILP (append))
3164 if (lseek (desc, 0, 2) < 0)
3165 {
3166 #ifdef CLASH_DETECTION
3167 if (!auto_saving) unlock_file (visit_file);
3168 #endif /* CLASH_DETECTION */
3169 report_file_error ("Lseek error", Fcons (filename, Qnil));
3170 }
3171
3172 #ifdef VMS
3173 /*
3174 * Kludge Warning: The VMS C RTL likes to insert carriage returns
3175 * if we do writes that don't end with a carriage return. Furthermore
3176 * it cannot handle writes of more then 16K. The modified
3177 * version of "sys_write" in SYSDEP.C (see comment there) copes with
3178 * this EXCEPT for the last record (iff it doesn't end with a carriage
3179 * return). This implies that if your buffer doesn't end with a carriage
3180 * return, you get one free... tough. However it also means that if
3181 * we make two calls to sys_write (a la the following code) you can
3182 * get one at the gap as well. The easiest way to fix this (honest)
3183 * is to move the gap to the next newline (or the end of the buffer).
3184 * Thus this change.
3185 *
3186 * Yech!
3187 */
3188 if (GPT > BEG && GPT_ADDR[-1] != '\n')
3189 move_gap (find_next_newline (GPT, 1));
3190 #endif
3191
3192 failure = 0;
3193 immediate_quit = 1;
3194
3195 if (STRINGP (start))
3196 {
3197 failure = 0 > a_write (desc, XSTRING (start)->data,
3198 XSTRING (start)->size, 0, &annotations);
3199 save_errno = errno;
3200 }
3201 else if (XINT (start) != XINT (end))
3202 {
3203 int nwritten = 0;
3204 if (XINT (start) < GPT)
3205 {
3206 register int end1 = XINT (end);
3207 tem = XINT (start);
3208 failure = 0 > a_write (desc, &FETCH_CHAR (tem),
3209 min (GPT, end1) - tem, tem, &annotations);
3210 nwritten += min (GPT, end1) - tem;
3211 save_errno = errno;
3212 }
3213
3214 if (XINT (end) > GPT && !failure)
3215 {
3216 tem = XINT (start);
3217 tem = max (tem, GPT);
3218 failure = 0 > a_write (desc, &FETCH_CHAR (tem), XINT (end) - tem,
3219 tem, &annotations);
3220 nwritten += XINT (end) - tem;
3221 save_errno = errno;
3222 }
3223
3224 if (nwritten == 0)
3225 {
3226 /* If file was empty, still need to write the annotations */
3227 failure = 0 > a_write (desc, "", 0, XINT (start), &annotations);
3228 save_errno = errno;
3229 }
3230 }
3231
3232 immediate_quit = 0;
3233
3234 #ifdef HAVE_FSYNC
3235 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
3236 Disk full in NFS may be reported here. */
3237 /* mib says that closing the file will try to write as fast as NFS can do
3238 it, and that means the fsync here is not crucial for autosave files. */
3239 if (!auto_saving && fsync (desc) < 0)
3240 failure = 1, save_errno = errno;
3241 #endif
3242
3243 /* Spurious "file has changed on disk" warnings have been
3244 observed on Suns as well.
3245 It seems that `close' can change the modtime, under nfs.
3246
3247 (This has supposedly been fixed in Sunos 4,
3248 but who knows about all the other machines with NFS?) */
3249 #if 0
3250
3251 /* On VMS and APOLLO, must do the stat after the close
3252 since closing changes the modtime. */
3253 #ifndef VMS
3254 #ifndef APOLLO
3255 /* Recall that #if defined does not work on VMS. */
3256 #define FOO
3257 fstat (desc, &st);
3258 #endif
3259 #endif
3260 #endif
3261
3262 /* NFS can report a write failure now. */
3263 if (close (desc) < 0)
3264 failure = 1, save_errno = errno;
3265
3266 #ifdef VMS
3267 /* If we wrote to a temporary name and had no errors, rename to real name. */
3268 if (fname)
3269 {
3270 if (!failure)
3271 failure = (rename (fn, fname) != 0), save_errno = errno;
3272 fn = fname;
3273 }
3274 #endif /* VMS */
3275
3276 #ifndef FOO
3277 stat (fn, &st);
3278 #endif
3279 /* Discard the unwind protect for close_file_unwind. */
3280 specpdl_ptr = specpdl + count1;
3281 /* Restore the original current buffer. */
3282 visit_file = unbind_to (count, visit_file);
3283
3284 #ifdef CLASH_DETECTION
3285 if (!auto_saving)
3286 unlock_file (visit_file);
3287 #endif /* CLASH_DETECTION */
3288
3289 /* Do this before reporting IO error
3290 to avoid a "file has changed on disk" warning on
3291 next attempt to save. */
3292 if (visiting)
3293 current_buffer->modtime = st.st_mtime;
3294
3295 if (failure)
3296 error ("IO error writing %s: %s", fn, strerror (save_errno));
3297
3298 if (visiting)
3299 {
3300 current_buffer->save_modified = MODIFF;
3301 XFASTINT (current_buffer->save_length) = Z - BEG;
3302 current_buffer->filename = visit_file;
3303 update_mode_lines++;
3304 }
3305 else if (quietly)
3306 return Qnil;
3307
3308 if (!auto_saving)
3309 message ("Wrote %s", XSTRING (visit_file)->data);
3310
3311 return Qnil;
3312 }
3313
3314 Lisp_Object merge ();
3315
3316 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
3317 "Return t if (car A) is numerically less than (car B).")
3318 (a, b)
3319 Lisp_Object a, b;
3320 {
3321 return Flss (Fcar (a), Fcar (b));
3322 }
3323
3324 /* Build the complete list of annotations appropriate for writing out
3325 the text between START and END, by calling all the functions in
3326 write-region-annotate-functions and merging the lists they return.
3327 If one of these functions switches to a different buffer, we assume
3328 that buffer contains altered text. Therefore, the caller must
3329 make sure to restore the current buffer in all cases,
3330 as save-excursion would do. */
3331
3332 static Lisp_Object
3333 build_annotations (start, end)
3334 Lisp_Object start, end;
3335 {
3336 Lisp_Object annotations;
3337 Lisp_Object p, res;
3338 struct gcpro gcpro1, gcpro2;
3339
3340 annotations = Qnil;
3341 p = Vwrite_region_annotate_functions;
3342 GCPRO2 (annotations, p);
3343 while (!NILP (p))
3344 {
3345 struct buffer *given_buffer = current_buffer;
3346 Vwrite_region_annotations_so_far = annotations;
3347 res = call2 (Fcar (p), start, end);
3348 /* If the function makes a different buffer current,
3349 assume that means this buffer contains altered text to be output.
3350 Reset START and END from the buffer bounds
3351 and discard all previous annotations because they should have
3352 been dealt with by this function. */
3353 if (current_buffer != given_buffer)
3354 {
3355 start = BEGV;
3356 end = ZV;
3357 annotations = Qnil;
3358 }
3359 Flength (res); /* Check basic validity of return value */
3360 annotations = merge (annotations, res, Qcar_less_than_car);
3361 p = Fcdr (p);
3362 }
3363 UNGCPRO;
3364 return annotations;
3365 }
3366
3367 /* Write to descriptor DESC the LEN characters starting at ADDR,
3368 assuming they start at position POS in the buffer.
3369 Intersperse with them the annotations from *ANNOT
3370 (those which fall within the range of positions POS to POS + LEN),
3371 each at its appropriate position.
3372
3373 Modify *ANNOT by discarding elements as we output them.
3374 The return value is negative in case of system call failure. */
3375
3376 int
3377 a_write (desc, addr, len, pos, annot)
3378 int desc;
3379 register char *addr;
3380 register int len;
3381 int pos;
3382 Lisp_Object *annot;
3383 {
3384 Lisp_Object tem;
3385 int nextpos;
3386 int lastpos = pos + len;
3387
3388 while (NILP (*annot) || CONSP (*annot))
3389 {
3390 tem = Fcar_safe (Fcar (*annot));
3391 if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos)
3392 nextpos = XFASTINT (tem);
3393 else
3394 return e_write (desc, addr, lastpos - pos);
3395 if (nextpos > pos)
3396 {
3397 if (0 > e_write (desc, addr, nextpos - pos))
3398 return -1;
3399 addr += nextpos - pos;
3400 pos = nextpos;
3401 }
3402 tem = Fcdr (Fcar (*annot));
3403 if (STRINGP (tem))
3404 {
3405 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size))
3406 return -1;
3407 }
3408 *annot = Fcdr (*annot);
3409 }
3410 }
3411
3412 int
3413 e_write (desc, addr, len)
3414 int desc;
3415 register char *addr;
3416 register int len;
3417 {
3418 char buf[16 * 1024];
3419 register char *p, *end;
3420
3421 if (!EQ (current_buffer->selective_display, Qt))
3422 return write (desc, addr, len) - len;
3423 else
3424 {
3425 p = buf;
3426 end = p + sizeof buf;
3427 while (len--)
3428 {
3429 if (p == end)
3430 {
3431 if (write (desc, buf, sizeof buf) != sizeof buf)
3432 return -1;
3433 p = buf;
3434 }
3435 *p = *addr++;
3436 if (*p++ == '\015')
3437 p[-1] = '\n';
3438 }
3439 if (p != buf)
3440 if (write (desc, buf, p - buf) != p - buf)
3441 return -1;
3442 }
3443 return 0;
3444 }
3445
3446 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
3447 Sverify_visited_file_modtime, 1, 1, 0,
3448 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
3449 This means that the file has not been changed since it was visited or saved.")
3450 (buf)
3451 Lisp_Object buf;
3452 {
3453 struct buffer *b;
3454 struct stat st;
3455 Lisp_Object handler;
3456
3457 CHECK_BUFFER (buf, 0);
3458 b = XBUFFER (buf);
3459
3460 if (XTYPE (b->filename) != Lisp_String) return Qt;
3461 if (b->modtime == 0) return Qt;
3462
3463 /* If the file name has special constructs in it,
3464 call the corresponding file handler. */
3465 handler = Ffind_file_name_handler (b->filename,
3466 Qverify_visited_file_modtime);
3467 if (!NILP (handler))
3468 return call2 (handler, Qverify_visited_file_modtime, buf);
3469
3470 if (stat (XSTRING (b->filename)->data, &st) < 0)
3471 {
3472 /* If the file doesn't exist now and didn't exist before,
3473 we say that it isn't modified, provided the error is a tame one. */
3474 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
3475 st.st_mtime = -1;
3476 else
3477 st.st_mtime = 0;
3478 }
3479 if (st.st_mtime == b->modtime
3480 /* If both are positive, accept them if they are off by one second. */
3481 || (st.st_mtime > 0 && b->modtime > 0
3482 && (st.st_mtime == b->modtime + 1
3483 || st.st_mtime == b->modtime - 1)))
3484 return Qt;
3485 return Qnil;
3486 }
3487
3488 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
3489 Sclear_visited_file_modtime, 0, 0, 0,
3490 "Clear out records of last mod time of visited file.\n\
3491 Next attempt to save will certainly not complain of a discrepancy.")
3492 ()
3493 {
3494 current_buffer->modtime = 0;
3495 return Qnil;
3496 }
3497
3498 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
3499 Svisited_file_modtime, 0, 0, 0,
3500 "Return the current buffer's recorded visited file modification time.\n\
3501 The value is a list of the form (HIGH . LOW), like the time values\n\
3502 that `file-attributes' returns.")
3503 ()
3504 {
3505 return long_to_cons (current_buffer->modtime);
3506 }
3507
3508 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
3509 Sset_visited_file_modtime, 0, 1, 0,
3510 "Update buffer's recorded modification time from the visited file's time.\n\
3511 Useful if the buffer was not read from the file normally\n\
3512 or if the file itself has been changed for some known benign reason.\n\
3513 An argument specifies the modification time value to use\n\
3514 \(instead of that of the visited file), in the form of a list\n\
3515 \(HIGH . LOW) or (HIGH LOW).")
3516 (time_list)
3517 Lisp_Object time_list;
3518 {
3519 if (!NILP (time_list))
3520 current_buffer->modtime = cons_to_long (time_list);
3521 else
3522 {
3523 register Lisp_Object filename;
3524 struct stat st;
3525 Lisp_Object handler;
3526
3527 filename = Fexpand_file_name (current_buffer->filename, Qnil);
3528
3529 /* If the file name has special constructs in it,
3530 call the corresponding file handler. */
3531 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
3532 if (!NILP (handler))
3533 /* The handler can find the file name the same way we did. */
3534 return call2 (handler, Qset_visited_file_modtime, Qnil);
3535 else if (stat (XSTRING (filename)->data, &st) >= 0)
3536 current_buffer->modtime = st.st_mtime;
3537 }
3538
3539 return Qnil;
3540 }
3541 \f
3542 Lisp_Object
3543 auto_save_error ()
3544 {
3545 ring_bell ();
3546 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
3547 Fsleep_for (make_number (1), Qnil);
3548 message ("Autosaving...error!for %s", XSTRING (current_buffer->name)->data);
3549 Fsleep_for (make_number (1), Qnil);
3550 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
3551 Fsleep_for (make_number (1), Qnil);
3552 return Qnil;
3553 }
3554
3555 Lisp_Object
3556 auto_save_1 ()
3557 {
3558 unsigned char *fn;
3559 struct stat st;
3560
3561 /* Get visited file's mode to become the auto save file's mode. */
3562 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
3563 /* But make sure we can overwrite it later! */
3564 auto_save_mode_bits = st.st_mode | 0600;
3565 else
3566 auto_save_mode_bits = 0666;
3567
3568 return
3569 Fwrite_region (Qnil, Qnil,
3570 current_buffer->auto_save_file_name,
3571 Qnil, Qlambda);
3572 }
3573
3574 static Lisp_Object
3575 do_auto_save_unwind (desc) /* used as unwind-protect function */
3576 Lisp_Object desc;
3577 {
3578 close (XINT (desc));
3579 return Qnil;
3580 }
3581
3582 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
3583 "Auto-save all buffers that need it.\n\
3584 This is all buffers that have auto-saving enabled\n\
3585 and are changed since last auto-saved.\n\
3586 Auto-saving writes the buffer into a file\n\
3587 so that your editing is not lost if the system crashes.\n\
3588 This file is not the file you visited; that changes only when you save.\n\
3589 Normally we run the normal hook `auto-save-hook' before saving.\n\n\
3590 Non-nil first argument means do not print any message if successful.\n\
3591 Non-nil second argument means save only current buffer.")
3592 (no_message, current_only)
3593 Lisp_Object no_message, current_only;
3594 {
3595 struct buffer *old = current_buffer, *b;
3596 Lisp_Object tail, buf;
3597 int auto_saved = 0;
3598 char *omessage = echo_area_glyphs;
3599 int omessage_length = echo_area_glyphs_length;
3600 extern int minibuf_level;
3601 int do_handled_files;
3602 Lisp_Object oquit;
3603 int listdesc;
3604 int count = specpdl_ptr - specpdl;
3605 int *ptr;
3606
3607 /* Ordinarily don't quit within this function,
3608 but don't make it impossible to quit (in case we get hung in I/O). */
3609 oquit = Vquit_flag;
3610 Vquit_flag = Qnil;
3611
3612 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
3613 point to non-strings reached from Vbuffer_alist. */
3614
3615 auto_saving = 1;
3616 if (minibuf_level)
3617 no_message = Qt;
3618
3619 if (!NILP (Vrun_hooks))
3620 call1 (Vrun_hooks, intern ("auto-save-hook"));
3621
3622 if (STRINGP (Vauto_save_list_file_name))
3623 {
3624 #ifdef MSDOS
3625 listdesc = open (XSTRING (Vauto_save_list_file_name)->data,
3626 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
3627 S_IREAD | S_IWRITE);
3628 #else /* not MSDOS */
3629 listdesc = creat (XSTRING (Vauto_save_list_file_name)->data, 0666);
3630 #endif /* not MSDOS */
3631 }
3632 else
3633 listdesc = -1;
3634
3635 /* Arrange to close that file whether or not we get an error. */
3636 if (listdesc >= 0)
3637 record_unwind_protect (do_auto_save_unwind, make_number (listdesc));
3638
3639 /* First, save all files which don't have handlers. If Emacs is
3640 crashing, the handlers may tweak what is causing Emacs to crash
3641 in the first place, and it would be a shame if Emacs failed to
3642 autosave perfectly ordinary files because it couldn't handle some
3643 ange-ftp'd file. */
3644 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
3645 for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
3646 tail = XCONS (tail)->cdr)
3647 {
3648 buf = XCONS (XCONS (tail)->car)->cdr;
3649 b = XBUFFER (buf);
3650
3651 /* Record all the buffers that have auto save mode
3652 in the special file that lists them. */
3653 if (XTYPE (b->auto_save_file_name) == Lisp_String
3654 && listdesc >= 0 && do_handled_files == 0)
3655 {
3656 write (listdesc, XSTRING (b->auto_save_file_name)->data,
3657 XSTRING (b->auto_save_file_name)->size);
3658 write (listdesc, "\n", 1);
3659 }
3660
3661 if (!NILP (current_only)
3662 && b != current_buffer)
3663 continue;
3664
3665 /* Check for auto save enabled
3666 and file changed since last auto save
3667 and file changed since last real save. */
3668 if (XTYPE (b->auto_save_file_name) == Lisp_String
3669 && b->save_modified < BUF_MODIFF (b)
3670 && b->auto_save_modified < BUF_MODIFF (b)
3671 /* -1 means we've turned off autosaving for a while--see below. */
3672 && XINT (b->save_length) >= 0
3673 && (do_handled_files
3674 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
3675 Qwrite_region))))
3676 {
3677 EMACS_TIME before_time, after_time;
3678
3679 EMACS_GET_TIME (before_time);
3680
3681 /* If we had a failure, don't try again for 20 minutes. */
3682 if (b->auto_save_failure_time >= 0
3683 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
3684 continue;
3685
3686 if ((XFASTINT (b->save_length) * 10
3687 > (BUF_Z (b) - BUF_BEG (b)) * 13)
3688 /* A short file is likely to change a large fraction;
3689 spare the user annoying messages. */
3690 && XFASTINT (b->save_length) > 5000
3691 /* These messages are frequent and annoying for `*mail*'. */
3692 && !EQ (b->filename, Qnil)
3693 && NILP (no_message))
3694 {
3695 /* It has shrunk too much; turn off auto-saving here. */
3696 message ("Buffer %s has shrunk a lot; auto save turned off there",
3697 XSTRING (b->name)->data);
3698 /* Turn off auto-saving until there's a real save,
3699 and prevent any more warnings. */
3700 XSET (b->save_length, Lisp_Int, -1);
3701 Fsleep_for (make_number (1), Qnil);
3702 continue;
3703 }
3704 set_buffer_internal (b);
3705 if (!auto_saved && NILP (no_message))
3706 message1 ("Auto-saving...");
3707 internal_condition_case (auto_save_1, Qt, auto_save_error);
3708 auto_saved++;
3709 b->auto_save_modified = BUF_MODIFF (b);
3710 XFASTINT (current_buffer->save_length) = Z - BEG;
3711 set_buffer_internal (old);
3712
3713 EMACS_GET_TIME (after_time);
3714
3715 /* If auto-save took more than 60 seconds,
3716 assume it was an NFS failure that got a timeout. */
3717 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
3718 b->auto_save_failure_time = EMACS_SECS (after_time);
3719 }
3720 }
3721
3722 /* Prevent another auto save till enough input events come in. */
3723 record_auto_save ();
3724
3725 if (auto_saved && NILP (no_message))
3726 {
3727 if (omessage)
3728 message2 (omessage, omessage_length);
3729 else
3730 message1 ("Auto-saving...done");
3731 }
3732
3733 Vquit_flag = oquit;
3734
3735 auto_saving = 0;
3736 unbind_to (count, Qnil);
3737 return Qnil;
3738 }
3739
3740 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
3741 Sset_buffer_auto_saved, 0, 0, 0,
3742 "Mark current buffer as auto-saved with its current text.\n\
3743 No auto-save file will be written until the buffer changes again.")
3744 ()
3745 {
3746 current_buffer->auto_save_modified = MODIFF;
3747 XFASTINT (current_buffer->save_length) = Z - BEG;
3748 current_buffer->auto_save_failure_time = -1;
3749 return Qnil;
3750 }
3751
3752 DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
3753 Sclear_buffer_auto_save_failure, 0, 0, 0,
3754 "Clear any record of a recent auto-save failure in the current buffer.")
3755 ()
3756 {
3757 current_buffer->auto_save_failure_time = -1;
3758 return Qnil;
3759 }
3760
3761 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
3762 0, 0, 0,
3763 "Return t if buffer has been auto-saved since last read in or saved.")
3764 ()
3765 {
3766 return (current_buffer->save_modified < current_buffer->auto_save_modified) ? Qt : Qnil;
3767 }
3768 \f
3769 /* Reading and completing file names */
3770 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
3771
3772 /* In the string VAL, change each $ to $$ and return the result. */
3773
3774 static Lisp_Object
3775 double_dollars (val)
3776 Lisp_Object val;
3777 {
3778 register unsigned char *old, *new;
3779 register int n;
3780 int osize, count;
3781
3782 osize = XSTRING (val)->size;
3783 /* Quote "$" as "$$" to get it past substitute-in-file-name */
3784 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
3785 if (*old++ == '$') count++;
3786 if (count > 0)
3787 {
3788 old = XSTRING (val)->data;
3789 val = Fmake_string (make_number (osize + count), make_number (0));
3790 new = XSTRING (val)->data;
3791 for (n = osize; n > 0; n--)
3792 if (*old != '$')
3793 *new++ = *old++;
3794 else
3795 {
3796 *new++ = '$';
3797 *new++ = '$';
3798 old++;
3799 }
3800 }
3801 return val;
3802 }
3803
3804 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
3805 3, 3, 0,
3806 "Internal subroutine for read-file-name. Do not call this.")
3807 (string, dir, action)
3808 Lisp_Object string, dir, action;
3809 /* action is nil for complete, t for return list of completions,
3810 lambda for verify final value */
3811 {
3812 Lisp_Object name, specdir, realdir, val, orig_string;
3813 int changed;
3814 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3815
3816 realdir = dir;
3817 name = string;
3818 orig_string = Qnil;
3819 specdir = Qnil;
3820 changed = 0;
3821 /* No need to protect ACTION--we only compare it with t and nil. */
3822 GCPRO4 (string, realdir, name, specdir);
3823
3824 if (XSTRING (string)->size == 0)
3825 {
3826 if (EQ (action, Qlambda))
3827 {
3828 UNGCPRO;
3829 return Qnil;
3830 }
3831 }
3832 else
3833 {
3834 orig_string = string;
3835 string = Fsubstitute_in_file_name (string);
3836 changed = NILP (Fstring_equal (string, orig_string));
3837 name = Ffile_name_nondirectory (string);
3838 val = Ffile_name_directory (string);
3839 if (! NILP (val))
3840 realdir = Fexpand_file_name (val, realdir);
3841 }
3842
3843 if (NILP (action))
3844 {
3845 specdir = Ffile_name_directory (string);
3846 val = Ffile_name_completion (name, realdir);
3847 UNGCPRO;
3848 if (XTYPE (val) != Lisp_String)
3849 {
3850 if (changed)
3851 return double_dollars (string);
3852 return val;
3853 }
3854
3855 if (!NILP (specdir))
3856 val = concat2 (specdir, val);
3857 #ifndef VMS
3858 return double_dollars (val);
3859 #else /* not VMS */
3860 return val;
3861 #endif /* not VMS */
3862 }
3863 UNGCPRO;
3864
3865 if (EQ (action, Qt))
3866 return Ffile_name_all_completions (name, realdir);
3867 /* Only other case actually used is ACTION = lambda */
3868 #ifdef VMS
3869 /* Supposedly this helps commands such as `cd' that read directory names,
3870 but can someone explain how it helps them? -- RMS */
3871 if (XSTRING (name)->size == 0)
3872 return Qt;
3873 #endif /* VMS */
3874 return Ffile_exists_p (string);
3875 }
3876
3877 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
3878 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3879 Value is not expanded---you must call `expand-file-name' yourself.\n\
3880 Default name to DEFAULT if user enters a null string.\n\
3881 (If DEFAULT is omitted, the visited file name is used.)\n\
3882 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3883 Non-nil and non-t means also require confirmation after completion.\n\
3884 Fifth arg INITIAL specifies text to start with.\n\
3885 DIR defaults to current buffer's directory default.")
3886 (prompt, dir, defalt, mustmatch, initial)
3887 Lisp_Object prompt, dir, defalt, mustmatch, initial;
3888 {
3889 Lisp_Object val, insdef, insdef1, tem;
3890 struct gcpro gcpro1, gcpro2;
3891 register char *homedir;
3892 int count;
3893
3894 if (NILP (dir))
3895 dir = current_buffer->directory;
3896 if (NILP (defalt))
3897 defalt = current_buffer->filename;
3898
3899 /* If dir starts with user's homedir, change that to ~. */
3900 homedir = (char *) egetenv ("HOME");
3901 if (homedir != 0
3902 && XTYPE (dir) == Lisp_String
3903 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
3904 && XSTRING (dir)->data[strlen (homedir)] == '/')
3905 {
3906 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
3907 XSTRING (dir)->size - strlen (homedir) + 1);
3908 XSTRING (dir)->data[0] = '~';
3909 }
3910
3911 if (insert_default_directory)
3912 {
3913 insdef = dir;
3914 if (!NILP (initial))
3915 {
3916 Lisp_Object args[2], pos;
3917
3918 args[0] = insdef;
3919 args[1] = initial;
3920 insdef = Fconcat (2, args);
3921 pos = make_number (XSTRING (double_dollars (dir))->size);
3922 insdef1 = Fcons (double_dollars (insdef), pos);
3923 }
3924 else
3925 insdef1 = double_dollars (insdef);
3926 }
3927 else if (!NILP (initial))
3928 {
3929 insdef = initial;
3930 insdef1 = Fcons (double_dollars (insdef), 0);
3931 }
3932 else
3933 insdef = Qnil, insdef1 = Qnil;
3934
3935 #ifdef VMS
3936 count = specpdl_ptr - specpdl;
3937 specbind (intern ("completion-ignore-case"), Qt);
3938 #endif
3939
3940 GCPRO2 (insdef, defalt);
3941 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
3942 dir, mustmatch, insdef1,
3943 Qfile_name_history);
3944
3945 #ifdef VMS
3946 unbind_to (count, Qnil);
3947 #endif
3948
3949 UNGCPRO;
3950 if (NILP (val))
3951 error ("No file name specified");
3952 tem = Fstring_equal (val, insdef);
3953 if (!NILP (tem) && !NILP (defalt))
3954 return defalt;
3955 if (XSTRING (val)->size == 0 && NILP (insdef))
3956 {
3957 if (!NILP (defalt))
3958 return defalt;
3959 else
3960 error ("No default file name");
3961 }
3962 return Fsubstitute_in_file_name (val);
3963 }
3964
3965 #if 0 /* Old version */
3966 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
3967 /* Don't confuse make-docfile by having two doc strings for this function.
3968 make-docfile does not pay attention to #if, for good reason! */
3969 0)
3970 (prompt, dir, defalt, mustmatch, initial)
3971 Lisp_Object prompt, dir, defalt, mustmatch, initial;
3972 {
3973 Lisp_Object val, insdef, tem;
3974 struct gcpro gcpro1, gcpro2;
3975 register char *homedir;
3976 int count;
3977
3978 if (NILP (dir))
3979 dir = current_buffer->directory;
3980 if (NILP (defalt))
3981 defalt = current_buffer->filename;
3982
3983 /* If dir starts with user's homedir, change that to ~. */
3984 homedir = (char *) egetenv ("HOME");
3985 if (homedir != 0
3986 && XTYPE (dir) == Lisp_String
3987 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
3988 && XSTRING (dir)->data[strlen (homedir)] == '/')
3989 {
3990 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
3991 XSTRING (dir)->size - strlen (homedir) + 1);
3992 XSTRING (dir)->data[0] = '~';
3993 }
3994
3995 if (!NILP (initial))
3996 insdef = initial;
3997 else if (insert_default_directory)
3998 insdef = dir;
3999 else
4000 insdef = build_string ("");
4001
4002 #ifdef VMS
4003 count = specpdl_ptr - specpdl;
4004 specbind (intern ("completion-ignore-case"), Qt);
4005 #endif
4006
4007 GCPRO2 (insdef, defalt);
4008 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4009 dir, mustmatch,
4010 insert_default_directory ? insdef : Qnil,
4011 Qfile_name_history);
4012
4013 #ifdef VMS
4014 unbind_to (count, Qnil);
4015 #endif
4016
4017 UNGCPRO;
4018 if (NILP (val))
4019 error ("No file name specified");
4020 tem = Fstring_equal (val, insdef);
4021 if (!NILP (tem) && !NILP (defalt))
4022 return defalt;
4023 return Fsubstitute_in_file_name (val);
4024 }
4025 #endif /* Old version */
4026 \f
4027 syms_of_fileio ()
4028 {
4029 Qexpand_file_name = intern ("expand-file-name");
4030 Qdirectory_file_name = intern ("directory-file-name");
4031 Qfile_name_directory = intern ("file-name-directory");
4032 Qfile_name_nondirectory = intern ("file-name-nondirectory");
4033 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
4034 Qfile_name_as_directory = intern ("file-name-as-directory");
4035 Qcopy_file = intern ("copy-file");
4036 Qmake_directory_internal = intern ("make-directory-internal");
4037 Qdelete_directory = intern ("delete-directory");
4038 Qdelete_file = intern ("delete-file");
4039 Qrename_file = intern ("rename-file");
4040 Qadd_name_to_file = intern ("add-name-to-file");
4041 Qmake_symbolic_link = intern ("make-symbolic-link");
4042 Qfile_exists_p = intern ("file-exists-p");
4043 Qfile_executable_p = intern ("file-executable-p");
4044 Qfile_readable_p = intern ("file-readable-p");
4045 Qfile_symlink_p = intern ("file-symlink-p");
4046 Qfile_writable_p = intern ("file-writable-p");
4047 Qfile_directory_p = intern ("file-directory-p");
4048 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
4049 Qfile_modes = intern ("file-modes");
4050 Qset_file_modes = intern ("set-file-modes");
4051 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
4052 Qinsert_file_contents = intern ("insert-file-contents");
4053 Qwrite_region = intern ("write-region");
4054 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
4055 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
4056
4057 staticpro (&Qexpand_file_name);
4058 staticpro (&Qdirectory_file_name);
4059 staticpro (&Qfile_name_directory);
4060 staticpro (&Qfile_name_nondirectory);
4061 staticpro (&Qunhandled_file_name_directory);
4062 staticpro (&Qfile_name_as_directory);
4063 staticpro (&Qcopy_file);
4064 staticpro (&Qmake_directory_internal);
4065 staticpro (&Qdelete_directory);
4066 staticpro (&Qdelete_file);
4067 staticpro (&Qrename_file);
4068 staticpro (&Qadd_name_to_file);
4069 staticpro (&Qmake_symbolic_link);
4070 staticpro (&Qfile_exists_p);
4071 staticpro (&Qfile_executable_p);
4072 staticpro (&Qfile_readable_p);
4073 staticpro (&Qfile_symlink_p);
4074 staticpro (&Qfile_writable_p);
4075 staticpro (&Qfile_directory_p);
4076 staticpro (&Qfile_accessible_directory_p);
4077 staticpro (&Qfile_modes);
4078 staticpro (&Qset_file_modes);
4079 staticpro (&Qfile_newer_than_file_p);
4080 staticpro (&Qinsert_file_contents);
4081 staticpro (&Qwrite_region);
4082 staticpro (&Qverify_visited_file_modtime);
4083
4084 Qfile_name_history = intern ("file-name-history");
4085 Fset (Qfile_name_history, Qnil);
4086 staticpro (&Qfile_name_history);
4087
4088 Qfile_error = intern ("file-error");
4089 staticpro (&Qfile_error);
4090 Qfile_already_exists = intern("file-already-exists");
4091 staticpro (&Qfile_already_exists);
4092
4093 #ifdef MSDOS
4094 Qfind_buffer_file_type = intern ("find-buffer-file-type");
4095 staticpro (&Qfind_buffer_file_type);
4096 #endif
4097
4098 Qcar_less_than_car = intern ("car-less-than-car");
4099 staticpro (&Qcar_less_than_car);
4100
4101 Fput (Qfile_error, Qerror_conditions,
4102 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
4103 Fput (Qfile_error, Qerror_message,
4104 build_string ("File error"));
4105
4106 Fput (Qfile_already_exists, Qerror_conditions,
4107 Fcons (Qfile_already_exists,
4108 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
4109 Fput (Qfile_already_exists, Qerror_message,
4110 build_string ("File already exists"));
4111
4112 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
4113 "*Non-nil means when reading a filename start with default dir in minibuffer.");
4114 insert_default_directory = 1;
4115
4116 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
4117 "*Non-nil means write new files with record format `stmlf'.\n\
4118 nil means use format `var'. This variable is meaningful only on VMS.");
4119 vms_stmlf_recfm = 0;
4120
4121 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
4122 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
4123 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
4124 HANDLER.\n\
4125 \n\
4126 The first argument given to HANDLER is the name of the I/O primitive\n\
4127 to be handled; the remaining arguments are the arguments that were\n\
4128 passed to that primitive. For example, if you do\n\
4129 (file-exists-p FILENAME)\n\
4130 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
4131 (funcall HANDLER 'file-exists-p FILENAME)\n\
4132 The function `find-file-name-handler' checks this list for a handler\n\
4133 for its argument.");
4134 Vfile_name_handler_alist = Qnil;
4135
4136 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
4137 "A list of functions to be called at the end of `insert-file-contents'.\n\
4138 Each is passed one argument, the number of bytes inserted. It should return\n\
4139 the new byte count, and leave point the same. If `insert-file-contents' is\n\
4140 intercepted by a handler from `file-name-handler-alist', that handler is\n\
4141 responsible for calling the after-insert-file-functions if appropriate.");
4142 Vafter_insert_file_functions = Qnil;
4143
4144 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
4145 "A list of functions to be called at the start of `write-region'.\n\
4146 Each is passed two arguments, START and END as for `write-region'. It should\n\
4147 return a list of pairs (POSITION . STRING) of strings to be effectively\n\
4148 inserted at the specified positions of the file being written (1 means to\n\
4149 insert before the first byte written). The POSITIONs must be sorted into\n\
4150 increasing order. If there are several functions in the list, the several\n\
4151 lists are merged destructively.");
4152 Vwrite_region_annotate_functions = Qnil;
4153
4154 DEFVAR_LISP ("write-region-annotations-so-far",
4155 &Vwrite_region_annotations_so_far,
4156 "When an annotation function is called, this holds the previous annotations.\n\
4157 These are the annotations made by other annotation functions\n\
4158 that were already called. See also `write-region-annotate-functions'.");
4159 Vwrite_region_annotations_so_far = Qnil;
4160
4161 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
4162 "A list of file name handlers that temporarily should not be used.\n\
4163 This applies only to the operation `inhibit-file-name-operation'.");
4164 Vinhibit_file_name_handlers = Qnil;
4165
4166 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
4167 "The operation for which `inhibit-file-name-handlers' is applicable.");
4168 Vinhibit_file_name_operation = Qnil;
4169
4170 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
4171 "File name in which we write a list of all auto save file names.");
4172 Vauto_save_list_file_name = Qnil;
4173
4174 defsubr (&Sfind_file_name_handler);
4175 defsubr (&Sfile_name_directory);
4176 defsubr (&Sfile_name_nondirectory);
4177 defsubr (&Sunhandled_file_name_directory);
4178 defsubr (&Sfile_name_as_directory);
4179 defsubr (&Sdirectory_file_name);
4180 defsubr (&Smake_temp_name);
4181 defsubr (&Sexpand_file_name);
4182 defsubr (&Ssubstitute_in_file_name);
4183 defsubr (&Scopy_file);
4184 defsubr (&Smake_directory_internal);
4185 defsubr (&Sdelete_directory);
4186 defsubr (&Sdelete_file);
4187 defsubr (&Srename_file);
4188 defsubr (&Sadd_name_to_file);
4189 #ifdef S_IFLNK
4190 defsubr (&Smake_symbolic_link);
4191 #endif /* S_IFLNK */
4192 #ifdef VMS
4193 defsubr (&Sdefine_logical_name);
4194 #endif /* VMS */
4195 #ifdef HPUX_NET
4196 defsubr (&Ssysnetunam);
4197 #endif /* HPUX_NET */
4198 defsubr (&Sfile_name_absolute_p);
4199 defsubr (&Sfile_exists_p);
4200 defsubr (&Sfile_executable_p);
4201 defsubr (&Sfile_readable_p);
4202 defsubr (&Sfile_writable_p);
4203 defsubr (&Sfile_symlink_p);
4204 defsubr (&Sfile_directory_p);
4205 defsubr (&Sfile_accessible_directory_p);
4206 defsubr (&Sfile_modes);
4207 defsubr (&Sset_file_modes);
4208 defsubr (&Sset_default_file_modes);
4209 defsubr (&Sdefault_file_modes);
4210 defsubr (&Sfile_newer_than_file_p);
4211 defsubr (&Sinsert_file_contents);
4212 defsubr (&Swrite_region);
4213 defsubr (&Scar_less_than_car);
4214 defsubr (&Sverify_visited_file_modtime);
4215 defsubr (&Sclear_visited_file_modtime);
4216 defsubr (&Svisited_file_modtime);
4217 defsubr (&Sset_visited_file_modtime);
4218 defsubr (&Sdo_auto_save);
4219 defsubr (&Sset_buffer_auto_saved);
4220 defsubr (&Sclear_buffer_auto_save_failure);
4221 defsubr (&Srecent_auto_save_p);
4222
4223 defsubr (&Sread_file_name_internal);
4224 defsubr (&Sread_file_name);
4225
4226 #ifdef unix
4227 defsubr (&Sunix_sync);
4228 #endif
4229 }