1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 1992 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)
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. */
22 #include <sys/types.h>
44 extern char *sys_errlist
[];
48 #define err_str(a) ((a) < sys_nerr ? sys_errlist[a] : "unknown error")
63 #include "intervals.h"
87 #define min(a, b) ((a) < (b) ? (a) : (b))
88 #define max(a, b) ((a) > (b) ? (a) : (b))
90 /* Nonzero during writing of auto-save files */
93 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
94 a new file with the same mode as the original */
95 int auto_save_mode_bits
;
97 /* Alist of elements (REGEXP . HANDLER) for file names
98 whose I/O is done with a special handler. */
99 Lisp_Object Vfile_name_handler_alist
;
101 /* Nonzero means, when reading a filename in the minibuffer,
102 start out by inserting the default directory into the minibuffer. */
103 int insert_default_directory
;
105 /* On VMS, nonzero means write new files with record format stmlf.
106 Zero means use var format. */
109 Lisp_Object Qfile_error
, Qfile_already_exists
;
111 Lisp_Object Qfile_name_history
;
113 report_file_error (string
, data
)
117 Lisp_Object errstring
;
119 if (errno
>= 0 && errno
< sys_nerr
)
120 errstring
= build_string (sys_errlist
[errno
]);
122 errstring
= build_string ("undocumented error code");
124 /* System error messages are capitalized. Downcase the initial
125 unless it is followed by a slash. */
126 if (XSTRING (errstring
)->data
[1] != '/')
127 XSTRING (errstring
)->data
[0] = DOWNCASE (XSTRING (errstring
)->data
[0]);
130 Fsignal (Qfile_error
,
131 Fcons (build_string (string
), Fcons (errstring
, data
)));
134 close_file_unwind (fd
)
137 close (XFASTINT (fd
));
140 Lisp_Object Qexpand_file_name
;
141 Lisp_Object Qdirectory_file_name
;
142 Lisp_Object Qfile_name_directory
;
143 Lisp_Object Qfile_name_nondirectory
;
144 Lisp_Object Qunhandled_file_name_directory
;
145 Lisp_Object Qfile_name_as_directory
;
146 Lisp_Object Qcopy_file
;
147 Lisp_Object Qmake_directory
;
148 Lisp_Object Qdelete_directory
;
149 Lisp_Object Qdelete_file
;
150 Lisp_Object Qrename_file
;
151 Lisp_Object Qadd_name_to_file
;
152 Lisp_Object Qmake_symbolic_link
;
153 Lisp_Object Qfile_exists_p
;
154 Lisp_Object Qfile_executable_p
;
155 Lisp_Object Qfile_readable_p
;
156 Lisp_Object Qfile_symlink_p
;
157 Lisp_Object Qfile_writable_p
;
158 Lisp_Object Qfile_directory_p
;
159 Lisp_Object Qfile_accessible_directory_p
;
160 Lisp_Object Qfile_modes
;
161 Lisp_Object Qset_file_modes
;
162 Lisp_Object Qfile_newer_than_file_p
;
163 Lisp_Object Qinsert_file_contents
;
164 Lisp_Object Qwrite_region
;
165 Lisp_Object Qverify_visited_file_modtime
;
167 DEFUN ("find-file-name-handler", Ffind_file_name_handler
, Sfind_file_name_handler
, 1, 1, 0,
168 "Return FILENAME's handler function, if its syntax is handled specially.\n\
169 Otherwise, return nil.\n\
170 A file name is handled if one of the regular expressions in\n\
171 `file-name-handler-alist' matches it.")
173 Lisp_Object filename
;
175 /* This function must not munge the match data. */
178 for (chain
= Vfile_name_handler_alist
; XTYPE (chain
) == Lisp_Cons
;
179 chain
= XCONS (chain
)->cdr
)
182 elt
= XCONS (chain
)->car
;
183 if (XTYPE (elt
) == Lisp_Cons
)
186 string
= XCONS (elt
)->car
;
187 if (XTYPE (string
) == Lisp_String
188 && fast_string_match (string
, filename
) >= 0)
189 return XCONS (elt
)->cdr
;
197 DEFUN ("file-name-directory", Ffile_name_directory
, Sfile_name_directory
,
199 "Return the directory component in file name NAME.\n\
200 Return nil if NAME does not include a directory.\n\
201 Otherwise return a directory spec.\n\
202 Given a Unix syntax file name, returns a string ending in slash;\n\
203 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
207 register unsigned char *beg
;
208 register unsigned char *p
;
211 CHECK_STRING (file
, 0);
213 /* If the file name has special constructs in it,
214 call the corresponding file handler. */
215 handler
= Ffind_file_name_handler (file
);
217 return call2 (handler
, Qfile_name_directory
, file
);
219 beg
= XSTRING (file
)->data
;
220 p
= beg
+ XSTRING (file
)->size
;
222 while (p
!= beg
&& p
[-1] != '/'
224 && p
[-1] != ':' && p
[-1] != ']' && p
[-1] != '>'
230 return make_string (beg
, p
- beg
);
233 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory
, Sfile_name_nondirectory
,
235 "Return file name NAME sans its directory.\n\
236 For example, in a Unix-syntax file name,\n\
237 this is everything after the last slash,\n\
238 or the entire name if it contains no slash.")
242 register unsigned char *beg
, *p
, *end
;
245 CHECK_STRING (file
, 0);
247 /* If the file name has special constructs in it,
248 call the corresponding file handler. */
249 handler
= Ffind_file_name_handler (file
);
251 return call2 (handler
, Qfile_name_nondirectory
, file
);
253 beg
= XSTRING (file
)->data
;
254 end
= p
= beg
+ XSTRING (file
)->size
;
256 while (p
!= beg
&& p
[-1] != '/'
258 && p
[-1] != ':' && p
[-1] != ']' && p
[-1] != '>'
262 return make_string (p
, end
- p
);
265 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory
, Sunhandled_file_name_directory
, 1, 1, 0,
266 "Return a directly usable directory name somehow associated with FILENAME.\n\
267 A `directly usable' directory name is one that may be used without the\n\
268 intervention of any file handler.\n\
269 If FILENAME is a directly usable file itself, return\n\
270 (file-name-directory FILENAME).\n\
271 The `call-process' and `start-process' functions use this function to\n\
272 get a current directory to run processes in.")
274 Lisp_Object filename
;
278 /* If the file name has special constructs in it,
279 call the corresponding file handler. */
280 handler
= Ffind_file_name_handler (filename
);
282 return call2 (handler
, Qunhandled_file_name_directory
, filename
);
284 return Ffile_name_directory (filename
);
289 file_name_as_directory (out
, in
)
292 int size
= strlen (in
) - 1;
297 /* Is it already a directory string? */
298 if (in
[size
] == ':' || in
[size
] == ']' || in
[size
] == '>')
300 /* Is it a VMS directory file name? If so, hack VMS syntax. */
301 else if (! index (in
, '/')
302 && ((size
> 3 && ! strcmp (&in
[size
- 3], ".DIR"))
303 || (size
> 3 && ! strcmp (&in
[size
- 3], ".dir"))
304 || (size
> 5 && (! strncmp (&in
[size
- 5], ".DIR", 4)
305 || ! strncmp (&in
[size
- 5], ".dir", 4))
306 && (in
[size
- 1] == '.' || in
[size
- 1] == ';')
307 && in
[size
] == '1')))
309 register char *p
, *dot
;
313 dir:x.dir --> dir:[x]
314 dir:[x]y.dir --> dir:[x.y] */
316 while (p
!= in
&& *p
!= ':' && *p
!= '>' && *p
!= ']') p
--;
319 strncpy (out
, in
, p
- in
);
338 dot
= index (p
, '.');
341 /* blindly remove any extension */
342 size
= strlen (out
) + (dot
- p
);
343 strncat (out
, p
, dot
- p
);
354 /* For Unix syntax, Append a slash if necessary */
355 if (out
[size
] != '/')
361 DEFUN ("file-name-as-directory", Ffile_name_as_directory
,
362 Sfile_name_as_directory
, 1, 1, 0,
363 "Return a string representing file FILENAME interpreted as a directory.\n\
364 This operation exists because a directory is also a file, but its name as\n\
365 a directory is different from its name as a file.\n\
366 The result can be used as the value of `default-directory'\n\
367 or passed as second argument to `expand-file-name'.\n\
368 For a Unix-syntax file name, just appends a slash.\n\
369 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
376 CHECK_STRING (file
, 0);
380 /* If the file name has special constructs in it,
381 call the corresponding file handler. */
382 handler
= Ffind_file_name_handler (file
);
384 return call2 (handler
, Qfile_name_as_directory
, file
);
386 buf
= (char *) alloca (XSTRING (file
)->size
+ 10);
387 return build_string (file_name_as_directory (buf
, XSTRING (file
)->data
));
391 * Convert from directory name to filename.
393 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
394 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
395 * On UNIX, it's simple: just make sure there is a terminating /
397 * Value is nonzero if the string output is different from the input.
400 directory_file_name (src
, dst
)
408 struct FAB fab
= cc$rms_fab
;
409 struct NAM nam
= cc$rms_nam
;
410 char esa
[NAM$C_MAXRSS
];
415 if (! index (src
, '/')
416 && (src
[slen
- 1] == ']'
417 || src
[slen
- 1] == ':'
418 || src
[slen
- 1] == '>'))
420 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
422 fab
.fab$b_fns
= slen
;
423 fab
.fab$l_nam
= &nam
;
424 fab
.fab$l_fop
= FAB$M_NAM
;
427 nam
.nam$b_ess
= sizeof esa
;
428 nam
.nam$b_nop
|= NAM$M_SYNCHK
;
430 /* We call SYS$PARSE to handle such things as [--] for us. */
431 if (SYS$
PARSE(&fab
, 0, 0) == RMS$_NORMAL
)
433 slen
= nam
.nam$b_esl
;
434 if (esa
[slen
- 1] == ';' && esa
[slen
- 2] == '.')
439 if (src
[slen
- 1] != ']' && src
[slen
- 1] != '>')
441 /* what about when we have logical_name:???? */
442 if (src
[slen
- 1] == ':')
443 { /* Xlate logical name and see what we get */
444 ptr
= strcpy (dst
, src
); /* upper case for getenv */
447 if ('a' <= *ptr
&& *ptr
<= 'z')
451 dst
[slen
- 1] = 0; /* remove colon */
452 if (!(src
= egetenv (dst
)))
454 /* should we jump to the beginning of this procedure?
455 Good points: allows us to use logical names that xlate
457 Bad points: can be a problem if we just translated to a device
459 For now, I'll punt and always expect VMS names, and hope for
462 if (src
[slen
- 1] != ']' && src
[slen
- 1] != '>')
463 { /* no recursion here! */
469 { /* not a directory spec */
474 bracket
= src
[slen
- 1];
476 /* If bracket is ']' or '>', bracket - 2 is the corresponding
478 ptr
= index (src
, bracket
- 2);
480 { /* no opening bracket */
484 if (!(rptr
= rindex (src
, '.')))
487 strncpy (dst
, src
, slen
);
491 dst
[slen
++] = bracket
;
496 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
497 then translate the device and recurse. */
498 if (dst
[slen
- 1] == ':'
499 && dst
[slen
- 2] != ':' /* skip decnet nodes */
500 && strcmp(src
+ slen
, "[000000]") == 0)
502 dst
[slen
- 1] = '\0';
503 if ((ptr
= egetenv (dst
))
504 && (rlen
= strlen (ptr
) - 1) > 0
505 && (ptr
[rlen
] == ']' || ptr
[rlen
] == '>')
506 && ptr
[rlen
- 1] == '.')
508 char * buf
= (char *) alloca (strlen (ptr
) + 1);
512 return directory_file_name (buf
, dst
);
517 strcat (dst
, "[000000]");
521 rlen
= strlen (rptr
) - 1;
522 strncat (dst
, rptr
, rlen
);
523 dst
[slen
+ rlen
] = '\0';
524 strcat (dst
, ".DIR.1");
528 /* Process as Unix format: just remove any final slash.
529 But leave "/" unchanged; do not change it to "". */
531 if (slen
> 1 && dst
[slen
- 1] == '/')
536 DEFUN ("directory-file-name", Fdirectory_file_name
, Sdirectory_file_name
,
538 "Returns the file name of the directory named DIR.\n\
539 This is the name of the file that holds the data for the directory DIR.\n\
540 This operation exists because a directory is also a file, but its name as\n\
541 a directory is different from its name as a file.\n\
542 In Unix-syntax, this function just removes the final slash.\n\
543 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
544 it returns a file name such as \"[X]Y.DIR.1\".")
546 Lisp_Object directory
;
551 CHECK_STRING (directory
, 0);
553 if (NILP (directory
))
556 /* If the file name has special constructs in it,
557 call the corresponding file handler. */
558 handler
= Ffind_file_name_handler (directory
);
560 return call2 (handler
, Qdirectory_file_name
, directory
);
563 /* 20 extra chars is insufficient for VMS, since we might perform a
564 logical name translation. an equivalence string can be up to 255
565 chars long, so grab that much extra space... - sss */
566 buf
= (char *) alloca (XSTRING (directory
)->size
+ 20 + 255);
568 buf
= (char *) alloca (XSTRING (directory
)->size
+ 20);
570 directory_file_name (XSTRING (directory
)->data
, buf
);
571 return build_string (buf
);
574 DEFUN ("make-temp-name", Fmake_temp_name
, Smake_temp_name
, 1, 1, 0,
575 "Generate temporary file name (string) starting with PREFIX (a string).\n\
576 The Emacs process number forms part of the result,\n\
577 so there is no danger of generating a name being used by another process.")
582 val
= concat2 (prefix
, build_string ("XXXXXX"));
583 mktemp (XSTRING (val
)->data
);
587 DEFUN ("expand-file-name", Fexpand_file_name
, Sexpand_file_name
, 1, 2, 0,
588 "Convert FILENAME to absolute, and canonicalize it.\n\
589 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
590 (does not start with slash); if DEFAULT is nil or missing,\n\
591 the current buffer's value of default-directory is used.\n\
592 Path components that are `.' are removed, and \n\
593 path components followed by `..' are removed, along with the `..' itself;\n\
594 note that these simplifications are done without checking the resulting\n\
595 paths in the file system.\n\
596 An initial `~/' expands to your home directory.\n\
597 An initial `~USER/' expands to USER's home directory.\n\
598 See also the function `substitute-in-file-name'.")
600 Lisp_Object name
, defalt
;
604 register unsigned char *newdir
, *p
, *o
;
606 unsigned char *target
;
609 unsigned char * colon
= 0;
610 unsigned char * close
= 0;
611 unsigned char * slash
= 0;
612 unsigned char * brack
= 0;
613 int lbrack
= 0, rbrack
= 0;
618 CHECK_STRING (name
, 0);
620 /* If the file name has special constructs in it,
621 call the corresponding file handler. */
622 handler
= Ffind_file_name_handler (name
);
624 return call3 (handler
, Qexpand_file_name
, name
, defalt
);
626 /* Use the buffer's default-directory if DEFALT is omitted. */
628 defalt
= current_buffer
->directory
;
629 CHECK_STRING (defalt
, 1);
631 /* Make sure DEFALT is properly expanded.
632 It would be better to do this down below where we actually use
633 defalt. Unfortunately, calling Fexpand_file_name recursively
634 could invoke GC, and the strings might be relocated. This would
635 be annoying because we have pointers into strings lying around
636 that would need adjusting, and people would add new pointers to
637 the code and forget to adjust them, resulting in intermittent bugs.
638 Putting this call here avoids all that crud.
640 The EQ test avoids infinite recursion. */
641 if (! NILP (defalt
) && !EQ (defalt
, name
)
642 /* This saves time in a common case. */
643 && XSTRING (defalt
)->data
[0] != '/')
648 defalt
= Fexpand_file_name (defalt
, Qnil
);
653 /* Filenames on VMS are always upper case. */
654 name
= Fupcase (name
);
657 nm
= XSTRING (name
)->data
;
659 /* If nm is absolute, flush ...// and detect /./ and /../.
660 If no /./ or /../ we can return right away. */
668 /* If it turns out that the filename we want to return is just a
669 suffix of FILENAME, we don't need to go through and edit
670 things; we just need to construct a new string using data
671 starting at the middle of FILENAME. If we set lose to a
672 non-zero value, that means we've discovered that we can't do
679 /* Since we know the path is absolute, we can assume that each
680 element starts with a "/". */
682 /* "//" anywhere isn't necessarily hairy; we just start afresh
683 with the second slash. */
684 if (p
[0] == '/' && p
[1] == '/'
686 /* // at start of filename is meaningful on Apollo system */
692 /* "~" is hairy as the start of any path element. */
693 if (p
[0] == '/' && p
[1] == '~')
694 nm
= p
+ 1, lose
= 1;
696 /* "." and ".." are hairy. */
701 || (p
[2] == '.' && (p
[3] == '/'
708 /* if dev:[dir]/, move nm to / */
709 if (!slash
&& p
> nm
&& (brack
|| colon
)) {
710 nm
= (brack
? brack
+ 1 : colon
+ 1);
719 /* VMS pre V4.4,convert '-'s in filenames. */
720 if (lbrack
== rbrack
)
722 if (dots
< 2) /* this is to allow negative version numbers */
727 if (lbrack
> rbrack
&&
728 ((p
[-1] == '.' || p
[-1] == '[' || p
[-1] == '<') &&
729 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>')))
735 /* count open brackets, reset close bracket pointer */
736 if (p
[0] == '[' || p
[0] == '<')
738 /* count close brackets, set close bracket pointer */
739 if (p
[0] == ']' || p
[0] == '>')
741 /* detect ][ or >< */
742 if ((p
[0] == ']' || p
[0] == '>') && (p
[1] == '[' || p
[1] == '<'))
744 if ((p
[0] == ':' || p
[0] == ']' || p
[0] == '>') && p
[1] == '~')
745 nm
= p
+ 1, lose
= 1;
746 if (p
[0] == ':' && (colon
|| slash
))
747 /* if dev1:[dir]dev2:, move nm to dev2: */
753 /* if /pathname/dev:, move nm to dev: */
756 /* if node::dev:, move colon following dev */
757 else if (colon
&& colon
[-1] == ':')
759 /* if dev1:dev2:, move nm to dev2: */
760 else if (colon
&& colon
[-1] != ':')
765 if (p
[0] == ':' && !colon
)
771 if (lbrack
== rbrack
)
774 else if (p
[0] == '.')
783 return build_string (sys_translate_unix (nm
));
785 if (nm
== XSTRING (name
)->data
)
787 return build_string (nm
);
791 /* Now determine directory to start with and put it in newdir */
795 if (nm
[0] == '~') /* prefix ~ */
801 || nm
[1] == 0) /* ~ by itself */
803 if (!(newdir
= (unsigned char *) egetenv ("HOME")))
804 newdir
= (unsigned char *) "";
807 nm
++; /* Don't leave the slash in nm. */
810 else /* ~user/filename */
812 for (p
= nm
; *p
&& (*p
!= '/'
817 o
= (unsigned char *) alloca (p
- nm
+ 1);
818 bcopy ((char *) nm
, o
, p
- nm
);
821 pw
= (struct passwd
*) getpwnam (o
+ 1);
824 newdir
= (unsigned char *) pw
-> pw_dir
;
826 nm
= p
+ 1; /* skip the terminator */
832 /* If we don't find a user of that name, leave the name
833 unchanged; don't move nm forward to p. */
843 newdir
= XSTRING (defalt
)->data
;
848 /* Get rid of any slash at the end of newdir. */
849 int length
= strlen (newdir
);
850 if (newdir
[length
- 1] == '/')
852 unsigned char *temp
= (unsigned char *) alloca (length
);
853 bcopy (newdir
, temp
, length
- 1);
854 temp
[length
- 1] = 0;
862 /* Now concatenate the directory and name to new space in the stack frame */
863 tlen
+= strlen (nm
) + 1;
864 target
= (unsigned char *) alloca (tlen
);
870 if (nm
[0] == 0 || nm
[0] == '/')
871 strcpy (target
, newdir
);
874 file_name_as_directory (target
, newdir
);
879 if (index (target
, '/'))
880 strcpy (target
, sys_translate_unix (target
));
883 /* Now canonicalize by removing /. and /foo/.. if they appear. */
891 if (*p
!= ']' && *p
!= '>' && *p
!= '-')
897 else if ((p
[0] == ']' || p
[0] == '>') && p
[0] == p
[1] + 2)
898 /* brackets are offset from each other by 2 */
901 if (*p
!= '.' && *p
!= '-' && o
[-1] != '.')
902 /* convert [foo][bar] to [bar] */
903 while (o
[-1] != '[' && o
[-1] != '<')
905 else if (*p
== '-' && *o
!= '.')
908 else if (p
[0] == '-' && o
[-1] == '.' &&
909 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>'))
910 /* flush .foo.- ; leave - if stopped by '[' or '<' */
914 while (o
[-1] != '.' && o
[-1] != '[' && o
[-1] != '<');
915 if (p
[1] == '.') /* foo.-.bar ==> bar*/
917 else if (o
[-1] == '.') /* '.foo.-]' ==> ']' */
919 /* else [foo.-] ==> [-] */
925 o
[-1] != '[' && o
[-1] != '<' && o
[-1] != '.' &&
926 p
[1] != ']' && p
[1] != '>' && p
[1] != '.')
936 else if (!strncmp (p
, "//", 2)
938 /* // at start of filename is meaningful in Apollo system */
951 /* If "/." is the entire filename, keep the "/". Otherwise,
952 just delete the whole "/.". */
953 if (o
== target
&& p
[2] == '\0')
957 else if (!strncmp (p
, "/..", 3)
958 /* `/../' is the "superroot" on certain file systems. */
960 && (p
[3] == '/' || p
[3] == 0))
962 while (o
!= target
&& *--o
!= '/')
965 if (o
== target
+ 1 && o
[-1] == '/' && o
[0] == '/')
969 if (o
== target
&& *o
== '/')
980 return make_string (target
, o
- target
);
983 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'.
984 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
985 "Convert FILENAME to absolute, and canonicalize it.\n\
986 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
987 (does not start with slash); if DEFAULT is nil or missing,\n\
988 the current buffer's value of default-directory is used.\n\
989 Filenames containing `.' or `..' as components are simplified;\n\
990 initial `~/' expands to your home directory.\n\
991 See also the function `substitute-in-file-name'.")
993 Lisp_Object name, defalt;
997 register unsigned char *newdir, *p, *o;
999 unsigned char *target;
1003 unsigned char * colon = 0;
1004 unsigned char * close = 0;
1005 unsigned char * slash = 0;
1006 unsigned char * brack = 0;
1007 int lbrack = 0, rbrack = 0;
1011 CHECK_STRING (name
, 0);
1014 /* Filenames on VMS are always upper case. */
1015 name
= Fupcase (name
);
1018 nm
= XSTRING (name
)->data
;
1020 /* If nm is absolute, flush ...// and detect /./ and /../.
1021 If no /./ or /../ we can return right away. */
1033 if (p
[0] == '/' && p
[1] == '/'
1035 /* // at start of filename is meaningful on Apollo system */
1040 if (p
[0] == '/' && p
[1] == '~')
1041 nm
= p
+ 1, lose
= 1;
1042 if (p
[0] == '/' && p
[1] == '.'
1043 && (p
[2] == '/' || p
[2] == 0
1044 || (p
[2] == '.' && (p
[3] == '/' || p
[3] == 0))))
1050 /* if dev:[dir]/, move nm to / */
1051 if (!slash
&& p
> nm
&& (brack
|| colon
)) {
1052 nm
= (brack
? brack
+ 1 : colon
+ 1);
1053 lbrack
= rbrack
= 0;
1061 /* VMS pre V4.4,convert '-'s in filenames. */
1062 if (lbrack
== rbrack
)
1064 if (dots
< 2) /* this is to allow negative version numbers */
1069 if (lbrack
> rbrack
&&
1070 ((p
[-1] == '.' || p
[-1] == '[' || p
[-1] == '<') &&
1071 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>')))
1077 /* count open brackets, reset close bracket pointer */
1078 if (p
[0] == '[' || p
[0] == '<')
1079 lbrack
++, brack
= 0;
1080 /* count close brackets, set close bracket pointer */
1081 if (p
[0] == ']' || p
[0] == '>')
1082 rbrack
++, brack
= p
;
1083 /* detect ][ or >< */
1084 if ((p
[0] == ']' || p
[0] == '>') && (p
[1] == '[' || p
[1] == '<'))
1086 if ((p
[0] == ':' || p
[0] == ']' || p
[0] == '>') && p
[1] == '~')
1087 nm
= p
+ 1, lose
= 1;
1088 if (p
[0] == ':' && (colon
|| slash
))
1089 /* if dev1:[dir]dev2:, move nm to dev2: */
1095 /* if /pathname/dev:, move nm to dev: */
1098 /* if node::dev:, move colon following dev */
1099 else if (colon
&& colon
[-1] == ':')
1101 /* if dev1:dev2:, move nm to dev2: */
1102 else if (colon
&& colon
[-1] != ':')
1107 if (p
[0] == ':' && !colon
)
1113 if (lbrack
== rbrack
)
1116 else if (p
[0] == '.')
1124 if (index (nm
, '/'))
1125 return build_string (sys_translate_unix (nm
));
1127 if (nm
== XSTRING (name
)->data
)
1129 return build_string (nm
);
1133 /* Now determine directory to start with and put it in NEWDIR */
1137 if (nm
[0] == '~') /* prefix ~ */
1142 || nm
[1] == 0)/* ~/filename */
1144 if (!(newdir
= (unsigned char *) egetenv ("HOME")))
1145 newdir
= (unsigned char *) "";
1148 nm
++; /* Don't leave the slash in nm. */
1151 else /* ~user/filename */
1153 /* Get past ~ to user */
1154 unsigned char *user
= nm
+ 1;
1155 /* Find end of name. */
1156 unsigned char *ptr
= (unsigned char *) index (user
, '/');
1157 int len
= ptr
? ptr
- user
: strlen (user
);
1159 unsigned char *ptr1
= index (user
, ':');
1160 if (ptr1
!= 0 && ptr1
- user
< len
)
1163 /* Copy the user name into temp storage. */
1164 o
= (unsigned char *) alloca (len
+ 1);
1165 bcopy ((char *) user
, o
, len
);
1168 /* Look up the user name. */
1169 pw
= (struct passwd
*) getpwnam (o
+ 1);
1171 error ("\"%s\" isn't a registered user", o
+ 1);
1173 newdir
= (unsigned char *) pw
->pw_dir
;
1175 /* Discard the user name from NM. */
1182 #endif /* not VMS */
1186 defalt
= current_buffer
->directory
;
1187 CHECK_STRING (defalt
, 1);
1188 newdir
= XSTRING (defalt
)->data
;
1191 /* Now concatenate the directory and name to new space in the stack frame */
1193 tlen
= (newdir
? strlen (newdir
) + 1 : 0) + strlen (nm
) + 1;
1194 target
= (unsigned char *) alloca (tlen
);
1200 if (nm
[0] == 0 || nm
[0] == '/')
1201 strcpy (target
, newdir
);
1204 file_name_as_directory (target
, newdir
);
1207 strcat (target
, nm
);
1209 if (index (target
, '/'))
1210 strcpy (target
, sys_translate_unix (target
));
1213 /* Now canonicalize by removing /. and /foo/.. if they appear */
1221 if (*p
!= ']' && *p
!= '>' && *p
!= '-')
1227 else if ((p
[0] == ']' || p
[0] == '>') && p
[0] == p
[1] + 2)
1228 /* brackets are offset from each other by 2 */
1231 if (*p
!= '.' && *p
!= '-' && o
[-1] != '.')
1232 /* convert [foo][bar] to [bar] */
1233 while (o
[-1] != '[' && o
[-1] != '<')
1235 else if (*p
== '-' && *o
!= '.')
1238 else if (p
[0] == '-' && o
[-1] == '.' &&
1239 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>'))
1240 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1244 while (o
[-1] != '.' && o
[-1] != '[' && o
[-1] != '<');
1245 if (p
[1] == '.') /* foo.-.bar ==> bar*/
1247 else if (o
[-1] == '.') /* '.foo.-]' ==> ']' */
1249 /* else [foo.-] ==> [-] */
1255 o
[-1] != '[' && o
[-1] != '<' && o
[-1] != '.' &&
1256 p
[1] != ']' && p
[1] != '>' && p
[1] != '.')
1266 else if (!strncmp (p
, "//", 2)
1268 /* // at start of filename is meaningful in Apollo system */
1276 else if (p
[0] == '/' && p
[1] == '.' &&
1277 (p
[2] == '/' || p
[2] == 0))
1279 else if (!strncmp (p
, "/..", 3)
1280 /* `/../' is the "superroot" on certain file systems. */
1282 && (p
[3] == '/' || p
[3] == 0))
1284 while (o
!= target
&& *--o
!= '/')
1287 if (o
== target
+ 1 && o
[-1] == '/' && o
[0] == '/')
1291 if (o
== target
&& *o
== '/')
1299 #endif /* not VMS */
1302 return make_string (target
, o
- target
);
1306 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name
,
1307 Ssubstitute_in_file_name
, 1, 1, 0,
1308 "Substitute environment variables referred to in FILENAME.\n\
1309 `$FOO' where FOO is an environment variable name means to substitute\n\
1310 the value of that variable. The variable name should be terminated\n\
1311 with a character not a letter, digit or underscore; otherwise, enclose\n\
1312 the entire variable name in braces.\n\
1313 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1314 On VMS, `$' substitution is not done; this function does little and only\n\
1315 duplicates what `expand-file-name' does.")
1321 register unsigned char *s
, *p
, *o
, *x
, *endp
;
1322 unsigned char *target
;
1324 int substituted
= 0;
1327 CHECK_STRING (string
, 0);
1329 nm
= XSTRING (string
)->data
;
1330 endp
= nm
+ XSTRING (string
)->size
;
1332 /* If /~ or // appears, discard everything through first slash. */
1334 for (p
= nm
; p
!= endp
; p
++)
1338 /* // at start of file name is meaningful in Apollo system */
1339 (p
[0] == '/' && p
- 1 != nm
)
1340 #else /* not APOLLO */
1342 #endif /* not APOLLO */
1346 (p
[-1] == ':' || p
[-1] == ']' || p
[-1] == '>' ||
1359 return build_string (nm
);
1362 /* See if any variables are substituted into the string
1363 and find the total length of their values in `total' */
1365 for (p
= nm
; p
!= endp
;)
1375 /* "$$" means a single "$" */
1384 while (p
!= endp
&& *p
!= '}') p
++;
1385 if (*p
!= '}') goto missingclose
;
1391 while (p
!= endp
&& (isalnum (*p
) || *p
== '_')) p
++;
1395 /* Copy out the variable name */
1396 target
= (unsigned char *) alloca (s
- o
+ 1);
1397 strncpy (target
, o
, s
- o
);
1400 /* Get variable value */
1401 o
= (unsigned char *) egetenv (target
);
1402 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1405 if (!o
&& !strcmp (target
, "USER"))
1406 o
= egetenv ("LOGNAME");
1409 if (!o
) goto badvar
;
1410 total
+= strlen (o
);
1417 /* If substitution required, recopy the string and do it */
1418 /* Make space in stack frame for the new copy */
1419 xnm
= (unsigned char *) alloca (XSTRING (string
)->size
+ total
+ 1);
1422 /* Copy the rest of the name through, replacing $ constructs with values */
1439 while (p
!= endp
&& *p
!= '}') p
++;
1440 if (*p
!= '}') goto missingclose
;
1446 while (p
!= endp
&& (isalnum (*p
) || *p
== '_')) p
++;
1450 /* Copy out the variable name */
1451 target
= (unsigned char *) alloca (s
- o
+ 1);
1452 strncpy (target
, o
, s
- o
);
1455 /* Get variable value */
1456 o
= (unsigned char *) egetenv (target
);
1457 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1460 if (!o
&& !strcmp (target
, "USER"))
1461 o
= egetenv ("LOGNAME");
1473 /* If /~ or // appears, discard everything through first slash. */
1475 for (p
= xnm
; p
!= x
; p
++)
1478 /* // at start of file name is meaningful in Apollo system */
1479 (p
[0] == '/' && p
- 1 != xnm
)
1480 #else /* not APOLLO */
1482 #endif /* not APOLLO */
1484 && p
!= nm
&& p
[-1] == '/')
1487 return make_string (xnm
, x
- xnm
);
1490 error ("Bad format environment-variable substitution");
1492 error ("Missing \"}\" in environment-variable substitution");
1494 error ("Substituting nonexistent environment variable \"%s\"", target
);
1497 #endif /* not VMS */
1500 /* A slightly faster and more convenient way to get
1501 (directory-file-name (expand-file-name FOO)). The return value may
1502 have had its last character zapped with a '\0' character, meaning
1503 that it is acceptable to system calls, but not to other lisp
1504 functions. Callers should make sure that the return value doesn't
1508 expand_and_dir_to_file (filename
, defdir
)
1509 Lisp_Object filename
, defdir
;
1511 register Lisp_Object abspath
;
1513 abspath
= Fexpand_file_name (filename
, defdir
);
1516 register int c
= XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1];
1517 if (c
== ':' || c
== ']' || c
== '>')
1518 abspath
= Fdirectory_file_name (abspath
);
1521 /* Remove final slash, if any (unless path is root).
1522 stat behaves differently depending! */
1523 if (XSTRING (abspath
)->size
> 1
1524 && XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1] == '/')
1526 if (EQ (abspath
, filename
))
1527 abspath
= Fcopy_sequence (abspath
);
1528 XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1] = 0;
1534 barf_or_query_if_file_exists (absname
, querystring
, interactive
)
1535 Lisp_Object absname
;
1536 unsigned char *querystring
;
1539 register Lisp_Object tem
;
1540 struct gcpro gcpro1
;
1542 if (access (XSTRING (absname
)->data
, 4) >= 0)
1545 Fsignal (Qfile_already_exists
,
1546 Fcons (build_string ("File already exists"),
1547 Fcons (absname
, Qnil
)));
1549 tem
= do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1550 XSTRING (absname
)->data
, querystring
));
1553 Fsignal (Qfile_already_exists
,
1554 Fcons (build_string ("File already exists"),
1555 Fcons (absname
, Qnil
)));
1560 DEFUN ("copy-file", Fcopy_file
, Scopy_file
, 2, 4,
1561 "fCopy file: \nFCopy %s to file: \np\nP",
1562 "Copy FILE to NEWNAME. Both args must be strings.\n\
1563 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1564 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1565 A number as third arg means request confirmation if NEWNAME already exists.\n\
1566 This is what happens in interactive use with M-x.\n\
1567 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1568 last-modified time as the old one. (This works on only some systems.)\n\
1569 A prefix arg makes KEEP-TIME non-nil.")
1570 (filename
, newname
, ok_if_already_exists
, keep_date
)
1571 Lisp_Object filename
, newname
, ok_if_already_exists
, keep_date
;
1574 char buf
[16 * 1024];
1576 Lisp_Object handler
;
1577 struct gcpro gcpro1
, gcpro2
;
1578 int count
= specpdl_ptr
- specpdl
;
1580 GCPRO2 (filename
, newname
);
1581 CHECK_STRING (filename
, 0);
1582 CHECK_STRING (newname
, 1);
1583 filename
= Fexpand_file_name (filename
, Qnil
);
1584 newname
= Fexpand_file_name (newname
, Qnil
);
1586 /* If the input file name has special constructs in it,
1587 call the corresponding file handler. */
1588 handler
= Ffind_file_name_handler (filename
);
1589 if (!NILP (handler
))
1590 return call3 (handler
, Qcopy_file
, filename
, newname
);
1591 /* Likewise for output file name. */
1592 handler
= Ffind_file_name_handler (newname
);
1593 if (!NILP (handler
))
1594 return call3 (handler
, Qcopy_file
, filename
, newname
);
1596 if (NILP (ok_if_already_exists
)
1597 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1598 barf_or_query_if_file_exists (newname
, "copy to it",
1599 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1601 ifd
= open (XSTRING (filename
)->data
, 0);
1603 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
1605 record_unwind_protect (close_file_unwind
, make_number (ifd
));
1608 /* Create the copy file with the same record format as the input file */
1609 ofd
= sys_creat (XSTRING (newname
)->data
, 0666, ifd
);
1611 ofd
= creat (XSTRING (newname
)->data
, 0666);
1614 report_file_error ("Opening output file", Fcons (newname
, Qnil
));
1616 record_unwind_protect (close_file_unwind
, make_number (ofd
));
1620 while ((n
= read (ifd
, buf
, sizeof buf
)) > 0)
1621 if (write (ofd
, buf
, n
) != n
)
1622 report_file_error ("I/O error", Fcons (newname
, Qnil
));
1625 if (fstat (ifd
, &st
) >= 0)
1627 if (!NILP (keep_date
))
1629 EMACS_TIME atime
, mtime
;
1630 EMACS_SET_SECS_USECS (atime
, st
.st_atime
, 0);
1631 EMACS_SET_SECS_USECS (mtime
, st
.st_mtime
, 0);
1632 EMACS_SET_UTIMES (XSTRING (newname
)->data
, atime
, mtime
);
1635 if (!egetenv ("USE_DOMAIN_ACLS"))
1637 chmod (XSTRING (newname
)->data
, st
.st_mode
& 07777);
1640 /* Discard the unwind protects. */
1641 specpdl_ptr
= specpdl
+ count
;
1644 if (close (ofd
) < 0)
1645 report_file_error ("I/O error", Fcons (newname
, Qnil
));
1651 DEFUN ("make-directory-internal", Fmake_directory_internal
,
1652 Smake_directory_internal
, 1, 1, 0,
1653 "Create a directory. One argument, a file name string.")
1655 Lisp_Object dirname
;
1658 Lisp_Object handler
;
1660 CHECK_STRING (dirname
, 0);
1661 dirname
= Fexpand_file_name (dirname
, Qnil
);
1663 handler
= Ffind_file_name_handler (dirname
);
1664 if (!NILP (handler
))
1665 return call3 (handler
, Qmake_directory
, dirname
, Qnil
);
1667 dir
= XSTRING (dirname
)->data
;
1669 if (mkdir (dir
, 0777) != 0)
1670 report_file_error ("Creating directory", Flist (1, &dirname
));
1675 DEFUN ("delete-directory", Fdelete_directory
, Sdelete_directory
, 1, 1, "FDelete directory: ",
1676 "Delete a directory. One argument, a file name string.")
1678 Lisp_Object dirname
;
1681 Lisp_Object handler
;
1683 CHECK_STRING (dirname
, 0);
1684 dirname
= Fexpand_file_name (dirname
, Qnil
);
1685 dir
= XSTRING (dirname
)->data
;
1687 handler
= Ffind_file_name_handler (dirname
);
1688 if (!NILP (handler
))
1689 return call2 (handler
, Qdelete_directory
, dirname
);
1691 if (rmdir (dir
) != 0)
1692 report_file_error ("Removing directory", Flist (1, &dirname
));
1697 DEFUN ("delete-file", Fdelete_file
, Sdelete_file
, 1, 1, "fDelete file: ",
1698 "Delete specified file. One argument, a file name string.\n\
1699 If file has multiple names, it continues to exist with the other names.")
1701 Lisp_Object filename
;
1703 Lisp_Object handler
;
1704 CHECK_STRING (filename
, 0);
1705 filename
= Fexpand_file_name (filename
, Qnil
);
1707 handler
= Ffind_file_name_handler (filename
);
1708 if (!NILP (handler
))
1709 return call2 (handler
, Qdelete_file
, filename
);
1711 if (0 > unlink (XSTRING (filename
)->data
))
1712 report_file_error ("Removing old name", Flist (1, &filename
));
1716 DEFUN ("rename-file", Frename_file
, Srename_file
, 2, 3,
1717 "fRename file: \nFRename %s to file: \np",
1718 "Rename FILE as NEWNAME. Both args strings.\n\
1719 If file has names other than FILE, it continues to have those names.\n\
1720 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1721 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1722 A number as third arg means request confirmation if NEWNAME already exists.\n\
1723 This is what happens in interactive use with M-x.")
1724 (filename
, newname
, ok_if_already_exists
)
1725 Lisp_Object filename
, newname
, ok_if_already_exists
;
1728 Lisp_Object args
[2];
1730 Lisp_Object handler
;
1731 struct gcpro gcpro1
, gcpro2
;
1733 GCPRO2 (filename
, newname
);
1734 CHECK_STRING (filename
, 0);
1735 CHECK_STRING (newname
, 1);
1736 filename
= Fexpand_file_name (filename
, Qnil
);
1737 newname
= Fexpand_file_name (newname
, Qnil
);
1739 /* If the file name has special constructs in it,
1740 call the corresponding file handler. */
1741 handler
= Ffind_file_name_handler (filename
);
1742 if (!NILP (handler
))
1743 return call3 (handler
, Qrename_file
, filename
, newname
);
1745 if (NILP (ok_if_already_exists
)
1746 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1747 barf_or_query_if_file_exists (newname
, "rename to it",
1748 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1750 if (0 > rename (XSTRING (filename
)->data
, XSTRING (newname
)->data
))
1752 if (0 > link (XSTRING (filename
)->data
, XSTRING (newname
)->data
)
1753 || 0 > unlink (XSTRING (filename
)->data
))
1758 Fcopy_file (filename
, newname
, ok_if_already_exists
, Qt
);
1759 Fdelete_file (filename
);
1766 report_file_error ("Renaming", Flist (2, args
));
1769 report_file_error ("Renaming", Flist (2, &filename
));
1776 DEFUN ("add-name-to-file", Fadd_name_to_file
, Sadd_name_to_file
, 2, 3,
1777 "fAdd name to file: \nFName to add to %s: \np",
1778 "Give FILE additional name NEWNAME. Both args strings.\n\
1779 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1780 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1781 A number as third arg means request confirmation if NEWNAME already exists.\n\
1782 This is what happens in interactive use with M-x.")
1783 (filename
, newname
, ok_if_already_exists
)
1784 Lisp_Object filename
, newname
, ok_if_already_exists
;
1787 Lisp_Object args
[2];
1789 Lisp_Object handler
;
1790 struct gcpro gcpro1
, gcpro2
;
1792 GCPRO2 (filename
, newname
);
1793 CHECK_STRING (filename
, 0);
1794 CHECK_STRING (newname
, 1);
1795 filename
= Fexpand_file_name (filename
, Qnil
);
1796 newname
= Fexpand_file_name (newname
, Qnil
);
1798 /* If the file name has special constructs in it,
1799 call the corresponding file handler. */
1800 handler
= Ffind_file_name_handler (filename
);
1801 if (!NILP (handler
))
1802 return call3 (handler
, Qadd_name_to_file
, filename
, newname
);
1804 if (NILP (ok_if_already_exists
)
1805 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1806 barf_or_query_if_file_exists (newname
, "make it a new name",
1807 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1808 unlink (XSTRING (newname
)->data
);
1809 if (0 > link (XSTRING (filename
)->data
, XSTRING (newname
)->data
))
1814 report_file_error ("Adding new name", Flist (2, args
));
1816 report_file_error ("Adding new name", Flist (2, &filename
));
1825 DEFUN ("make-symbolic-link", Fmake_symbolic_link
, Smake_symbolic_link
, 2, 3,
1826 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
1827 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
1828 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1829 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1830 A number as third arg means request confirmation if NEWNAME already exists.\n\
1831 This happens for interactive use with M-x.")
1832 (filename
, linkname
, ok_if_already_exists
)
1833 Lisp_Object filename
, linkname
, ok_if_already_exists
;
1836 Lisp_Object args
[2];
1838 Lisp_Object handler
;
1839 struct gcpro gcpro1
, gcpro2
;
1841 GCPRO2 (filename
, linkname
);
1842 CHECK_STRING (filename
, 0);
1843 CHECK_STRING (linkname
, 1);
1844 #if 0 /* This made it impossible to make a link to a relative name. */
1845 filename
= Fexpand_file_name (filename
, Qnil
);
1847 linkname
= Fexpand_file_name (linkname
, Qnil
);
1849 /* If the file name has special constructs in it,
1850 call the corresponding file handler. */
1851 handler
= Ffind_file_name_handler (filename
);
1852 if (!NILP (handler
))
1853 return call3 (handler
, Qmake_symbolic_link
, filename
, linkname
);
1855 if (NILP (ok_if_already_exists
)
1856 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1857 barf_or_query_if_file_exists (linkname
, "make it a link",
1858 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1859 if (0 > symlink (XSTRING (filename
)->data
, XSTRING (linkname
)->data
))
1861 /* If we didn't complain already, silently delete existing file. */
1862 if (errno
== EEXIST
)
1864 unlink (XSTRING (filename
)->data
);
1865 if (0 <= symlink (XSTRING (filename
)->data
, XSTRING (linkname
)->data
))
1872 report_file_error ("Making symbolic link", Flist (2, args
));
1874 report_file_error ("Making symbolic link", Flist (2, &filename
));
1880 #endif /* S_IFLNK */
1884 DEFUN ("define-logical-name", Fdefine_logical_name
, Sdefine_logical_name
,
1885 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
1886 "Define the job-wide logical name NAME to have the value STRING.\n\
1887 If STRING is nil or a null string, the logical name NAME is deleted.")
1889 Lisp_Object varname
;
1892 CHECK_STRING (varname
, 0);
1894 delete_logical_name (XSTRING (varname
)->data
);
1897 CHECK_STRING (string
, 1);
1899 if (XSTRING (string
)->size
== 0)
1900 delete_logical_name (XSTRING (varname
)->data
);
1902 define_logical_name (XSTRING (varname
)->data
, XSTRING (string
)->data
);
1911 DEFUN ("sysnetunam", Fsysnetunam
, Ssysnetunam
, 2, 2, 0,
1912 "Open a network connection to PATH using LOGIN as the login string.")
1914 Lisp_Object path
, login
;
1918 CHECK_STRING (path
, 0);
1919 CHECK_STRING (login
, 0);
1921 netresult
= netunam (XSTRING (path
)->data
, XSTRING (login
)->data
);
1923 if (netresult
== -1)
1928 #endif /* HPUX_NET */
1930 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p
, Sfile_name_absolute_p
,
1932 "Return t if file FILENAME specifies an absolute path name.\n\
1933 On Unix, this is a name starting with a `/' or a `~'.")
1935 Lisp_Object filename
;
1939 CHECK_STRING (filename
, 0);
1940 ptr
= XSTRING (filename
)->data
;
1941 if (*ptr
== '/' || *ptr
== '~'
1943 /* ??? This criterion is probably wrong for '<'. */
1944 || index (ptr
, ':') || index (ptr
, '<')
1945 || (*ptr
== '[' && (ptr
[1] != '-' || (ptr
[2] != '.' && ptr
[2] != ']'))
1954 DEFUN ("file-exists-p", Ffile_exists_p
, Sfile_exists_p
, 1, 1, 0,
1955 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
1956 See also `file-readable-p' and `file-attributes'.")
1958 Lisp_Object filename
;
1960 Lisp_Object abspath
;
1961 Lisp_Object handler
;
1963 CHECK_STRING (filename
, 0);
1964 abspath
= Fexpand_file_name (filename
, Qnil
);
1966 /* If the file name has special constructs in it,
1967 call the corresponding file handler. */
1968 handler
= Ffind_file_name_handler (abspath
);
1969 if (!NILP (handler
))
1970 return call2 (handler
, Qfile_exists_p
, abspath
);
1972 return (access (XSTRING (abspath
)->data
, 0) >= 0) ? Qt
: Qnil
;
1975 DEFUN ("file-executable-p", Ffile_executable_p
, Sfile_executable_p
, 1, 1, 0,
1976 "Return t if FILENAME can be executed by you.\n\
1977 For a directory, this means you can access files in that directory.")
1979 Lisp_Object filename
;
1982 Lisp_Object abspath
;
1983 Lisp_Object handler
;
1985 CHECK_STRING (filename
, 0);
1986 abspath
= Fexpand_file_name (filename
, Qnil
);
1988 /* If the file name has special constructs in it,
1989 call the corresponding file handler. */
1990 handler
= Ffind_file_name_handler (abspath
);
1991 if (!NILP (handler
))
1992 return call2 (handler
, Qfile_executable_p
, abspath
);
1994 return (access (XSTRING (abspath
)->data
, 1) >= 0) ? Qt
: Qnil
;
1997 DEFUN ("file-readable-p", Ffile_readable_p
, Sfile_readable_p
, 1, 1, 0,
1998 "Return t if file FILENAME exists and you can read it.\n\
1999 See also `file-exists-p' and `file-attributes'.")
2001 Lisp_Object filename
;
2003 Lisp_Object abspath
;
2004 Lisp_Object handler
;
2006 CHECK_STRING (filename
, 0);
2007 abspath
= Fexpand_file_name (filename
, Qnil
);
2009 /* If the file name has special constructs in it,
2010 call the corresponding file handler. */
2011 handler
= Ffind_file_name_handler (abspath
);
2012 if (!NILP (handler
))
2013 return call2 (handler
, Qfile_readable_p
, abspath
);
2015 return (access (XSTRING (abspath
)->data
, 4) >= 0) ? Qt
: Qnil
;
2018 DEFUN ("file-symlink-p", Ffile_symlink_p
, Sfile_symlink_p
, 1, 1, 0,
2019 "If file FILENAME is the name of a symbolic link\n\
2020 returns the name of the file to which it is linked.\n\
2021 Otherwise returns NIL.")
2023 Lisp_Object filename
;
2030 Lisp_Object handler
;
2032 CHECK_STRING (filename
, 0);
2033 filename
= Fexpand_file_name (filename
, Qnil
);
2035 /* If the file name has special constructs in it,
2036 call the corresponding file handler. */
2037 handler
= Ffind_file_name_handler (filename
);
2038 if (!NILP (handler
))
2039 return call2 (handler
, Qfile_symlink_p
, filename
);
2044 buf
= (char *) xmalloc (bufsize
);
2045 bzero (buf
, bufsize
);
2046 valsize
= readlink (XSTRING (filename
)->data
, buf
, bufsize
);
2047 if (valsize
< bufsize
) break;
2048 /* Buffer was not long enough */
2057 val
= make_string (buf
, valsize
);
2060 #else /* not S_IFLNK */
2062 #endif /* not S_IFLNK */
2065 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2067 DEFUN ("file-writable-p", Ffile_writable_p
, Sfile_writable_p
, 1, 1, 0,
2068 "Return t if file FILENAME can be written or created by you.")
2070 Lisp_Object filename
;
2072 Lisp_Object abspath
, dir
;
2073 Lisp_Object handler
;
2075 CHECK_STRING (filename
, 0);
2076 abspath
= Fexpand_file_name (filename
, Qnil
);
2078 /* If the file name has special constructs in it,
2079 call the corresponding file handler. */
2080 handler
= Ffind_file_name_handler (abspath
);
2081 if (!NILP (handler
))
2082 return call2 (handler
, Qfile_writable_p
, abspath
);
2084 if (access (XSTRING (abspath
)->data
, 0) >= 0)
2085 return (access (XSTRING (abspath
)->data
, 2) >= 0) ? Qt
: Qnil
;
2086 dir
= Ffile_name_directory (abspath
);
2089 dir
= Fdirectory_file_name (dir
);
2091 return (access (!NILP (dir
) ? (char *) XSTRING (dir
)->data
: "", 2) >= 0
2095 DEFUN ("file-directory-p", Ffile_directory_p
, Sfile_directory_p
, 1, 1, 0,
2096 "Return t if file FILENAME is the name of a directory as a file.\n\
2097 A directory name spec may be given instead; then the value is t\n\
2098 if the directory so specified exists and really is a directory.")
2100 Lisp_Object filename
;
2102 register Lisp_Object abspath
;
2104 Lisp_Object handler
;
2106 abspath
= expand_and_dir_to_file (filename
, current_buffer
->directory
);
2108 /* If the file name has special constructs in it,
2109 call the corresponding file handler. */
2110 handler
= Ffind_file_name_handler (abspath
);
2111 if (!NILP (handler
))
2112 return call2 (handler
, Qfile_directory_p
, abspath
);
2114 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2116 return (st
.st_mode
& S_IFMT
) == S_IFDIR
? Qt
: Qnil
;
2119 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p
, Sfile_accessible_directory_p
, 1, 1, 0,
2120 "Return t if file FILENAME is the name of a directory as a file,\n\
2121 and files in that directory can be opened by you. In order to use a\n\
2122 directory as a buffer's current directory, this predicate must return true.\n\
2123 A directory name spec may be given instead; then the value is t\n\
2124 if the directory so specified exists and really is a readable and\n\
2125 searchable directory.")
2127 Lisp_Object filename
;
2129 Lisp_Object handler
;
2131 /* If the file name has special constructs in it,
2132 call the corresponding file handler. */
2133 handler
= Ffind_file_name_handler (filename
);
2134 if (!NILP (handler
))
2135 return call2 (handler
, Qfile_accessible_directory_p
, filename
);
2137 if (NILP (Ffile_directory_p (filename
))
2138 || NILP (Ffile_executable_p (filename
)))
2144 DEFUN ("file-modes", Ffile_modes
, Sfile_modes
, 1, 1, 0,
2145 "Return mode bits of FILE, as an integer.")
2147 Lisp_Object filename
;
2149 Lisp_Object abspath
;
2151 Lisp_Object handler
;
2153 abspath
= expand_and_dir_to_file (filename
, current_buffer
->directory
);
2155 /* If the file name has special constructs in it,
2156 call the corresponding file handler. */
2157 handler
= Ffind_file_name_handler (abspath
);
2158 if (!NILP (handler
))
2159 return call2 (handler
, Qfile_modes
, abspath
);
2161 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2163 return make_number (st
.st_mode
& 07777);
2166 DEFUN ("set-file-modes", Fset_file_modes
, Sset_file_modes
, 2, 2, 0,
2167 "Set mode bits of FILE to MODE (an integer).\n\
2168 Only the 12 low bits of MODE are used.")
2170 Lisp_Object filename
, mode
;
2172 Lisp_Object abspath
;
2173 Lisp_Object handler
;
2175 abspath
= Fexpand_file_name (filename
, current_buffer
->directory
);
2176 CHECK_NUMBER (mode
, 1);
2178 /* If the file name has special constructs in it,
2179 call the corresponding file handler. */
2180 handler
= Ffind_file_name_handler (abspath
);
2181 if (!NILP (handler
))
2182 return call3 (handler
, Qset_file_modes
, abspath
, mode
);
2185 if (chmod (XSTRING (abspath
)->data
, XINT (mode
)) < 0)
2186 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2188 if (!egetenv ("USE_DOMAIN_ACLS"))
2191 struct timeval tvp
[2];
2193 /* chmod on apollo also change the file's modtime; need to save the
2194 modtime and then restore it. */
2195 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2197 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2201 if (chmod (XSTRING (abspath
)->data
, XINT (mode
)) < 0)
2202 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2204 /* reset the old accessed and modified times. */
2205 tvp
[0].tv_sec
= st
.st_atime
+ 1; /* +1 due to an Apollo roundoff bug */
2207 tvp
[1].tv_sec
= st
.st_mtime
+ 1; /* +1 due to an Apollo roundoff bug */
2210 if (utimes (XSTRING (abspath
)->data
, tvp
) < 0)
2211 report_file_error ("Doing utimes", Fcons (abspath
, Qnil
));
2218 DEFUN ("set-default-file-modes", Fset_default_file_modes
, Sset_default_file_modes
, 1, 1, 0,
2219 "Set the file permission bits for newly created files.\n\
2220 The argument MODE should be an integer; only the low 9 bits are used.\n\
2221 This setting is inherited by subprocesses.")
2225 CHECK_NUMBER (mode
, 0);
2227 umask ((~ XINT (mode
)) & 0777);
2232 DEFUN ("default-file-modes", Fdefault_file_modes
, Sdefault_file_modes
, 0, 0, 0,
2233 "Return the default file protection for created files.\n\
2234 The value is an integer.")
2240 realmask
= umask (0);
2243 XSET (value
, Lisp_Int
, (~ realmask
) & 0777);
2249 DEFUN ("unix-sync", Funix_sync
, Sunix_sync
, 0, 0, "",
2250 "Tell Unix to finish all pending disk updates.")
2259 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p
, Sfile_newer_than_file_p
, 2, 2, 0,
2260 "Return t if file FILE1 is newer than file FILE2.\n\
2261 If FILE1 does not exist, the answer is nil;\n\
2262 otherwise, if FILE2 does not exist, the answer is t.")
2264 Lisp_Object file1
, file2
;
2266 Lisp_Object abspath1
, abspath2
;
2269 Lisp_Object handler
;
2270 struct gcpro gcpro1
, gcpro2
;
2272 CHECK_STRING (file1
, 0);
2273 CHECK_STRING (file2
, 0);
2276 GCPRO2 (abspath1
, file2
);
2277 abspath1
= expand_and_dir_to_file (file1
, current_buffer
->directory
);
2278 abspath2
= expand_and_dir_to_file (file2
, current_buffer
->directory
);
2281 /* If the file name has special constructs in it,
2282 call the corresponding file handler. */
2283 handler
= Ffind_file_name_handler (abspath1
);
2284 if (!NILP (handler
))
2285 return call3 (handler
, Qfile_newer_than_file_p
, abspath1
, abspath2
);
2287 if (stat (XSTRING (abspath1
)->data
, &st
) < 0)
2290 mtime1
= st
.st_mtime
;
2292 if (stat (XSTRING (abspath2
)->data
, &st
) < 0)
2295 return (mtime1
> st
.st_mtime
) ? Qt
: Qnil
;
2298 DEFUN ("insert-file-contents", Finsert_file_contents
, Sinsert_file_contents
,
2300 "Insert contents of file FILENAME after point.\n\
2301 Returns list of absolute pathname and length of data inserted.\n\
2302 If second argument VISIT is non-nil, the buffer's visited filename\n\
2303 and last save file modtime are set, and it is marked unmodified.\n\
2304 If visiting and the file does not exist, visiting is completed\n\
2305 before the error is signaled.")
2307 Lisp_Object filename
, visit
;
2311 register int inserted
= 0;
2312 register int how_much
;
2313 int count
= specpdl_ptr
- specpdl
;
2314 struct gcpro gcpro1
;
2315 Lisp_Object handler
, val
;
2320 if (!NILP (current_buffer
->read_only
))
2321 Fbarf_if_buffer_read_only();
2323 CHECK_STRING (filename
, 0);
2324 filename
= Fexpand_file_name (filename
, Qnil
);
2326 /* If the file name has special constructs in it,
2327 call the corresponding file handler. */
2328 handler
= Ffind_file_name_handler (filename
);
2329 if (!NILP (handler
))
2331 val
= call3 (handler
, Qinsert_file_contents
, filename
, visit
);
2339 if (stat (XSTRING (filename
)->data
, &st
) < 0
2340 || (fd
= open (XSTRING (filename
)->data
, 0)) < 0)
2342 if ((fd
= open (XSTRING (filename
)->data
, 0)) < 0
2343 || fstat (fd
, &st
) < 0)
2344 #endif /* not APOLLO */
2346 if (fd
>= 0) close (fd
);
2348 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
2354 record_unwind_protect (close_file_unwind
, make_number (fd
));
2357 /* This code will need to be changed in order to work on named
2358 pipes, and it's probably just not worth it. So we should at
2359 least signal an error. */
2360 if ((st
.st_mode
& S_IFMT
) == S_IFSOCK
)
2361 Fsignal (Qfile_error
,
2362 Fcons (build_string ("reading from named pipe"),
2363 Fcons (filename
, Qnil
)));
2366 /* Supposedly happens on VMS. */
2368 error ("File size is negative");
2371 register Lisp_Object temp
;
2373 /* Make sure point-max won't overflow after this insertion. */
2374 XSET (temp
, Lisp_Int
, st
.st_size
+ Z
);
2375 if (st
.st_size
+ Z
!= XINT (temp
))
2376 error ("maximum buffer size exceeded");
2380 prepare_to_modify_buffer (point
, point
);
2383 if (GAP_SIZE
< st
.st_size
)
2384 make_gap (st
.st_size
- GAP_SIZE
);
2388 int try = min (st
.st_size
- inserted
, 64 << 10);
2391 /* Allow quitting out of the actual I/O. */
2394 this = read (fd
, &FETCH_CHAR (point
+ inserted
- 1) + 1, try);
2412 record_insert (point
, inserted
);
2414 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2415 offset_intervals (current_buffer
, point
, inserted
);
2421 /* Discard the unwind protect */
2422 specpdl_ptr
= specpdl
+ count
;
2425 error ("IO error reading %s: %s",
2426 XSTRING (filename
)->data
, err_str (errno
));
2433 current_buffer
->undo_list
= Qnil
;
2435 stat (XSTRING (filename
)->data
, &st
);
2437 current_buffer
->modtime
= st
.st_mtime
;
2438 current_buffer
->save_modified
= MODIFF
;
2439 current_buffer
->auto_save_modified
= MODIFF
;
2440 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2441 #ifdef CLASH_DETECTION
2444 if (!NILP (current_buffer
->filename
))
2445 unlock_file (current_buffer
->filename
);
2446 unlock_file (filename
);
2448 #endif /* CLASH_DETECTION */
2449 current_buffer
->filename
= filename
;
2450 /* If visiting nonexistent file, return nil. */
2451 if (current_buffer
->modtime
== -1)
2452 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
2455 signal_after_change (point
, 0, inserted
);
2458 RETURN_UNGCPRO (val
);
2459 RETURN_UNGCPRO (Fcons (filename
,
2460 Fcons (make_number (inserted
),
2464 DEFUN ("write-region", Fwrite_region
, Swrite_region
, 3, 5,
2465 "r\nFWrite region to file: ",
2466 "Write current region into specified file.\n\
2467 When called from a program, takes three arguments:\n\
2468 START, END and FILENAME. START and END are buffer positions.\n\
2469 Optional fourth argument APPEND if non-nil means\n\
2470 append to existing file contents (if any).\n\
2471 Optional fifth argument VISIT if t means\n\
2472 set the last-save-file-modtime of buffer to this file's modtime\n\
2473 and mark buffer not modified.\n\
2474 If VISIT is a string, it is a second file name;\n\
2475 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
2476 VISIT is also the file name to lock and unlock for clash detection.\n\
2477 If VISIT is neither t nor nil nor a string,\n\
2478 that means do not print the \"Wrote file\" message.\n\
2479 Kludgy feature: if START is a string, then that string is written\n\
2480 to the file, instead of any buffer contents, and END is ignored.")
2481 (start
, end
, filename
, append
, visit
)
2482 Lisp_Object start
, end
, filename
, append
, visit
;
2490 int count
= specpdl_ptr
- specpdl
;
2492 unsigned char *fname
= 0; /* If non-0, original filename (must rename) */
2494 Lisp_Object handler
;
2495 Lisp_Object visit_file
;
2496 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
2498 /* Special kludge to simplify auto-saving */
2501 XFASTINT (start
) = BEG
;
2504 else if (XTYPE (start
) != Lisp_String
)
2505 validate_region (&start
, &end
);
2507 filename
= Fexpand_file_name (filename
, Qnil
);
2508 if (XTYPE (visit
) == Lisp_String
)
2509 visit
= Fexpand_file_name (visit
, Qnil
);
2511 visit_file
= filename
;
2513 GCPRO4 (start
, filename
, visit
, visit_file
);
2515 /* If the file name has special constructs in it,
2516 call the corresponding file handler. */
2517 handler
= Ffind_file_name_handler (filename
);
2519 if (!NILP (handler
))
2521 Lisp_Object args
[7];
2524 args
[1] = Qwrite_region
;
2530 val
= Ffuncall (7, args
);
2532 /* Do this before reporting IO error
2533 to avoid a "file has changed on disk" warning on
2534 next attempt to save. */
2535 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2537 current_buffer
->modtime
= 0;
2538 current_buffer
->save_modified
= MODIFF
;
2539 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2540 current_buffer
->filename
= visit_file
;
2546 #ifdef CLASH_DETECTION
2548 lock_file (visit_file
);
2549 #endif /* CLASH_DETECTION */
2551 fn
= XSTRING (filename
)->data
;
2554 desc
= open (fn
, O_WRONLY
);
2558 if (auto_saving
) /* Overwrite any previous version of autosave file */
2560 vms_truncate (fn
); /* if fn exists, truncate to zero length */
2561 desc
= open (fn
, O_RDWR
);
2563 desc
= creat_copy_attrs (XTYPE (current_buffer
->filename
) == Lisp_String
2564 ? XSTRING (current_buffer
->filename
)->data
: 0,
2567 else /* Write to temporary name and rename if no errors */
2569 Lisp_Object temp_name
;
2570 temp_name
= Ffile_name_directory (filename
);
2572 if (!NILP (temp_name
))
2574 temp_name
= Fmake_temp_name (concat2 (temp_name
,
2575 build_string ("$$SAVE$$")));
2576 fname
= XSTRING (filename
)->data
;
2577 fn
= XSTRING (temp_name
)->data
;
2578 desc
= creat_copy_attrs (fname
, fn
);
2581 /* If we can't open the temporary file, try creating a new
2582 version of the original file. VMS "creat" creates a
2583 new version rather than truncating an existing file. */
2586 desc
= creat (fn
, 0666);
2587 #if 0 /* This can clobber an existing file and fail to replace it,
2588 if the user runs out of space. */
2591 /* We can't make a new version;
2592 try to truncate and rewrite existing version if any. */
2594 desc
= open (fn
, O_RDWR
);
2600 desc
= creat (fn
, 0666);
2603 desc
= creat (fn
, auto_saving
? auto_save_mode_bits
: 0666);
2604 #endif /* not VMS */
2610 #ifdef CLASH_DETECTION
2612 if (!auto_saving
) unlock_file (visit_file
);
2614 #endif /* CLASH_DETECTION */
2615 report_file_error ("Opening output file", Fcons (filename
, Qnil
));
2618 record_unwind_protect (close_file_unwind
, make_number (desc
));
2621 if (lseek (desc
, 0, 2) < 0)
2623 #ifdef CLASH_DETECTION
2624 if (!auto_saving
) unlock_file (visit_file
);
2625 #endif /* CLASH_DETECTION */
2626 report_file_error ("Lseek error", Fcons (filename
, Qnil
));
2631 * Kludge Warning: The VMS C RTL likes to insert carriage returns
2632 * if we do writes that don't end with a carriage return. Furthermore
2633 * it cannot handle writes of more then 16K. The modified
2634 * version of "sys_write" in SYSDEP.C (see comment there) copes with
2635 * this EXCEPT for the last record (iff it doesn't end with a carriage
2636 * return). This implies that if your buffer doesn't end with a carriage
2637 * return, you get one free... tough. However it also means that if
2638 * we make two calls to sys_write (a la the following code) you can
2639 * get one at the gap as well. The easiest way to fix this (honest)
2640 * is to move the gap to the next newline (or the end of the buffer).
2645 if (GPT
> BEG
&& GPT_ADDR
[-1] != '\n')
2646 move_gap (find_next_newline (GPT
, 1));
2652 if (XTYPE (start
) == Lisp_String
)
2654 failure
= 0 > e_write (desc
, XSTRING (start
)->data
,
2655 XSTRING (start
)->size
);
2658 else if (XINT (start
) != XINT (end
))
2660 if (XINT (start
) < GPT
)
2662 register int end1
= XINT (end
);
2664 failure
= 0 > e_write (desc
, &FETCH_CHAR (tem
),
2665 min (GPT
, end1
) - tem
);
2669 if (XINT (end
) > GPT
&& !failure
)
2672 tem
= max (tem
, GPT
);
2673 failure
= 0 > e_write (desc
, &FETCH_CHAR (tem
), XINT (end
) - tem
);
2681 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
2682 Disk full in NFS may be reported here. */
2683 if (fsync (desc
) < 0)
2684 failure
= 1, save_errno
= errno
;
2687 /* Spurious "file has changed on disk" warnings have been
2688 observed on Suns as well.
2689 It seems that `close' can change the modtime, under nfs.
2691 (This has supposedly been fixed in Sunos 4,
2692 but who knows about all the other machines with NFS?) */
2695 /* On VMS and APOLLO, must do the stat after the close
2696 since closing changes the modtime. */
2699 /* Recall that #if defined does not work on VMS. */
2706 /* NFS can report a write failure now. */
2707 if (close (desc
) < 0)
2708 failure
= 1, save_errno
= errno
;
2711 /* If we wrote to a temporary name and had no errors, rename to real name. */
2715 failure
= (rename (fn
, fname
) != 0), save_errno
= errno
;
2723 /* Discard the unwind protect */
2724 specpdl_ptr
= specpdl
+ count
;
2726 #ifdef CLASH_DETECTION
2728 unlock_file (visit_file
);
2729 #endif /* CLASH_DETECTION */
2731 /* Do this before reporting IO error
2732 to avoid a "file has changed on disk" warning on
2733 next attempt to save. */
2734 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2735 current_buffer
->modtime
= st
.st_mtime
;
2738 error ("IO error writing %s: %s", fn
, err_str (save_errno
));
2740 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2742 current_buffer
->save_modified
= MODIFF
;
2743 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2744 current_buffer
->filename
= visit_file
;
2746 else if (!NILP (visit
))
2750 message ("Wrote %s", XSTRING (visit_file
)->data
);
2756 e_write (desc
, addr
, len
)
2758 register char *addr
;
2761 char buf
[16 * 1024];
2762 register char *p
, *end
;
2764 if (!EQ (current_buffer
->selective_display
, Qt
))
2765 return write (desc
, addr
, len
) - len
;
2769 end
= p
+ sizeof buf
;
2774 if (write (desc
, buf
, sizeof buf
) != sizeof buf
)
2783 if (write (desc
, buf
, p
- buf
) != p
- buf
)
2789 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime
,
2790 Sverify_visited_file_modtime
, 1, 1, 0,
2791 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
2792 This means that the file has not been changed since it was visited or saved.")
2798 Lisp_Object handler
;
2800 CHECK_BUFFER (buf
, 0);
2803 if (XTYPE (b
->filename
) != Lisp_String
) return Qt
;
2804 if (b
->modtime
== 0) return Qt
;
2806 /* If the file name has special constructs in it,
2807 call the corresponding file handler. */
2808 handler
= Ffind_file_name_handler (b
->filename
);
2809 if (!NILP (handler
))
2810 return call2 (handler
, Qverify_visited_file_modtime
, buf
);
2812 if (stat (XSTRING (b
->filename
)->data
, &st
) < 0)
2814 /* If the file doesn't exist now and didn't exist before,
2815 we say that it isn't modified, provided the error is a tame one. */
2816 if (errno
== ENOENT
|| errno
== EACCES
|| errno
== ENOTDIR
)
2821 if (st
.st_mtime
== b
->modtime
2822 /* If both are positive, accept them if they are off by one second. */
2823 || (st
.st_mtime
> 0 && b
->modtime
> 0
2824 && (st
.st_mtime
== b
->modtime
+ 1
2825 || st
.st_mtime
== b
->modtime
- 1)))
2830 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime
,
2831 Sclear_visited_file_modtime
, 0, 0, 0,
2832 "Clear out records of last mod time of visited file.\n\
2833 Next attempt to save will certainly not complain of a discrepancy.")
2836 current_buffer
->modtime
= 0;
2840 DEFUN ("visited-file-modtime", Fvisited_file_modtime
,
2841 Svisited_file_modtime
, 0, 0, 0,
2842 "Return the current buffer's recorded visited file modification time.\n\
2843 The value is a list of the form (HIGH . LOW), like the time values\n\
2844 that `file-attributes' returns.")
2847 return long_to_cons (current_buffer
->modtime
);
2850 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime
,
2851 Sset_visited_file_modtime
, 0, 1, 0,
2852 "Update buffer's recorded modification time from the visited file's time.\n\
2853 Useful if the buffer was not read from the file normally\n\
2854 or if the file itself has been changed for some known benign reason.\n\
2855 An argument specifies the modification time value to use\n\
2856 \(instead of that of the visited file), in the form of a list\n\
2857 \(HIGH . LOW) or (HIGH LOW).")
2859 Lisp_Object time_list
;
2861 if (!NILP (time_list
))
2862 current_buffer
->modtime
= cons_to_long (time_list
);
2865 register Lisp_Object filename
;
2867 Lisp_Object handler
;
2869 filename
= Fexpand_file_name (current_buffer
->filename
, Qnil
);
2871 /* If the file name has special constructs in it,
2872 call the corresponding file handler. */
2873 handler
= Ffind_file_name_handler (filename
);
2874 if (!NILP (handler
))
2875 return call3 (handler
, Qfile_name_directory
, filename
, Qnil
);
2876 else if (stat (XSTRING (filename
)->data
, &st
) >= 0)
2877 current_buffer
->modtime
= st
.st_mtime
;
2886 unsigned char *name
= XSTRING (current_buffer
->name
)->data
;
2889 message ("Autosaving...error for %s", name
);
2890 Fsleep_for (make_number (1), Qnil
);
2891 message ("Autosaving...error!for %s", name
);
2892 Fsleep_for (make_number (1), Qnil
);
2893 message ("Autosaving...error for %s", name
);
2894 Fsleep_for (make_number (1), Qnil
);
2904 /* Get visited file's mode to become the auto save file's mode. */
2905 if (stat (XSTRING (current_buffer
->filename
)->data
, &st
) >= 0)
2906 /* But make sure we can overwrite it later! */
2907 auto_save_mode_bits
= st
.st_mode
| 0600;
2909 auto_save_mode_bits
= 0666;
2912 Fwrite_region (Qnil
, Qnil
,
2913 current_buffer
->auto_save_file_name
,
2917 DEFUN ("do-auto-save", Fdo_auto_save
, Sdo_auto_save
, 0, 2, "",
2918 "Auto-save all buffers that need it.\n\
2919 This is all buffers that have auto-saving enabled\n\
2920 and are changed since last auto-saved.\n\
2921 Auto-saving writes the buffer into a file\n\
2922 so that your editing is not lost if the system crashes.\n\
2923 This file is not the file you visited; that changes only when you save.\n\n\
2924 Non-nil first argument means do not print any message if successful.\n\
2925 Non-nil second argument means save only current buffer.")
2926 (no_message
, current_only
)
2927 Lisp_Object no_message
, current_only
;
2929 struct buffer
*old
= current_buffer
, *b
;
2930 Lisp_Object tail
, buf
;
2932 char *omessage
= echo_area_glyphs
;
2933 extern int minibuf_level
;
2934 int do_handled_files
;
2936 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
2937 point to non-strings reached from Vbuffer_alist. */
2943 /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
2944 eventually call do-auto-save, so don't err here in that case. */
2945 if (!NILP (Vrun_hooks
))
2946 call1 (Vrun_hooks
, intern ("auto-save-hook"));
2948 /* First, save all files which don't have handlers. If Emacs is
2949 crashing, the handlers may tweak what is causing Emacs to crash
2950 in the first place, and it would be a shame if Emacs failed to
2951 autosave perfectly ordinary files because it couldn't handle some
2953 for (do_handled_files
= 0; do_handled_files
< 2; do_handled_files
++)
2954 for (tail
= Vbuffer_alist
; XGCTYPE (tail
) == Lisp_Cons
;
2955 tail
= XCONS (tail
)->cdr
)
2957 buf
= XCONS (XCONS (tail
)->car
)->cdr
;
2960 if (!NILP (current_only
)
2961 && b
!= current_buffer
)
2964 /* Check for auto save enabled
2965 and file changed since last auto save
2966 and file changed since last real save. */
2967 if (XTYPE (b
->auto_save_file_name
) == Lisp_String
2968 && b
->save_modified
< BUF_MODIFF (b
)
2969 && b
->auto_save_modified
< BUF_MODIFF (b
)
2970 && (do_handled_files
2971 || NILP (Ffind_file_name_handler (b
->auto_save_file_name
))))
2973 if ((XFASTINT (b
->save_length
) * 10
2974 > (BUF_Z (b
) - BUF_BEG (b
)) * 13)
2975 /* A short file is likely to change a large fraction;
2976 spare the user annoying messages. */
2977 && XFASTINT (b
->save_length
) > 5000
2978 /* These messages are frequent and annoying for `*mail*'. */
2979 && !EQ (b
->filename
, Qnil
)
2980 && NILP (no_message
))
2982 /* It has shrunk too much; turn off auto-saving here. */
2983 message ("Buffer %s has shrunk a lot; auto save turned off there",
2984 XSTRING (b
->name
)->data
);
2985 /* User can reenable saving with M-x auto-save. */
2986 b
->auto_save_file_name
= Qnil
;
2987 /* Prevent warning from repeating if user does so. */
2988 XFASTINT (b
->save_length
) = 0;
2989 Fsleep_for (make_number (1), Qnil
);
2992 set_buffer_internal (b
);
2993 if (!auto_saved
&& NILP (no_message
))
2994 message1 ("Auto-saving...");
2995 internal_condition_case (auto_save_1
, Qt
, auto_save_error
);
2997 b
->auto_save_modified
= BUF_MODIFF (b
);
2998 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2999 set_buffer_internal (old
);
3003 /* Prevent another auto save till enough input events come in. */
3004 record_auto_save ();
3006 if (auto_saved
&& NILP (no_message
))
3007 message1 (omessage
? omessage
: "Auto-saving...done");
3013 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved
,
3014 Sset_buffer_auto_saved
, 0, 0, 0,
3015 "Mark current buffer as auto-saved with its current text.\n\
3016 No auto-save file will be written until the buffer changes again.")
3019 current_buffer
->auto_save_modified
= MODIFF
;
3020 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
3024 DEFUN ("recent-auto-save-p", Frecent_auto_save_p
, Srecent_auto_save_p
,
3026 "Return t if buffer has been auto-saved since last read in or saved.")
3029 return (current_buffer
->save_modified
< current_buffer
->auto_save_modified
) ? Qt
: Qnil
;
3032 /* Reading and completing file names */
3033 extern Lisp_Object
Ffile_name_completion (), Ffile_name_all_completions ();
3035 DEFUN ("read-file-name-internal", Fread_file_name_internal
, Sread_file_name_internal
,
3037 "Internal subroutine for read-file-name. Do not call this.")
3038 (string
, dir
, action
)
3039 Lisp_Object string
, dir
, action
;
3040 /* action is nil for complete, t for return list of completions,
3041 lambda for verify final value */
3043 Lisp_Object name
, specdir
, realdir
, val
, orig_string
;
3045 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3052 /* No need to protect ACTION--we only compare it with t and nil. */
3053 GCPRO4 (string
, realdir
, name
, specdir
);
3055 if (XSTRING (string
)->size
== 0)
3057 if (EQ (action
, Qlambda
))
3065 orig_string
= string
;
3066 string
= Fsubstitute_in_file_name (string
);
3067 changed
= NILP (Fstring_equal (string
, orig_string
));
3068 name
= Ffile_name_nondirectory (string
);
3069 val
= Ffile_name_directory (string
);
3071 realdir
= Fexpand_file_name (val
, realdir
);
3076 specdir
= Ffile_name_directory (string
);
3077 val
= Ffile_name_completion (name
, realdir
);
3079 if (XTYPE (val
) != Lisp_String
)
3086 if (!NILP (specdir
))
3087 val
= concat2 (specdir
, val
);
3090 register unsigned char *old
, *new;
3094 osize
= XSTRING (val
)->size
;
3095 /* Quote "$" as "$$" to get it past substitute-in-file-name */
3096 for (n
= osize
, count
= 0, old
= XSTRING (val
)->data
; n
> 0; n
--)
3097 if (*old
++ == '$') count
++;
3100 old
= XSTRING (val
)->data
;
3101 val
= Fmake_string (make_number (osize
+ count
), make_number (0));
3102 new = XSTRING (val
)->data
;
3103 for (n
= osize
; n
> 0; n
--)
3114 #endif /* Not VMS */
3119 if (EQ (action
, Qt
))
3120 return Ffile_name_all_completions (name
, realdir
);
3121 /* Only other case actually used is ACTION = lambda */
3123 /* Supposedly this helps commands such as `cd' that read directory names,
3124 but can someone explain how it helps them? -- RMS */
3125 if (XSTRING (name
)->size
== 0)
3128 return Ffile_exists_p (string
);
3131 DEFUN ("read-file-name", Fread_file_name
, Sread_file_name
, 1, 5, 0,
3132 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3133 Value is not expanded---you must call `expand-file-name' yourself.\n\
3134 Default name to DEFAULT if user enters a null string.\n\
3135 (If DEFAULT is omitted, the visited file name is used.)\n\
3136 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3137 Non-nil and non-t means also require confirmation after completion.\n\
3138 Fifth arg INITIAL specifies text to start with.\n\
3139 DIR defaults to current buffer's directory default.")
3140 (prompt
, dir
, defalt
, mustmatch
, initial
)
3141 Lisp_Object prompt
, dir
, defalt
, mustmatch
, initial
;
3143 Lisp_Object val
, insdef
, insdef1
, tem
;
3144 struct gcpro gcpro1
, gcpro2
;
3145 register char *homedir
;
3149 dir
= current_buffer
->directory
;
3151 defalt
= current_buffer
->filename
;
3153 /* If dir starts with user's homedir, change that to ~. */
3154 homedir
= (char *) egetenv ("HOME");
3156 && XTYPE (dir
) == Lisp_String
3157 && !strncmp (homedir
, XSTRING (dir
)->data
, strlen (homedir
))
3158 && XSTRING (dir
)->data
[strlen (homedir
)] == '/')
3160 dir
= make_string (XSTRING (dir
)->data
+ strlen (homedir
) - 1,
3161 XSTRING (dir
)->size
- strlen (homedir
) + 1);
3162 XSTRING (dir
)->data
[0] = '~';
3165 if (insert_default_directory
)
3169 if (!NILP (initial
))
3171 Lisp_Object args
[2], pos
;
3175 insdef
= Fconcat (2, args
);
3176 pos
= make_number (XSTRING (dir
)->size
);
3177 insdef1
= Fcons (insdef
, pos
);
3181 insdef
= Qnil
, insdef1
= Qnil
;
3184 count
= specpdl_ptr
- specpdl
;
3185 specbind (intern ("completion-ignore-case"), Qt
);
3188 GCPRO2 (insdef
, defalt
);
3189 val
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
3190 dir
, mustmatch
, insdef1
,
3191 Qfile_name_history
);
3194 unbind_to (count
, Qnil
);
3199 error ("No file name specified");
3200 tem
= Fstring_equal (val
, insdef
);
3201 if (!NILP (tem
) && !NILP (defalt
))
3203 return Fsubstitute_in_file_name (val
);
3206 #if 0 /* Old version */
3207 DEFUN ("read-file-name", Fread_file_name
, Sread_file_name
, 1, 5, 0,
3208 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3209 Value is not expanded---you must call `expand-file-name' yourself.\n\
3210 Default name to DEFAULT if user enters a null string.\n\
3211 (If DEFAULT is omitted, the visited file name is used.)\n\
3212 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3213 Non-nil and non-t means also require confirmation after completion.\n\
3214 Fifth arg INITIAL specifies text to start with.\n\
3215 DIR defaults to current buffer's directory default.")
3216 (prompt
, dir
, defalt
, mustmatch
, initial
)
3217 Lisp_Object prompt
, dir
, defalt
, mustmatch
, initial
;
3219 Lisp_Object val
, insdef
, tem
;
3220 struct gcpro gcpro1
, gcpro2
;
3221 register char *homedir
;
3225 dir
= current_buffer
->directory
;
3227 defalt
= current_buffer
->filename
;
3229 /* If dir starts with user's homedir, change that to ~. */
3230 homedir
= (char *) egetenv ("HOME");
3232 && XTYPE (dir
) == Lisp_String
3233 && !strncmp (homedir
, XSTRING (dir
)->data
, strlen (homedir
))
3234 && XSTRING (dir
)->data
[strlen (homedir
)] == '/')
3236 dir
= make_string (XSTRING (dir
)->data
+ strlen (homedir
) - 1,
3237 XSTRING (dir
)->size
- strlen (homedir
) + 1);
3238 XSTRING (dir
)->data
[0] = '~';
3241 if (!NILP (initial
))
3243 else if (insert_default_directory
)
3246 insdef
= build_string ("");
3249 count
= specpdl_ptr
- specpdl
;
3250 specbind (intern ("completion-ignore-case"), Qt
);
3253 GCPRO2 (insdef
, defalt
);
3254 val
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
3256 insert_default_directory
? insdef
: Qnil
,
3257 Qfile_name_history
);
3260 unbind_to (count
, Qnil
);
3265 error ("No file name specified");
3266 tem
= Fstring_equal (val
, insdef
);
3267 if (!NILP (tem
) && !NILP (defalt
))
3269 return Fsubstitute_in_file_name (val
);
3271 #endif /* Old version */
3275 Qexpand_file_name
= intern ("expand-file-name");
3276 Qdirectory_file_name
= intern ("directory-file-name");
3277 Qfile_name_directory
= intern ("file-name-directory");
3278 Qfile_name_nondirectory
= intern ("file-name-nondirectory");
3279 Qunhandled_file_name_directory
= intern ("unhandled-file-name-directory");
3280 Qfile_name_as_directory
= intern ("file-name-as-directory");
3281 Qcopy_file
= intern ("copy-file");
3282 Qmake_directory
= intern ("make-directory");
3283 Qdelete_directory
= intern ("delete-directory");
3284 Qdelete_file
= intern ("delete-file");
3285 Qrename_file
= intern ("rename-file");
3286 Qadd_name_to_file
= intern ("add-name-to-file");
3287 Qmake_symbolic_link
= intern ("make-symbolic-link");
3288 Qfile_exists_p
= intern ("file-exists-p");
3289 Qfile_executable_p
= intern ("file-executable-p");
3290 Qfile_readable_p
= intern ("file-readable-p");
3291 Qfile_symlink_p
= intern ("file-symlink-p");
3292 Qfile_writable_p
= intern ("file-writable-p");
3293 Qfile_directory_p
= intern ("file-directory-p");
3294 Qfile_accessible_directory_p
= intern ("file-accessible-directory-p");
3295 Qfile_modes
= intern ("file-modes");
3296 Qset_file_modes
= intern ("set-file-modes");
3297 Qfile_newer_than_file_p
= intern ("file-newer-than-file-p");
3298 Qinsert_file_contents
= intern ("insert-file-contents");
3299 Qwrite_region
= intern ("write-region");
3300 Qverify_visited_file_modtime
= intern ("verify-visited-file-modtime");
3302 staticpro (&Qexpand_file_name
);
3303 staticpro (&Qdirectory_file_name
);
3304 staticpro (&Qfile_name_directory
);
3305 staticpro (&Qfile_name_nondirectory
);
3306 staticpro (&Qunhandled_file_name_directory
);
3307 staticpro (&Qfile_name_as_directory
);
3308 staticpro (&Qcopy_file
);
3309 staticpro (&Qmake_directory
);
3310 staticpro (&Qdelete_directory
);
3311 staticpro (&Qdelete_file
);
3312 staticpro (&Qrename_file
);
3313 staticpro (&Qadd_name_to_file
);
3314 staticpro (&Qmake_symbolic_link
);
3315 staticpro (&Qfile_exists_p
);
3316 staticpro (&Qfile_executable_p
);
3317 staticpro (&Qfile_readable_p
);
3318 staticpro (&Qfile_symlink_p
);
3319 staticpro (&Qfile_writable_p
);
3320 staticpro (&Qfile_directory_p
);
3321 staticpro (&Qfile_accessible_directory_p
);
3322 staticpro (&Qfile_modes
);
3323 staticpro (&Qset_file_modes
);
3324 staticpro (&Qfile_newer_than_file_p
);
3325 staticpro (&Qinsert_file_contents
);
3326 staticpro (&Qwrite_region
);
3327 staticpro (&Qverify_visited_file_modtime
);
3329 Qfile_name_history
= intern ("file-name-history");
3330 Fset (Qfile_name_history
, Qnil
);
3331 staticpro (&Qfile_name_history
);
3333 Qfile_error
= intern ("file-error");
3334 staticpro (&Qfile_error
);
3335 Qfile_already_exists
= intern("file-already-exists");
3336 staticpro (&Qfile_already_exists
);
3338 Fput (Qfile_error
, Qerror_conditions
,
3339 Fcons (Qfile_error
, Fcons (Qerror
, Qnil
)));
3340 Fput (Qfile_error
, Qerror_message
,
3341 build_string ("File error"));
3343 Fput (Qfile_already_exists
, Qerror_conditions
,
3344 Fcons (Qfile_already_exists
,
3345 Fcons (Qfile_error
, Fcons (Qerror
, Qnil
))));
3346 Fput (Qfile_already_exists
, Qerror_message
,
3347 build_string ("File already exists"));
3349 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory
,
3350 "*Non-nil means when reading a filename start with default dir in minibuffer.");
3351 insert_default_directory
= 1;
3353 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm
,
3354 "*Non-nil means write new files with record format `stmlf'.\n\
3355 nil means use format `var'. This variable is meaningful only on VMS.");
3356 vms_stmlf_recfm
= 0;
3358 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist
,
3359 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
3360 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
3363 The first argument given to HANDLER is the name of the I/O primitive\n\
3364 to be handled; the remaining arguments are the arguments that were\n\
3365 passed to that primitive. For example, if you do\n\
3366 (file-exists-p FILENAME)\n\
3367 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
3368 (funcall HANDLER 'file-exists-p FILENAME)\n\
3369 The function `find-file-name-handler' checks this list for a handler\n\
3370 for its argument.");
3371 Vfile_name_handler_alist
= Qnil
;
3373 defsubr (&Sfind_file_name_handler
);
3374 defsubr (&Sfile_name_directory
);
3375 defsubr (&Sfile_name_nondirectory
);
3376 defsubr (&Sunhandled_file_name_directory
);
3377 defsubr (&Sfile_name_as_directory
);
3378 defsubr (&Sdirectory_file_name
);
3379 defsubr (&Smake_temp_name
);
3380 defsubr (&Sexpand_file_name
);
3381 defsubr (&Ssubstitute_in_file_name
);
3382 defsubr (&Scopy_file
);
3383 defsubr (&Smake_directory_internal
);
3384 defsubr (&Sdelete_directory
);
3385 defsubr (&Sdelete_file
);
3386 defsubr (&Srename_file
);
3387 defsubr (&Sadd_name_to_file
);
3389 defsubr (&Smake_symbolic_link
);
3390 #endif /* S_IFLNK */
3392 defsubr (&Sdefine_logical_name
);
3395 defsubr (&Ssysnetunam
);
3396 #endif /* HPUX_NET */
3397 defsubr (&Sfile_name_absolute_p
);
3398 defsubr (&Sfile_exists_p
);
3399 defsubr (&Sfile_executable_p
);
3400 defsubr (&Sfile_readable_p
);
3401 defsubr (&Sfile_writable_p
);
3402 defsubr (&Sfile_symlink_p
);
3403 defsubr (&Sfile_directory_p
);
3404 defsubr (&Sfile_accessible_directory_p
);
3405 defsubr (&Sfile_modes
);
3406 defsubr (&Sset_file_modes
);
3407 defsubr (&Sset_default_file_modes
);
3408 defsubr (&Sdefault_file_modes
);
3409 defsubr (&Sfile_newer_than_file_p
);
3410 defsubr (&Sinsert_file_contents
);
3411 defsubr (&Swrite_region
);
3412 defsubr (&Sverify_visited_file_modtime
);
3413 defsubr (&Sclear_visited_file_modtime
);
3414 defsubr (&Svisited_file_modtime
);
3415 defsubr (&Sset_visited_file_modtime
);
3416 defsubr (&Sdo_auto_save
);
3417 defsubr (&Sset_buffer_auto_saved
);
3418 defsubr (&Srecent_auto_save_p
);
3420 defsubr (&Sread_file_name_internal
);
3421 defsubr (&Sread_file_name
);
3424 defsubr (&Sunix_sync
);