(menu-bar-help-menu): Binding for view-emacs-FAQ.
[emacs.git] / src / fileio.c
blob8a13ce5f39a47d0bf5f720ae0f1dc8fd4c02f0a6
1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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. */
20 #include <config.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
29 #if !defined (S_ISLNK) && defined (S_IFLNK)
30 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
31 #endif
33 #if !defined (S_ISREG) && defined (S_IFREG)
34 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
35 #endif
37 #ifdef VMS
38 #include "vms-pwd.h"
39 #else
40 #include <pwd.h>
41 #endif
43 #ifdef MSDOS
44 #include "msdos.h"
45 #include <sys/param.h>
46 #endif
48 #include <ctype.h>
50 #ifdef VMS
51 #include "vmsdir.h"
52 #include <perror.h>
53 #include <stddef.h>
54 #include <string.h>
55 #endif
57 #include <errno.h>
59 #ifndef vax11c
60 extern int errno;
61 #endif
63 extern char *strerror ();
65 #ifdef APOLLO
66 #include <sys/time.h>
67 #endif
69 #ifndef USG
70 #ifndef VMS
71 #ifndef BSD4_1
72 #ifndef WINDOWSNT
73 #define HAVE_FSYNC
74 #endif
75 #endif
76 #endif
77 #endif
79 #include "lisp.h"
80 #include "intervals.h"
81 #include "buffer.h"
82 #include "window.h"
84 #ifdef WINDOWSNT
85 #define NOMINMAX 1
86 #include <windows.h>
87 #include <stdlib.h>
88 #include <fcntl.h>
89 #endif /* not WINDOWSNT */
91 #ifdef VMS
92 #include <file.h>
93 #include <rmsdef.h>
94 #include <fab.h>
95 #include <nam.h>
96 #endif
98 #include "systime.h"
100 #ifdef HPUX
101 #include <netio.h>
102 #ifndef HPUX8
103 #ifndef HPUX9
104 #include <errnet.h>
105 #endif
106 #endif
107 #endif
109 #ifndef O_WRONLY
110 #define O_WRONLY 1
111 #endif
113 #ifndef O_RDONLY
114 #define O_RDONLY 0
115 #endif
117 #define min(a, b) ((a) < (b) ? (a) : (b))
118 #define max(a, b) ((a) > (b) ? (a) : (b))
120 /* Nonzero during writing of auto-save files */
121 int auto_saving;
123 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
124 a new file with the same mode as the original */
125 int auto_save_mode_bits;
127 /* Alist of elements (REGEXP . HANDLER) for file names
128 whose I/O is done with a special handler. */
129 Lisp_Object Vfile_name_handler_alist;
131 /* Functions to be called to process text properties in inserted file. */
132 Lisp_Object Vafter_insert_file_functions;
134 /* Functions to be called to create text property annotations for file. */
135 Lisp_Object Vwrite_region_annotate_functions;
137 /* During build_annotations, each time an annotation function is called,
138 this holds the annotations made by the previous functions. */
139 Lisp_Object Vwrite_region_annotations_so_far;
141 /* File name in which we write a list of all our auto save files. */
142 Lisp_Object Vauto_save_list_file_name;
144 /* Nonzero means, when reading a filename in the minibuffer,
145 start out by inserting the default directory into the minibuffer. */
146 int insert_default_directory;
148 /* On VMS, nonzero means write new files with record format stmlf.
149 Zero means use var format. */
150 int vms_stmlf_recfm;
152 /* These variables describe handlers that have "already" had a chance
153 to handle the current operation.
155 Vinhibit_file_name_handlers is a list of file name handlers.
156 Vinhibit_file_name_operation is the operation being handled.
157 If we try to handle that operation, we ignore those handlers. */
159 static Lisp_Object Vinhibit_file_name_handlers;
160 static Lisp_Object Vinhibit_file_name_operation;
162 Lisp_Object Qfile_error, Qfile_already_exists;
164 Lisp_Object Qfile_name_history;
166 Lisp_Object Qcar_less_than_car;
168 report_file_error (string, data)
169 char *string;
170 Lisp_Object data;
172 Lisp_Object errstring;
174 errstring = build_string (strerror (errno));
176 /* System error messages are capitalized. Downcase the initial
177 unless it is followed by a slash. */
178 if (XSTRING (errstring)->data[1] != '/')
179 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
181 while (1)
182 Fsignal (Qfile_error,
183 Fcons (build_string (string), Fcons (errstring, data)));
186 close_file_unwind (fd)
187 Lisp_Object fd;
189 close (XFASTINT (fd));
192 /* Restore point, having saved it as a marker. */
194 restore_point_unwind (location)
195 Lisp_Object location;
197 SET_PT (marker_position (location));
198 Fset_marker (location, Qnil, Qnil);
201 Lisp_Object Qexpand_file_name;
202 Lisp_Object Qsubstitute_in_file_name;
203 Lisp_Object Qdirectory_file_name;
204 Lisp_Object Qfile_name_directory;
205 Lisp_Object Qfile_name_nondirectory;
206 Lisp_Object Qunhandled_file_name_directory;
207 Lisp_Object Qfile_name_as_directory;
208 Lisp_Object Qcopy_file;
209 Lisp_Object Qmake_directory_internal;
210 Lisp_Object Qdelete_directory;
211 Lisp_Object Qdelete_file;
212 Lisp_Object Qrename_file;
213 Lisp_Object Qadd_name_to_file;
214 Lisp_Object Qmake_symbolic_link;
215 Lisp_Object Qfile_exists_p;
216 Lisp_Object Qfile_executable_p;
217 Lisp_Object Qfile_readable_p;
218 Lisp_Object Qfile_symlink_p;
219 Lisp_Object Qfile_writable_p;
220 Lisp_Object Qfile_directory_p;
221 Lisp_Object Qfile_accessible_directory_p;
222 Lisp_Object Qfile_modes;
223 Lisp_Object Qset_file_modes;
224 Lisp_Object Qfile_newer_than_file_p;
225 Lisp_Object Qinsert_file_contents;
226 Lisp_Object Qwrite_region;
227 Lisp_Object Qverify_visited_file_modtime;
228 Lisp_Object Qset_visited_file_modtime;
230 DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
231 "Return FILENAME's handler function for OPERATION, if it has one.\n\
232 Otherwise, return nil.\n\
233 A file name is handled if one of the regular expressions in\n\
234 `file-name-handler-alist' matches it.\n\n\
235 If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
236 any handlers that are members of `inhibit-file-name-handlers',\n\
237 but we still do run any other handlers. This lets handlers\n\
238 use the standard functions without calling themselves recursively.")
239 (filename, operation)
240 Lisp_Object filename, operation;
242 /* This function must not munge the match data. */
243 Lisp_Object chain, inhibited_handlers;
245 CHECK_STRING (filename, 0);
247 if (EQ (operation, Vinhibit_file_name_operation))
248 inhibited_handlers = Vinhibit_file_name_handlers;
249 else
250 inhibited_handlers = Qnil;
252 for (chain = Vfile_name_handler_alist; CONSP (chain);
253 chain = XCONS (chain)->cdr)
255 Lisp_Object elt;
256 elt = XCONS (chain)->car;
257 if (CONSP (elt))
259 Lisp_Object string;
260 string = XCONS (elt)->car;
261 if (STRINGP (string) && fast_string_match (string, filename) >= 0)
263 Lisp_Object handler, tem;
265 handler = XCONS (elt)->cdr;
266 tem = Fmemq (handler, inhibited_handlers);
267 if (NILP (tem))
268 return handler;
272 QUIT;
274 return Qnil;
277 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
278 1, 1, 0,
279 "Return the directory component in file name NAME.\n\
280 Return nil if NAME does not include a directory.\n\
281 Otherwise return a directory spec.\n\
282 Given a Unix syntax file name, returns a string ending in slash;\n\
283 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
284 (file)
285 Lisp_Object file;
287 register unsigned char *beg;
288 register unsigned char *p;
289 Lisp_Object handler;
291 CHECK_STRING (file, 0);
293 /* If the file name has special constructs in it,
294 call the corresponding file handler. */
295 handler = Ffind_file_name_handler (file, Qfile_name_directory);
296 if (!NILP (handler))
297 return call2 (handler, Qfile_name_directory, file);
299 #ifdef FILE_SYSTEM_CASE
300 file = FILE_SYSTEM_CASE (file);
301 #endif
302 beg = XSTRING (file)->data;
303 p = beg + XSTRING (file)->size;
305 while (p != beg && !IS_ANY_SEP (p[-1])
306 #ifdef VMS
307 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
308 #endif /* VMS */
309 ) p--;
311 if (p == beg)
312 return Qnil;
313 #ifdef DOS_NT
314 /* Expansion of "c:" to drive and default directory. */
315 /* (NT does the right thing.) */
316 if (p == beg + 2 && beg[1] == ':')
318 int drive = (*beg) - 'a';
319 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
320 unsigned char *res = alloca (MAXPATHLEN + 5);
321 unsigned char *res1;
322 #ifdef WINDOWSNT
323 res1 = res;
324 /* The NT version places the drive letter at the beginning already. */
325 #else /* not WINDOWSNT */
326 /* On MSDOG we must put the drive letter in by hand. */
327 res1 = res + 2;
328 #endif /* not WINDOWSNT */
329 if (getdefdir (drive + 1, res))
331 #ifdef MSDOS
332 res[0] = drive + 'a';
333 res[1] = ':';
334 #endif /* MSDOS */
335 if (IS_DIRECTORY_SEP (res[strlen (res) - 1]))
336 strcat (res, "/");
337 beg = res;
338 p = beg + strlen (beg);
341 #endif /* DOS_NT */
342 return make_string (beg, p - beg);
345 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
346 1, 1, 0,
347 "Return file name NAME sans its directory.\n\
348 For example, in a Unix-syntax file name,\n\
349 this is everything after the last slash,\n\
350 or the entire name if it contains no slash.")
351 (file)
352 Lisp_Object file;
354 register unsigned char *beg, *p, *end;
355 Lisp_Object handler;
357 CHECK_STRING (file, 0);
359 /* If the file name has special constructs in it,
360 call the corresponding file handler. */
361 handler = Ffind_file_name_handler (file, Qfile_name_nondirectory);
362 if (!NILP (handler))
363 return call2 (handler, Qfile_name_nondirectory, file);
365 beg = XSTRING (file)->data;
366 end = p = beg + XSTRING (file)->size;
368 while (p != beg && !IS_ANY_SEP (p[-1])
369 #ifdef VMS
370 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
371 #endif /* VMS */
372 ) p--;
374 return make_string (p, end - p);
377 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
378 "Return a directly usable directory name somehow associated with FILENAME.\n\
379 A `directly usable' directory name is one that may be used without the\n\
380 intervention of any file handler.\n\
381 If FILENAME is a directly usable file itself, return\n\
382 (file-name-directory FILENAME).\n\
383 The `call-process' and `start-process' functions use this function to\n\
384 get a current directory to run processes in.")
385 (filename)
386 Lisp_Object filename;
388 Lisp_Object handler;
390 /* If the file name has special constructs in it,
391 call the corresponding file handler. */
392 handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
393 if (!NILP (handler))
394 return call2 (handler, Qunhandled_file_name_directory, filename);
396 return Ffile_name_directory (filename);
400 char *
401 file_name_as_directory (out, in)
402 char *out, *in;
404 int size = strlen (in) - 1;
406 strcpy (out, in);
408 #ifdef VMS
409 /* Is it already a directory string? */
410 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
411 return out;
412 /* Is it a VMS directory file name? If so, hack VMS syntax. */
413 else if (! index (in, '/')
414 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
415 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
416 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
417 || ! strncmp (&in[size - 5], ".dir", 4))
418 && (in[size - 1] == '.' || in[size - 1] == ';')
419 && in[size] == '1')))
421 register char *p, *dot;
422 char brack;
424 /* x.dir -> [.x]
425 dir:x.dir --> dir:[x]
426 dir:[x]y.dir --> dir:[x.y] */
427 p = in + size;
428 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
429 if (p != in)
431 strncpy (out, in, p - in);
432 out[p - in] = '\0';
433 if (*p == ':')
435 brack = ']';
436 strcat (out, ":[");
438 else
440 brack = *p;
441 strcat (out, ".");
443 p++;
445 else
447 brack = ']';
448 strcpy (out, "[.");
450 dot = index (p, '.');
451 if (dot)
453 /* blindly remove any extension */
454 size = strlen (out) + (dot - p);
455 strncat (out, p, dot - p);
457 else
459 strcat (out, p);
460 size = strlen (out);
462 out[size++] = brack;
463 out[size] = '\0';
465 #else /* not VMS */
466 /* For Unix syntax, Append a slash if necessary */
467 if (!IS_ANY_SEP (out[size]))
469 out[size + 1] = DIRECTORY_SEP;
470 out[size + 2] = '\0';
472 #endif /* not VMS */
473 return out;
476 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
477 Sfile_name_as_directory, 1, 1, 0,
478 "Return a string representing file FILENAME interpreted as a directory.\n\
479 This operation exists because a directory is also a file, but its name as\n\
480 a directory is different from its name as a file.\n\
481 The result can be used as the value of `default-directory'\n\
482 or passed as second argument to `expand-file-name'.\n\
483 For a Unix-syntax file name, just appends a slash.\n\
484 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
485 (file)
486 Lisp_Object file;
488 char *buf;
489 Lisp_Object handler;
491 CHECK_STRING (file, 0);
492 if (NILP (file))
493 return Qnil;
495 /* If the file name has special constructs in it,
496 call the corresponding file handler. */
497 handler = Ffind_file_name_handler (file, Qfile_name_as_directory);
498 if (!NILP (handler))
499 return call2 (handler, Qfile_name_as_directory, file);
501 buf = (char *) alloca (XSTRING (file)->size + 10);
502 return build_string (file_name_as_directory (buf, XSTRING (file)->data));
506 * Convert from directory name to filename.
507 * On VMS:
508 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
509 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
510 * On UNIX, it's simple: just make sure there is a terminating /
512 * Value is nonzero if the string output is different from the input.
515 directory_file_name (src, dst)
516 char *src, *dst;
518 long slen;
519 #ifdef VMS
520 long rlen;
521 char * ptr, * rptr;
522 char bracket;
523 struct FAB fab = cc$rms_fab;
524 struct NAM nam = cc$rms_nam;
525 char esa[NAM$C_MAXRSS];
526 #endif /* VMS */
528 slen = strlen (src);
529 #ifdef VMS
530 if (! index (src, '/')
531 && (src[slen - 1] == ']'
532 || src[slen - 1] == ':'
533 || src[slen - 1] == '>'))
535 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
536 fab.fab$l_fna = src;
537 fab.fab$b_fns = slen;
538 fab.fab$l_nam = &nam;
539 fab.fab$l_fop = FAB$M_NAM;
541 nam.nam$l_esa = esa;
542 nam.nam$b_ess = sizeof esa;
543 nam.nam$b_nop |= NAM$M_SYNCHK;
545 /* We call SYS$PARSE to handle such things as [--] for us. */
546 if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
548 slen = nam.nam$b_esl;
549 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
550 slen -= 2;
551 esa[slen] = '\0';
552 src = esa;
554 if (src[slen - 1] != ']' && src[slen - 1] != '>')
556 /* what about when we have logical_name:???? */
557 if (src[slen - 1] == ':')
558 { /* Xlate logical name and see what we get */
559 ptr = strcpy (dst, src); /* upper case for getenv */
560 while (*ptr)
562 if ('a' <= *ptr && *ptr <= 'z')
563 *ptr -= 040;
564 ptr++;
566 dst[slen - 1] = 0; /* remove colon */
567 if (!(src = egetenv (dst)))
568 return 0;
569 /* should we jump to the beginning of this procedure?
570 Good points: allows us to use logical names that xlate
571 to Unix names,
572 Bad points: can be a problem if we just translated to a device
573 name...
574 For now, I'll punt and always expect VMS names, and hope for
575 the best! */
576 slen = strlen (src);
577 if (src[slen - 1] != ']' && src[slen - 1] != '>')
578 { /* no recursion here! */
579 strcpy (dst, src);
580 return 0;
583 else
584 { /* not a directory spec */
585 strcpy (dst, src);
586 return 0;
589 bracket = src[slen - 1];
591 /* If bracket is ']' or '>', bracket - 2 is the corresponding
592 opening bracket. */
593 ptr = index (src, bracket - 2);
594 if (ptr == 0)
595 { /* no opening bracket */
596 strcpy (dst, src);
597 return 0;
599 if (!(rptr = rindex (src, '.')))
600 rptr = ptr;
601 slen = rptr - src;
602 strncpy (dst, src, slen);
603 dst[slen] = '\0';
604 if (*rptr == '.')
606 dst[slen++] = bracket;
607 dst[slen] = '\0';
609 else
611 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
612 then translate the device and recurse. */
613 if (dst[slen - 1] == ':'
614 && dst[slen - 2] != ':' /* skip decnet nodes */
615 && strcmp(src + slen, "[000000]") == 0)
617 dst[slen - 1] = '\0';
618 if ((ptr = egetenv (dst))
619 && (rlen = strlen (ptr) - 1) > 0
620 && (ptr[rlen] == ']' || ptr[rlen] == '>')
621 && ptr[rlen - 1] == '.')
623 char * buf = (char *) alloca (strlen (ptr) + 1);
624 strcpy (buf, ptr);
625 buf[rlen - 1] = ']';
626 buf[rlen] = '\0';
627 return directory_file_name (buf, dst);
629 else
630 dst[slen - 1] = ':';
632 strcat (dst, "[000000]");
633 slen += 8;
635 rptr++;
636 rlen = strlen (rptr) - 1;
637 strncat (dst, rptr, rlen);
638 dst[slen + rlen] = '\0';
639 strcat (dst, ".DIR.1");
640 return 1;
642 #endif /* VMS */
643 /* Process as Unix format: just remove any final slash.
644 But leave "/" unchanged; do not change it to "". */
645 strcpy (dst, src);
646 if (slen > 1
647 && IS_DIRECTORY_SEP (dst[slen - 1])
648 && !IS_DEVICE_SEP (dst[slen - 2]))
649 dst[slen - 1] = 0;
650 return 1;
653 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
654 1, 1, 0,
655 "Returns the file name of the directory named DIR.\n\
656 This is the name of the file that holds the data for the directory DIR.\n\
657 This operation exists because a directory is also a file, but its name as\n\
658 a directory is different from its name as a file.\n\
659 In Unix-syntax, this function just removes the final slash.\n\
660 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
661 it returns a file name such as \"[X]Y.DIR.1\".")
662 (directory)
663 Lisp_Object directory;
665 char *buf;
666 Lisp_Object handler;
668 CHECK_STRING (directory, 0);
670 if (NILP (directory))
671 return Qnil;
673 /* If the file name has special constructs in it,
674 call the corresponding file handler. */
675 handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
676 if (!NILP (handler))
677 return call2 (handler, Qdirectory_file_name, directory);
679 #ifdef VMS
680 /* 20 extra chars is insufficient for VMS, since we might perform a
681 logical name translation. an equivalence string can be up to 255
682 chars long, so grab that much extra space... - sss */
683 buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
684 #else
685 buf = (char *) alloca (XSTRING (directory)->size + 20);
686 #endif
687 directory_file_name (XSTRING (directory)->data, buf);
688 return build_string (buf);
691 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
692 "Generate temporary file name (string) starting with PREFIX (a string).\n\
693 The Emacs process number forms part of the result,\n\
694 so there is no danger of generating a name being used by another process.")
695 (prefix)
696 Lisp_Object prefix;
698 Lisp_Object val;
699 val = concat2 (prefix, build_string ("XXXXXX"));
700 mktemp (XSTRING (val)->data);
701 return val;
704 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
705 "Convert FILENAME to absolute, and canonicalize it.\n\
706 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
707 (does not start with slash); if DEFAULT is nil or missing,\n\
708 the current buffer's value of default-directory is used.\n\
709 Path components that are `.' are removed, and \n\
710 path components followed by `..' are removed, along with the `..' itself;\n\
711 note that these simplifications are done without checking the resulting\n\
712 paths in the file system.\n\
713 An initial `~/' expands to your home directory.\n\
714 An initial `~USER/' expands to USER's home directory.\n\
715 See also the function `substitute-in-file-name'.")
716 (name, defalt)
717 Lisp_Object name, defalt;
719 unsigned char *nm;
721 register unsigned char *newdir, *p, *o;
722 int tlen;
723 unsigned char *target;
724 struct passwd *pw;
725 #ifdef VMS
726 unsigned char * colon = 0;
727 unsigned char * close = 0;
728 unsigned char * slash = 0;
729 unsigned char * brack = 0;
730 int lbrack = 0, rbrack = 0;
731 int dots = 0;
732 #endif /* VMS */
733 #ifdef DOS_NT
734 /* Demacs 1.1.2 91/10/20 Manabu Higashida */
735 int drive = -1;
736 int relpath = 0;
737 unsigned char *tmp, *defdir;
738 #endif /* DOS_NT */
739 Lisp_Object handler;
741 CHECK_STRING (name, 0);
743 /* If the file name has special constructs in it,
744 call the corresponding file handler. */
745 handler = Ffind_file_name_handler (name, Qexpand_file_name);
746 if (!NILP (handler))
747 return call3 (handler, Qexpand_file_name, name, defalt);
749 /* Use the buffer's default-directory if DEFALT is omitted. */
750 if (NILP (defalt))
751 defalt = current_buffer->directory;
752 CHECK_STRING (defalt, 1);
754 if (!NILP (defalt))
756 handler = Ffind_file_name_handler (defalt, Qexpand_file_name);
757 if (!NILP (handler))
758 return call3 (handler, Qexpand_file_name, name, defalt);
761 o = XSTRING (defalt)->data;
763 /* Make sure DEFALT is properly expanded.
764 It would be better to do this down below where we actually use
765 defalt. Unfortunately, calling Fexpand_file_name recursively
766 could invoke GC, and the strings might be relocated. This would
767 be annoying because we have pointers into strings lying around
768 that would need adjusting, and people would add new pointers to
769 the code and forget to adjust them, resulting in intermittent bugs.
770 Putting this call here avoids all that crud.
772 The EQ test avoids infinite recursion. */
773 if (! NILP (defalt) && !EQ (defalt, name)
774 /* This saves time in a common case. */
775 && ! (XSTRING (defalt)->size >= 3
776 && IS_DIRECTORY_SEP (XSTRING (defalt)->data[0])
777 && IS_DEVICE_SEP (XSTRING (defalt)->data[1])))
779 struct gcpro gcpro1;
781 GCPRO1 (name);
782 defalt = Fexpand_file_name (defalt, Qnil);
783 UNGCPRO;
786 #ifdef VMS
787 /* Filenames on VMS are always upper case. */
788 name = Fupcase (name);
789 #endif
790 #ifdef FILE_SYSTEM_CASE
791 name = FILE_SYSTEM_CASE (name);
792 #endif
794 nm = XSTRING (name)->data;
796 #ifdef MSDOS
797 /* First map all backslashes to slashes. */
798 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
799 #endif
801 #ifdef DOS_NT
802 /* Now strip drive name. */
804 unsigned char *colon = rindex (nm, ':');
805 if (colon)
806 if (nm == colon)
807 nm++;
808 else
810 drive = tolower (colon[-1]) - 'a';
811 nm = colon + 1;
812 if (!IS_DIRECTORY_SEP (*nm))
814 defdir = alloca (MAXPATHLEN + 1);
815 relpath = getdefdir (drive + 1, defdir);
819 #endif /* DOS_NT */
821 /* If nm is absolute, flush ...// and detect /./ and /../.
822 If no /./ or /../ we can return right away. */
823 if (
824 IS_DIRECTORY_SEP (nm[0])
825 #ifdef VMS
826 || index (nm, ':')
827 #endif /* VMS */
830 /* If it turns out that the filename we want to return is just a
831 suffix of FILENAME, we don't need to go through and edit
832 things; we just need to construct a new string using data
833 starting at the middle of FILENAME. If we set lose to a
834 non-zero value, that means we've discovered that we can't do
835 that cool trick. */
836 int lose = 0;
838 p = nm;
839 while (*p)
841 /* Since we know the path is absolute, we can assume that each
842 element starts with a "/". */
844 /* "//" anywhere isn't necessarily hairy; we just start afresh
845 with the second slash. */
846 if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
847 #ifdef APOLLO
848 /* // at start of filename is meaningful on Apollo system */
849 && nm != p
850 #endif /* APOLLO */
851 #ifdef WINDOWSNT
852 /* \\ or // at the start of a pathname is meaningful on NT. */
853 && nm != p
854 #endif /* WINDOWSNT */
856 nm = p + 1;
858 /* "~" is hairy as the start of any path element. */
859 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~')
860 nm = p + 1, lose = 1;
862 /* "." and ".." are hairy. */
863 if (IS_DIRECTORY_SEP (p[0])
864 && p[1] == '.'
865 && (IS_DIRECTORY_SEP (p[2])
866 || p[2] == 0
867 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
868 || p[3] == 0))))
869 lose = 1;
870 #ifdef VMS
871 if (p[0] == '\\')
872 lose = 1;
873 if (p[0] == '/') {
874 /* if dev:[dir]/, move nm to / */
875 if (!slash && p > nm && (brack || colon)) {
876 nm = (brack ? brack + 1 : colon + 1);
877 lbrack = rbrack = 0;
878 brack = 0;
879 colon = 0;
881 slash = p;
883 if (p[0] == '-')
884 #ifndef VMS4_4
885 /* VMS pre V4.4,convert '-'s in filenames. */
886 if (lbrack == rbrack)
888 if (dots < 2) /* this is to allow negative version numbers */
889 p[0] = '_';
891 else
892 #endif /* VMS4_4 */
893 if (lbrack > rbrack &&
894 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
895 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
896 lose = 1;
897 #ifndef VMS4_4
898 else
899 p[0] = '_';
900 #endif /* VMS4_4 */
901 /* count open brackets, reset close bracket pointer */
902 if (p[0] == '[' || p[0] == '<')
903 lbrack++, brack = 0;
904 /* count close brackets, set close bracket pointer */
905 if (p[0] == ']' || p[0] == '>')
906 rbrack++, brack = p;
907 /* detect ][ or >< */
908 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
909 lose = 1;
910 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
911 nm = p + 1, lose = 1;
912 if (p[0] == ':' && (colon || slash))
913 /* if dev1:[dir]dev2:, move nm to dev2: */
914 if (brack)
916 nm = brack + 1;
917 brack = 0;
919 /* if /pathname/dev:, move nm to dev: */
920 else if (slash)
921 nm = slash + 1;
922 /* if node::dev:, move colon following dev */
923 else if (colon && colon[-1] == ':')
924 colon = p;
925 /* if dev1:dev2:, move nm to dev2: */
926 else if (colon && colon[-1] != ':')
928 nm = colon + 1;
929 colon = 0;
931 if (p[0] == ':' && !colon)
933 if (p[1] == ':')
934 p++;
935 colon = p;
937 if (lbrack == rbrack)
938 if (p[0] == ';')
939 dots = 2;
940 else if (p[0] == '.')
941 dots++;
942 #endif /* VMS */
943 p++;
945 if (!lose)
947 #ifdef VMS
948 if (index (nm, '/'))
949 return build_string (sys_translate_unix (nm));
950 #endif /* VMS */
951 #ifndef DOS_NT
952 if (nm == XSTRING (name)->data)
953 return name;
954 return build_string (nm);
955 #endif /* not DOS_NT */
959 /* Now determine directory to start with and put it in newdir */
961 newdir = 0;
963 if (nm[0] == '~') /* prefix ~ */
965 if (IS_DIRECTORY_SEP (nm[1])
966 #ifdef VMS
967 || nm[1] == ':'
968 #endif /* VMS */
969 || nm[1] == 0) /* ~ by itself */
971 if (!(newdir = (unsigned char *) egetenv ("HOME")))
972 newdir = (unsigned char *) "";
973 #ifdef DOS_NT
974 dostounix_filename (newdir);
975 #endif
976 nm++;
977 #ifdef VMS
978 nm++; /* Don't leave the slash in nm. */
979 #endif /* VMS */
981 else /* ~user/filename */
983 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)
984 #ifdef VMS
985 && *p != ':'
986 #endif /* VMS */
987 ); p++);
988 o = (unsigned char *) alloca (p - nm + 1);
989 bcopy ((char *) nm, o, p - nm);
990 o [p - nm] = 0;
992 #ifdef WINDOWSNT
993 newdir = (unsigned char *) egetenv ("HOME");
994 dostounix_filename (newdir);
995 #else /* not WINDOWSNT */
996 pw = (struct passwd *) getpwnam (o + 1);
997 if (pw)
999 newdir = (unsigned char *) pw -> pw_dir;
1000 #ifdef VMS
1001 nm = p + 1; /* skip the terminator */
1002 #else
1003 nm = p;
1004 #endif /* VMS */
1006 #endif /* not WINDOWSNT */
1008 /* If we don't find a user of that name, leave the name
1009 unchanged; don't move nm forward to p. */
1013 if (!IS_ANY_SEP (nm[0])
1014 #ifdef VMS
1015 && !index (nm, ':')
1016 #endif /* not VMS */
1017 #ifdef DOS_NT
1018 && drive == -1
1019 #endif /* DOS_NT */
1020 && !newdir)
1022 newdir = XSTRING (defalt)->data;
1025 #ifdef DOS_NT
1026 if (newdir == 0 && relpath)
1027 newdir = defdir;
1028 #endif /* DOS_NT */
1029 if (newdir != 0)
1031 /* Get rid of any slash at the end of newdir. */
1032 int length = strlen (newdir);
1033 /* Adding `length > 1 &&' makes ~ expand into / when homedir
1034 is the root dir. People disagree about whether that is right.
1035 Anyway, we can't take the risk of this change now. */
1036 #ifdef MSDOS
1037 if (newdir[1] != ':' && length > 1)
1038 #endif
1039 if (IS_DIRECTORY_SEP (newdir[length - 1]))
1041 unsigned char *temp = (unsigned char *) alloca (length);
1042 bcopy (newdir, temp, length - 1);
1043 temp[length - 1] = 0;
1044 newdir = temp;
1046 tlen = length + 1;
1048 else
1049 tlen = 0;
1051 /* Now concatenate the directory and name to new space in the stack frame */
1052 tlen += strlen (nm) + 1;
1053 #ifdef DOS_NT
1054 /* Add reserved space for drive name. (The Microsoft x86 compiler
1055 produces incorrect code if the following two lines are combined.) */
1056 target = (unsigned char *) alloca (tlen + 2);
1057 target += 2;
1058 #else /* not DOS_NT */
1059 target = (unsigned char *) alloca (tlen);
1060 #endif /* not DOS_NT */
1061 *target = 0;
1063 if (newdir)
1065 #ifndef VMS
1066 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
1067 strcpy (target, newdir);
1068 else
1069 #endif
1070 file_name_as_directory (target, newdir);
1073 strcat (target, nm);
1074 #ifdef VMS
1075 if (index (target, '/'))
1076 strcpy (target, sys_translate_unix (target));
1077 #endif /* VMS */
1079 /* Now canonicalize by removing /. and /foo/.. if they appear. */
1081 p = target;
1082 o = target;
1084 while (*p)
1086 #ifdef VMS
1087 if (*p != ']' && *p != '>' && *p != '-')
1089 if (*p == '\\')
1090 p++;
1091 *o++ = *p++;
1093 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1094 /* brackets are offset from each other by 2 */
1096 p += 2;
1097 if (*p != '.' && *p != '-' && o[-1] != '.')
1098 /* convert [foo][bar] to [bar] */
1099 while (o[-1] != '[' && o[-1] != '<')
1100 o--;
1101 else if (*p == '-' && *o != '.')
1102 *--p = '.';
1104 else if (p[0] == '-' && o[-1] == '.' &&
1105 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1106 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1109 o--;
1110 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1111 if (p[1] == '.') /* foo.-.bar ==> bar. */
1112 p += 2;
1113 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1114 p++, o--;
1115 /* else [foo.-] ==> [-] */
1117 else
1119 #ifndef VMS4_4
1120 if (*p == '-' &&
1121 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1122 p[1] != ']' && p[1] != '>' && p[1] != '.')
1123 *p = '_';
1124 #endif /* VMS4_4 */
1125 *o++ = *p++;
1127 #else /* not VMS */
1128 if (!IS_DIRECTORY_SEP (*p))
1130 *o++ = *p++;
1132 #ifdef WINDOWSNT
1133 else if (!strncmp (p, "\\\\", 2) || !strncmp (p, "//", 2))
1134 #else /* not WINDOWSNT */
1135 else if (!strncmp (p, "//", 2)
1136 #endif /* not WINDOWSNT */
1137 #ifdef APOLLO
1138 /* // at start of filename is meaningful in Apollo system */
1139 && o != target
1140 #endif /* APOLLO */
1141 #ifdef WINDOWSNT
1142 /* \\ at start of filename is meaningful in Windows-NT */
1143 && o != target
1144 #endif /* WINDOWSNT */
1147 o = target;
1148 p++;
1150 else if (IS_DIRECTORY_SEP (p[0])
1151 && p[1] == '.'
1152 && (IS_DIRECTORY_SEP (p[2])
1153 || p[2] == 0))
1155 /* If "/." is the entire filename, keep the "/". Otherwise,
1156 just delete the whole "/.". */
1157 if (o == target && p[2] == '\0')
1158 *o++ = *p;
1159 p += 2;
1161 #ifdef WINDOWSNT
1162 else if (!strncmp (p, "\\..", 3) || !strncmp (p, "/..", 3))
1163 #else /* not WINDOWSNT */
1164 else if (!strncmp (p, "/..", 3)
1165 #endif /* not WINDOWSNT */
1166 /* `/../' is the "superroot" on certain file systems. */
1167 && o != target
1168 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
1170 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
1172 #ifdef APOLLO
1173 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1174 ++o;
1175 else
1176 #endif /* APOLLO */
1177 #ifdef WINDOWSNT
1178 if (o == target + 1 && (o[-1] == '/' && o[0] == '/')
1179 || (o[-1] == '\\' && o[0] == '\\'))
1180 ++o;
1181 else
1182 #endif /* WINDOWSNT */
1183 if (o == target && IS_ANY_SEP (*o))
1184 ++o;
1185 p += 3;
1187 else
1189 *o++ = *p++;
1191 #endif /* not VMS */
1194 #ifdef DOS_NT
1195 /* at last, set drive name. */
1196 if (target[1] != ':'
1197 #ifdef WINDOWSNT
1198 /* Allow network paths that look like "\\foo" */
1199 && !(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))
1200 #endif /* WINDOWSNT */
1203 target -= 2;
1204 target[0] = (drive < 0 ? getdisk () : drive) + 'a';
1205 target[1] = ':';
1207 #endif /* DOS_NT */
1209 return make_string (target, o - target);
1212 #if 0
1213 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
1214 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1215 "Convert FILENAME to absolute, and canonicalize it.\n\
1216 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
1217 (does not start with slash); if DEFAULT is nil or missing,\n\
1218 the current buffer's value of default-directory is used.\n\
1219 Filenames containing `.' or `..' as components are simplified;\n\
1220 initial `~/' expands to your home directory.\n\
1221 See also the function `substitute-in-file-name'.")
1222 (name, defalt)
1223 Lisp_Object name, defalt;
1225 unsigned char *nm;
1227 register unsigned char *newdir, *p, *o;
1228 int tlen;
1229 unsigned char *target;
1230 struct passwd *pw;
1231 int lose;
1232 #ifdef VMS
1233 unsigned char * colon = 0;
1234 unsigned char * close = 0;
1235 unsigned char * slash = 0;
1236 unsigned char * brack = 0;
1237 int lbrack = 0, rbrack = 0;
1238 int dots = 0;
1239 #endif /* VMS */
1241 CHECK_STRING (name, 0);
1243 #ifdef VMS
1244 /* Filenames on VMS are always upper case. */
1245 name = Fupcase (name);
1246 #endif
1248 nm = XSTRING (name)->data;
1250 /* If nm is absolute, flush ...// and detect /./ and /../.
1251 If no /./ or /../ we can return right away. */
1252 if (
1253 nm[0] == '/'
1254 #ifdef VMS
1255 || index (nm, ':')
1256 #endif /* VMS */
1259 p = nm;
1260 lose = 0;
1261 while (*p)
1263 if (p[0] == '/' && p[1] == '/'
1264 #ifdef APOLLO
1265 /* // at start of filename is meaningful on Apollo system */
1266 && nm != p
1267 #endif /* APOLLO */
1269 nm = p + 1;
1270 if (p[0] == '/' && p[1] == '~')
1271 nm = p + 1, lose = 1;
1272 if (p[0] == '/' && p[1] == '.'
1273 && (p[2] == '/' || p[2] == 0
1274 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
1275 lose = 1;
1276 #ifdef VMS
1277 if (p[0] == '\\')
1278 lose = 1;
1279 if (p[0] == '/') {
1280 /* if dev:[dir]/, move nm to / */
1281 if (!slash && p > nm && (brack || colon)) {
1282 nm = (brack ? brack + 1 : colon + 1);
1283 lbrack = rbrack = 0;
1284 brack = 0;
1285 colon = 0;
1287 slash = p;
1289 if (p[0] == '-')
1290 #ifndef VMS4_4
1291 /* VMS pre V4.4,convert '-'s in filenames. */
1292 if (lbrack == rbrack)
1294 if (dots < 2) /* this is to allow negative version numbers */
1295 p[0] = '_';
1297 else
1298 #endif /* VMS4_4 */
1299 if (lbrack > rbrack &&
1300 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1301 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1302 lose = 1;
1303 #ifndef VMS4_4
1304 else
1305 p[0] = '_';
1306 #endif /* VMS4_4 */
1307 /* count open brackets, reset close bracket pointer */
1308 if (p[0] == '[' || p[0] == '<')
1309 lbrack++, brack = 0;
1310 /* count close brackets, set close bracket pointer */
1311 if (p[0] == ']' || p[0] == '>')
1312 rbrack++, brack = p;
1313 /* detect ][ or >< */
1314 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1315 lose = 1;
1316 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1317 nm = p + 1, lose = 1;
1318 if (p[0] == ':' && (colon || slash))
1319 /* if dev1:[dir]dev2:, move nm to dev2: */
1320 if (brack)
1322 nm = brack + 1;
1323 brack = 0;
1325 /* if /pathname/dev:, move nm to dev: */
1326 else if (slash)
1327 nm = slash + 1;
1328 /* if node::dev:, move colon following dev */
1329 else if (colon && colon[-1] == ':')
1330 colon = p;
1331 /* if dev1:dev2:, move nm to dev2: */
1332 else if (colon && colon[-1] != ':')
1334 nm = colon + 1;
1335 colon = 0;
1337 if (p[0] == ':' && !colon)
1339 if (p[1] == ':')
1340 p++;
1341 colon = p;
1343 if (lbrack == rbrack)
1344 if (p[0] == ';')
1345 dots = 2;
1346 else if (p[0] == '.')
1347 dots++;
1348 #endif /* VMS */
1349 p++;
1351 if (!lose)
1353 #ifdef VMS
1354 if (index (nm, '/'))
1355 return build_string (sys_translate_unix (nm));
1356 #endif /* VMS */
1357 if (nm == XSTRING (name)->data)
1358 return name;
1359 return build_string (nm);
1363 /* Now determine directory to start with and put it in NEWDIR */
1365 newdir = 0;
1367 if (nm[0] == '~') /* prefix ~ */
1368 if (nm[1] == '/'
1369 #ifdef VMS
1370 || nm[1] == ':'
1371 #endif /* VMS */
1372 || nm[1] == 0)/* ~/filename */
1374 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1375 newdir = (unsigned char *) "";
1376 nm++;
1377 #ifdef VMS
1378 nm++; /* Don't leave the slash in nm. */
1379 #endif /* VMS */
1381 else /* ~user/filename */
1383 /* Get past ~ to user */
1384 unsigned char *user = nm + 1;
1385 /* Find end of name. */
1386 unsigned char *ptr = (unsigned char *) index (user, '/');
1387 int len = ptr ? ptr - user : strlen (user);
1388 #ifdef VMS
1389 unsigned char *ptr1 = index (user, ':');
1390 if (ptr1 != 0 && ptr1 - user < len)
1391 len = ptr1 - user;
1392 #endif /* VMS */
1393 /* Copy the user name into temp storage. */
1394 o = (unsigned char *) alloca (len + 1);
1395 bcopy ((char *) user, o, len);
1396 o[len] = 0;
1398 /* Look up the user name. */
1399 pw = (struct passwd *) getpwnam (o + 1);
1400 if (!pw)
1401 error ("\"%s\" isn't a registered user", o + 1);
1403 newdir = (unsigned char *) pw->pw_dir;
1405 /* Discard the user name from NM. */
1406 nm += len;
1409 if (nm[0] != '/'
1410 #ifdef VMS
1411 && !index (nm, ':')
1412 #endif /* not VMS */
1413 && !newdir)
1415 if (NILP (defalt))
1416 defalt = current_buffer->directory;
1417 CHECK_STRING (defalt, 1);
1418 newdir = XSTRING (defalt)->data;
1421 /* Now concatenate the directory and name to new space in the stack frame */
1423 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1424 target = (unsigned char *) alloca (tlen);
1425 *target = 0;
1427 if (newdir)
1429 #ifndef VMS
1430 if (nm[0] == 0 || nm[0] == '/')
1431 strcpy (target, newdir);
1432 else
1433 #endif
1434 file_name_as_directory (target, newdir);
1437 strcat (target, nm);
1438 #ifdef VMS
1439 if (index (target, '/'))
1440 strcpy (target, sys_translate_unix (target));
1441 #endif /* VMS */
1443 /* Now canonicalize by removing /. and /foo/.. if they appear */
1445 p = target;
1446 o = target;
1448 while (*p)
1450 #ifdef VMS
1451 if (*p != ']' && *p != '>' && *p != '-')
1453 if (*p == '\\')
1454 p++;
1455 *o++ = *p++;
1457 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1458 /* brackets are offset from each other by 2 */
1460 p += 2;
1461 if (*p != '.' && *p != '-' && o[-1] != '.')
1462 /* convert [foo][bar] to [bar] */
1463 while (o[-1] != '[' && o[-1] != '<')
1464 o--;
1465 else if (*p == '-' && *o != '.')
1466 *--p = '.';
1468 else if (p[0] == '-' && o[-1] == '.' &&
1469 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1470 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1473 o--;
1474 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1475 if (p[1] == '.') /* foo.-.bar ==> bar. */
1476 p += 2;
1477 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1478 p++, o--;
1479 /* else [foo.-] ==> [-] */
1481 else
1483 #ifndef VMS4_4
1484 if (*p == '-' &&
1485 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1486 p[1] != ']' && p[1] != '>' && p[1] != '.')
1487 *p = '_';
1488 #endif /* VMS4_4 */
1489 *o++ = *p++;
1491 #else /* not VMS */
1492 if (*p != '/')
1494 *o++ = *p++;
1496 else if (!strncmp (p, "//", 2)
1497 #ifdef APOLLO
1498 /* // at start of filename is meaningful in Apollo system */
1499 && o != target
1500 #endif /* APOLLO */
1503 o = target;
1504 p++;
1506 else if (p[0] == '/' && p[1] == '.' &&
1507 (p[2] == '/' || p[2] == 0))
1508 p += 2;
1509 else if (!strncmp (p, "/..", 3)
1510 /* `/../' is the "superroot" on certain file systems. */
1511 && o != target
1512 && (p[3] == '/' || p[3] == 0))
1514 while (o != target && *--o != '/')
1516 #ifdef APOLLO
1517 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1518 ++o;
1519 else
1520 #endif /* APOLLO */
1521 if (o == target && *o == '/')
1522 ++o;
1523 p += 3;
1525 else
1527 *o++ = *p++;
1529 #endif /* not VMS */
1532 return make_string (target, o - target);
1534 #endif
1536 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
1537 Ssubstitute_in_file_name, 1, 1, 0,
1538 "Substitute environment variables referred to in FILENAME.\n\
1539 `$FOO' where FOO is an environment variable name means to substitute\n\
1540 the value of that variable. The variable name should be terminated\n\
1541 with a character not a letter, digit or underscore; otherwise, enclose\n\
1542 the entire variable name in braces.\n\
1543 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1544 On VMS, `$' substitution is not done; this function does little and only\n\
1545 duplicates what `expand-file-name' does.")
1546 (string)
1547 Lisp_Object string;
1549 unsigned char *nm;
1551 register unsigned char *s, *p, *o, *x, *endp;
1552 unsigned char *target;
1553 int total = 0;
1554 int substituted = 0;
1555 unsigned char *xnm;
1556 Lisp_Object handler;
1558 CHECK_STRING (string, 0);
1560 /* If the file name has special constructs in it,
1561 call the corresponding file handler. */
1562 handler = Ffind_file_name_handler (string, Qsubstitute_in_file_name);
1563 if (!NILP (handler))
1564 return call2 (handler, Qsubstitute_in_file_name, string);
1566 nm = XSTRING (string)->data;
1567 #ifdef MSDOS
1568 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
1569 substituted = !strcmp (nm, XSTRING (string)->data);
1570 #endif
1571 endp = nm + XSTRING (string)->size;
1573 /* If /~ or // appears, discard everything through first slash. */
1575 for (p = nm; p != endp; p++)
1577 if ((p[0] == '~' ||
1578 #ifdef APOLLO
1579 /* // at start of file name is meaningful in Apollo system */
1580 (p[0] == '/' && p - 1 != nm)
1581 #else /* not APOLLO */
1582 #ifdef WINDOWSNT
1583 (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
1584 #else /* not WINDOWSNT */
1585 p[0] == '/'
1586 #endif /* not WINDOWSNT */
1587 #endif /* not APOLLO */
1589 && p != nm
1590 && (0
1591 #ifdef VMS
1592 || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
1593 #endif /* VMS */
1594 || IS_DIRECTORY_SEP (p[-1])))
1596 nm = p;
1597 substituted = 1;
1599 #ifdef DOS_NT
1600 if (p[0] && p[1] == ':')
1602 nm = p;
1603 substituted = 1;
1605 #endif /* DOS_NT */
1608 #ifdef VMS
1609 return build_string (nm);
1610 #else
1612 /* See if any variables are substituted into the string
1613 and find the total length of their values in `total' */
1615 for (p = nm; p != endp;)
1616 if (*p != '$')
1617 p++;
1618 else
1620 p++;
1621 if (p == endp)
1622 goto badsubst;
1623 else if (*p == '$')
1625 /* "$$" means a single "$" */
1626 p++;
1627 total -= 1;
1628 substituted = 1;
1629 continue;
1631 else if (*p == '{')
1633 o = ++p;
1634 while (p != endp && *p != '}') p++;
1635 if (*p != '}') goto missingclose;
1636 s = p;
1638 else
1640 o = p;
1641 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1642 s = p;
1645 /* Copy out the variable name */
1646 target = (unsigned char *) alloca (s - o + 1);
1647 strncpy (target, o, s - o);
1648 target[s - o] = 0;
1649 #ifdef DOS_NT
1650 strupr (target); /* $home == $HOME etc. */
1651 #endif /* DOS_NT */
1653 /* Get variable value */
1654 o = (unsigned char *) egetenv (target);
1655 if (!o) goto badvar;
1656 total += strlen (o);
1657 substituted = 1;
1660 if (!substituted)
1661 return string;
1663 /* If substitution required, recopy the string and do it */
1664 /* Make space in stack frame for the new copy */
1665 xnm = (unsigned char *) alloca (XSTRING (string)->size + total + 1);
1666 x = xnm;
1668 /* Copy the rest of the name through, replacing $ constructs with values */
1669 for (p = nm; *p;)
1670 if (*p != '$')
1671 *x++ = *p++;
1672 else
1674 p++;
1675 if (p == endp)
1676 goto badsubst;
1677 else if (*p == '$')
1679 *x++ = *p++;
1680 continue;
1682 else if (*p == '{')
1684 o = ++p;
1685 while (p != endp && *p != '}') p++;
1686 if (*p != '}') goto missingclose;
1687 s = p++;
1689 else
1691 o = p;
1692 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1693 s = p;
1696 /* Copy out the variable name */
1697 target = (unsigned char *) alloca (s - o + 1);
1698 strncpy (target, o, s - o);
1699 target[s - o] = 0;
1700 #ifdef DOS_NT
1701 strupr (target); /* $home == $HOME etc. */
1702 #endif /* DOS_NT */
1704 /* Get variable value */
1705 o = (unsigned char *) egetenv (target);
1706 if (!o)
1707 goto badvar;
1709 strcpy (x, o);
1710 x += strlen (o);
1713 *x = 0;
1715 /* If /~ or // appears, discard everything through first slash. */
1717 for (p = xnm; p != x; p++)
1718 if ((p[0] == '~'
1719 #ifdef APOLLO
1720 /* // at start of file name is meaningful in Apollo system */
1721 || (p[0] == '/' && p - 1 != xnm)
1722 #else /* not APOLLO */
1723 #ifdef WINDOWSNT
1724 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
1725 #else /* not WINDOWSNT */
1726 || p[0] == '/'
1727 #endif /* not WINDOWSNT */
1728 #endif /* not APOLLO */
1730 && p != nm && IS_DIRECTORY_SEP (p[-1]))
1731 xnm = p;
1732 #ifdef DOS_NT
1733 else if (p[0] && p[1] == ':')
1734 xnm = p;
1735 #endif
1737 return make_string (xnm, x - xnm);
1739 badsubst:
1740 error ("Bad format environment-variable substitution");
1741 missingclose:
1742 error ("Missing \"}\" in environment-variable substitution");
1743 badvar:
1744 error ("Substituting nonexistent environment variable \"%s\"", target);
1746 /* NOTREACHED */
1747 #endif /* not VMS */
1750 /* A slightly faster and more convenient way to get
1751 (directory-file-name (expand-file-name FOO)). */
1753 Lisp_Object
1754 expand_and_dir_to_file (filename, defdir)
1755 Lisp_Object filename, defdir;
1757 register Lisp_Object abspath;
1759 abspath = Fexpand_file_name (filename, defdir);
1760 #ifdef VMS
1762 register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1];
1763 if (c == ':' || c == ']' || c == '>')
1764 abspath = Fdirectory_file_name (abspath);
1766 #else
1767 /* Remove final slash, if any (unless path is root).
1768 stat behaves differently depending! */
1769 if (XSTRING (abspath)->size > 1
1770 && IS_DIRECTORY_SEP (XSTRING (abspath)->data[XSTRING (abspath)->size - 1])
1771 && !IS_DEVICE_SEP (XSTRING (abspath)->data[XSTRING (abspath)->size-2]))
1772 /* We cannot take shortcuts; they might be wrong for magic file names. */
1773 abspath = Fdirectory_file_name (abspath);
1774 #endif
1775 return abspath;
1778 void
1779 barf_or_query_if_file_exists (absname, querystring, interactive)
1780 Lisp_Object absname;
1781 unsigned char *querystring;
1782 int interactive;
1784 register Lisp_Object tem;
1785 struct stat statbuf;
1786 struct gcpro gcpro1;
1788 /* stat is a good way to tell whether the file exists,
1789 regardless of what access permissions it has. */
1790 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
1792 if (! interactive)
1793 Fsignal (Qfile_already_exists,
1794 Fcons (build_string ("File already exists"),
1795 Fcons (absname, Qnil)));
1796 GCPRO1 (absname);
1797 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1798 XSTRING (absname)->data, querystring));
1799 UNGCPRO;
1800 if (NILP (tem))
1801 Fsignal (Qfile_already_exists,
1802 Fcons (build_string ("File already exists"),
1803 Fcons (absname, Qnil)));
1805 return;
1808 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
1809 "fCopy file: \nFCopy %s to file: \np\nP",
1810 "Copy FILE to NEWNAME. Both args must be strings.\n\
1811 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1812 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1813 A number as third arg means request confirmation if NEWNAME already exists.\n\
1814 This is what happens in interactive use with M-x.\n\
1815 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1816 last-modified time as the old one. (This works on only some systems.)\n\
1817 A prefix arg makes KEEP-TIME non-nil.")
1818 (filename, newname, ok_if_already_exists, keep_date)
1819 Lisp_Object filename, newname, ok_if_already_exists, keep_date;
1821 int ifd, ofd, n;
1822 char buf[16 * 1024];
1823 struct stat st;
1824 Lisp_Object handler;
1825 struct gcpro gcpro1, gcpro2;
1826 int count = specpdl_ptr - specpdl;
1827 int input_file_statable_p;
1829 GCPRO2 (filename, newname);
1830 CHECK_STRING (filename, 0);
1831 CHECK_STRING (newname, 1);
1832 filename = Fexpand_file_name (filename, Qnil);
1833 newname = Fexpand_file_name (newname, Qnil);
1835 /* If the input file name has special constructs in it,
1836 call the corresponding file handler. */
1837 handler = Ffind_file_name_handler (filename, Qcopy_file);
1838 /* Likewise for output file name. */
1839 if (NILP (handler))
1840 handler = Ffind_file_name_handler (newname, Qcopy_file);
1841 if (!NILP (handler))
1842 RETURN_UNGCPRO (call5 (handler, Qcopy_file, filename, newname,
1843 ok_if_already_exists, keep_date));
1845 if (NILP (ok_if_already_exists)
1846 || INTEGERP (ok_if_already_exists))
1847 barf_or_query_if_file_exists (newname, "copy to it",
1848 INTEGERP (ok_if_already_exists));
1850 ifd = open (XSTRING (filename)->data, O_RDONLY);
1851 if (ifd < 0)
1852 report_file_error ("Opening input file", Fcons (filename, Qnil));
1854 record_unwind_protect (close_file_unwind, make_number (ifd));
1856 /* We can only copy regular files and symbolic links. Other files are not
1857 copyable by us. */
1858 input_file_statable_p = (fstat (ifd, &st) >= 0);
1860 #if defined (S_ISREG) && defined (S_ISLNK)
1861 if (input_file_statable_p)
1863 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
1865 #if defined (EISDIR)
1866 /* Get a better looking error message. */
1867 errno = EISDIR;
1868 #endif /* EISDIR */
1869 report_file_error ("Non-regular file", Fcons (filename, Qnil));
1872 #endif /* S_ISREG && S_ISLNK */
1874 #ifdef VMS
1875 /* Create the copy file with the same record format as the input file */
1876 ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
1877 #else
1878 #ifdef MSDOS
1879 /* System's default file type was set to binary by _fmode in emacs.c. */
1880 ofd = creat (XSTRING (newname)->data, S_IREAD | S_IWRITE);
1881 #else /* not MSDOS */
1882 ofd = creat (XSTRING (newname)->data, 0666);
1883 #endif /* not MSDOS */
1884 #endif /* VMS */
1885 if (ofd < 0)
1886 report_file_error ("Opening output file", Fcons (newname, Qnil));
1888 record_unwind_protect (close_file_unwind, make_number (ofd));
1890 immediate_quit = 1;
1891 QUIT;
1892 while ((n = read (ifd, buf, sizeof buf)) > 0)
1893 if (write (ofd, buf, n) != n)
1894 report_file_error ("I/O error", Fcons (newname, Qnil));
1895 immediate_quit = 0;
1897 /* Closing the output clobbers the file times on some systems. */
1898 if (close (ofd) < 0)
1899 report_file_error ("I/O error", Fcons (newname, Qnil));
1901 if (input_file_statable_p)
1903 if (!NILP (keep_date))
1905 EMACS_TIME atime, mtime;
1906 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
1907 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
1908 if (set_file_times (XSTRING (newname)->data, atime, mtime))
1909 report_file_error ("I/O error", Fcons (newname, Qnil));
1911 #ifdef APOLLO
1912 if (!egetenv ("USE_DOMAIN_ACLS"))
1913 #endif
1914 chmod (XSTRING (newname)->data, st.st_mode & 07777);
1917 close (ifd);
1919 /* Discard the unwind protects. */
1920 specpdl_ptr = specpdl + count;
1922 UNGCPRO;
1923 return Qnil;
1926 DEFUN ("make-directory-internal", Fmake_directory_internal,
1927 Smake_directory_internal, 1, 1, 0,
1928 "Create a directory. One argument, a file name string.")
1929 (dirname)
1930 Lisp_Object dirname;
1932 unsigned char *dir;
1933 Lisp_Object handler;
1935 CHECK_STRING (dirname, 0);
1936 dirname = Fexpand_file_name (dirname, Qnil);
1938 handler = Ffind_file_name_handler (dirname, Qmake_directory_internal);
1939 if (!NILP (handler))
1940 return call2 (handler, Qmake_directory_internal, dirname);
1942 dir = XSTRING (dirname)->data;
1944 #ifdef WINDOWSNT
1945 if (mkdir (dir) != 0)
1946 #else
1947 if (mkdir (dir, 0777) != 0)
1948 #endif
1949 report_file_error ("Creating directory", Flist (1, &dirname));
1951 return Qnil;
1954 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
1955 "Delete a directory. One argument, a file name or directory name string.")
1956 (dirname)
1957 Lisp_Object dirname;
1959 unsigned char *dir;
1960 Lisp_Object handler;
1962 CHECK_STRING (dirname, 0);
1963 dirname = Fdirectory_file_name (Fexpand_file_name (dirname, Qnil));
1964 dir = XSTRING (dirname)->data;
1966 handler = Ffind_file_name_handler (dirname, Qdelete_directory);
1967 if (!NILP (handler))
1968 return call2 (handler, Qdelete_directory, dirname);
1970 if (rmdir (dir) != 0)
1971 report_file_error ("Removing directory", Flist (1, &dirname));
1973 return Qnil;
1976 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
1977 "Delete specified file. One argument, a file name string.\n\
1978 If file has multiple names, it continues to exist with the other names.")
1979 (filename)
1980 Lisp_Object filename;
1982 Lisp_Object handler;
1983 CHECK_STRING (filename, 0);
1984 filename = Fexpand_file_name (filename, Qnil);
1986 handler = Ffind_file_name_handler (filename, Qdelete_file);
1987 if (!NILP (handler))
1988 return call2 (handler, Qdelete_file, filename);
1990 if (0 > unlink (XSTRING (filename)->data))
1991 report_file_error ("Removing old name", Flist (1, &filename));
1992 return Qnil;
1995 static Lisp_Object
1996 internal_delete_file_1 (ignore)
1997 Lisp_Object ignore;
1999 return Qt;
2002 /* Delete file FILENAME, returning 1 if successful and 0 if failed. */
2005 internal_delete_file (filename)
2006 Lisp_Object filename;
2008 return NILP (internal_condition_case_1 (Fdelete_file, filename,
2009 Qt, internal_delete_file_1));
2012 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2013 "fRename file: \nFRename %s to file: \np",
2014 "Rename FILE as NEWNAME. Both args strings.\n\
2015 If file has names other than FILE, it continues to have those names.\n\
2016 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2017 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2018 A number as third arg means request confirmation if NEWNAME already exists.\n\
2019 This is what happens in interactive use with M-x.")
2020 (filename, newname, ok_if_already_exists)
2021 Lisp_Object filename, newname, ok_if_already_exists;
2023 #ifdef NO_ARG_ARRAY
2024 Lisp_Object args[2];
2025 #endif
2026 Lisp_Object handler;
2027 struct gcpro gcpro1, gcpro2;
2029 GCPRO2 (filename, newname);
2030 CHECK_STRING (filename, 0);
2031 CHECK_STRING (newname, 1);
2032 filename = Fexpand_file_name (filename, Qnil);
2033 newname = Fexpand_file_name (newname, Qnil);
2035 /* If the file name has special constructs in it,
2036 call the corresponding file handler. */
2037 handler = Ffind_file_name_handler (filename, Qrename_file);
2038 if (NILP (handler))
2039 handler = Ffind_file_name_handler (newname, Qrename_file);
2040 if (!NILP (handler))
2041 RETURN_UNGCPRO (call4 (handler, Qrename_file,
2042 filename, newname, ok_if_already_exists));
2044 if (NILP (ok_if_already_exists)
2045 || INTEGERP (ok_if_already_exists))
2046 barf_or_query_if_file_exists (newname, "rename to it",
2047 INTEGERP (ok_if_already_exists));
2048 #ifndef BSD4_1
2049 if (0 > rename (XSTRING (filename)->data, XSTRING (newname)->data))
2050 #else
2051 #ifdef WINDOWSNT
2052 if (!MoveFile (XSTRING (filename)->data, XSTRING (newname)->data))
2053 #else /* not WINDOWSNT */
2054 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data)
2055 || 0 > unlink (XSTRING (filename)->data))
2056 #endif /* not WINDOWSNT */
2057 #endif
2059 #ifdef WINDOWSNT
2060 /* Why two? And why doesn't MS document what MoveFile will return? */
2061 if (GetLastError () == ERROR_FILE_EXISTS
2062 || GetLastError () == ERROR_ALREADY_EXISTS)
2063 #else /* not WINDOWSNT */
2064 if (errno == EXDEV)
2065 #endif /* not WINDOWSNT */
2067 Fcopy_file (filename, newname,
2068 /* We have already prompted if it was an integer,
2069 so don't have copy-file prompt again. */
2070 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
2071 Fdelete_file (filename);
2073 else
2074 #ifdef NO_ARG_ARRAY
2076 args[0] = filename;
2077 args[1] = newname;
2078 report_file_error ("Renaming", Flist (2, args));
2080 #else
2081 report_file_error ("Renaming", Flist (2, &filename));
2082 #endif
2084 UNGCPRO;
2085 return Qnil;
2088 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
2089 "fAdd name to file: \nFName to add to %s: \np",
2090 "Give FILE additional name NEWNAME. Both args strings.\n\
2091 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2092 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2093 A number as third arg means request confirmation if NEWNAME already exists.\n\
2094 This is what happens in interactive use with M-x.")
2095 (filename, newname, ok_if_already_exists)
2096 Lisp_Object filename, newname, ok_if_already_exists;
2098 #ifdef NO_ARG_ARRAY
2099 Lisp_Object args[2];
2100 #endif
2101 Lisp_Object handler;
2102 struct gcpro gcpro1, gcpro2;
2104 GCPRO2 (filename, newname);
2105 CHECK_STRING (filename, 0);
2106 CHECK_STRING (newname, 1);
2107 filename = Fexpand_file_name (filename, Qnil);
2108 newname = Fexpand_file_name (newname, Qnil);
2110 /* If the file name has special constructs in it,
2111 call the corresponding file handler. */
2112 handler = Ffind_file_name_handler (filename, Qadd_name_to_file);
2113 if (!NILP (handler))
2114 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, filename,
2115 newname, ok_if_already_exists));
2117 if (NILP (ok_if_already_exists)
2118 || INTEGERP (ok_if_already_exists))
2119 barf_or_query_if_file_exists (newname, "make it a new name",
2120 INTEGERP (ok_if_already_exists));
2121 #ifdef WINDOWSNT
2122 /* Windows does not support this operation. */
2123 report_file_error ("Adding new name", Flist (2, &filename));
2124 #else /* not WINDOWSNT */
2126 unlink (XSTRING (newname)->data);
2127 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data))
2129 #ifdef NO_ARG_ARRAY
2130 args[0] = filename;
2131 args[1] = newname;
2132 report_file_error ("Adding new name", Flist (2, args));
2133 #else
2134 report_file_error ("Adding new name", Flist (2, &filename));
2135 #endif
2137 #endif /* not WINDOWSNT */
2139 UNGCPRO;
2140 return Qnil;
2143 #ifdef S_IFLNK
2144 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2145 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2146 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
2147 Signals a `file-already-exists' error if a file LINKNAME already exists\n\
2148 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2149 A number as third arg means request confirmation if LINKNAME already exists.\n\
2150 This happens for interactive use with M-x.")
2151 (filename, linkname, ok_if_already_exists)
2152 Lisp_Object filename, linkname, ok_if_already_exists;
2154 #ifdef NO_ARG_ARRAY
2155 Lisp_Object args[2];
2156 #endif
2157 Lisp_Object handler;
2158 struct gcpro gcpro1, gcpro2;
2160 GCPRO2 (filename, linkname);
2161 CHECK_STRING (filename, 0);
2162 CHECK_STRING (linkname, 1);
2163 /* If the link target has a ~, we must expand it to get
2164 a truly valid file name. Otherwise, do not expand;
2165 we want to permit links to relative file names. */
2166 if (XSTRING (filename)->data[0] == '~')
2167 filename = Fexpand_file_name (filename, Qnil);
2168 linkname = Fexpand_file_name (linkname, Qnil);
2170 /* If the file name has special constructs in it,
2171 call the corresponding file handler. */
2172 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
2173 if (!NILP (handler))
2174 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2175 linkname, ok_if_already_exists));
2177 if (NILP (ok_if_already_exists)
2178 || INTEGERP (ok_if_already_exists))
2179 barf_or_query_if_file_exists (linkname, "make it a link",
2180 INTEGERP (ok_if_already_exists));
2181 if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2183 /* If we didn't complain already, silently delete existing file. */
2184 if (errno == EEXIST)
2186 unlink (XSTRING (linkname)->data);
2187 if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2189 UNGCPRO;
2190 return Qnil;
2194 #ifdef NO_ARG_ARRAY
2195 args[0] = filename;
2196 args[1] = linkname;
2197 report_file_error ("Making symbolic link", Flist (2, args));
2198 #else
2199 report_file_error ("Making symbolic link", Flist (2, &filename));
2200 #endif
2202 UNGCPRO;
2203 return Qnil;
2205 #endif /* S_IFLNK */
2207 #ifdef VMS
2209 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2210 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
2211 "Define the job-wide logical name NAME to have the value STRING.\n\
2212 If STRING is nil or a null string, the logical name NAME is deleted.")
2213 (varname, string)
2214 Lisp_Object varname;
2215 Lisp_Object string;
2217 CHECK_STRING (varname, 0);
2218 if (NILP (string))
2219 delete_logical_name (XSTRING (varname)->data);
2220 else
2222 CHECK_STRING (string, 1);
2224 if (XSTRING (string)->size == 0)
2225 delete_logical_name (XSTRING (varname)->data);
2226 else
2227 define_logical_name (XSTRING (varname)->data, XSTRING (string)->data);
2230 return string;
2232 #endif /* VMS */
2234 #ifdef HPUX_NET
2236 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2237 "Open a network connection to PATH using LOGIN as the login string.")
2238 (path, login)
2239 Lisp_Object path, login;
2241 int netresult;
2243 CHECK_STRING (path, 0);
2244 CHECK_STRING (login, 0);
2246 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2248 if (netresult == -1)
2249 return Qnil;
2250 else
2251 return Qt;
2253 #endif /* HPUX_NET */
2255 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2256 1, 1, 0,
2257 "Return t if file FILENAME specifies an absolute path name.\n\
2258 On Unix, this is a name starting with a `/' or a `~'.")
2259 (filename)
2260 Lisp_Object filename;
2262 unsigned char *ptr;
2264 CHECK_STRING (filename, 0);
2265 ptr = XSTRING (filename)->data;
2266 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
2267 #ifdef VMS
2268 /* ??? This criterion is probably wrong for '<'. */
2269 || index (ptr, ':') || index (ptr, '<')
2270 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2271 && ptr[1] != '.')
2272 #endif /* VMS */
2273 #ifdef DOS_NT
2274 || (*ptr != 0 && ptr[1] == ':' && (ptr[2] == '/' || ptr[2] == '\\'))
2275 #endif
2277 return Qt;
2278 else
2279 return Qnil;
2282 /* Return nonzero if file FILENAME exists and can be executed. */
2284 static int
2285 check_executable (filename)
2286 char *filename;
2288 #ifdef HAVE_EACCESS
2289 return (eaccess (filename, 1) >= 0);
2290 #else
2291 /* Access isn't quite right because it uses the real uid
2292 and we really want to test with the effective uid.
2293 But Unix doesn't give us a right way to do it. */
2294 return (access (filename, 1) >= 0);
2295 #endif
2298 /* Return nonzero if file FILENAME exists and can be written. */
2300 static int
2301 check_writable (filename)
2302 char *filename;
2304 #ifdef HAVE_EACCESS
2305 return (eaccess (filename, 2) >= 0);
2306 #else
2307 /* Access isn't quite right because it uses the real uid
2308 and we really want to test with the effective uid.
2309 But Unix doesn't give us a right way to do it.
2310 Opening with O_WRONLY could work for an ordinary file,
2311 but would lose for directories. */
2312 return (access (filename, 2) >= 0);
2313 #endif
2316 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2317 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
2318 See also `file-readable-p' and `file-attributes'.")
2319 (filename)
2320 Lisp_Object filename;
2322 Lisp_Object abspath;
2323 Lisp_Object handler;
2324 struct stat statbuf;
2326 CHECK_STRING (filename, 0);
2327 abspath = Fexpand_file_name (filename, Qnil);
2329 /* If the file name has special constructs in it,
2330 call the corresponding file handler. */
2331 handler = Ffind_file_name_handler (abspath, Qfile_exists_p);
2332 if (!NILP (handler))
2333 return call2 (handler, Qfile_exists_p, abspath);
2335 return (stat (XSTRING (abspath)->data, &statbuf) >= 0) ? Qt : Qnil;
2338 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
2339 "Return t if FILENAME can be executed by you.\n\
2340 For a directory, this means you can access files in that directory.")
2341 (filename)
2342 Lisp_Object filename;
2345 Lisp_Object abspath;
2346 Lisp_Object handler;
2348 CHECK_STRING (filename, 0);
2349 abspath = Fexpand_file_name (filename, Qnil);
2351 /* If the file name has special constructs in it,
2352 call the corresponding file handler. */
2353 handler = Ffind_file_name_handler (abspath, Qfile_executable_p);
2354 if (!NILP (handler))
2355 return call2 (handler, Qfile_executable_p, abspath);
2357 return (check_executable (XSTRING (abspath)->data) ? Qt : Qnil);
2360 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2361 "Return t if file FILENAME exists and you can read it.\n\
2362 See also `file-exists-p' and `file-attributes'.")
2363 (filename)
2364 Lisp_Object filename;
2366 Lisp_Object abspath;
2367 Lisp_Object handler;
2368 int desc;
2370 CHECK_STRING (filename, 0);
2371 abspath = Fexpand_file_name (filename, Qnil);
2373 /* If the file name has special constructs in it,
2374 call the corresponding file handler. */
2375 handler = Ffind_file_name_handler (abspath, Qfile_readable_p);
2376 if (!NILP (handler))
2377 return call2 (handler, Qfile_readable_p, abspath);
2379 desc = open (XSTRING (abspath)->data, O_RDONLY);
2380 if (desc < 0)
2381 return Qnil;
2382 close (desc);
2383 return Qt;
2386 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2387 on the RT/PC. */
2388 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2389 "Return t if file FILENAME can be written or created by you.")
2390 (filename)
2391 Lisp_Object filename;
2393 Lisp_Object abspath, dir;
2394 Lisp_Object handler;
2395 struct stat statbuf;
2397 CHECK_STRING (filename, 0);
2398 abspath = Fexpand_file_name (filename, Qnil);
2400 /* If the file name has special constructs in it,
2401 call the corresponding file handler. */
2402 handler = Ffind_file_name_handler (abspath, Qfile_writable_p);
2403 if (!NILP (handler))
2404 return call2 (handler, Qfile_writable_p, abspath);
2406 if (stat (XSTRING (abspath)->data, &statbuf) >= 0)
2407 return (check_writable (XSTRING (abspath)->data)
2408 ? Qt : Qnil);
2409 dir = Ffile_name_directory (abspath);
2410 #ifdef VMS
2411 if (!NILP (dir))
2412 dir = Fdirectory_file_name (dir);
2413 #endif /* VMS */
2414 #ifdef MSDOS
2415 if (!NILP (dir))
2416 dir = Fdirectory_file_name (dir);
2417 #endif /* MSDOS */
2418 return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
2419 ? Qt : Qnil);
2422 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2423 "Return non-nil if file FILENAME is the name of a symbolic link.\n\
2424 The value is the name of the file to which it is linked.\n\
2425 Otherwise returns nil.")
2426 (filename)
2427 Lisp_Object filename;
2429 #ifdef S_IFLNK
2430 char *buf;
2431 int bufsize;
2432 int valsize;
2433 Lisp_Object val;
2434 Lisp_Object handler;
2436 CHECK_STRING (filename, 0);
2437 filename = Fexpand_file_name (filename, Qnil);
2439 /* If the file name has special constructs in it,
2440 call the corresponding file handler. */
2441 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
2442 if (!NILP (handler))
2443 return call2 (handler, Qfile_symlink_p, filename);
2445 bufsize = 100;
2446 while (1)
2448 buf = (char *) xmalloc (bufsize);
2449 bzero (buf, bufsize);
2450 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
2451 if (valsize < bufsize) break;
2452 /* Buffer was not long enough */
2453 xfree (buf);
2454 bufsize *= 2;
2456 if (valsize == -1)
2458 xfree (buf);
2459 return Qnil;
2461 val = make_string (buf, valsize);
2462 xfree (buf);
2463 return val;
2464 #else /* not S_IFLNK */
2465 return Qnil;
2466 #endif /* not S_IFLNK */
2469 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2470 "Return t if file FILENAME is the name of a directory as a file.\n\
2471 A directory name spec may be given instead; then the value is t\n\
2472 if the directory so specified exists and really is a directory.")
2473 (filename)
2474 Lisp_Object filename;
2476 register Lisp_Object abspath;
2477 struct stat st;
2478 Lisp_Object handler;
2480 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2482 /* If the file name has special constructs in it,
2483 call the corresponding file handler. */
2484 handler = Ffind_file_name_handler (abspath, Qfile_directory_p);
2485 if (!NILP (handler))
2486 return call2 (handler, Qfile_directory_p, abspath);
2488 if (stat (XSTRING (abspath)->data, &st) < 0)
2489 return Qnil;
2490 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2493 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
2494 "Return t if file FILENAME is the name of a directory as a file,\n\
2495 and files in that directory can be opened by you. In order to use a\n\
2496 directory as a buffer's current directory, this predicate must return true.\n\
2497 A directory name spec may be given instead; then the value is t\n\
2498 if the directory so specified exists and really is a readable and\n\
2499 searchable directory.")
2500 (filename)
2501 Lisp_Object filename;
2503 Lisp_Object handler;
2504 int tem;
2505 struct gcpro gcpro1;
2507 /* If the file name has special constructs in it,
2508 call the corresponding file handler. */
2509 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2510 if (!NILP (handler))
2511 return call2 (handler, Qfile_accessible_directory_p, filename);
2513 /* It's an unlikely combination, but yes we really do need to gcpro:
2514 Suppose that file-accessible-directory-p has no handler, but
2515 file-directory-p does have a handler; this handler causes a GC which
2516 relocates the string in `filename'; and finally file-directory-p
2517 returns non-nil. Then we would end up passing a garbaged string
2518 to file-executable-p. */
2519 GCPRO1 (filename);
2520 tem = (NILP (Ffile_directory_p (filename))
2521 || NILP (Ffile_executable_p (filename)));
2522 UNGCPRO;
2523 return tem ? Qnil : Qt;
2526 DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
2527 "Return t if file FILENAME is the name of a regular file.\n\
2528 This is the sort of file that holds an ordinary stream of data bytes.")
2529 (filename)
2530 Lisp_Object filename;
2532 register Lisp_Object abspath;
2533 struct stat st;
2534 Lisp_Object handler;
2536 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2538 /* If the file name has special constructs in it,
2539 call the corresponding file handler. */
2540 handler = Ffind_file_name_handler (abspath, Qfile_directory_p);
2541 if (!NILP (handler))
2542 return call2 (handler, Qfile_directory_p, abspath);
2544 if (stat (XSTRING (abspath)->data, &st) < 0)
2545 return Qnil;
2546 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
2549 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2550 "Return mode bits of FILE, as an integer.")
2551 (filename)
2552 Lisp_Object filename;
2554 Lisp_Object abspath;
2555 struct stat st;
2556 Lisp_Object handler;
2558 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2560 /* If the file name has special constructs in it,
2561 call the corresponding file handler. */
2562 handler = Ffind_file_name_handler (abspath, Qfile_modes);
2563 if (!NILP (handler))
2564 return call2 (handler, Qfile_modes, abspath);
2566 if (stat (XSTRING (abspath)->data, &st) < 0)
2567 return Qnil;
2568 #ifdef DOS_NT
2570 int len;
2571 char *suffix;
2572 if (S_ISREG (st.st_mode)
2573 && (len = XSTRING (abspath)->size) >= 5
2574 && (stricmp ((suffix = XSTRING (abspath)->data + len-4), ".com") == 0
2575 || stricmp (suffix, ".exe") == 0
2576 || stricmp (suffix, ".bat") == 0))
2577 st.st_mode |= S_IEXEC;
2579 #endif /* DOS_NT */
2581 return make_number (st.st_mode & 07777);
2584 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
2585 "Set mode bits of FILE to MODE (an integer).\n\
2586 Only the 12 low bits of MODE are used.")
2587 (filename, mode)
2588 Lisp_Object filename, mode;
2590 Lisp_Object abspath;
2591 Lisp_Object handler;
2593 abspath = Fexpand_file_name (filename, current_buffer->directory);
2594 CHECK_NUMBER (mode, 1);
2596 /* If the file name has special constructs in it,
2597 call the corresponding file handler. */
2598 handler = Ffind_file_name_handler (abspath, Qset_file_modes);
2599 if (!NILP (handler))
2600 return call3 (handler, Qset_file_modes, abspath, mode);
2602 #ifndef APOLLO
2603 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2604 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2605 #else /* APOLLO */
2606 if (!egetenv ("USE_DOMAIN_ACLS"))
2608 struct stat st;
2609 struct timeval tvp[2];
2611 /* chmod on apollo also change the file's modtime; need to save the
2612 modtime and then restore it. */
2613 if (stat (XSTRING (abspath)->data, &st) < 0)
2615 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2616 return (Qnil);
2619 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2620 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2622 /* reset the old accessed and modified times. */
2623 tvp[0].tv_sec = st.st_atime + 1; /* +1 due to an Apollo roundoff bug */
2624 tvp[0].tv_usec = 0;
2625 tvp[1].tv_sec = st.st_mtime + 1; /* +1 due to an Apollo roundoff bug */
2626 tvp[1].tv_usec = 0;
2628 if (utimes (XSTRING (abspath)->data, tvp) < 0)
2629 report_file_error ("Doing utimes", Fcons (abspath, Qnil));
2631 #endif /* APOLLO */
2633 return Qnil;
2636 DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
2637 "Set the file permission bits for newly created files.\n\
2638 The argument MODE should be an integer; only the low 9 bits are used.\n\
2639 This setting is inherited by subprocesses.")
2640 (mode)
2641 Lisp_Object mode;
2643 CHECK_NUMBER (mode, 0);
2645 umask ((~ XINT (mode)) & 0777);
2647 return Qnil;
2650 DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
2651 "Return the default file protection for created files.\n\
2652 The value is an integer.")
2655 int realmask;
2656 Lisp_Object value;
2658 realmask = umask (0);
2659 umask (realmask);
2661 XSETINT (value, (~ realmask) & 0777);
2662 return value;
2665 #ifdef unix
2667 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
2668 "Tell Unix to finish all pending disk updates.")
2671 sync ();
2672 return Qnil;
2675 #endif /* unix */
2677 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
2678 "Return t if file FILE1 is newer than file FILE2.\n\
2679 If FILE1 does not exist, the answer is nil;\n\
2680 otherwise, if FILE2 does not exist, the answer is t.")
2681 (file1, file2)
2682 Lisp_Object file1, file2;
2684 Lisp_Object abspath1, abspath2;
2685 struct stat st;
2686 int mtime1;
2687 Lisp_Object handler;
2688 struct gcpro gcpro1, gcpro2;
2690 CHECK_STRING (file1, 0);
2691 CHECK_STRING (file2, 0);
2693 abspath1 = Qnil;
2694 GCPRO2 (abspath1, file2);
2695 abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
2696 abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
2697 UNGCPRO;
2699 /* If the file name has special constructs in it,
2700 call the corresponding file handler. */
2701 handler = Ffind_file_name_handler (abspath1, Qfile_newer_than_file_p);
2702 if (NILP (handler))
2703 handler = Ffind_file_name_handler (abspath2, Qfile_newer_than_file_p);
2704 if (!NILP (handler))
2705 return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2);
2707 if (stat (XSTRING (abspath1)->data, &st) < 0)
2708 return Qnil;
2710 mtime1 = st.st_mtime;
2712 if (stat (XSTRING (abspath2)->data, &st) < 0)
2713 return Qt;
2715 return (mtime1 > st.st_mtime) ? Qt : Qnil;
2718 #ifdef DOS_NT
2719 Lisp_Object Qfind_buffer_file_type;
2720 #endif /* DOS_NT */
2722 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
2723 1, 5, 0,
2724 "Insert contents of file FILENAME after point.\n\
2725 Returns list of absolute file name and length of data inserted.\n\
2726 If second argument VISIT is non-nil, the buffer's visited filename\n\
2727 and last save file modtime are set, and it is marked unmodified.\n\
2728 If visiting and the file does not exist, visiting is completed\n\
2729 before the error is signaled.\n\n\
2730 The optional third and fourth arguments BEG and END\n\
2731 specify what portion of the file to insert.\n\
2732 If VISIT is non-nil, BEG and END must be nil.\n\
2733 If optional fifth argument REPLACE is non-nil,\n\
2734 it means replace the current buffer contents (in the accessible portion)\n\
2735 with the file contents. This is better than simply deleting and inserting\n\
2736 the whole thing because (1) it preserves some marker positions\n\
2737 and (2) it puts less data in the undo list.")
2738 (filename, visit, beg, end, replace)
2739 Lisp_Object filename, visit, beg, end, replace;
2741 struct stat st;
2742 register int fd;
2743 register int inserted = 0;
2744 register int how_much;
2745 int count = specpdl_ptr - specpdl;
2746 struct gcpro gcpro1, gcpro2, gcpro3;
2747 Lisp_Object handler, val, insval;
2748 Lisp_Object p;
2749 int total;
2750 int not_regular = 0;
2752 if (current_buffer->base_buffer && ! NILP (visit))
2753 error ("Cannot do file visiting in an indirect buffer");
2755 if (!NILP (current_buffer->read_only))
2756 Fbarf_if_buffer_read_only ();
2758 val = Qnil;
2759 p = Qnil;
2761 GCPRO3 (filename, val, p);
2763 CHECK_STRING (filename, 0);
2764 filename = Fexpand_file_name (filename, Qnil);
2766 /* If the file name has special constructs in it,
2767 call the corresponding file handler. */
2768 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
2769 if (!NILP (handler))
2771 val = call6 (handler, Qinsert_file_contents, filename,
2772 visit, beg, end, replace);
2773 goto handled;
2776 fd = -1;
2778 #ifndef APOLLO
2779 if (stat (XSTRING (filename)->data, &st) < 0)
2780 #else
2781 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
2782 || fstat (fd, &st) < 0)
2783 #endif /* not APOLLO */
2785 if (fd >= 0) close (fd);
2786 badopen:
2787 if (NILP (visit))
2788 report_file_error ("Opening input file", Fcons (filename, Qnil));
2789 st.st_mtime = -1;
2790 how_much = 0;
2791 goto notfound;
2794 #ifdef S_IFREG
2795 /* This code will need to be changed in order to work on named
2796 pipes, and it's probably just not worth it. So we should at
2797 least signal an error. */
2798 if (!S_ISREG (st.st_mode))
2800 if (NILP (visit))
2801 Fsignal (Qfile_error,
2802 Fcons (build_string ("not a regular file"),
2803 Fcons (filename, Qnil)));
2805 not_regular = 1;
2806 goto notfound;
2808 #endif
2810 if (fd < 0)
2811 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
2812 goto badopen;
2814 /* Replacement should preserve point as it preserves markers. */
2815 if (!NILP (replace))
2816 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
2818 record_unwind_protect (close_file_unwind, make_number (fd));
2820 /* Supposedly happens on VMS. */
2821 if (st.st_size < 0)
2822 error ("File size is negative");
2824 if (!NILP (beg) || !NILP (end))
2825 if (!NILP (visit))
2826 error ("Attempt to visit less than an entire file");
2828 if (!NILP (beg))
2829 CHECK_NUMBER (beg, 0);
2830 else
2831 XSETFASTINT (beg, 0);
2833 if (!NILP (end))
2834 CHECK_NUMBER (end, 0);
2835 else
2837 XSETINT (end, st.st_size);
2838 if (XINT (end) != st.st_size)
2839 error ("maximum buffer size exceeded");
2842 /* If requested, replace the accessible part of the buffer
2843 with the file contents. Avoid replacing text at the
2844 beginning or end of the buffer that matches the file contents;
2845 that preserves markers pointing to the unchanged parts. */
2846 #ifdef DOS_NT
2847 /* On MSDOS, replace mode doesn't really work, except for binary files,
2848 and it's not worth supporting just for them. */
2849 if (!NILP (replace))
2851 replace = Qnil;
2852 XSETFASTINT (beg, 0);
2853 XSETFASTINT (end, st.st_size);
2854 del_range_1 (BEGV, ZV, 0);
2856 #else /* not DOS_NT */
2857 if (!NILP (replace))
2859 unsigned char buffer[1 << 14];
2860 int same_at_start = BEGV;
2861 int same_at_end = ZV;
2862 int overlap;
2864 immediate_quit = 1;
2865 QUIT;
2866 /* Count how many chars at the start of the file
2867 match the text at the beginning of the buffer. */
2868 while (1)
2870 int nread, bufpos;
2872 nread = read (fd, buffer, sizeof buffer);
2873 if (nread < 0)
2874 error ("IO error reading %s: %s",
2875 XSTRING (filename)->data, strerror (errno));
2876 else if (nread == 0)
2877 break;
2878 bufpos = 0;
2879 while (bufpos < nread && same_at_start < ZV
2880 && FETCH_CHAR (same_at_start) == buffer[bufpos])
2881 same_at_start++, bufpos++;
2882 /* If we found a discrepancy, stop the scan.
2883 Otherwise loop around and scan the next bufferfull. */
2884 if (bufpos != nread)
2885 break;
2887 immediate_quit = 0;
2888 /* If the file matches the buffer completely,
2889 there's no need to replace anything. */
2890 if (same_at_start - BEGV == st.st_size)
2892 close (fd);
2893 specpdl_ptr--;
2894 /* Truncate the buffer to the size of the file. */
2895 del_range_1 (same_at_start, same_at_end, 0);
2896 goto handled;
2898 immediate_quit = 1;
2899 QUIT;
2900 /* Count how many chars at the end of the file
2901 match the text at the end of the buffer. */
2902 while (1)
2904 int total_read, nread, bufpos, curpos, trial;
2906 /* At what file position are we now scanning? */
2907 curpos = st.st_size - (ZV - same_at_end);
2908 /* If the entire file matches the buffer tail, stop the scan. */
2909 if (curpos == 0)
2910 break;
2911 /* How much can we scan in the next step? */
2912 trial = min (curpos, sizeof buffer);
2913 if (lseek (fd, curpos - trial, 0) < 0)
2914 report_file_error ("Setting file position",
2915 Fcons (filename, Qnil));
2917 total_read = 0;
2918 while (total_read < trial)
2920 nread = read (fd, buffer + total_read, trial - total_read);
2921 if (nread <= 0)
2922 error ("IO error reading %s: %s",
2923 XSTRING (filename)->data, strerror (errno));
2924 total_read += nread;
2926 /* Scan this bufferfull from the end, comparing with
2927 the Emacs buffer. */
2928 bufpos = total_read;
2929 /* Compare with same_at_start to avoid counting some buffer text
2930 as matching both at the file's beginning and at the end. */
2931 while (bufpos > 0 && same_at_end > same_at_start
2932 && FETCH_CHAR (same_at_end - 1) == buffer[bufpos - 1])
2933 same_at_end--, bufpos--;
2934 /* If we found a discrepancy, stop the scan.
2935 Otherwise loop around and scan the preceding bufferfull. */
2936 if (bufpos != 0)
2937 break;
2939 immediate_quit = 0;
2941 /* Don't try to reuse the same piece of text twice. */
2942 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV);
2943 if (overlap > 0)
2944 same_at_end += overlap;
2946 /* Arrange to read only the nonmatching middle part of the file. */
2947 XSETFASTINT (beg, same_at_start - BEGV);
2948 XSETFASTINT (end, st.st_size - (ZV - same_at_end));
2950 del_range_1 (same_at_start, same_at_end, 0);
2951 /* Insert from the file at the proper position. */
2952 SET_PT (same_at_start);
2954 #endif /* not DOS_NT */
2956 total = XINT (end) - XINT (beg);
2959 register Lisp_Object temp;
2961 /* Make sure point-max won't overflow after this insertion. */
2962 XSETINT (temp, total);
2963 if (total != XINT (temp))
2964 error ("maximum buffer size exceeded");
2967 if (NILP (visit) && total > 0)
2968 prepare_to_modify_buffer (point, point);
2970 move_gap (point);
2971 if (GAP_SIZE < total)
2972 make_gap (total - GAP_SIZE);
2974 if (XINT (beg) != 0 || !NILP (replace))
2976 if (lseek (fd, XINT (beg), 0) < 0)
2977 report_file_error ("Setting file position", Fcons (filename, Qnil));
2980 how_much = 0;
2981 while (inserted < total)
2983 /* try is reserved in some compilers (Microsoft C) */
2984 int trytry = min (total - inserted, 64 << 10);
2985 int this;
2987 /* Allow quitting out of the actual I/O. */
2988 immediate_quit = 1;
2989 QUIT;
2990 this = read (fd, &FETCH_CHAR (point + inserted - 1) + 1, trytry);
2991 immediate_quit = 0;
2993 if (this <= 0)
2995 how_much = this;
2996 break;
2999 GPT += this;
3000 GAP_SIZE -= this;
3001 ZV += this;
3002 Z += this;
3003 inserted += this;
3006 #ifdef DOS_NT
3007 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
3008 /* Determine file type from name and remove LFs from CR-LFs if the file
3009 is deemed to be a text file. */
3011 current_buffer->buffer_file_type
3012 = call1 (Qfind_buffer_file_type, filename);
3013 if (NILP (current_buffer->buffer_file_type))
3015 int reduced_size
3016 = inserted - crlf_to_lf (inserted, &FETCH_CHAR (point - 1) + 1);
3017 ZV -= reduced_size;
3018 Z -= reduced_size;
3019 GPT -= reduced_size;
3020 GAP_SIZE += reduced_size;
3021 inserted -= reduced_size;
3024 #endif /* DOS_NT */
3026 if (inserted > 0)
3028 record_insert (point, inserted);
3030 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3031 offset_intervals (current_buffer, point, inserted);
3032 MODIFF++;
3035 close (fd);
3037 /* Discard the unwind protect for closing the file. */
3038 specpdl_ptr--;
3040 if (how_much < 0)
3041 error ("IO error reading %s: %s",
3042 XSTRING (filename)->data, strerror (errno));
3044 notfound:
3045 handled:
3047 if (!NILP (visit))
3049 if (!EQ (current_buffer->undo_list, Qt))
3050 current_buffer->undo_list = Qnil;
3051 #ifdef APOLLO
3052 stat (XSTRING (filename)->data, &st);
3053 #endif
3055 if (NILP (handler))
3057 current_buffer->modtime = st.st_mtime;
3058 current_buffer->filename = filename;
3061 SAVE_MODIFF = MODIFF;
3062 current_buffer->auto_save_modified = MODIFF;
3063 XSETFASTINT (current_buffer->save_length, Z - BEG);
3064 #ifdef CLASH_DETECTION
3065 if (NILP (handler))
3067 if (!NILP (current_buffer->filename))
3068 unlock_file (current_buffer->filename);
3069 unlock_file (filename);
3071 #endif /* CLASH_DETECTION */
3072 if (not_regular)
3073 Fsignal (Qfile_error,
3074 Fcons (build_string ("not a regular file"),
3075 Fcons (filename, Qnil)));
3077 /* If visiting nonexistent file, return nil. */
3078 if (current_buffer->modtime == -1)
3079 report_file_error ("Opening input file", Fcons (filename, Qnil));
3082 if (inserted > 0 && NILP (visit) && total > 0)
3083 signal_after_change (point, 0, inserted);
3085 if (inserted > 0)
3087 p = Vafter_insert_file_functions;
3088 while (!NILP (p))
3090 insval = call1 (Fcar (p), make_number (inserted));
3091 if (!NILP (insval))
3093 CHECK_NUMBER (insval, 0);
3094 inserted = XFASTINT (insval);
3096 QUIT;
3097 p = Fcdr (p);
3101 if (NILP (val))
3102 val = Fcons (filename,
3103 Fcons (make_number (inserted),
3104 Qnil));
3106 RETURN_UNGCPRO (unbind_to (count, val));
3109 static Lisp_Object build_annotations ();
3111 /* If build_annotations switched buffers, switch back to BUF.
3112 Kill the temporary buffer that was selected in the meantime. */
3114 static Lisp_Object
3115 build_annotations_unwind (buf)
3116 Lisp_Object buf;
3118 Lisp_Object tembuf;
3120 if (XBUFFER (buf) == current_buffer)
3121 return Qnil;
3122 tembuf = Fcurrent_buffer ();
3123 Fset_buffer (buf);
3124 Fkill_buffer (tembuf);
3125 return Qnil;
3128 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
3129 "r\nFWrite region to file: ",
3130 "Write current region into specified file.\n\
3131 When called from a program, takes three arguments:\n\
3132 START, END and FILENAME. START and END are buffer positions.\n\
3133 Optional fourth argument APPEND if non-nil means\n\
3134 append to existing file contents (if any).\n\
3135 Optional fifth argument VISIT if t means\n\
3136 set the last-save-file-modtime of buffer to this file's modtime\n\
3137 and mark buffer not modified.\n\
3138 If VISIT is a string, it is a second file name;\n\
3139 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
3140 VISIT is also the file name to lock and unlock for clash detection.\n\
3141 If VISIT is neither t nor nil nor a string,\n\
3142 that means do not print the \"Wrote file\" message.\n\
3143 Kludgy feature: if START is a string, then that string is written\n\
3144 to the file, instead of any buffer contents, and END is ignored.")
3145 (start, end, filename, append, visit)
3146 Lisp_Object start, end, filename, append, visit;
3148 register int desc;
3149 int failure;
3150 int save_errno;
3151 unsigned char *fn;
3152 struct stat st;
3153 int tem;
3154 int count = specpdl_ptr - specpdl;
3155 int count1;
3156 #ifdef VMS
3157 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
3158 #endif /* VMS */
3159 Lisp_Object handler;
3160 Lisp_Object visit_file;
3161 Lisp_Object annotations;
3162 int visiting, quietly;
3163 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3164 struct buffer *given_buffer;
3165 #ifdef DOS_NT
3166 int buffer_file_type
3167 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
3168 #endif /* DOS_NT */
3170 if (current_buffer->base_buffer && ! NILP (visit))
3171 error ("Cannot do file visiting in an indirect buffer");
3173 if (!NILP (start) && !STRINGP (start))
3174 validate_region (&start, &end);
3176 GCPRO2 (filename, visit);
3177 filename = Fexpand_file_name (filename, Qnil);
3178 if (STRINGP (visit))
3179 visit_file = Fexpand_file_name (visit, Qnil);
3180 else
3181 visit_file = filename;
3182 UNGCPRO;
3184 visiting = (EQ (visit, Qt) || STRINGP (visit));
3185 quietly = !NILP (visit);
3187 annotations = Qnil;
3189 GCPRO4 (start, filename, annotations, visit_file);
3191 /* If the file name has special constructs in it,
3192 call the corresponding file handler. */
3193 handler = Ffind_file_name_handler (filename, Qwrite_region);
3194 /* If FILENAME has no handler, see if VISIT has one. */
3195 if (NILP (handler) && STRINGP (visit))
3196 handler = Ffind_file_name_handler (visit, Qwrite_region);
3198 if (!NILP (handler))
3200 Lisp_Object val;
3201 val = call6 (handler, Qwrite_region, start, end,
3202 filename, append, visit);
3204 if (visiting)
3206 SAVE_MODIFF = MODIFF;
3207 XSETFASTINT (current_buffer->save_length, Z - BEG);
3208 current_buffer->filename = visit_file;
3210 UNGCPRO;
3211 return val;
3214 /* Special kludge to simplify auto-saving. */
3215 if (NILP (start))
3217 XSETFASTINT (start, BEG);
3218 XSETFASTINT (end, Z);
3221 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
3222 count1 = specpdl_ptr - specpdl;
3224 given_buffer = current_buffer;
3225 annotations = build_annotations (start, end);
3226 if (current_buffer != given_buffer)
3228 start = BEGV;
3229 end = ZV;
3232 #ifdef CLASH_DETECTION
3233 if (!auto_saving)
3234 lock_file (visit_file);
3235 #endif /* CLASH_DETECTION */
3237 fn = XSTRING (filename)->data;
3238 desc = -1;
3239 if (!NILP (append))
3240 #ifdef DOS_NT
3241 desc = open (fn, O_WRONLY | buffer_file_type);
3242 #else /* not DOS_NT */
3243 desc = open (fn, O_WRONLY);
3244 #endif /* not DOS_NT */
3246 if (desc < 0)
3247 #ifdef VMS
3248 if (auto_saving) /* Overwrite any previous version of autosave file */
3250 vms_truncate (fn); /* if fn exists, truncate to zero length */
3251 desc = open (fn, O_RDWR);
3252 if (desc < 0)
3253 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
3254 ? XSTRING (current_buffer->filename)->data : 0,
3255 fn);
3257 else /* Write to temporary name and rename if no errors */
3259 Lisp_Object temp_name;
3260 temp_name = Ffile_name_directory (filename);
3262 if (!NILP (temp_name))
3264 temp_name = Fmake_temp_name (concat2 (temp_name,
3265 build_string ("$$SAVE$$")));
3266 fname = XSTRING (filename)->data;
3267 fn = XSTRING (temp_name)->data;
3268 desc = creat_copy_attrs (fname, fn);
3269 if (desc < 0)
3271 /* If we can't open the temporary file, try creating a new
3272 version of the original file. VMS "creat" creates a
3273 new version rather than truncating an existing file. */
3274 fn = fname;
3275 fname = 0;
3276 desc = creat (fn, 0666);
3277 #if 0 /* This can clobber an existing file and fail to replace it,
3278 if the user runs out of space. */
3279 if (desc < 0)
3281 /* We can't make a new version;
3282 try to truncate and rewrite existing version if any. */
3283 vms_truncate (fn);
3284 desc = open (fn, O_RDWR);
3286 #endif
3289 else
3290 desc = creat (fn, 0666);
3292 #else /* not VMS */
3293 #ifdef DOS_NT
3294 desc = open (fn,
3295 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
3296 S_IREAD | S_IWRITE);
3297 #else /* not DOS_NT */
3298 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
3299 #endif /* not DOS_NT */
3300 #endif /* not VMS */
3302 UNGCPRO;
3304 if (desc < 0)
3306 #ifdef CLASH_DETECTION
3307 save_errno = errno;
3308 if (!auto_saving) unlock_file (visit_file);
3309 errno = save_errno;
3310 #endif /* CLASH_DETECTION */
3311 report_file_error ("Opening output file", Fcons (filename, Qnil));
3314 record_unwind_protect (close_file_unwind, make_number (desc));
3316 if (!NILP (append))
3317 if (lseek (desc, 0, 2) < 0)
3319 #ifdef CLASH_DETECTION
3320 if (!auto_saving) unlock_file (visit_file);
3321 #endif /* CLASH_DETECTION */
3322 report_file_error ("Lseek error", Fcons (filename, Qnil));
3325 #ifdef VMS
3327 * Kludge Warning: The VMS C RTL likes to insert carriage returns
3328 * if we do writes that don't end with a carriage return. Furthermore
3329 * it cannot handle writes of more then 16K. The modified
3330 * version of "sys_write" in SYSDEP.C (see comment there) copes with
3331 * this EXCEPT for the last record (iff it doesn't end with a carriage
3332 * return). This implies that if your buffer doesn't end with a carriage
3333 * return, you get one free... tough. However it also means that if
3334 * we make two calls to sys_write (a la the following code) you can
3335 * get one at the gap as well. The easiest way to fix this (honest)
3336 * is to move the gap to the next newline (or the end of the buffer).
3337 * Thus this change.
3339 * Yech!
3341 if (GPT > BEG && GPT_ADDR[-1] != '\n')
3342 move_gap (find_next_newline (GPT, 1));
3343 #endif
3345 failure = 0;
3346 immediate_quit = 1;
3348 if (STRINGP (start))
3350 failure = 0 > a_write (desc, XSTRING (start)->data,
3351 XSTRING (start)->size, 0, &annotations);
3352 save_errno = errno;
3354 else if (XINT (start) != XINT (end))
3356 int nwritten = 0;
3357 if (XINT (start) < GPT)
3359 register int end1 = XINT (end);
3360 tem = XINT (start);
3361 failure = 0 > a_write (desc, &FETCH_CHAR (tem),
3362 min (GPT, end1) - tem, tem, &annotations);
3363 nwritten += min (GPT, end1) - tem;
3364 save_errno = errno;
3367 if (XINT (end) > GPT && !failure)
3369 tem = XINT (start);
3370 tem = max (tem, GPT);
3371 failure = 0 > a_write (desc, &FETCH_CHAR (tem), XINT (end) - tem,
3372 tem, &annotations);
3373 nwritten += XINT (end) - tem;
3374 save_errno = errno;
3377 if (nwritten == 0)
3379 /* If file was empty, still need to write the annotations */
3380 failure = 0 > a_write (desc, "", 0, XINT (start), &annotations);
3381 save_errno = errno;
3385 immediate_quit = 0;
3387 #ifdef HAVE_FSYNC
3388 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
3389 Disk full in NFS may be reported here. */
3390 /* mib says that closing the file will try to write as fast as NFS can do
3391 it, and that means the fsync here is not crucial for autosave files. */
3392 if (!auto_saving && fsync (desc) < 0)
3393 failure = 1, save_errno = errno;
3394 #endif
3396 /* Spurious "file has changed on disk" warnings have been
3397 observed on Suns as well.
3398 It seems that `close' can change the modtime, under nfs.
3400 (This has supposedly been fixed in Sunos 4,
3401 but who knows about all the other machines with NFS?) */
3402 #if 0
3404 /* On VMS and APOLLO, must do the stat after the close
3405 since closing changes the modtime. */
3406 #ifndef VMS
3407 #ifndef APOLLO
3408 /* Recall that #if defined does not work on VMS. */
3409 #define FOO
3410 fstat (desc, &st);
3411 #endif
3412 #endif
3413 #endif
3415 /* NFS can report a write failure now. */
3416 if (close (desc) < 0)
3417 failure = 1, save_errno = errno;
3419 #ifdef VMS
3420 /* If we wrote to a temporary name and had no errors, rename to real name. */
3421 if (fname)
3423 if (!failure)
3424 failure = (rename (fn, fname) != 0), save_errno = errno;
3425 fn = fname;
3427 #endif /* VMS */
3429 #ifndef FOO
3430 stat (fn, &st);
3431 #endif
3432 /* Discard the unwind protect for close_file_unwind. */
3433 specpdl_ptr = specpdl + count1;
3434 /* Restore the original current buffer. */
3435 visit_file = unbind_to (count, visit_file);
3437 #ifdef CLASH_DETECTION
3438 if (!auto_saving)
3439 unlock_file (visit_file);
3440 #endif /* CLASH_DETECTION */
3442 /* Do this before reporting IO error
3443 to avoid a "file has changed on disk" warning on
3444 next attempt to save. */
3445 if (visiting)
3446 current_buffer->modtime = st.st_mtime;
3448 if (failure)
3449 error ("IO error writing %s: %s", fn, strerror (save_errno));
3451 if (visiting)
3453 SAVE_MODIFF = MODIFF;
3454 XSETFASTINT (current_buffer->save_length, Z - BEG);
3455 current_buffer->filename = visit_file;
3456 update_mode_lines++;
3458 else if (quietly)
3459 return Qnil;
3461 if (!auto_saving)
3462 message ("Wrote %s", XSTRING (visit_file)->data);
3464 return Qnil;
3467 Lisp_Object merge ();
3469 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
3470 "Return t if (car A) is numerically less than (car B).")
3471 (a, b)
3472 Lisp_Object a, b;
3474 return Flss (Fcar (a), Fcar (b));
3477 /* Build the complete list of annotations appropriate for writing out
3478 the text between START and END, by calling all the functions in
3479 write-region-annotate-functions and merging the lists they return.
3480 If one of these functions switches to a different buffer, we assume
3481 that buffer contains altered text. Therefore, the caller must
3482 make sure to restore the current buffer in all cases,
3483 as save-excursion would do. */
3485 static Lisp_Object
3486 build_annotations (start, end)
3487 Lisp_Object start, end;
3489 Lisp_Object annotations;
3490 Lisp_Object p, res;
3491 struct gcpro gcpro1, gcpro2;
3493 annotations = Qnil;
3494 p = Vwrite_region_annotate_functions;
3495 GCPRO2 (annotations, p);
3496 while (!NILP (p))
3498 struct buffer *given_buffer = current_buffer;
3499 Vwrite_region_annotations_so_far = annotations;
3500 res = call2 (Fcar (p), start, end);
3501 /* If the function makes a different buffer current,
3502 assume that means this buffer contains altered text to be output.
3503 Reset START and END from the buffer bounds
3504 and discard all previous annotations because they should have
3505 been dealt with by this function. */
3506 if (current_buffer != given_buffer)
3508 start = BEGV;
3509 end = ZV;
3510 annotations = Qnil;
3512 Flength (res); /* Check basic validity of return value */
3513 annotations = merge (annotations, res, Qcar_less_than_car);
3514 p = Fcdr (p);
3516 UNGCPRO;
3517 return annotations;
3520 /* Write to descriptor DESC the LEN characters starting at ADDR,
3521 assuming they start at position POS in the buffer.
3522 Intersperse with them the annotations from *ANNOT
3523 (those which fall within the range of positions POS to POS + LEN),
3524 each at its appropriate position.
3526 Modify *ANNOT by discarding elements as we output them.
3527 The return value is negative in case of system call failure. */
3530 a_write (desc, addr, len, pos, annot)
3531 int desc;
3532 register char *addr;
3533 register int len;
3534 int pos;
3535 Lisp_Object *annot;
3537 Lisp_Object tem;
3538 int nextpos;
3539 int lastpos = pos + len;
3541 while (NILP (*annot) || CONSP (*annot))
3543 tem = Fcar_safe (Fcar (*annot));
3544 if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos)
3545 nextpos = XFASTINT (tem);
3546 else
3547 return e_write (desc, addr, lastpos - pos);
3548 if (nextpos > pos)
3550 if (0 > e_write (desc, addr, nextpos - pos))
3551 return -1;
3552 addr += nextpos - pos;
3553 pos = nextpos;
3555 tem = Fcdr (Fcar (*annot));
3556 if (STRINGP (tem))
3558 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size))
3559 return -1;
3561 *annot = Fcdr (*annot);
3566 e_write (desc, addr, len)
3567 int desc;
3568 register char *addr;
3569 register int len;
3571 char buf[16 * 1024];
3572 register char *p, *end;
3574 if (!EQ (current_buffer->selective_display, Qt))
3575 return write (desc, addr, len) - len;
3576 else
3578 p = buf;
3579 end = p + sizeof buf;
3580 while (len--)
3582 if (p == end)
3584 if (write (desc, buf, sizeof buf) != sizeof buf)
3585 return -1;
3586 p = buf;
3588 *p = *addr++;
3589 if (*p++ == '\015')
3590 p[-1] = '\n';
3592 if (p != buf)
3593 if (write (desc, buf, p - buf) != p - buf)
3594 return -1;
3596 return 0;
3599 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
3600 Sverify_visited_file_modtime, 1, 1, 0,
3601 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
3602 This means that the file has not been changed since it was visited or saved.")
3603 (buf)
3604 Lisp_Object buf;
3606 struct buffer *b;
3607 struct stat st;
3608 Lisp_Object handler;
3610 CHECK_BUFFER (buf, 0);
3611 b = XBUFFER (buf);
3613 if (!STRINGP (b->filename)) return Qt;
3614 if (b->modtime == 0) return Qt;
3616 /* If the file name has special constructs in it,
3617 call the corresponding file handler. */
3618 handler = Ffind_file_name_handler (b->filename,
3619 Qverify_visited_file_modtime);
3620 if (!NILP (handler))
3621 return call2 (handler, Qverify_visited_file_modtime, buf);
3623 if (stat (XSTRING (b->filename)->data, &st) < 0)
3625 /* If the file doesn't exist now and didn't exist before,
3626 we say that it isn't modified, provided the error is a tame one. */
3627 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
3628 st.st_mtime = -1;
3629 else
3630 st.st_mtime = 0;
3632 if (st.st_mtime == b->modtime
3633 /* If both are positive, accept them if they are off by one second. */
3634 || (st.st_mtime > 0 && b->modtime > 0
3635 && (st.st_mtime == b->modtime + 1
3636 || st.st_mtime == b->modtime - 1)))
3637 return Qt;
3638 return Qnil;
3641 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
3642 Sclear_visited_file_modtime, 0, 0, 0,
3643 "Clear out records of last mod time of visited file.\n\
3644 Next attempt to save will certainly not complain of a discrepancy.")
3647 current_buffer->modtime = 0;
3648 return Qnil;
3651 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
3652 Svisited_file_modtime, 0, 0, 0,
3653 "Return the current buffer's recorded visited file modification time.\n\
3654 The value is a list of the form (HIGH . LOW), like the time values\n\
3655 that `file-attributes' returns.")
3658 return long_to_cons (current_buffer->modtime);
3661 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
3662 Sset_visited_file_modtime, 0, 1, 0,
3663 "Update buffer's recorded modification time from the visited file's time.\n\
3664 Useful if the buffer was not read from the file normally\n\
3665 or if the file itself has been changed for some known benign reason.\n\
3666 An argument specifies the modification time value to use\n\
3667 \(instead of that of the visited file), in the form of a list\n\
3668 \(HIGH . LOW) or (HIGH LOW).")
3669 (time_list)
3670 Lisp_Object time_list;
3672 if (!NILP (time_list))
3673 current_buffer->modtime = cons_to_long (time_list);
3674 else
3676 register Lisp_Object filename;
3677 struct stat st;
3678 Lisp_Object handler;
3680 filename = Fexpand_file_name (current_buffer->filename, Qnil);
3682 /* If the file name has special constructs in it,
3683 call the corresponding file handler. */
3684 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
3685 if (!NILP (handler))
3686 /* The handler can find the file name the same way we did. */
3687 return call2 (handler, Qset_visited_file_modtime, Qnil);
3688 else if (stat (XSTRING (filename)->data, &st) >= 0)
3689 current_buffer->modtime = st.st_mtime;
3692 return Qnil;
3695 Lisp_Object
3696 auto_save_error ()
3698 ring_bell ();
3699 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
3700 Fsleep_for (make_number (1), Qnil);
3701 message ("Autosaving...error!for %s", XSTRING (current_buffer->name)->data);
3702 Fsleep_for (make_number (1), Qnil);
3703 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
3704 Fsleep_for (make_number (1), Qnil);
3705 return Qnil;
3708 Lisp_Object
3709 auto_save_1 ()
3711 unsigned char *fn;
3712 struct stat st;
3714 /* Get visited file's mode to become the auto save file's mode. */
3715 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
3716 /* But make sure we can overwrite it later! */
3717 auto_save_mode_bits = st.st_mode | 0600;
3718 else
3719 auto_save_mode_bits = 0666;
3721 return
3722 Fwrite_region (Qnil, Qnil,
3723 current_buffer->auto_save_file_name,
3724 Qnil, Qlambda);
3727 static Lisp_Object
3728 do_auto_save_unwind (desc) /* used as unwind-protect function */
3729 Lisp_Object desc;
3731 close (XINT (desc));
3732 return Qnil;
3735 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
3736 "Auto-save all buffers that need it.\n\
3737 This is all buffers that have auto-saving enabled\n\
3738 and are changed since last auto-saved.\n\
3739 Auto-saving writes the buffer into a file\n\
3740 so that your editing is not lost if the system crashes.\n\
3741 This file is not the file you visited; that changes only when you save.\n\
3742 Normally we run the normal hook `auto-save-hook' before saving.\n\n\
3743 Non-nil first argument means do not print any message if successful.\n\
3744 Non-nil second argument means save only current buffer.")
3745 (no_message, current_only)
3746 Lisp_Object no_message, current_only;
3748 struct buffer *old = current_buffer, *b;
3749 Lisp_Object tail, buf;
3750 int auto_saved = 0;
3751 char *omessage = echo_area_glyphs;
3752 int omessage_length = echo_area_glyphs_length;
3753 extern int minibuf_level;
3754 int do_handled_files;
3755 Lisp_Object oquit;
3756 int listdesc;
3757 int count = specpdl_ptr - specpdl;
3758 int *ptr;
3760 /* Ordinarily don't quit within this function,
3761 but don't make it impossible to quit (in case we get hung in I/O). */
3762 oquit = Vquit_flag;
3763 Vquit_flag = Qnil;
3765 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
3766 point to non-strings reached from Vbuffer_alist. */
3768 auto_saving = 1;
3769 if (minibuf_level)
3770 no_message = Qt;
3772 if (!NILP (Vrun_hooks))
3773 call1 (Vrun_hooks, intern ("auto-save-hook"));
3775 if (STRINGP (Vauto_save_list_file_name))
3777 #ifdef DOS_NT
3778 listdesc = open (XSTRING (Vauto_save_list_file_name)->data,
3779 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
3780 S_IREAD | S_IWRITE);
3781 #else /* not DOS_NT */
3782 listdesc = creat (XSTRING (Vauto_save_list_file_name)->data, 0666);
3783 #endif /* not DOS_NT */
3785 else
3786 listdesc = -1;
3788 /* Arrange to close that file whether or not we get an error. */
3789 if (listdesc >= 0)
3790 record_unwind_protect (do_auto_save_unwind, make_number (listdesc));
3792 /* First, save all files which don't have handlers. If Emacs is
3793 crashing, the handlers may tweak what is causing Emacs to crash
3794 in the first place, and it would be a shame if Emacs failed to
3795 autosave perfectly ordinary files because it couldn't handle some
3796 ange-ftp'd file. */
3797 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
3798 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
3800 buf = XCONS (XCONS (tail)->car)->cdr;
3801 b = XBUFFER (buf);
3803 /* Record all the buffers that have auto save mode
3804 in the special file that lists them. */
3805 if (STRINGP (b->auto_save_file_name)
3806 && listdesc >= 0 && do_handled_files == 0)
3808 write (listdesc, XSTRING (b->auto_save_file_name)->data,
3809 XSTRING (b->auto_save_file_name)->size);
3810 write (listdesc, "\n", 1);
3813 if (!NILP (current_only)
3814 && b != current_buffer)
3815 continue;
3817 /* Don't auto-save indirect buffers.
3818 The base buffer takes care of it. */
3819 if (b->base_buffer)
3820 continue;
3822 /* Check for auto save enabled
3823 and file changed since last auto save
3824 and file changed since last real save. */
3825 if (STRINGP (b->auto_save_file_name)
3826 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
3827 && b->auto_save_modified < BUF_MODIFF (b)
3828 /* -1 means we've turned off autosaving for a while--see below. */
3829 && XINT (b->save_length) >= 0
3830 && (do_handled_files
3831 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
3832 Qwrite_region))))
3834 EMACS_TIME before_time, after_time;
3836 EMACS_GET_TIME (before_time);
3838 /* If we had a failure, don't try again for 20 minutes. */
3839 if (b->auto_save_failure_time >= 0
3840 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
3841 continue;
3843 if ((XFASTINT (b->save_length) * 10
3844 > (BUF_Z (b) - BUF_BEG (b)) * 13)
3845 /* A short file is likely to change a large fraction;
3846 spare the user annoying messages. */
3847 && XFASTINT (b->save_length) > 5000
3848 /* These messages are frequent and annoying for `*mail*'. */
3849 && !EQ (b->filename, Qnil)
3850 && NILP (no_message))
3852 /* It has shrunk too much; turn off auto-saving here. */
3853 message ("Buffer %s has shrunk a lot; auto save turned off there",
3854 XSTRING (b->name)->data);
3855 /* Turn off auto-saving until there's a real save,
3856 and prevent any more warnings. */
3857 XSETINT (b->save_length, -1);
3858 Fsleep_for (make_number (1), Qnil);
3859 continue;
3861 set_buffer_internal (b);
3862 if (!auto_saved && NILP (no_message))
3863 message1 ("Auto-saving...");
3864 internal_condition_case (auto_save_1, Qt, auto_save_error);
3865 auto_saved++;
3866 b->auto_save_modified = BUF_MODIFF (b);
3867 XSETFASTINT (current_buffer->save_length, Z - BEG);
3868 set_buffer_internal (old);
3870 EMACS_GET_TIME (after_time);
3872 /* If auto-save took more than 60 seconds,
3873 assume it was an NFS failure that got a timeout. */
3874 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
3875 b->auto_save_failure_time = EMACS_SECS (after_time);
3879 /* Prevent another auto save till enough input events come in. */
3880 record_auto_save ();
3882 if (auto_saved && NILP (no_message))
3884 if (omessage)
3885 message2 (omessage, omessage_length);
3886 else
3887 message1 ("Auto-saving...done");
3890 Vquit_flag = oquit;
3892 auto_saving = 0;
3893 unbind_to (count, Qnil);
3894 return Qnil;
3897 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
3898 Sset_buffer_auto_saved, 0, 0, 0,
3899 "Mark current buffer as auto-saved with its current text.\n\
3900 No auto-save file will be written until the buffer changes again.")
3903 current_buffer->auto_save_modified = MODIFF;
3904 XSETFASTINT (current_buffer->save_length, Z - BEG);
3905 current_buffer->auto_save_failure_time = -1;
3906 return Qnil;
3909 DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
3910 Sclear_buffer_auto_save_failure, 0, 0, 0,
3911 "Clear any record of a recent auto-save failure in the current buffer.")
3914 current_buffer->auto_save_failure_time = -1;
3915 return Qnil;
3918 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
3919 0, 0, 0,
3920 "Return t if buffer has been auto-saved since last read in or saved.")
3923 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
3926 /* Reading and completing file names */
3927 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
3929 /* In the string VAL, change each $ to $$ and return the result. */
3931 static Lisp_Object
3932 double_dollars (val)
3933 Lisp_Object val;
3935 register unsigned char *old, *new;
3936 register int n;
3937 int osize, count;
3939 osize = XSTRING (val)->size;
3940 /* Quote "$" as "$$" to get it past substitute-in-file-name */
3941 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
3942 if (*old++ == '$') count++;
3943 if (count > 0)
3945 old = XSTRING (val)->data;
3946 val = Fmake_string (make_number (osize + count), make_number (0));
3947 new = XSTRING (val)->data;
3948 for (n = osize; n > 0; n--)
3949 if (*old != '$')
3950 *new++ = *old++;
3951 else
3953 *new++ = '$';
3954 *new++ = '$';
3955 old++;
3958 return val;
3961 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
3962 3, 3, 0,
3963 "Internal subroutine for read-file-name. Do not call this.")
3964 (string, dir, action)
3965 Lisp_Object string, dir, action;
3966 /* action is nil for complete, t for return list of completions,
3967 lambda for verify final value */
3969 Lisp_Object name, specdir, realdir, val, orig_string;
3970 int changed;
3971 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
3973 realdir = dir;
3974 name = string;
3975 orig_string = Qnil;
3976 specdir = Qnil;
3977 changed = 0;
3978 /* No need to protect ACTION--we only compare it with t and nil. */
3979 GCPRO5 (string, realdir, name, specdir, orig_string);
3981 if (XSTRING (string)->size == 0)
3983 if (EQ (action, Qlambda))
3985 UNGCPRO;
3986 return Qnil;
3989 else
3991 orig_string = string;
3992 string = Fsubstitute_in_file_name (string);
3993 changed = NILP (Fstring_equal (string, orig_string));
3994 name = Ffile_name_nondirectory (string);
3995 val = Ffile_name_directory (string);
3996 if (! NILP (val))
3997 realdir = Fexpand_file_name (val, realdir);
4000 if (NILP (action))
4002 specdir = Ffile_name_directory (string);
4003 val = Ffile_name_completion (name, realdir);
4004 UNGCPRO;
4005 if (!STRINGP (val))
4007 if (changed)
4008 return double_dollars (string);
4009 return val;
4012 if (!NILP (specdir))
4013 val = concat2 (specdir, val);
4014 #ifndef VMS
4015 return double_dollars (val);
4016 #else /* not VMS */
4017 return val;
4018 #endif /* not VMS */
4020 UNGCPRO;
4022 if (EQ (action, Qt))
4023 return Ffile_name_all_completions (name, realdir);
4024 /* Only other case actually used is ACTION = lambda */
4025 #ifdef VMS
4026 /* Supposedly this helps commands such as `cd' that read directory names,
4027 but can someone explain how it helps them? -- RMS */
4028 if (XSTRING (name)->size == 0)
4029 return Qt;
4030 #endif /* VMS */
4031 return Ffile_exists_p (string);
4034 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
4035 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
4036 Value is not expanded---you must call `expand-file-name' yourself.\n\
4037 Default name to DEFAULT if user enters a null string.\n\
4038 (If DEFAULT is omitted, the visited file name is used,\n\
4039 except that if INITIAL is specified, that combined with DIR is used.)\n\
4040 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
4041 Non-nil and non-t means also require confirmation after completion.\n\
4042 Fifth arg INITIAL specifies text to start with.\n\
4043 DIR defaults to current buffer's directory default.")
4044 (prompt, dir, defalt, mustmatch, initial)
4045 Lisp_Object prompt, dir, defalt, mustmatch, initial;
4047 Lisp_Object val, insdef, insdef1, tem;
4048 struct gcpro gcpro1, gcpro2;
4049 register char *homedir;
4050 int count;
4052 if (NILP (dir))
4053 dir = current_buffer->directory;
4054 if (NILP (defalt))
4056 if (! NILP (initial))
4057 defalt = Fexpand_file_name (initial, dir);
4058 else
4059 defalt = current_buffer->filename;
4062 /* If dir starts with user's homedir, change that to ~. */
4063 homedir = (char *) egetenv ("HOME");
4064 if (homedir != 0
4065 && STRINGP (dir)
4066 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
4067 && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
4069 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
4070 XSTRING (dir)->size - strlen (homedir) + 1);
4071 XSTRING (dir)->data[0] = '~';
4074 if (insert_default_directory)
4076 insdef = dir;
4077 if (!NILP (initial))
4079 Lisp_Object args[2], pos;
4081 args[0] = insdef;
4082 args[1] = initial;
4083 insdef = Fconcat (2, args);
4084 pos = make_number (XSTRING (double_dollars (dir))->size);
4085 insdef1 = Fcons (double_dollars (insdef), pos);
4087 else
4088 insdef1 = double_dollars (insdef);
4090 else if (!NILP (initial))
4092 insdef = initial;
4093 insdef1 = Fcons (double_dollars (insdef), 0);
4095 else
4096 insdef = Qnil, insdef1 = Qnil;
4098 #ifdef VMS
4099 count = specpdl_ptr - specpdl;
4100 specbind (intern ("completion-ignore-case"), Qt);
4101 #endif
4103 GCPRO2 (insdef, defalt);
4104 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4105 dir, mustmatch, insdef1,
4106 Qfile_name_history);
4108 #ifdef VMS
4109 unbind_to (count, Qnil);
4110 #endif
4112 UNGCPRO;
4113 if (NILP (val))
4114 error ("No file name specified");
4115 tem = Fstring_equal (val, insdef);
4116 if (!NILP (tem) && !NILP (defalt))
4117 return defalt;
4118 if (XSTRING (val)->size == 0 && NILP (insdef))
4120 if (!NILP (defalt))
4121 return defalt;
4122 else
4123 error ("No default file name");
4125 return Fsubstitute_in_file_name (val);
4128 #if 0 /* Old version */
4129 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
4130 /* Don't confuse make-docfile by having two doc strings for this function.
4131 make-docfile does not pay attention to #if, for good reason! */
4133 (prompt, dir, defalt, mustmatch, initial)
4134 Lisp_Object prompt, dir, defalt, mustmatch, initial;
4136 Lisp_Object val, insdef, tem;
4137 struct gcpro gcpro1, gcpro2;
4138 register char *homedir;
4139 int count;
4141 if (NILP (dir))
4142 dir = current_buffer->directory;
4143 if (NILP (defalt))
4144 defalt = current_buffer->filename;
4146 /* If dir starts with user's homedir, change that to ~. */
4147 homedir = (char *) egetenv ("HOME");
4148 if (homedir != 0
4149 && STRINGP (dir)
4150 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
4151 && XSTRING (dir)->data[strlen (homedir)] == '/')
4153 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
4154 XSTRING (dir)->size - strlen (homedir) + 1);
4155 XSTRING (dir)->data[0] = '~';
4158 if (!NILP (initial))
4159 insdef = initial;
4160 else if (insert_default_directory)
4161 insdef = dir;
4162 else
4163 insdef = build_string ("");
4165 #ifdef VMS
4166 count = specpdl_ptr - specpdl;
4167 specbind (intern ("completion-ignore-case"), Qt);
4168 #endif
4170 GCPRO2 (insdef, defalt);
4171 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4172 dir, mustmatch,
4173 insert_default_directory ? insdef : Qnil,
4174 Qfile_name_history);
4176 #ifdef VMS
4177 unbind_to (count, Qnil);
4178 #endif
4180 UNGCPRO;
4181 if (NILP (val))
4182 error ("No file name specified");
4183 tem = Fstring_equal (val, insdef);
4184 if (!NILP (tem) && !NILP (defalt))
4185 return defalt;
4186 return Fsubstitute_in_file_name (val);
4188 #endif /* Old version */
4190 syms_of_fileio ()
4192 Qexpand_file_name = intern ("expand-file-name");
4193 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
4194 Qdirectory_file_name = intern ("directory-file-name");
4195 Qfile_name_directory = intern ("file-name-directory");
4196 Qfile_name_nondirectory = intern ("file-name-nondirectory");
4197 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
4198 Qfile_name_as_directory = intern ("file-name-as-directory");
4199 Qcopy_file = intern ("copy-file");
4200 Qmake_directory_internal = intern ("make-directory-internal");
4201 Qdelete_directory = intern ("delete-directory");
4202 Qdelete_file = intern ("delete-file");
4203 Qrename_file = intern ("rename-file");
4204 Qadd_name_to_file = intern ("add-name-to-file");
4205 Qmake_symbolic_link = intern ("make-symbolic-link");
4206 Qfile_exists_p = intern ("file-exists-p");
4207 Qfile_executable_p = intern ("file-executable-p");
4208 Qfile_readable_p = intern ("file-readable-p");
4209 Qfile_symlink_p = intern ("file-symlink-p");
4210 Qfile_writable_p = intern ("file-writable-p");
4211 Qfile_directory_p = intern ("file-directory-p");
4212 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
4213 Qfile_modes = intern ("file-modes");
4214 Qset_file_modes = intern ("set-file-modes");
4215 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
4216 Qinsert_file_contents = intern ("insert-file-contents");
4217 Qwrite_region = intern ("write-region");
4218 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
4219 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
4221 staticpro (&Qexpand_file_name);
4222 staticpro (&Qsubstitute_in_file_name);
4223 staticpro (&Qdirectory_file_name);
4224 staticpro (&Qfile_name_directory);
4225 staticpro (&Qfile_name_nondirectory);
4226 staticpro (&Qunhandled_file_name_directory);
4227 staticpro (&Qfile_name_as_directory);
4228 staticpro (&Qcopy_file);
4229 staticpro (&Qmake_directory_internal);
4230 staticpro (&Qdelete_directory);
4231 staticpro (&Qdelete_file);
4232 staticpro (&Qrename_file);
4233 staticpro (&Qadd_name_to_file);
4234 staticpro (&Qmake_symbolic_link);
4235 staticpro (&Qfile_exists_p);
4236 staticpro (&Qfile_executable_p);
4237 staticpro (&Qfile_readable_p);
4238 staticpro (&Qfile_symlink_p);
4239 staticpro (&Qfile_writable_p);
4240 staticpro (&Qfile_directory_p);
4241 staticpro (&Qfile_accessible_directory_p);
4242 staticpro (&Qfile_modes);
4243 staticpro (&Qset_file_modes);
4244 staticpro (&Qfile_newer_than_file_p);
4245 staticpro (&Qinsert_file_contents);
4246 staticpro (&Qwrite_region);
4247 staticpro (&Qverify_visited_file_modtime);
4249 Qfile_name_history = intern ("file-name-history");
4250 Fset (Qfile_name_history, Qnil);
4251 staticpro (&Qfile_name_history);
4253 Qfile_error = intern ("file-error");
4254 staticpro (&Qfile_error);
4255 Qfile_already_exists = intern("file-already-exists");
4256 staticpro (&Qfile_already_exists);
4258 #ifdef DOS_NT
4259 Qfind_buffer_file_type = intern ("find-buffer-file-type");
4260 staticpro (&Qfind_buffer_file_type);
4261 #endif /* DOS_NT */
4263 Qcar_less_than_car = intern ("car-less-than-car");
4264 staticpro (&Qcar_less_than_car);
4266 Fput (Qfile_error, Qerror_conditions,
4267 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
4268 Fput (Qfile_error, Qerror_message,
4269 build_string ("File error"));
4271 Fput (Qfile_already_exists, Qerror_conditions,
4272 Fcons (Qfile_already_exists,
4273 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
4274 Fput (Qfile_already_exists, Qerror_message,
4275 build_string ("File already exists"));
4277 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
4278 "*Non-nil means when reading a filename start with default dir in minibuffer.");
4279 insert_default_directory = 1;
4281 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
4282 "*Non-nil means write new files with record format `stmlf'.\n\
4283 nil means use format `var'. This variable is meaningful only on VMS.");
4284 vms_stmlf_recfm = 0;
4286 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
4287 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
4288 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
4289 HANDLER.\n\
4291 The first argument given to HANDLER is the name of the I/O primitive\n\
4292 to be handled; the remaining arguments are the arguments that were\n\
4293 passed to that primitive. For example, if you do\n\
4294 (file-exists-p FILENAME)\n\
4295 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
4296 (funcall HANDLER 'file-exists-p FILENAME)\n\
4297 The function `find-file-name-handler' checks this list for a handler\n\
4298 for its argument.");
4299 Vfile_name_handler_alist = Qnil;
4301 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
4302 "A list of functions to be called at the end of `insert-file-contents'.\n\
4303 Each is passed one argument, the number of bytes inserted. It should return\n\
4304 the new byte count, and leave point the same. If `insert-file-contents' is\n\
4305 intercepted by a handler from `file-name-handler-alist', that handler is\n\
4306 responsible for calling the after-insert-file-functions if appropriate.");
4307 Vafter_insert_file_functions = Qnil;
4309 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
4310 "A list of functions to be called at the start of `write-region'.\n\
4311 Each is passed two arguments, START and END as for `write-region'. It should\n\
4312 return a list of pairs (POSITION . STRING) of strings to be effectively\n\
4313 inserted at the specified positions of the file being written (1 means to\n\
4314 insert before the first byte written). The POSITIONs must be sorted into\n\
4315 increasing order. If there are several functions in the list, the several\n\
4316 lists are merged destructively.");
4317 Vwrite_region_annotate_functions = Qnil;
4319 DEFVAR_LISP ("write-region-annotations-so-far",
4320 &Vwrite_region_annotations_so_far,
4321 "When an annotation function is called, this holds the previous annotations.\n\
4322 These are the annotations made by other annotation functions\n\
4323 that were already called. See also `write-region-annotate-functions'.");
4324 Vwrite_region_annotations_so_far = Qnil;
4326 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
4327 "A list of file name handlers that temporarily should not be used.\n\
4328 This applies only to the operation `inhibit-file-name-operation'.");
4329 Vinhibit_file_name_handlers = Qnil;
4331 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
4332 "The operation for which `inhibit-file-name-handlers' is applicable.");
4333 Vinhibit_file_name_operation = Qnil;
4335 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
4336 "File name in which we write a list of all auto save file names.");
4337 Vauto_save_list_file_name = Qnil;
4339 defsubr (&Sfind_file_name_handler);
4340 defsubr (&Sfile_name_directory);
4341 defsubr (&Sfile_name_nondirectory);
4342 defsubr (&Sunhandled_file_name_directory);
4343 defsubr (&Sfile_name_as_directory);
4344 defsubr (&Sdirectory_file_name);
4345 defsubr (&Smake_temp_name);
4346 defsubr (&Sexpand_file_name);
4347 defsubr (&Ssubstitute_in_file_name);
4348 defsubr (&Scopy_file);
4349 defsubr (&Smake_directory_internal);
4350 defsubr (&Sdelete_directory);
4351 defsubr (&Sdelete_file);
4352 defsubr (&Srename_file);
4353 defsubr (&Sadd_name_to_file);
4354 #ifdef S_IFLNK
4355 defsubr (&Smake_symbolic_link);
4356 #endif /* S_IFLNK */
4357 #ifdef VMS
4358 defsubr (&Sdefine_logical_name);
4359 #endif /* VMS */
4360 #ifdef HPUX_NET
4361 defsubr (&Ssysnetunam);
4362 #endif /* HPUX_NET */
4363 defsubr (&Sfile_name_absolute_p);
4364 defsubr (&Sfile_exists_p);
4365 defsubr (&Sfile_executable_p);
4366 defsubr (&Sfile_readable_p);
4367 defsubr (&Sfile_writable_p);
4368 defsubr (&Sfile_symlink_p);
4369 defsubr (&Sfile_directory_p);
4370 defsubr (&Sfile_accessible_directory_p);
4371 defsubr (&Sfile_regular_p);
4372 defsubr (&Sfile_modes);
4373 defsubr (&Sset_file_modes);
4374 defsubr (&Sset_default_file_modes);
4375 defsubr (&Sdefault_file_modes);
4376 defsubr (&Sfile_newer_than_file_p);
4377 defsubr (&Sinsert_file_contents);
4378 defsubr (&Swrite_region);
4379 defsubr (&Scar_less_than_car);
4380 defsubr (&Sverify_visited_file_modtime);
4381 defsubr (&Sclear_visited_file_modtime);
4382 defsubr (&Svisited_file_modtime);
4383 defsubr (&Sset_visited_file_modtime);
4384 defsubr (&Sdo_auto_save);
4385 defsubr (&Sset_buffer_auto_saved);
4386 defsubr (&Sclear_buffer_auto_save_failure);
4387 defsubr (&Srecent_auto_save_p);
4389 defsubr (&Sread_file_name_internal);
4390 defsubr (&Sread_file_name);
4392 #ifdef unix
4393 defsubr (&Sunix_sync);
4394 #endif