1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993 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"
89 #define min(a, b) ((a) < (b) ? (a) : (b))
90 #define max(a, b) ((a) > (b) ? (a) : (b))
92 /* Nonzero during writing of auto-save files */
95 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
96 a new file with the same mode as the original */
97 int auto_save_mode_bits
;
99 /* Alist of elements (REGEXP . HANDLER) for file names
100 whose I/O is done with a special handler. */
101 Lisp_Object Vfile_name_handler_alist
;
103 /* Nonzero means, when reading a filename in the minibuffer,
104 start out by inserting the default directory into the minibuffer. */
105 int insert_default_directory
;
107 /* On VMS, nonzero means write new files with record format stmlf.
108 Zero means use var format. */
111 Lisp_Object Qfile_error
, Qfile_already_exists
;
113 Lisp_Object Qfile_name_history
;
115 report_file_error (string
, data
)
119 Lisp_Object errstring
;
121 if (errno
>= 0 && errno
< sys_nerr
)
122 errstring
= build_string (sys_errlist
[errno
]);
124 errstring
= build_string ("undocumented error code");
126 /* System error messages are capitalized. Downcase the initial
127 unless it is followed by a slash. */
128 if (XSTRING (errstring
)->data
[1] != '/')
129 XSTRING (errstring
)->data
[0] = DOWNCASE (XSTRING (errstring
)->data
[0]);
132 Fsignal (Qfile_error
,
133 Fcons (build_string (string
), Fcons (errstring
, data
)));
136 close_file_unwind (fd
)
139 close (XFASTINT (fd
));
142 Lisp_Object Qexpand_file_name
;
143 Lisp_Object Qdirectory_file_name
;
144 Lisp_Object Qfile_name_directory
;
145 Lisp_Object Qfile_name_nondirectory
;
146 Lisp_Object Qunhandled_file_name_directory
;
147 Lisp_Object Qfile_name_as_directory
;
148 Lisp_Object Qcopy_file
;
149 Lisp_Object Qmake_directory
;
150 Lisp_Object Qdelete_directory
;
151 Lisp_Object Qdelete_file
;
152 Lisp_Object Qrename_file
;
153 Lisp_Object Qadd_name_to_file
;
154 Lisp_Object Qmake_symbolic_link
;
155 Lisp_Object Qfile_exists_p
;
156 Lisp_Object Qfile_executable_p
;
157 Lisp_Object Qfile_readable_p
;
158 Lisp_Object Qfile_symlink_p
;
159 Lisp_Object Qfile_writable_p
;
160 Lisp_Object Qfile_directory_p
;
161 Lisp_Object Qfile_accessible_directory_p
;
162 Lisp_Object Qfile_modes
;
163 Lisp_Object Qset_file_modes
;
164 Lisp_Object Qfile_newer_than_file_p
;
165 Lisp_Object Qinsert_file_contents
;
166 Lisp_Object Qwrite_region
;
167 Lisp_Object Qverify_visited_file_modtime
;
169 DEFUN ("find-file-name-handler", Ffind_file_name_handler
, Sfind_file_name_handler
, 1, 1, 0,
170 "Return FILENAME's handler function, if its syntax is handled specially.\n\
171 Otherwise, return nil.\n\
172 A file name is handled if one of the regular expressions in\n\
173 `file-name-handler-alist' matches it.")
175 Lisp_Object filename
;
177 /* This function must not munge the match data. */
180 CHECK_STRING (filename
, 0);
182 for (chain
= Vfile_name_handler_alist
; XTYPE (chain
) == Lisp_Cons
;
183 chain
= XCONS (chain
)->cdr
)
186 elt
= XCONS (chain
)->car
;
187 if (XTYPE (elt
) == Lisp_Cons
)
190 string
= XCONS (elt
)->car
;
191 if (XTYPE (string
) == Lisp_String
192 && fast_string_match (string
, filename
) >= 0)
193 return XCONS (elt
)->cdr
;
201 DEFUN ("file-name-directory", Ffile_name_directory
, Sfile_name_directory
,
203 "Return the directory component in file name NAME.\n\
204 Return nil if NAME does not include a directory.\n\
205 Otherwise return a directory spec.\n\
206 Given a Unix syntax file name, returns a string ending in slash;\n\
207 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
211 register unsigned char *beg
;
212 register unsigned char *p
;
215 CHECK_STRING (file
, 0);
217 /* If the file name has special constructs in it,
218 call the corresponding file handler. */
219 handler
= Ffind_file_name_handler (file
);
221 return call2 (handler
, Qfile_name_directory
, file
);
223 beg
= XSTRING (file
)->data
;
224 p
= beg
+ XSTRING (file
)->size
;
226 while (p
!= beg
&& p
[-1] != '/'
228 && p
[-1] != ':' && p
[-1] != ']' && p
[-1] != '>'
234 return make_string (beg
, p
- beg
);
237 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory
, Sfile_name_nondirectory
,
239 "Return file name NAME sans its directory.\n\
240 For example, in a Unix-syntax file name,\n\
241 this is everything after the last slash,\n\
242 or the entire name if it contains no slash.")
246 register unsigned char *beg
, *p
, *end
;
249 CHECK_STRING (file
, 0);
251 /* If the file name has special constructs in it,
252 call the corresponding file handler. */
253 handler
= Ffind_file_name_handler (file
);
255 return call2 (handler
, Qfile_name_nondirectory
, file
);
257 beg
= XSTRING (file
)->data
;
258 end
= p
= beg
+ XSTRING (file
)->size
;
260 while (p
!= beg
&& p
[-1] != '/'
262 && p
[-1] != ':' && p
[-1] != ']' && p
[-1] != '>'
266 return make_string (p
, end
- p
);
269 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory
, Sunhandled_file_name_directory
, 1, 1, 0,
270 "Return a directly usable directory name somehow associated with FILENAME.\n\
271 A `directly usable' directory name is one that may be used without the\n\
272 intervention of any file handler.\n\
273 If FILENAME is a directly usable file itself, return\n\
274 (file-name-directory FILENAME).\n\
275 The `call-process' and `start-process' functions use this function to\n\
276 get a current directory to run processes in.")
278 Lisp_Object filename
;
282 /* If the file name has special constructs in it,
283 call the corresponding file handler. */
284 handler
= Ffind_file_name_handler (filename
);
286 return call2 (handler
, Qunhandled_file_name_directory
, filename
);
288 return Ffile_name_directory (filename
);
293 file_name_as_directory (out
, in
)
296 int size
= strlen (in
) - 1;
301 /* Is it already a directory string? */
302 if (in
[size
] == ':' || in
[size
] == ']' || in
[size
] == '>')
304 /* Is it a VMS directory file name? If so, hack VMS syntax. */
305 else if (! index (in
, '/')
306 && ((size
> 3 && ! strcmp (&in
[size
- 3], ".DIR"))
307 || (size
> 3 && ! strcmp (&in
[size
- 3], ".dir"))
308 || (size
> 5 && (! strncmp (&in
[size
- 5], ".DIR", 4)
309 || ! strncmp (&in
[size
- 5], ".dir", 4))
310 && (in
[size
- 1] == '.' || in
[size
- 1] == ';')
311 && in
[size
] == '1')))
313 register char *p
, *dot
;
317 dir:x.dir --> dir:[x]
318 dir:[x]y.dir --> dir:[x.y] */
320 while (p
!= in
&& *p
!= ':' && *p
!= '>' && *p
!= ']') p
--;
323 strncpy (out
, in
, p
- in
);
342 dot
= index (p
, '.');
345 /* blindly remove any extension */
346 size
= strlen (out
) + (dot
- p
);
347 strncat (out
, p
, dot
- p
);
358 /* For Unix syntax, Append a slash if necessary */
359 if (out
[size
] != '/')
365 DEFUN ("file-name-as-directory", Ffile_name_as_directory
,
366 Sfile_name_as_directory
, 1, 1, 0,
367 "Return a string representing file FILENAME interpreted as a directory.\n\
368 This operation exists because a directory is also a file, but its name as\n\
369 a directory is different from its name as a file.\n\
370 The result can be used as the value of `default-directory'\n\
371 or passed as second argument to `expand-file-name'.\n\
372 For a Unix-syntax file name, just appends a slash.\n\
373 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
380 CHECK_STRING (file
, 0);
384 /* If the file name has special constructs in it,
385 call the corresponding file handler. */
386 handler
= Ffind_file_name_handler (file
);
388 return call2 (handler
, Qfile_name_as_directory
, file
);
390 buf
= (char *) alloca (XSTRING (file
)->size
+ 10);
391 return build_string (file_name_as_directory (buf
, XSTRING (file
)->data
));
395 * Convert from directory name to filename.
397 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
398 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
399 * On UNIX, it's simple: just make sure there is a terminating /
401 * Value is nonzero if the string output is different from the input.
404 directory_file_name (src
, dst
)
412 struct FAB fab
= cc$rms_fab
;
413 struct NAM nam
= cc$rms_nam
;
414 char esa
[NAM$C_MAXRSS
];
419 if (! index (src
, '/')
420 && (src
[slen
- 1] == ']'
421 || src
[slen
- 1] == ':'
422 || src
[slen
- 1] == '>'))
424 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
426 fab
.fab$b_fns
= slen
;
427 fab
.fab$l_nam
= &nam
;
428 fab
.fab$l_fop
= FAB$M_NAM
;
431 nam
.nam$b_ess
= sizeof esa
;
432 nam
.nam$b_nop
|= NAM$M_SYNCHK
;
434 /* We call SYS$PARSE to handle such things as [--] for us. */
435 if (SYS$
PARSE(&fab
, 0, 0) == RMS$_NORMAL
)
437 slen
= nam
.nam$b_esl
;
438 if (esa
[slen
- 1] == ';' && esa
[slen
- 2] == '.')
443 if (src
[slen
- 1] != ']' && src
[slen
- 1] != '>')
445 /* what about when we have logical_name:???? */
446 if (src
[slen
- 1] == ':')
447 { /* Xlate logical name and see what we get */
448 ptr
= strcpy (dst
, src
); /* upper case for getenv */
451 if ('a' <= *ptr
&& *ptr
<= 'z')
455 dst
[slen
- 1] = 0; /* remove colon */
456 if (!(src
= egetenv (dst
)))
458 /* should we jump to the beginning of this procedure?
459 Good points: allows us to use logical names that xlate
461 Bad points: can be a problem if we just translated to a device
463 For now, I'll punt and always expect VMS names, and hope for
466 if (src
[slen
- 1] != ']' && src
[slen
- 1] != '>')
467 { /* no recursion here! */
473 { /* not a directory spec */
478 bracket
= src
[slen
- 1];
480 /* If bracket is ']' or '>', bracket - 2 is the corresponding
482 ptr
= index (src
, bracket
- 2);
484 { /* no opening bracket */
488 if (!(rptr
= rindex (src
, '.')))
491 strncpy (dst
, src
, slen
);
495 dst
[slen
++] = bracket
;
500 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
501 then translate the device and recurse. */
502 if (dst
[slen
- 1] == ':'
503 && dst
[slen
- 2] != ':' /* skip decnet nodes */
504 && strcmp(src
+ slen
, "[000000]") == 0)
506 dst
[slen
- 1] = '\0';
507 if ((ptr
= egetenv (dst
))
508 && (rlen
= strlen (ptr
) - 1) > 0
509 && (ptr
[rlen
] == ']' || ptr
[rlen
] == '>')
510 && ptr
[rlen
- 1] == '.')
512 char * buf
= (char *) alloca (strlen (ptr
) + 1);
516 return directory_file_name (buf
, dst
);
521 strcat (dst
, "[000000]");
525 rlen
= strlen (rptr
) - 1;
526 strncat (dst
, rptr
, rlen
);
527 dst
[slen
+ rlen
] = '\0';
528 strcat (dst
, ".DIR.1");
532 /* Process as Unix format: just remove any final slash.
533 But leave "/" unchanged; do not change it to "". */
535 if (slen
> 1 && dst
[slen
- 1] == '/')
540 DEFUN ("directory-file-name", Fdirectory_file_name
, Sdirectory_file_name
,
542 "Returns the file name of the directory named DIR.\n\
543 This is the name of the file that holds the data for the directory DIR.\n\
544 This operation exists because a directory is also a file, but its name as\n\
545 a directory is different from its name as a file.\n\
546 In Unix-syntax, this function just removes the final slash.\n\
547 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
548 it returns a file name such as \"[X]Y.DIR.1\".")
550 Lisp_Object directory
;
555 CHECK_STRING (directory
, 0);
557 if (NILP (directory
))
560 /* If the file name has special constructs in it,
561 call the corresponding file handler. */
562 handler
= Ffind_file_name_handler (directory
);
564 return call2 (handler
, Qdirectory_file_name
, directory
);
567 /* 20 extra chars is insufficient for VMS, since we might perform a
568 logical name translation. an equivalence string can be up to 255
569 chars long, so grab that much extra space... - sss */
570 buf
= (char *) alloca (XSTRING (directory
)->size
+ 20 + 255);
572 buf
= (char *) alloca (XSTRING (directory
)->size
+ 20);
574 directory_file_name (XSTRING (directory
)->data
, buf
);
575 return build_string (buf
);
578 DEFUN ("make-temp-name", Fmake_temp_name
, Smake_temp_name
, 1, 1, 0,
579 "Generate temporary file name (string) starting with PREFIX (a string).\n\
580 The Emacs process number forms part of the result,\n\
581 so there is no danger of generating a name being used by another process.")
586 val
= concat2 (prefix
, build_string ("XXXXXX"));
587 mktemp (XSTRING (val
)->data
);
591 DEFUN ("expand-file-name", Fexpand_file_name
, Sexpand_file_name
, 1, 2, 0,
592 "Convert FILENAME to absolute, and canonicalize it.\n\
593 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
594 (does not start with slash); if DEFAULT is nil or missing,\n\
595 the current buffer's value of default-directory is used.\n\
596 Path components that are `.' are removed, and \n\
597 path components followed by `..' are removed, along with the `..' itself;\n\
598 note that these simplifications are done without checking the resulting\n\
599 paths in the file system.\n\
600 An initial `~/' expands to your home directory.\n\
601 An initial `~USER/' expands to USER's home directory.\n\
602 See also the function `substitute-in-file-name'.")
604 Lisp_Object name
, defalt
;
608 register unsigned char *newdir
, *p
, *o
;
610 unsigned char *target
;
613 unsigned char * colon
= 0;
614 unsigned char * close
= 0;
615 unsigned char * slash
= 0;
616 unsigned char * brack
= 0;
617 int lbrack
= 0, rbrack
= 0;
622 CHECK_STRING (name
, 0);
624 /* If the file name has special constructs in it,
625 call the corresponding file handler. */
626 handler
= Ffind_file_name_handler (name
);
628 return call3 (handler
, Qexpand_file_name
, name
, defalt
);
630 /* Use the buffer's default-directory if DEFALT is omitted. */
632 defalt
= current_buffer
->directory
;
633 CHECK_STRING (defalt
, 1);
635 /* Make sure DEFALT is properly expanded.
636 It would be better to do this down below where we actually use
637 defalt. Unfortunately, calling Fexpand_file_name recursively
638 could invoke GC, and the strings might be relocated. This would
639 be annoying because we have pointers into strings lying around
640 that would need adjusting, and people would add new pointers to
641 the code and forget to adjust them, resulting in intermittent bugs.
642 Putting this call here avoids all that crud.
644 The EQ test avoids infinite recursion. */
645 if (! NILP (defalt
) && !EQ (defalt
, name
)
646 /* This saves time in a common case. */
647 && XSTRING (defalt
)->data
[0] != '/')
652 defalt
= Fexpand_file_name (defalt
, Qnil
);
657 /* Filenames on VMS are always upper case. */
658 name
= Fupcase (name
);
661 nm
= XSTRING (name
)->data
;
663 /* If nm is absolute, flush ...// and detect /./ and /../.
664 If no /./ or /../ we can return right away. */
672 /* If it turns out that the filename we want to return is just a
673 suffix of FILENAME, we don't need to go through and edit
674 things; we just need to construct a new string using data
675 starting at the middle of FILENAME. If we set lose to a
676 non-zero value, that means we've discovered that we can't do
683 /* Since we know the path is absolute, we can assume that each
684 element starts with a "/". */
686 /* "//" anywhere isn't necessarily hairy; we just start afresh
687 with the second slash. */
688 if (p
[0] == '/' && p
[1] == '/'
690 /* // at start of filename is meaningful on Apollo system */
696 /* "~" is hairy as the start of any path element. */
697 if (p
[0] == '/' && p
[1] == '~')
698 nm
= p
+ 1, lose
= 1;
700 /* "." and ".." are hairy. */
705 || (p
[2] == '.' && (p
[3] == '/'
712 /* if dev:[dir]/, move nm to / */
713 if (!slash
&& p
> nm
&& (brack
|| colon
)) {
714 nm
= (brack
? brack
+ 1 : colon
+ 1);
723 /* VMS pre V4.4,convert '-'s in filenames. */
724 if (lbrack
== rbrack
)
726 if (dots
< 2) /* this is to allow negative version numbers */
731 if (lbrack
> rbrack
&&
732 ((p
[-1] == '.' || p
[-1] == '[' || p
[-1] == '<') &&
733 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>')))
739 /* count open brackets, reset close bracket pointer */
740 if (p
[0] == '[' || p
[0] == '<')
742 /* count close brackets, set close bracket pointer */
743 if (p
[0] == ']' || p
[0] == '>')
745 /* detect ][ or >< */
746 if ((p
[0] == ']' || p
[0] == '>') && (p
[1] == '[' || p
[1] == '<'))
748 if ((p
[0] == ':' || p
[0] == ']' || p
[0] == '>') && p
[1] == '~')
749 nm
= p
+ 1, lose
= 1;
750 if (p
[0] == ':' && (colon
|| slash
))
751 /* if dev1:[dir]dev2:, move nm to dev2: */
757 /* if /pathname/dev:, move nm to dev: */
760 /* if node::dev:, move colon following dev */
761 else if (colon
&& colon
[-1] == ':')
763 /* if dev1:dev2:, move nm to dev2: */
764 else if (colon
&& colon
[-1] != ':')
769 if (p
[0] == ':' && !colon
)
775 if (lbrack
== rbrack
)
778 else if (p
[0] == '.')
787 return build_string (sys_translate_unix (nm
));
789 if (nm
== XSTRING (name
)->data
)
791 return build_string (nm
);
795 /* Now determine directory to start with and put it in newdir */
799 if (nm
[0] == '~') /* prefix ~ */
805 || nm
[1] == 0) /* ~ by itself */
807 if (!(newdir
= (unsigned char *) egetenv ("HOME")))
808 newdir
= (unsigned char *) "";
811 nm
++; /* Don't leave the slash in nm. */
814 else /* ~user/filename */
816 for (p
= nm
; *p
&& (*p
!= '/'
821 o
= (unsigned char *) alloca (p
- nm
+ 1);
822 bcopy ((char *) nm
, o
, p
- nm
);
825 pw
= (struct passwd
*) getpwnam (o
+ 1);
828 newdir
= (unsigned char *) pw
-> pw_dir
;
830 nm
= p
+ 1; /* skip the terminator */
836 /* If we don't find a user of that name, leave the name
837 unchanged; don't move nm forward to p. */
847 newdir
= XSTRING (defalt
)->data
;
852 /* Get rid of any slash at the end of newdir. */
853 int length
= strlen (newdir
);
854 /* Adding `length > 1 &&' makes ~ expand into / when homedir
855 is the root dir. People disagree about whether that is right.
856 Anyway, we can't take the risk of this change now. */
857 if (newdir
[length
- 1] == '/')
859 unsigned char *temp
= (unsigned char *) alloca (length
);
860 bcopy (newdir
, temp
, length
- 1);
861 temp
[length
- 1] = 0;
869 /* Now concatenate the directory and name to new space in the stack frame */
870 tlen
+= strlen (nm
) + 1;
871 target
= (unsigned char *) alloca (tlen
);
877 if (nm
[0] == 0 || nm
[0] == '/')
878 strcpy (target
, newdir
);
881 file_name_as_directory (target
, newdir
);
886 if (index (target
, '/'))
887 strcpy (target
, sys_translate_unix (target
));
890 /* Now canonicalize by removing /. and /foo/.. if they appear. */
898 if (*p
!= ']' && *p
!= '>' && *p
!= '-')
904 else if ((p
[0] == ']' || p
[0] == '>') && p
[0] == p
[1] + 2)
905 /* brackets are offset from each other by 2 */
908 if (*p
!= '.' && *p
!= '-' && o
[-1] != '.')
909 /* convert [foo][bar] to [bar] */
910 while (o
[-1] != '[' && o
[-1] != '<')
912 else if (*p
== '-' && *o
!= '.')
915 else if (p
[0] == '-' && o
[-1] == '.' &&
916 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>'))
917 /* flush .foo.- ; leave - if stopped by '[' or '<' */
921 while (o
[-1] != '.' && o
[-1] != '[' && o
[-1] != '<');
922 if (p
[1] == '.') /* foo.-.bar ==> bar*/
924 else if (o
[-1] == '.') /* '.foo.-]' ==> ']' */
926 /* else [foo.-] ==> [-] */
932 o
[-1] != '[' && o
[-1] != '<' && o
[-1] != '.' &&
933 p
[1] != ']' && p
[1] != '>' && p
[1] != '.')
943 else if (!strncmp (p
, "//", 2)
945 /* // at start of filename is meaningful in Apollo system */
958 /* If "/." is the entire filename, keep the "/". Otherwise,
959 just delete the whole "/.". */
960 if (o
== target
&& p
[2] == '\0')
964 else if (!strncmp (p
, "/..", 3)
965 /* `/../' is the "superroot" on certain file systems. */
967 && (p
[3] == '/' || p
[3] == 0))
969 while (o
!= target
&& *--o
!= '/')
972 if (o
== target
+ 1 && o
[-1] == '/' && o
[0] == '/')
976 if (o
== target
&& *o
== '/')
987 return make_string (target
, o
- target
);
990 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'.
991 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
992 "Convert FILENAME to absolute, and canonicalize it.\n\
993 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
994 (does not start with slash); if DEFAULT is nil or missing,\n\
995 the current buffer's value of default-directory is used.\n\
996 Filenames containing `.' or `..' as components are simplified;\n\
997 initial `~/' expands to your home directory.\n\
998 See also the function `substitute-in-file-name'.")
1000 Lisp_Object name, defalt;
1004 register unsigned char *newdir, *p, *o;
1006 unsigned char *target;
1010 unsigned char * colon = 0;
1011 unsigned char * close = 0;
1012 unsigned char * slash = 0;
1013 unsigned char * brack = 0;
1014 int lbrack = 0, rbrack = 0;
1018 CHECK_STRING (name
, 0);
1021 /* Filenames on VMS are always upper case. */
1022 name
= Fupcase (name
);
1025 nm
= XSTRING (name
)->data
;
1027 /* If nm is absolute, flush ...// and detect /./ and /../.
1028 If no /./ or /../ we can return right away. */
1040 if (p
[0] == '/' && p
[1] == '/'
1042 /* // at start of filename is meaningful on Apollo system */
1047 if (p
[0] == '/' && p
[1] == '~')
1048 nm
= p
+ 1, lose
= 1;
1049 if (p
[0] == '/' && p
[1] == '.'
1050 && (p
[2] == '/' || p
[2] == 0
1051 || (p
[2] == '.' && (p
[3] == '/' || p
[3] == 0))))
1057 /* if dev:[dir]/, move nm to / */
1058 if (!slash
&& p
> nm
&& (brack
|| colon
)) {
1059 nm
= (brack
? brack
+ 1 : colon
+ 1);
1060 lbrack
= rbrack
= 0;
1068 /* VMS pre V4.4,convert '-'s in filenames. */
1069 if (lbrack
== rbrack
)
1071 if (dots
< 2) /* this is to allow negative version numbers */
1076 if (lbrack
> rbrack
&&
1077 ((p
[-1] == '.' || p
[-1] == '[' || p
[-1] == '<') &&
1078 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>')))
1084 /* count open brackets, reset close bracket pointer */
1085 if (p
[0] == '[' || p
[0] == '<')
1086 lbrack
++, brack
= 0;
1087 /* count close brackets, set close bracket pointer */
1088 if (p
[0] == ']' || p
[0] == '>')
1089 rbrack
++, brack
= p
;
1090 /* detect ][ or >< */
1091 if ((p
[0] == ']' || p
[0] == '>') && (p
[1] == '[' || p
[1] == '<'))
1093 if ((p
[0] == ':' || p
[0] == ']' || p
[0] == '>') && p
[1] == '~')
1094 nm
= p
+ 1, lose
= 1;
1095 if (p
[0] == ':' && (colon
|| slash
))
1096 /* if dev1:[dir]dev2:, move nm to dev2: */
1102 /* if /pathname/dev:, move nm to dev: */
1105 /* if node::dev:, move colon following dev */
1106 else if (colon
&& colon
[-1] == ':')
1108 /* if dev1:dev2:, move nm to dev2: */
1109 else if (colon
&& colon
[-1] != ':')
1114 if (p
[0] == ':' && !colon
)
1120 if (lbrack
== rbrack
)
1123 else if (p
[0] == '.')
1131 if (index (nm
, '/'))
1132 return build_string (sys_translate_unix (nm
));
1134 if (nm
== XSTRING (name
)->data
)
1136 return build_string (nm
);
1140 /* Now determine directory to start with and put it in NEWDIR */
1144 if (nm
[0] == '~') /* prefix ~ */
1149 || nm
[1] == 0)/* ~/filename */
1151 if (!(newdir
= (unsigned char *) egetenv ("HOME")))
1152 newdir
= (unsigned char *) "";
1155 nm
++; /* Don't leave the slash in nm. */
1158 else /* ~user/filename */
1160 /* Get past ~ to user */
1161 unsigned char *user
= nm
+ 1;
1162 /* Find end of name. */
1163 unsigned char *ptr
= (unsigned char *) index (user
, '/');
1164 int len
= ptr
? ptr
- user
: strlen (user
);
1166 unsigned char *ptr1
= index (user
, ':');
1167 if (ptr1
!= 0 && ptr1
- user
< len
)
1170 /* Copy the user name into temp storage. */
1171 o
= (unsigned char *) alloca (len
+ 1);
1172 bcopy ((char *) user
, o
, len
);
1175 /* Look up the user name. */
1176 pw
= (struct passwd
*) getpwnam (o
+ 1);
1178 error ("\"%s\" isn't a registered user", o
+ 1);
1180 newdir
= (unsigned char *) pw
->pw_dir
;
1182 /* Discard the user name from NM. */
1189 #endif /* not VMS */
1193 defalt
= current_buffer
->directory
;
1194 CHECK_STRING (defalt
, 1);
1195 newdir
= XSTRING (defalt
)->data
;
1198 /* Now concatenate the directory and name to new space in the stack frame */
1200 tlen
= (newdir
? strlen (newdir
) + 1 : 0) + strlen (nm
) + 1;
1201 target
= (unsigned char *) alloca (tlen
);
1207 if (nm
[0] == 0 || nm
[0] == '/')
1208 strcpy (target
, newdir
);
1211 file_name_as_directory (target
, newdir
);
1214 strcat (target
, nm
);
1216 if (index (target
, '/'))
1217 strcpy (target
, sys_translate_unix (target
));
1220 /* Now canonicalize by removing /. and /foo/.. if they appear */
1228 if (*p
!= ']' && *p
!= '>' && *p
!= '-')
1234 else if ((p
[0] == ']' || p
[0] == '>') && p
[0] == p
[1] + 2)
1235 /* brackets are offset from each other by 2 */
1238 if (*p
!= '.' && *p
!= '-' && o
[-1] != '.')
1239 /* convert [foo][bar] to [bar] */
1240 while (o
[-1] != '[' && o
[-1] != '<')
1242 else if (*p
== '-' && *o
!= '.')
1245 else if (p
[0] == '-' && o
[-1] == '.' &&
1246 (p
[1] == '.' || p
[1] == ']' || p
[1] == '>'))
1247 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1251 while (o
[-1] != '.' && o
[-1] != '[' && o
[-1] != '<');
1252 if (p
[1] == '.') /* foo.-.bar ==> bar*/
1254 else if (o
[-1] == '.') /* '.foo.-]' ==> ']' */
1256 /* else [foo.-] ==> [-] */
1262 o
[-1] != '[' && o
[-1] != '<' && o
[-1] != '.' &&
1263 p
[1] != ']' && p
[1] != '>' && p
[1] != '.')
1273 else if (!strncmp (p
, "//", 2)
1275 /* // at start of filename is meaningful in Apollo system */
1283 else if (p
[0] == '/' && p
[1] == '.' &&
1284 (p
[2] == '/' || p
[2] == 0))
1286 else if (!strncmp (p
, "/..", 3)
1287 /* `/../' is the "superroot" on certain file systems. */
1289 && (p
[3] == '/' || p
[3] == 0))
1291 while (o
!= target
&& *--o
!= '/')
1294 if (o
== target
+ 1 && o
[-1] == '/' && o
[0] == '/')
1298 if (o
== target
&& *o
== '/')
1306 #endif /* not VMS */
1309 return make_string (target
, o
- target
);
1313 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name
,
1314 Ssubstitute_in_file_name
, 1, 1, 0,
1315 "Substitute environment variables referred to in FILENAME.\n\
1316 `$FOO' where FOO is an environment variable name means to substitute\n\
1317 the value of that variable. The variable name should be terminated\n\
1318 with a character not a letter, digit or underscore; otherwise, enclose\n\
1319 the entire variable name in braces.\n\
1320 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1321 On VMS, `$' substitution is not done; this function does little and only\n\
1322 duplicates what `expand-file-name' does.")
1328 register unsigned char *s
, *p
, *o
, *x
, *endp
;
1329 unsigned char *target
;
1331 int substituted
= 0;
1334 CHECK_STRING (string
, 0);
1336 nm
= XSTRING (string
)->data
;
1337 endp
= nm
+ XSTRING (string
)->size
;
1339 /* If /~ or // appears, discard everything through first slash. */
1341 for (p
= nm
; p
!= endp
; p
++)
1345 /* // at start of file name is meaningful in Apollo system */
1346 (p
[0] == '/' && p
- 1 != nm
)
1347 #else /* not APOLLO */
1349 #endif /* not APOLLO */
1353 (p
[-1] == ':' || p
[-1] == ']' || p
[-1] == '>' ||
1366 return build_string (nm
);
1369 /* See if any variables are substituted into the string
1370 and find the total length of their values in `total' */
1372 for (p
= nm
; p
!= endp
;)
1382 /* "$$" means a single "$" */
1391 while (p
!= endp
&& *p
!= '}') p
++;
1392 if (*p
!= '}') goto missingclose
;
1398 while (p
!= endp
&& (isalnum (*p
) || *p
== '_')) p
++;
1402 /* Copy out the variable name */
1403 target
= (unsigned char *) alloca (s
- o
+ 1);
1404 strncpy (target
, o
, s
- o
);
1407 /* Get variable value */
1408 o
= (unsigned char *) egetenv (target
);
1409 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1412 if (!o
&& !strcmp (target
, "USER"))
1413 o
= egetenv ("LOGNAME");
1416 if (!o
) goto badvar
;
1417 total
+= strlen (o
);
1424 /* If substitution required, recopy the string and do it */
1425 /* Make space in stack frame for the new copy */
1426 xnm
= (unsigned char *) alloca (XSTRING (string
)->size
+ total
+ 1);
1429 /* Copy the rest of the name through, replacing $ constructs with values */
1446 while (p
!= endp
&& *p
!= '}') p
++;
1447 if (*p
!= '}') goto missingclose
;
1453 while (p
!= endp
&& (isalnum (*p
) || *p
== '_')) p
++;
1457 /* Copy out the variable name */
1458 target
= (unsigned char *) alloca (s
- o
+ 1);
1459 strncpy (target
, o
, s
- o
);
1462 /* Get variable value */
1463 o
= (unsigned char *) egetenv (target
);
1464 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1467 if (!o
&& !strcmp (target
, "USER"))
1468 o
= egetenv ("LOGNAME");
1480 /* If /~ or // appears, discard everything through first slash. */
1482 for (p
= xnm
; p
!= x
; p
++)
1485 /* // at start of file name is meaningful in Apollo system */
1486 (p
[0] == '/' && p
- 1 != xnm
)
1487 #else /* not APOLLO */
1489 #endif /* not APOLLO */
1491 && p
!= nm
&& p
[-1] == '/')
1494 return make_string (xnm
, x
- xnm
);
1497 error ("Bad format environment-variable substitution");
1499 error ("Missing \"}\" in environment-variable substitution");
1501 error ("Substituting nonexistent environment variable \"%s\"", target
);
1504 #endif /* not VMS */
1507 /* A slightly faster and more convenient way to get
1508 (directory-file-name (expand-file-name FOO)). The return value may
1509 have had its last character zapped with a '\0' character, meaning
1510 that it is acceptable to system calls, but not to other lisp
1511 functions. Callers should make sure that the return value doesn't
1515 expand_and_dir_to_file (filename
, defdir
)
1516 Lisp_Object filename
, defdir
;
1518 register Lisp_Object abspath
;
1520 abspath
= Fexpand_file_name (filename
, defdir
);
1523 register int c
= XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1];
1524 if (c
== ':' || c
== ']' || c
== '>')
1525 abspath
= Fdirectory_file_name (abspath
);
1528 /* Remove final slash, if any (unless path is root).
1529 stat behaves differently depending! */
1530 if (XSTRING (abspath
)->size
> 1
1531 && XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1] == '/')
1533 if (EQ (abspath
, filename
))
1534 abspath
= Fcopy_sequence (abspath
);
1535 XSTRING (abspath
)->data
[XSTRING (abspath
)->size
- 1] = 0;
1541 barf_or_query_if_file_exists (absname
, querystring
, interactive
)
1542 Lisp_Object absname
;
1543 unsigned char *querystring
;
1546 register Lisp_Object tem
;
1547 struct gcpro gcpro1
;
1549 if (access (XSTRING (absname
)->data
, 4) >= 0)
1552 Fsignal (Qfile_already_exists
,
1553 Fcons (build_string ("File already exists"),
1554 Fcons (absname
, Qnil
)));
1556 tem
= do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1557 XSTRING (absname
)->data
, querystring
));
1560 Fsignal (Qfile_already_exists
,
1561 Fcons (build_string ("File already exists"),
1562 Fcons (absname
, Qnil
)));
1567 DEFUN ("copy-file", Fcopy_file
, Scopy_file
, 2, 4,
1568 "fCopy file: \nFCopy %s to file: \np\nP",
1569 "Copy FILE to NEWNAME. Both args must be strings.\n\
1570 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1571 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1572 A number as third arg means request confirmation if NEWNAME already exists.\n\
1573 This is what happens in interactive use with M-x.\n\
1574 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1575 last-modified time as the old one. (This works on only some systems.)\n\
1576 A prefix arg makes KEEP-TIME non-nil.")
1577 (filename
, newname
, ok_if_already_exists
, keep_date
)
1578 Lisp_Object filename
, newname
, ok_if_already_exists
, keep_date
;
1581 char buf
[16 * 1024];
1583 Lisp_Object handler
;
1584 struct gcpro gcpro1
, gcpro2
;
1585 int count
= specpdl_ptr
- specpdl
;
1587 GCPRO2 (filename
, newname
);
1588 CHECK_STRING (filename
, 0);
1589 CHECK_STRING (newname
, 1);
1590 filename
= Fexpand_file_name (filename
, Qnil
);
1591 newname
= Fexpand_file_name (newname
, Qnil
);
1593 /* If the input file name has special constructs in it,
1594 call the corresponding file handler. */
1595 handler
= Ffind_file_name_handler (filename
);
1596 if (!NILP (handler
))
1597 return call3 (handler
, Qcopy_file
, filename
, newname
);
1598 /* Likewise for output file name. */
1599 handler
= Ffind_file_name_handler (newname
);
1600 if (!NILP (handler
))
1601 return call3 (handler
, Qcopy_file
, filename
, newname
);
1603 if (NILP (ok_if_already_exists
)
1604 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1605 barf_or_query_if_file_exists (newname
, "copy to it",
1606 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1608 ifd
= open (XSTRING (filename
)->data
, 0);
1610 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
1612 record_unwind_protect (close_file_unwind
, make_number (ifd
));
1615 /* Create the copy file with the same record format as the input file */
1616 ofd
= sys_creat (XSTRING (newname
)->data
, 0666, ifd
);
1618 ofd
= creat (XSTRING (newname
)->data
, 0666);
1621 report_file_error ("Opening output file", Fcons (newname
, Qnil
));
1623 record_unwind_protect (close_file_unwind
, make_number (ofd
));
1627 while ((n
= read (ifd
, buf
, sizeof buf
)) > 0)
1628 if (write (ofd
, buf
, n
) != n
)
1629 report_file_error ("I/O error", Fcons (newname
, Qnil
));
1632 if (fstat (ifd
, &st
) >= 0)
1634 if (!NILP (keep_date
))
1636 EMACS_TIME atime
, mtime
;
1637 EMACS_SET_SECS_USECS (atime
, st
.st_atime
, 0);
1638 EMACS_SET_SECS_USECS (mtime
, st
.st_mtime
, 0);
1639 EMACS_SET_UTIMES (XSTRING (newname
)->data
, atime
, mtime
);
1642 if (!egetenv ("USE_DOMAIN_ACLS"))
1644 chmod (XSTRING (newname
)->data
, st
.st_mode
& 07777);
1647 /* Discard the unwind protects. */
1648 specpdl_ptr
= specpdl
+ count
;
1651 if (close (ofd
) < 0)
1652 report_file_error ("I/O error", Fcons (newname
, Qnil
));
1658 DEFUN ("make-directory-internal", Fmake_directory_internal
,
1659 Smake_directory_internal
, 1, 1, 0,
1660 "Create a directory. One argument, a file name string.")
1662 Lisp_Object dirname
;
1665 Lisp_Object handler
;
1667 CHECK_STRING (dirname
, 0);
1668 dirname
= Fexpand_file_name (dirname
, Qnil
);
1670 handler
= Ffind_file_name_handler (dirname
);
1671 if (!NILP (handler
))
1672 return call3 (handler
, Qmake_directory
, dirname
, Qnil
);
1674 dir
= XSTRING (dirname
)->data
;
1676 if (mkdir (dir
, 0777) != 0)
1677 report_file_error ("Creating directory", Flist (1, &dirname
));
1682 DEFUN ("delete-directory", Fdelete_directory
, Sdelete_directory
, 1, 1, "FDelete directory: ",
1683 "Delete a directory. One argument, a file name string.")
1685 Lisp_Object dirname
;
1688 Lisp_Object handler
;
1690 CHECK_STRING (dirname
, 0);
1691 dirname
= Fexpand_file_name (dirname
, Qnil
);
1692 dir
= XSTRING (dirname
)->data
;
1694 handler
= Ffind_file_name_handler (dirname
);
1695 if (!NILP (handler
))
1696 return call2 (handler
, Qdelete_directory
, dirname
);
1698 if (rmdir (dir
) != 0)
1699 report_file_error ("Removing directory", Flist (1, &dirname
));
1704 DEFUN ("delete-file", Fdelete_file
, Sdelete_file
, 1, 1, "fDelete file: ",
1705 "Delete specified file. One argument, a file name string.\n\
1706 If file has multiple names, it continues to exist with the other names.")
1708 Lisp_Object filename
;
1710 Lisp_Object handler
;
1711 CHECK_STRING (filename
, 0);
1712 filename
= Fexpand_file_name (filename
, Qnil
);
1714 handler
= Ffind_file_name_handler (filename
);
1715 if (!NILP (handler
))
1716 return call2 (handler
, Qdelete_file
, filename
);
1718 if (0 > unlink (XSTRING (filename
)->data
))
1719 report_file_error ("Removing old name", Flist (1, &filename
));
1723 DEFUN ("rename-file", Frename_file
, Srename_file
, 2, 3,
1724 "fRename file: \nFRename %s to file: \np",
1725 "Rename FILE as NEWNAME. Both args strings.\n\
1726 If file has names other than FILE, it continues to have those names.\n\
1727 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1728 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1729 A number as third arg means request confirmation if NEWNAME already exists.\n\
1730 This is what happens in interactive use with M-x.")
1731 (filename
, newname
, ok_if_already_exists
)
1732 Lisp_Object filename
, newname
, ok_if_already_exists
;
1735 Lisp_Object args
[2];
1737 Lisp_Object handler
;
1738 struct gcpro gcpro1
, gcpro2
;
1740 GCPRO2 (filename
, newname
);
1741 CHECK_STRING (filename
, 0);
1742 CHECK_STRING (newname
, 1);
1743 filename
= Fexpand_file_name (filename
, Qnil
);
1744 newname
= Fexpand_file_name (newname
, Qnil
);
1746 /* If the file name has special constructs in it,
1747 call the corresponding file handler. */
1748 handler
= Ffind_file_name_handler (filename
);
1749 if (!NILP (handler
))
1750 return call3 (handler
, Qrename_file
, filename
, newname
);
1752 if (NILP (ok_if_already_exists
)
1753 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1754 barf_or_query_if_file_exists (newname
, "rename to it",
1755 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1757 if (0 > rename (XSTRING (filename
)->data
, XSTRING (newname
)->data
))
1759 if (0 > link (XSTRING (filename
)->data
, XSTRING (newname
)->data
)
1760 || 0 > unlink (XSTRING (filename
)->data
))
1765 Fcopy_file (filename
, newname
, ok_if_already_exists
, Qt
);
1766 Fdelete_file (filename
);
1773 report_file_error ("Renaming", Flist (2, args
));
1776 report_file_error ("Renaming", Flist (2, &filename
));
1783 DEFUN ("add-name-to-file", Fadd_name_to_file
, Sadd_name_to_file
, 2, 3,
1784 "fAdd name to file: \nFName to add to %s: \np",
1785 "Give FILE additional name NEWNAME. Both args strings.\n\
1786 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1787 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1788 A number as third arg means request confirmation if NEWNAME already exists.\n\
1789 This is what happens in interactive use with M-x.")
1790 (filename
, newname
, ok_if_already_exists
)
1791 Lisp_Object filename
, newname
, ok_if_already_exists
;
1794 Lisp_Object args
[2];
1796 Lisp_Object handler
;
1797 struct gcpro gcpro1
, gcpro2
;
1799 GCPRO2 (filename
, newname
);
1800 CHECK_STRING (filename
, 0);
1801 CHECK_STRING (newname
, 1);
1802 filename
= Fexpand_file_name (filename
, Qnil
);
1803 newname
= Fexpand_file_name (newname
, Qnil
);
1805 /* If the file name has special constructs in it,
1806 call the corresponding file handler. */
1807 handler
= Ffind_file_name_handler (filename
);
1808 if (!NILP (handler
))
1809 return call3 (handler
, Qadd_name_to_file
, filename
, newname
);
1811 if (NILP (ok_if_already_exists
)
1812 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1813 barf_or_query_if_file_exists (newname
, "make it a new name",
1814 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1815 unlink (XSTRING (newname
)->data
);
1816 if (0 > link (XSTRING (filename
)->data
, XSTRING (newname
)->data
))
1821 report_file_error ("Adding new name", Flist (2, args
));
1823 report_file_error ("Adding new name", Flist (2, &filename
));
1832 DEFUN ("make-symbolic-link", Fmake_symbolic_link
, Smake_symbolic_link
, 2, 3,
1833 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
1834 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
1835 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1836 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1837 A number as third arg means request confirmation if NEWNAME already exists.\n\
1838 This happens for interactive use with M-x.")
1839 (filename
, linkname
, ok_if_already_exists
)
1840 Lisp_Object filename
, linkname
, ok_if_already_exists
;
1843 Lisp_Object args
[2];
1845 Lisp_Object handler
;
1846 struct gcpro gcpro1
, gcpro2
;
1848 GCPRO2 (filename
, linkname
);
1849 CHECK_STRING (filename
, 0);
1850 CHECK_STRING (linkname
, 1);
1851 #if 0 /* This made it impossible to make a link to a relative name. */
1852 filename
= Fexpand_file_name (filename
, Qnil
);
1854 linkname
= Fexpand_file_name (linkname
, Qnil
);
1856 /* If the file name has special constructs in it,
1857 call the corresponding file handler. */
1858 handler
= Ffind_file_name_handler (filename
);
1859 if (!NILP (handler
))
1860 return call3 (handler
, Qmake_symbolic_link
, filename
, linkname
);
1862 if (NILP (ok_if_already_exists
)
1863 || XTYPE (ok_if_already_exists
) == Lisp_Int
)
1864 barf_or_query_if_file_exists (linkname
, "make it a link",
1865 XTYPE (ok_if_already_exists
) == Lisp_Int
);
1866 if (0 > symlink (XSTRING (filename
)->data
, XSTRING (linkname
)->data
))
1868 /* If we didn't complain already, silently delete existing file. */
1869 if (errno
== EEXIST
)
1871 unlink (XSTRING (linkname
)->data
);
1872 if (0 <= symlink (XSTRING (filename
)->data
, XSTRING (linkname
)->data
))
1879 report_file_error ("Making symbolic link", Flist (2, args
));
1881 report_file_error ("Making symbolic link", Flist (2, &filename
));
1887 #endif /* S_IFLNK */
1891 DEFUN ("define-logical-name", Fdefine_logical_name
, Sdefine_logical_name
,
1892 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
1893 "Define the job-wide logical name NAME to have the value STRING.\n\
1894 If STRING is nil or a null string, the logical name NAME is deleted.")
1896 Lisp_Object varname
;
1899 CHECK_STRING (varname
, 0);
1901 delete_logical_name (XSTRING (varname
)->data
);
1904 CHECK_STRING (string
, 1);
1906 if (XSTRING (string
)->size
== 0)
1907 delete_logical_name (XSTRING (varname
)->data
);
1909 define_logical_name (XSTRING (varname
)->data
, XSTRING (string
)->data
);
1918 DEFUN ("sysnetunam", Fsysnetunam
, Ssysnetunam
, 2, 2, 0,
1919 "Open a network connection to PATH using LOGIN as the login string.")
1921 Lisp_Object path
, login
;
1925 CHECK_STRING (path
, 0);
1926 CHECK_STRING (login
, 0);
1928 netresult
= netunam (XSTRING (path
)->data
, XSTRING (login
)->data
);
1930 if (netresult
== -1)
1935 #endif /* HPUX_NET */
1937 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p
, Sfile_name_absolute_p
,
1939 "Return t if file FILENAME specifies an absolute path name.\n\
1940 On Unix, this is a name starting with a `/' or a `~'.")
1942 Lisp_Object filename
;
1946 CHECK_STRING (filename
, 0);
1947 ptr
= XSTRING (filename
)->data
;
1948 if (*ptr
== '/' || *ptr
== '~'
1950 /* ??? This criterion is probably wrong for '<'. */
1951 || index (ptr
, ':') || index (ptr
, '<')
1952 || (*ptr
== '[' && (ptr
[1] != '-' || (ptr
[2] != '.' && ptr
[2] != ']'))
1961 DEFUN ("file-exists-p", Ffile_exists_p
, Sfile_exists_p
, 1, 1, 0,
1962 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
1963 See also `file-readable-p' and `file-attributes'.")
1965 Lisp_Object filename
;
1967 Lisp_Object abspath
;
1968 Lisp_Object handler
;
1970 CHECK_STRING (filename
, 0);
1971 abspath
= Fexpand_file_name (filename
, Qnil
);
1973 /* If the file name has special constructs in it,
1974 call the corresponding file handler. */
1975 handler
= Ffind_file_name_handler (abspath
);
1976 if (!NILP (handler
))
1977 return call2 (handler
, Qfile_exists_p
, abspath
);
1979 return (access (XSTRING (abspath
)->data
, 0) >= 0) ? Qt
: Qnil
;
1982 DEFUN ("file-executable-p", Ffile_executable_p
, Sfile_executable_p
, 1, 1, 0,
1983 "Return t if FILENAME can be executed by you.\n\
1984 For a directory, this means you can access files in that directory.")
1986 Lisp_Object filename
;
1989 Lisp_Object abspath
;
1990 Lisp_Object handler
;
1992 CHECK_STRING (filename
, 0);
1993 abspath
= Fexpand_file_name (filename
, Qnil
);
1995 /* If the file name has special constructs in it,
1996 call the corresponding file handler. */
1997 handler
= Ffind_file_name_handler (abspath
);
1998 if (!NILP (handler
))
1999 return call2 (handler
, Qfile_executable_p
, abspath
);
2001 return (access (XSTRING (abspath
)->data
, 1) >= 0) ? Qt
: Qnil
;
2004 DEFUN ("file-readable-p", Ffile_readable_p
, Sfile_readable_p
, 1, 1, 0,
2005 "Return t if file FILENAME exists and you can read it.\n\
2006 See also `file-exists-p' and `file-attributes'.")
2008 Lisp_Object filename
;
2010 Lisp_Object abspath
;
2011 Lisp_Object handler
;
2013 CHECK_STRING (filename
, 0);
2014 abspath
= Fexpand_file_name (filename
, Qnil
);
2016 /* If the file name has special constructs in it,
2017 call the corresponding file handler. */
2018 handler
= Ffind_file_name_handler (abspath
);
2019 if (!NILP (handler
))
2020 return call2 (handler
, Qfile_readable_p
, abspath
);
2022 return (access (XSTRING (abspath
)->data
, 4) >= 0) ? Qt
: Qnil
;
2025 DEFUN ("file-symlink-p", Ffile_symlink_p
, Sfile_symlink_p
, 1, 1, 0,
2026 "If file FILENAME is the name of a symbolic link\n\
2027 returns the name of the file to which it is linked.\n\
2028 Otherwise returns NIL.")
2030 Lisp_Object filename
;
2037 Lisp_Object handler
;
2039 CHECK_STRING (filename
, 0);
2040 filename
= Fexpand_file_name (filename
, Qnil
);
2042 /* If the file name has special constructs in it,
2043 call the corresponding file handler. */
2044 handler
= Ffind_file_name_handler (filename
);
2045 if (!NILP (handler
))
2046 return call2 (handler
, Qfile_symlink_p
, filename
);
2051 buf
= (char *) xmalloc (bufsize
);
2052 bzero (buf
, bufsize
);
2053 valsize
= readlink (XSTRING (filename
)->data
, buf
, bufsize
);
2054 if (valsize
< bufsize
) break;
2055 /* Buffer was not long enough */
2064 val
= make_string (buf
, valsize
);
2067 #else /* not S_IFLNK */
2069 #endif /* not S_IFLNK */
2072 #ifdef SOLARIS_BROKEN_ACCESS
2073 /* In Solaris 2.1, the readonly-ness of the filesystem is not
2074 considered by the access system call. This is Sun's bug, but we
2075 still have to make Emacs work. */
2077 #include <sys/statvfs.h>
2083 struct statvfs statvfsb
;
2085 if (statvfs(path
, &statvfsb
))
2086 return 1; /* error from statvfs, be conservative and say not wrtable */
2088 /* Otherwise, fsys is ro if bit is set. */
2089 return statvfsb
.f_flag
& ST_RDONLY
;
2092 /* But on every other os, access has already done the right thing. */
2093 #define ro_fsys(path) 0
2096 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2098 DEFUN ("file-writable-p", Ffile_writable_p
, Sfile_writable_p
, 1, 1, 0,
2099 "Return t if file FILENAME can be written or created by you.")
2101 Lisp_Object filename
;
2103 Lisp_Object abspath
, dir
;
2104 Lisp_Object handler
;
2106 CHECK_STRING (filename
, 0);
2107 abspath
= Fexpand_file_name (filename
, Qnil
);
2109 /* If the file name has special constructs in it,
2110 call the corresponding file handler. */
2111 handler
= Ffind_file_name_handler (abspath
);
2112 if (!NILP (handler
))
2113 return call2 (handler
, Qfile_writable_p
, abspath
);
2115 if (access (XSTRING (abspath
)->data
, 0) >= 0)
2116 return ((access (XSTRING (abspath
)->data
, 2) >= 0
2117 && ! ro_fsys ((char *) XSTRING (abspath
)->data
))
2119 dir
= Ffile_name_directory (abspath
);
2122 dir
= Fdirectory_file_name (dir
);
2124 return ((access (!NILP (dir
) ? (char *) XSTRING (dir
)->data
: "", 2) >= 0
2125 && ! ro_fsys ((char *) XSTRING (dir
)->data
))
2129 DEFUN ("file-directory-p", Ffile_directory_p
, Sfile_directory_p
, 1, 1, 0,
2130 "Return t if file FILENAME is the name of a directory as a file.\n\
2131 A directory name spec may be given instead; then the value is t\n\
2132 if the directory so specified exists and really is a directory.")
2134 Lisp_Object filename
;
2136 register Lisp_Object abspath
;
2138 Lisp_Object handler
;
2140 abspath
= expand_and_dir_to_file (filename
, current_buffer
->directory
);
2142 /* If the file name has special constructs in it,
2143 call the corresponding file handler. */
2144 handler
= Ffind_file_name_handler (abspath
);
2145 if (!NILP (handler
))
2146 return call2 (handler
, Qfile_directory_p
, abspath
);
2148 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2150 return (st
.st_mode
& S_IFMT
) == S_IFDIR
? Qt
: Qnil
;
2153 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p
, Sfile_accessible_directory_p
, 1, 1, 0,
2154 "Return t if file FILENAME is the name of a directory as a file,\n\
2155 and files in that directory can be opened by you. In order to use a\n\
2156 directory as a buffer's current directory, this predicate must return true.\n\
2157 A directory name spec may be given instead; then the value is t\n\
2158 if the directory so specified exists and really is a readable and\n\
2159 searchable directory.")
2161 Lisp_Object filename
;
2163 Lisp_Object handler
;
2165 /* If the file name has special constructs in it,
2166 call the corresponding file handler. */
2167 handler
= Ffind_file_name_handler (filename
);
2168 if (!NILP (handler
))
2169 return call2 (handler
, Qfile_accessible_directory_p
, filename
);
2171 if (NILP (Ffile_directory_p (filename
))
2172 || NILP (Ffile_executable_p (filename
)))
2178 DEFUN ("file-modes", Ffile_modes
, Sfile_modes
, 1, 1, 0,
2179 "Return mode bits of FILE, as an integer.")
2181 Lisp_Object filename
;
2183 Lisp_Object abspath
;
2185 Lisp_Object handler
;
2187 abspath
= expand_and_dir_to_file (filename
, current_buffer
->directory
);
2189 /* If the file name has special constructs in it,
2190 call the corresponding file handler. */
2191 handler
= Ffind_file_name_handler (abspath
);
2192 if (!NILP (handler
))
2193 return call2 (handler
, Qfile_modes
, abspath
);
2195 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2197 return make_number (st
.st_mode
& 07777);
2200 DEFUN ("set-file-modes", Fset_file_modes
, Sset_file_modes
, 2, 2, 0,
2201 "Set mode bits of FILE to MODE (an integer).\n\
2202 Only the 12 low bits of MODE are used.")
2204 Lisp_Object filename
, mode
;
2206 Lisp_Object abspath
;
2207 Lisp_Object handler
;
2209 abspath
= Fexpand_file_name (filename
, current_buffer
->directory
);
2210 CHECK_NUMBER (mode
, 1);
2212 /* If the file name has special constructs in it,
2213 call the corresponding file handler. */
2214 handler
= Ffind_file_name_handler (abspath
);
2215 if (!NILP (handler
))
2216 return call3 (handler
, Qset_file_modes
, abspath
, mode
);
2219 if (chmod (XSTRING (abspath
)->data
, XINT (mode
)) < 0)
2220 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2222 if (!egetenv ("USE_DOMAIN_ACLS"))
2225 struct timeval tvp
[2];
2227 /* chmod on apollo also change the file's modtime; need to save the
2228 modtime and then restore it. */
2229 if (stat (XSTRING (abspath
)->data
, &st
) < 0)
2231 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2235 if (chmod (XSTRING (abspath
)->data
, XINT (mode
)) < 0)
2236 report_file_error ("Doing chmod", Fcons (abspath
, Qnil
));
2238 /* reset the old accessed and modified times. */
2239 tvp
[0].tv_sec
= st
.st_atime
+ 1; /* +1 due to an Apollo roundoff bug */
2241 tvp
[1].tv_sec
= st
.st_mtime
+ 1; /* +1 due to an Apollo roundoff bug */
2244 if (utimes (XSTRING (abspath
)->data
, tvp
) < 0)
2245 report_file_error ("Doing utimes", Fcons (abspath
, Qnil
));
2252 DEFUN ("set-default-file-modes", Fset_default_file_modes
, Sset_default_file_modes
, 1, 1, 0,
2253 "Set the file permission bits for newly created files.\n\
2254 The argument MODE should be an integer; only the low 9 bits are used.\n\
2255 This setting is inherited by subprocesses.")
2259 CHECK_NUMBER (mode
, 0);
2261 umask ((~ XINT (mode
)) & 0777);
2266 DEFUN ("default-file-modes", Fdefault_file_modes
, Sdefault_file_modes
, 0, 0, 0,
2267 "Return the default file protection for created files.\n\
2268 The value is an integer.")
2274 realmask
= umask (0);
2277 XSET (value
, Lisp_Int
, (~ realmask
) & 0777);
2283 DEFUN ("unix-sync", Funix_sync
, Sunix_sync
, 0, 0, "",
2284 "Tell Unix to finish all pending disk updates.")
2293 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p
, Sfile_newer_than_file_p
, 2, 2, 0,
2294 "Return t if file FILE1 is newer than file FILE2.\n\
2295 If FILE1 does not exist, the answer is nil;\n\
2296 otherwise, if FILE2 does not exist, the answer is t.")
2298 Lisp_Object file1
, file2
;
2300 Lisp_Object abspath1
, abspath2
;
2303 Lisp_Object handler
;
2304 struct gcpro gcpro1
, gcpro2
;
2306 CHECK_STRING (file1
, 0);
2307 CHECK_STRING (file2
, 0);
2310 GCPRO2 (abspath1
, file2
);
2311 abspath1
= expand_and_dir_to_file (file1
, current_buffer
->directory
);
2312 abspath2
= expand_and_dir_to_file (file2
, current_buffer
->directory
);
2315 /* If the file name has special constructs in it,
2316 call the corresponding file handler. */
2317 handler
= Ffind_file_name_handler (abspath1
);
2318 if (!NILP (handler
))
2319 return call3 (handler
, Qfile_newer_than_file_p
, abspath1
, abspath2
);
2321 if (stat (XSTRING (abspath1
)->data
, &st
) < 0)
2324 mtime1
= st
.st_mtime
;
2326 if (stat (XSTRING (abspath2
)->data
, &st
) < 0)
2329 return (mtime1
> st
.st_mtime
) ? Qt
: Qnil
;
2332 DEFUN ("insert-file-contents", Finsert_file_contents
, Sinsert_file_contents
,
2334 "Insert contents of file FILENAME after point.\n\
2335 Returns list of absolute pathname and length of data inserted.\n\
2336 If second argument VISIT is non-nil, the buffer's visited filename\n\
2337 and last save file modtime are set, and it is marked unmodified.\n\
2338 If visiting and the file does not exist, visiting is completed\n\
2339 before the error is signaled.")
2341 Lisp_Object filename
, visit
;
2345 register int inserted
= 0;
2346 register int how_much
;
2347 int count
= specpdl_ptr
- specpdl
;
2348 struct gcpro gcpro1
;
2349 Lisp_Object handler
, val
;
2354 if (!NILP (current_buffer
->read_only
))
2355 Fbarf_if_buffer_read_only();
2357 CHECK_STRING (filename
, 0);
2358 filename
= Fexpand_file_name (filename
, Qnil
);
2360 /* If the file name has special constructs in it,
2361 call the corresponding file handler. */
2362 handler
= Ffind_file_name_handler (filename
);
2363 if (!NILP (handler
))
2365 val
= call3 (handler
, Qinsert_file_contents
, filename
, visit
);
2373 if (stat (XSTRING (filename
)->data
, &st
) < 0
2374 || (fd
= open (XSTRING (filename
)->data
, 0)) < 0)
2376 if ((fd
= open (XSTRING (filename
)->data
, 0)) < 0
2377 || fstat (fd
, &st
) < 0)
2378 #endif /* not APOLLO */
2380 if (fd
>= 0) close (fd
);
2382 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
2388 record_unwind_protect (close_file_unwind
, make_number (fd
));
2391 /* This code will need to be changed in order to work on named
2392 pipes, and it's probably just not worth it. So we should at
2393 least signal an error. */
2394 if ((st
.st_mode
& S_IFMT
) == S_IFSOCK
)
2395 Fsignal (Qfile_error
,
2396 Fcons (build_string ("reading from named pipe"),
2397 Fcons (filename
, Qnil
)));
2400 /* Supposedly happens on VMS. */
2402 error ("File size is negative");
2405 register Lisp_Object temp
;
2407 /* Make sure point-max won't overflow after this insertion. */
2408 XSET (temp
, Lisp_Int
, st
.st_size
+ Z
);
2409 if (st
.st_size
+ Z
!= XINT (temp
))
2410 error ("maximum buffer size exceeded");
2414 prepare_to_modify_buffer (point
, point
);
2417 if (GAP_SIZE
< st
.st_size
)
2418 make_gap (st
.st_size
- GAP_SIZE
);
2422 int try = min (st
.st_size
- inserted
, 64 << 10);
2425 /* Allow quitting out of the actual I/O. */
2428 this = read (fd
, &FETCH_CHAR (point
+ inserted
- 1) + 1, try);
2446 record_insert (point
, inserted
);
2448 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2449 offset_intervals (current_buffer
, point
, inserted
);
2455 /* Discard the unwind protect */
2456 specpdl_ptr
= specpdl
+ count
;
2459 error ("IO error reading %s: %s",
2460 XSTRING (filename
)->data
, err_str (errno
));
2467 current_buffer
->undo_list
= Qnil
;
2469 stat (XSTRING (filename
)->data
, &st
);
2471 current_buffer
->modtime
= st
.st_mtime
;
2472 current_buffer
->save_modified
= MODIFF
;
2473 current_buffer
->auto_save_modified
= MODIFF
;
2474 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2475 #ifdef CLASH_DETECTION
2478 if (!NILP (current_buffer
->filename
))
2479 unlock_file (current_buffer
->filename
);
2480 unlock_file (filename
);
2482 #endif /* CLASH_DETECTION */
2483 current_buffer
->filename
= filename
;
2484 /* If visiting nonexistent file, return nil. */
2485 if (current_buffer
->modtime
== -1)
2486 report_file_error ("Opening input file", Fcons (filename
, Qnil
));
2489 signal_after_change (point
, 0, inserted
);
2492 RETURN_UNGCPRO (val
);
2493 RETURN_UNGCPRO (Fcons (filename
,
2494 Fcons (make_number (inserted
),
2498 DEFUN ("write-region", Fwrite_region
, Swrite_region
, 3, 5,
2499 "r\nFWrite region to file: ",
2500 "Write current region into specified file.\n\
2501 When called from a program, takes three arguments:\n\
2502 START, END and FILENAME. START and END are buffer positions.\n\
2503 Optional fourth argument APPEND if non-nil means\n\
2504 append to existing file contents (if any).\n\
2505 Optional fifth argument VISIT if t means\n\
2506 set the last-save-file-modtime of buffer to this file's modtime\n\
2507 and mark buffer not modified.\n\
2508 If VISIT is a string, it is a second file name;\n\
2509 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
2510 VISIT is also the file name to lock and unlock for clash detection.\n\
2511 If VISIT is neither t nor nil nor a string,\n\
2512 that means do not print the \"Wrote file\" message.\n\
2513 Kludgy feature: if START is a string, then that string is written\n\
2514 to the file, instead of any buffer contents, and END is ignored.")
2515 (start
, end
, filename
, append
, visit
)
2516 Lisp_Object start
, end
, filename
, append
, visit
;
2524 int count
= specpdl_ptr
- specpdl
;
2526 unsigned char *fname
= 0; /* If non-0, original filename (must rename) */
2528 Lisp_Object handler
;
2529 Lisp_Object visit_file
;
2530 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
2532 /* Special kludge to simplify auto-saving */
2535 XFASTINT (start
) = BEG
;
2538 else if (XTYPE (start
) != Lisp_String
)
2539 validate_region (&start
, &end
);
2541 filename
= Fexpand_file_name (filename
, Qnil
);
2542 if (XTYPE (visit
) == Lisp_String
)
2543 visit_file
= Fexpand_file_name (visit
, Qnil
);
2545 visit_file
= filename
;
2547 GCPRO4 (start
, filename
, visit
, visit_file
);
2549 /* If the file name has special constructs in it,
2550 call the corresponding file handler. */
2551 handler
= Ffind_file_name_handler (filename
);
2553 if (!NILP (handler
))
2555 Lisp_Object args
[7];
2558 args
[1] = Qwrite_region
;
2564 val
= Ffuncall (7, args
);
2566 /* Do this before reporting IO error
2567 to avoid a "file has changed on disk" warning on
2568 next attempt to save. */
2569 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2571 current_buffer
->modtime
= 0;
2572 current_buffer
->save_modified
= MODIFF
;
2573 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2574 current_buffer
->filename
= visit_file
;
2580 #ifdef CLASH_DETECTION
2582 lock_file (visit_file
);
2583 #endif /* CLASH_DETECTION */
2585 fn
= XSTRING (filename
)->data
;
2588 desc
= open (fn
, O_WRONLY
);
2592 if (auto_saving
) /* Overwrite any previous version of autosave file */
2594 vms_truncate (fn
); /* if fn exists, truncate to zero length */
2595 desc
= open (fn
, O_RDWR
);
2597 desc
= creat_copy_attrs (XTYPE (current_buffer
->filename
) == Lisp_String
2598 ? XSTRING (current_buffer
->filename
)->data
: 0,
2601 else /* Write to temporary name and rename if no errors */
2603 Lisp_Object temp_name
;
2604 temp_name
= Ffile_name_directory (filename
);
2606 if (!NILP (temp_name
))
2608 temp_name
= Fmake_temp_name (concat2 (temp_name
,
2609 build_string ("$$SAVE$$")));
2610 fname
= XSTRING (filename
)->data
;
2611 fn
= XSTRING (temp_name
)->data
;
2612 desc
= creat_copy_attrs (fname
, fn
);
2615 /* If we can't open the temporary file, try creating a new
2616 version of the original file. VMS "creat" creates a
2617 new version rather than truncating an existing file. */
2620 desc
= creat (fn
, 0666);
2621 #if 0 /* This can clobber an existing file and fail to replace it,
2622 if the user runs out of space. */
2625 /* We can't make a new version;
2626 try to truncate and rewrite existing version if any. */
2628 desc
= open (fn
, O_RDWR
);
2634 desc
= creat (fn
, 0666);
2637 desc
= creat (fn
, auto_saving
? auto_save_mode_bits
: 0666);
2638 #endif /* not VMS */
2644 #ifdef CLASH_DETECTION
2646 if (!auto_saving
) unlock_file (visit_file
);
2648 #endif /* CLASH_DETECTION */
2649 report_file_error ("Opening output file", Fcons (filename
, Qnil
));
2652 record_unwind_protect (close_file_unwind
, make_number (desc
));
2655 if (lseek (desc
, 0, 2) < 0)
2657 #ifdef CLASH_DETECTION
2658 if (!auto_saving
) unlock_file (visit_file
);
2659 #endif /* CLASH_DETECTION */
2660 report_file_error ("Lseek error", Fcons (filename
, Qnil
));
2665 * Kludge Warning: The VMS C RTL likes to insert carriage returns
2666 * if we do writes that don't end with a carriage return. Furthermore
2667 * it cannot handle writes of more then 16K. The modified
2668 * version of "sys_write" in SYSDEP.C (see comment there) copes with
2669 * this EXCEPT for the last record (iff it doesn't end with a carriage
2670 * return). This implies that if your buffer doesn't end with a carriage
2671 * return, you get one free... tough. However it also means that if
2672 * we make two calls to sys_write (a la the following code) you can
2673 * get one at the gap as well. The easiest way to fix this (honest)
2674 * is to move the gap to the next newline (or the end of the buffer).
2679 if (GPT
> BEG
&& GPT_ADDR
[-1] != '\n')
2680 move_gap (find_next_newline (GPT
, 1));
2686 if (XTYPE (start
) == Lisp_String
)
2688 failure
= 0 > e_write (desc
, XSTRING (start
)->data
,
2689 XSTRING (start
)->size
);
2692 else if (XINT (start
) != XINT (end
))
2694 if (XINT (start
) < GPT
)
2696 register int end1
= XINT (end
);
2698 failure
= 0 > e_write (desc
, &FETCH_CHAR (tem
),
2699 min (GPT
, end1
) - tem
);
2703 if (XINT (end
) > GPT
&& !failure
)
2706 tem
= max (tem
, GPT
);
2707 failure
= 0 > e_write (desc
, &FETCH_CHAR (tem
), XINT (end
) - tem
);
2715 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
2716 Disk full in NFS may be reported here. */
2717 /* mib says that closing the file will try to write as fast as NFS can do
2718 it, and that means the fsync here is not crucial for autosave files. */
2719 if (!auto_saving
&& fsync (desc
) < 0)
2720 failure
= 1, save_errno
= errno
;
2723 /* Spurious "file has changed on disk" warnings have been
2724 observed on Suns as well.
2725 It seems that `close' can change the modtime, under nfs.
2727 (This has supposedly been fixed in Sunos 4,
2728 but who knows about all the other machines with NFS?) */
2731 /* On VMS and APOLLO, must do the stat after the close
2732 since closing changes the modtime. */
2735 /* Recall that #if defined does not work on VMS. */
2742 /* NFS can report a write failure now. */
2743 if (close (desc
) < 0)
2744 failure
= 1, save_errno
= errno
;
2747 /* If we wrote to a temporary name and had no errors, rename to real name. */
2751 failure
= (rename (fn
, fname
) != 0), save_errno
= errno
;
2759 /* Discard the unwind protect */
2760 specpdl_ptr
= specpdl
+ count
;
2762 #ifdef CLASH_DETECTION
2764 unlock_file (visit_file
);
2765 #endif /* CLASH_DETECTION */
2767 /* Do this before reporting IO error
2768 to avoid a "file has changed on disk" warning on
2769 next attempt to save. */
2770 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2771 current_buffer
->modtime
= st
.st_mtime
;
2774 error ("IO error writing %s: %s", fn
, err_str (save_errno
));
2776 if (EQ (visit
, Qt
) || XTYPE (visit
) == Lisp_String
)
2778 current_buffer
->save_modified
= MODIFF
;
2779 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
2780 current_buffer
->filename
= visit_file
;
2782 else if (!NILP (visit
))
2786 message ("Wrote %s", XSTRING (visit_file
)->data
);
2792 e_write (desc
, addr
, len
)
2794 register char *addr
;
2797 char buf
[16 * 1024];
2798 register char *p
, *end
;
2800 if (!EQ (current_buffer
->selective_display
, Qt
))
2801 return write (desc
, addr
, len
) - len
;
2805 end
= p
+ sizeof buf
;
2810 if (write (desc
, buf
, sizeof buf
) != sizeof buf
)
2819 if (write (desc
, buf
, p
- buf
) != p
- buf
)
2825 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime
,
2826 Sverify_visited_file_modtime
, 1, 1, 0,
2827 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
2828 This means that the file has not been changed since it was visited or saved.")
2834 Lisp_Object handler
;
2836 CHECK_BUFFER (buf
, 0);
2839 if (XTYPE (b
->filename
) != Lisp_String
) return Qt
;
2840 if (b
->modtime
== 0) return Qt
;
2842 /* If the file name has special constructs in it,
2843 call the corresponding file handler. */
2844 handler
= Ffind_file_name_handler (b
->filename
);
2845 if (!NILP (handler
))
2846 return call2 (handler
, Qverify_visited_file_modtime
, buf
);
2848 if (stat (XSTRING (b
->filename
)->data
, &st
) < 0)
2850 /* If the file doesn't exist now and didn't exist before,
2851 we say that it isn't modified, provided the error is a tame one. */
2852 if (errno
== ENOENT
|| errno
== EACCES
|| errno
== ENOTDIR
)
2857 if (st
.st_mtime
== b
->modtime
2858 /* If both are positive, accept them if they are off by one second. */
2859 || (st
.st_mtime
> 0 && b
->modtime
> 0
2860 && (st
.st_mtime
== b
->modtime
+ 1
2861 || st
.st_mtime
== b
->modtime
- 1)))
2866 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime
,
2867 Sclear_visited_file_modtime
, 0, 0, 0,
2868 "Clear out records of last mod time of visited file.\n\
2869 Next attempt to save will certainly not complain of a discrepancy.")
2872 current_buffer
->modtime
= 0;
2876 DEFUN ("visited-file-modtime", Fvisited_file_modtime
,
2877 Svisited_file_modtime
, 0, 0, 0,
2878 "Return the current buffer's recorded visited file modification time.\n\
2879 The value is a list of the form (HIGH . LOW), like the time values\n\
2880 that `file-attributes' returns.")
2883 return long_to_cons (current_buffer
->modtime
);
2886 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime
,
2887 Sset_visited_file_modtime
, 0, 1, 0,
2888 "Update buffer's recorded modification time from the visited file's time.\n\
2889 Useful if the buffer was not read from the file normally\n\
2890 or if the file itself has been changed for some known benign reason.\n\
2891 An argument specifies the modification time value to use\n\
2892 \(instead of that of the visited file), in the form of a list\n\
2893 \(HIGH . LOW) or (HIGH LOW).")
2895 Lisp_Object time_list
;
2897 if (!NILP (time_list
))
2898 current_buffer
->modtime
= cons_to_long (time_list
);
2901 register Lisp_Object filename
;
2903 Lisp_Object handler
;
2905 filename
= Fexpand_file_name (current_buffer
->filename
, Qnil
);
2907 /* If the file name has special constructs in it,
2908 call the corresponding file handler. */
2909 handler
= Ffind_file_name_handler (filename
);
2910 if (!NILP (handler
))
2911 return call3 (handler
, Qfile_name_directory
, filename
, Qnil
);
2912 else if (stat (XSTRING (filename
)->data
, &st
) >= 0)
2913 current_buffer
->modtime
= st
.st_mtime
;
2922 unsigned char *name
= XSTRING (current_buffer
->name
)->data
;
2925 message ("Autosaving...error for %s", name
);
2926 Fsleep_for (make_number (1), Qnil
);
2927 message ("Autosaving...error!for %s", name
);
2928 Fsleep_for (make_number (1), Qnil
);
2929 message ("Autosaving...error for %s", name
);
2930 Fsleep_for (make_number (1), Qnil
);
2940 /* Get visited file's mode to become the auto save file's mode. */
2941 if (stat (XSTRING (current_buffer
->filename
)->data
, &st
) >= 0)
2942 /* But make sure we can overwrite it later! */
2943 auto_save_mode_bits
= st
.st_mode
| 0600;
2945 auto_save_mode_bits
= 0666;
2948 Fwrite_region (Qnil
, Qnil
,
2949 current_buffer
->auto_save_file_name
,
2953 DEFUN ("do-auto-save", Fdo_auto_save
, Sdo_auto_save
, 0, 2, "",
2954 "Auto-save all buffers that need it.\n\
2955 This is all buffers that have auto-saving enabled\n\
2956 and are changed since last auto-saved.\n\
2957 Auto-saving writes the buffer into a file\n\
2958 so that your editing is not lost if the system crashes.\n\
2959 This file is not the file you visited; that changes only when you save.\n\n\
2960 Non-nil first argument means do not print any message if successful.\n\
2961 Non-nil second argument means save only current buffer.")
2962 (no_message
, current_only
)
2963 Lisp_Object no_message
, current_only
;
2965 struct buffer
*old
= current_buffer
, *b
;
2966 Lisp_Object tail
, buf
;
2968 char *omessage
= echo_area_glyphs
;
2969 extern int minibuf_level
;
2970 int do_handled_files
;
2972 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
2973 point to non-strings reached from Vbuffer_alist. */
2979 /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
2980 eventually call do-auto-save, so don't err here in that case. */
2981 if (!NILP (Vrun_hooks
))
2982 call1 (Vrun_hooks
, intern ("auto-save-hook"));
2984 /* First, save all files which don't have handlers. If Emacs is
2985 crashing, the handlers may tweak what is causing Emacs to crash
2986 in the first place, and it would be a shame if Emacs failed to
2987 autosave perfectly ordinary files because it couldn't handle some
2989 for (do_handled_files
= 0; do_handled_files
< 2; do_handled_files
++)
2990 for (tail
= Vbuffer_alist
; XGCTYPE (tail
) == Lisp_Cons
;
2991 tail
= XCONS (tail
)->cdr
)
2993 buf
= XCONS (XCONS (tail
)->car
)->cdr
;
2996 if (!NILP (current_only
)
2997 && b
!= current_buffer
)
3000 /* Check for auto save enabled
3001 and file changed since last auto save
3002 and file changed since last real save. */
3003 if (XTYPE (b
->auto_save_file_name
) == Lisp_String
3004 && b
->save_modified
< BUF_MODIFF (b
)
3005 && b
->auto_save_modified
< BUF_MODIFF (b
)
3006 && (do_handled_files
3007 || NILP (Ffind_file_name_handler (b
->auto_save_file_name
))))
3009 if ((XFASTINT (b
->save_length
) * 10
3010 > (BUF_Z (b
) - BUF_BEG (b
)) * 13)
3011 /* A short file is likely to change a large fraction;
3012 spare the user annoying messages. */
3013 && XFASTINT (b
->save_length
) > 5000
3014 /* These messages are frequent and annoying for `*mail*'. */
3015 && !EQ (b
->filename
, Qnil
)
3016 && NILP (no_message
))
3018 /* It has shrunk too much; turn off auto-saving here. */
3019 message ("Buffer %s has shrunk a lot; auto save turned off there",
3020 XSTRING (b
->name
)->data
);
3021 /* User can reenable saving with M-x auto-save. */
3022 b
->auto_save_file_name
= Qnil
;
3023 /* Prevent warning from repeating if user does so. */
3024 XFASTINT (b
->save_length
) = 0;
3025 Fsleep_for (make_number (1), Qnil
);
3028 set_buffer_internal (b
);
3029 if (!auto_saved
&& NILP (no_message
))
3030 message1 ("Auto-saving...");
3031 internal_condition_case (auto_save_1
, Qt
, auto_save_error
);
3033 b
->auto_save_modified
= BUF_MODIFF (b
);
3034 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
3035 set_buffer_internal (old
);
3039 /* Prevent another auto save till enough input events come in. */
3040 record_auto_save ();
3042 if (auto_saved
&& NILP (no_message
))
3043 message1 (omessage
? omessage
: "Auto-saving...done");
3049 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved
,
3050 Sset_buffer_auto_saved
, 0, 0, 0,
3051 "Mark current buffer as auto-saved with its current text.\n\
3052 No auto-save file will be written until the buffer changes again.")
3055 current_buffer
->auto_save_modified
= MODIFF
;
3056 XFASTINT (current_buffer
->save_length
) = Z
- BEG
;
3060 DEFUN ("recent-auto-save-p", Frecent_auto_save_p
, Srecent_auto_save_p
,
3062 "Return t if buffer has been auto-saved since last read in or saved.")
3065 return (current_buffer
->save_modified
< current_buffer
->auto_save_modified
) ? Qt
: Qnil
;
3068 /* Reading and completing file names */
3069 extern Lisp_Object
Ffile_name_completion (), Ffile_name_all_completions ();
3071 DEFUN ("read-file-name-internal", Fread_file_name_internal
, Sread_file_name_internal
,
3073 "Internal subroutine for read-file-name. Do not call this.")
3074 (string
, dir
, action
)
3075 Lisp_Object string
, dir
, action
;
3076 /* action is nil for complete, t for return list of completions,
3077 lambda for verify final value */
3079 Lisp_Object name
, specdir
, realdir
, val
, orig_string
;
3081 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
3088 /* No need to protect ACTION--we only compare it with t and nil. */
3089 GCPRO4 (string
, realdir
, name
, specdir
);
3091 if (XSTRING (string
)->size
== 0)
3093 if (EQ (action
, Qlambda
))
3101 orig_string
= string
;
3102 string
= Fsubstitute_in_file_name (string
);
3103 changed
= NILP (Fstring_equal (string
, orig_string
));
3104 name
= Ffile_name_nondirectory (string
);
3105 val
= Ffile_name_directory (string
);
3107 realdir
= Fexpand_file_name (val
, realdir
);
3112 specdir
= Ffile_name_directory (string
);
3113 val
= Ffile_name_completion (name
, realdir
);
3115 if (XTYPE (val
) != Lisp_String
)
3122 if (!NILP (specdir
))
3123 val
= concat2 (specdir
, val
);
3126 register unsigned char *old
, *new;
3130 osize
= XSTRING (val
)->size
;
3131 /* Quote "$" as "$$" to get it past substitute-in-file-name */
3132 for (n
= osize
, count
= 0, old
= XSTRING (val
)->data
; n
> 0; n
--)
3133 if (*old
++ == '$') count
++;
3136 old
= XSTRING (val
)->data
;
3137 val
= Fmake_string (make_number (osize
+ count
), make_number (0));
3138 new = XSTRING (val
)->data
;
3139 for (n
= osize
; n
> 0; n
--)
3150 #endif /* Not VMS */
3155 if (EQ (action
, Qt
))
3156 return Ffile_name_all_completions (name
, realdir
);
3157 /* Only other case actually used is ACTION = lambda */
3159 /* Supposedly this helps commands such as `cd' that read directory names,
3160 but can someone explain how it helps them? -- RMS */
3161 if (XSTRING (name
)->size
== 0)
3164 return Ffile_exists_p (string
);
3167 DEFUN ("read-file-name", Fread_file_name
, Sread_file_name
, 1, 5, 0,
3168 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3169 Value is not expanded---you must call `expand-file-name' yourself.\n\
3170 Default name to DEFAULT if user enters a null string.\n\
3171 (If DEFAULT is omitted, the visited file name is used.)\n\
3172 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3173 Non-nil and non-t means also require confirmation after completion.\n\
3174 Fifth arg INITIAL specifies text to start with.\n\
3175 DIR defaults to current buffer's directory default.")
3176 (prompt
, dir
, defalt
, mustmatch
, initial
)
3177 Lisp_Object prompt
, dir
, defalt
, mustmatch
, initial
;
3179 Lisp_Object val
, insdef
, insdef1
, tem
;
3180 struct gcpro gcpro1
, gcpro2
;
3181 register char *homedir
;
3185 dir
= current_buffer
->directory
;
3187 defalt
= current_buffer
->filename
;
3189 /* If dir starts with user's homedir, change that to ~. */
3190 homedir
= (char *) egetenv ("HOME");
3192 && XTYPE (dir
) == Lisp_String
3193 && !strncmp (homedir
, XSTRING (dir
)->data
, strlen (homedir
))
3194 && XSTRING (dir
)->data
[strlen (homedir
)] == '/')
3196 dir
= make_string (XSTRING (dir
)->data
+ strlen (homedir
) - 1,
3197 XSTRING (dir
)->size
- strlen (homedir
) + 1);
3198 XSTRING (dir
)->data
[0] = '~';
3201 if (insert_default_directory
)
3205 if (!NILP (initial
))
3207 Lisp_Object args
[2], pos
;
3211 insdef
= Fconcat (2, args
);
3212 pos
= make_number (XSTRING (dir
)->size
);
3213 insdef1
= Fcons (insdef
, pos
);
3217 insdef
= Qnil
, insdef1
= Qnil
;
3220 count
= specpdl_ptr
- specpdl
;
3221 specbind (intern ("completion-ignore-case"), Qt
);
3224 GCPRO2 (insdef
, defalt
);
3225 val
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
3226 dir
, mustmatch
, insdef1
,
3227 Qfile_name_history
);
3230 unbind_to (count
, Qnil
);
3235 error ("No file name specified");
3236 tem
= Fstring_equal (val
, insdef
);
3237 if (!NILP (tem
) && !NILP (defalt
))
3239 if (XSTRING (val
)->size
== 0 && NILP (insdef
))
3241 return Fsubstitute_in_file_name (val
);
3244 #if 0 /* Old version */
3245 DEFUN ("read-file-name", Fread_file_name
, Sread_file_name
, 1, 5, 0,
3246 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3247 Value is not expanded---you must call `expand-file-name' yourself.\n\
3248 Default name to DEFAULT if user enters a null string.\n\
3249 (If DEFAULT is omitted, the visited file name is used.)\n\
3250 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3251 Non-nil and non-t means also require confirmation after completion.\n\
3252 Fifth arg INITIAL specifies text to start with.\n\
3253 DIR defaults to current buffer's directory default.")
3254 (prompt
, dir
, defalt
, mustmatch
, initial
)
3255 Lisp_Object prompt
, dir
, defalt
, mustmatch
, initial
;
3257 Lisp_Object val
, insdef
, tem
;
3258 struct gcpro gcpro1
, gcpro2
;
3259 register char *homedir
;
3263 dir
= current_buffer
->directory
;
3265 defalt
= current_buffer
->filename
;
3267 /* If dir starts with user's homedir, change that to ~. */
3268 homedir
= (char *) egetenv ("HOME");
3270 && XTYPE (dir
) == Lisp_String
3271 && !strncmp (homedir
, XSTRING (dir
)->data
, strlen (homedir
))
3272 && XSTRING (dir
)->data
[strlen (homedir
)] == '/')
3274 dir
= make_string (XSTRING (dir
)->data
+ strlen (homedir
) - 1,
3275 XSTRING (dir
)->size
- strlen (homedir
) + 1);
3276 XSTRING (dir
)->data
[0] = '~';
3279 if (!NILP (initial
))
3281 else if (insert_default_directory
)
3284 insdef
= build_string ("");
3287 count
= specpdl_ptr
- specpdl
;
3288 specbind (intern ("completion-ignore-case"), Qt
);
3291 GCPRO2 (insdef
, defalt
);
3292 val
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
3294 insert_default_directory
? insdef
: Qnil
,
3295 Qfile_name_history
);
3298 unbind_to (count
, Qnil
);
3303 error ("No file name specified");
3304 tem
= Fstring_equal (val
, insdef
);
3305 if (!NILP (tem
) && !NILP (defalt
))
3307 return Fsubstitute_in_file_name (val
);
3309 #endif /* Old version */
3313 Qexpand_file_name
= intern ("expand-file-name");
3314 Qdirectory_file_name
= intern ("directory-file-name");
3315 Qfile_name_directory
= intern ("file-name-directory");
3316 Qfile_name_nondirectory
= intern ("file-name-nondirectory");
3317 Qunhandled_file_name_directory
= intern ("unhandled-file-name-directory");
3318 Qfile_name_as_directory
= intern ("file-name-as-directory");
3319 Qcopy_file
= intern ("copy-file");
3320 Qmake_directory
= intern ("make-directory");
3321 Qdelete_directory
= intern ("delete-directory");
3322 Qdelete_file
= intern ("delete-file");
3323 Qrename_file
= intern ("rename-file");
3324 Qadd_name_to_file
= intern ("add-name-to-file");
3325 Qmake_symbolic_link
= intern ("make-symbolic-link");
3326 Qfile_exists_p
= intern ("file-exists-p");
3327 Qfile_executable_p
= intern ("file-executable-p");
3328 Qfile_readable_p
= intern ("file-readable-p");
3329 Qfile_symlink_p
= intern ("file-symlink-p");
3330 Qfile_writable_p
= intern ("file-writable-p");
3331 Qfile_directory_p
= intern ("file-directory-p");
3332 Qfile_accessible_directory_p
= intern ("file-accessible-directory-p");
3333 Qfile_modes
= intern ("file-modes");
3334 Qset_file_modes
= intern ("set-file-modes");
3335 Qfile_newer_than_file_p
= intern ("file-newer-than-file-p");
3336 Qinsert_file_contents
= intern ("insert-file-contents");
3337 Qwrite_region
= intern ("write-region");
3338 Qverify_visited_file_modtime
= intern ("verify-visited-file-modtime");
3340 staticpro (&Qexpand_file_name
);
3341 staticpro (&Qdirectory_file_name
);
3342 staticpro (&Qfile_name_directory
);
3343 staticpro (&Qfile_name_nondirectory
);
3344 staticpro (&Qunhandled_file_name_directory
);
3345 staticpro (&Qfile_name_as_directory
);
3346 staticpro (&Qcopy_file
);
3347 staticpro (&Qmake_directory
);
3348 staticpro (&Qdelete_directory
);
3349 staticpro (&Qdelete_file
);
3350 staticpro (&Qrename_file
);
3351 staticpro (&Qadd_name_to_file
);
3352 staticpro (&Qmake_symbolic_link
);
3353 staticpro (&Qfile_exists_p
);
3354 staticpro (&Qfile_executable_p
);
3355 staticpro (&Qfile_readable_p
);
3356 staticpro (&Qfile_symlink_p
);
3357 staticpro (&Qfile_writable_p
);
3358 staticpro (&Qfile_directory_p
);
3359 staticpro (&Qfile_accessible_directory_p
);
3360 staticpro (&Qfile_modes
);
3361 staticpro (&Qset_file_modes
);
3362 staticpro (&Qfile_newer_than_file_p
);
3363 staticpro (&Qinsert_file_contents
);
3364 staticpro (&Qwrite_region
);
3365 staticpro (&Qverify_visited_file_modtime
);
3367 Qfile_name_history
= intern ("file-name-history");
3368 Fset (Qfile_name_history
, Qnil
);
3369 staticpro (&Qfile_name_history
);
3371 Qfile_error
= intern ("file-error");
3372 staticpro (&Qfile_error
);
3373 Qfile_already_exists
= intern("file-already-exists");
3374 staticpro (&Qfile_already_exists
);
3376 Fput (Qfile_error
, Qerror_conditions
,
3377 Fcons (Qfile_error
, Fcons (Qerror
, Qnil
)));
3378 Fput (Qfile_error
, Qerror_message
,
3379 build_string ("File error"));
3381 Fput (Qfile_already_exists
, Qerror_conditions
,
3382 Fcons (Qfile_already_exists
,
3383 Fcons (Qfile_error
, Fcons (Qerror
, Qnil
))));
3384 Fput (Qfile_already_exists
, Qerror_message
,
3385 build_string ("File already exists"));
3387 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory
,
3388 "*Non-nil means when reading a filename start with default dir in minibuffer.");
3389 insert_default_directory
= 1;
3391 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm
,
3392 "*Non-nil means write new files with record format `stmlf'.\n\
3393 nil means use format `var'. This variable is meaningful only on VMS.");
3394 vms_stmlf_recfm
= 0;
3396 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist
,
3397 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
3398 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
3401 The first argument given to HANDLER is the name of the I/O primitive\n\
3402 to be handled; the remaining arguments are the arguments that were\n\
3403 passed to that primitive. For example, if you do\n\
3404 (file-exists-p FILENAME)\n\
3405 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
3406 (funcall HANDLER 'file-exists-p FILENAME)\n\
3407 The function `find-file-name-handler' checks this list for a handler\n\
3408 for its argument.");
3409 Vfile_name_handler_alist
= Qnil
;
3411 defsubr (&Sfind_file_name_handler
);
3412 defsubr (&Sfile_name_directory
);
3413 defsubr (&Sfile_name_nondirectory
);
3414 defsubr (&Sunhandled_file_name_directory
);
3415 defsubr (&Sfile_name_as_directory
);
3416 defsubr (&Sdirectory_file_name
);
3417 defsubr (&Smake_temp_name
);
3418 defsubr (&Sexpand_file_name
);
3419 defsubr (&Ssubstitute_in_file_name
);
3420 defsubr (&Scopy_file
);
3421 defsubr (&Smake_directory_internal
);
3422 defsubr (&Sdelete_directory
);
3423 defsubr (&Sdelete_file
);
3424 defsubr (&Srename_file
);
3425 defsubr (&Sadd_name_to_file
);
3427 defsubr (&Smake_symbolic_link
);
3428 #endif /* S_IFLNK */
3430 defsubr (&Sdefine_logical_name
);
3433 defsubr (&Ssysnetunam
);
3434 #endif /* HPUX_NET */
3435 defsubr (&Sfile_name_absolute_p
);
3436 defsubr (&Sfile_exists_p
);
3437 defsubr (&Sfile_executable_p
);
3438 defsubr (&Sfile_readable_p
);
3439 defsubr (&Sfile_writable_p
);
3440 defsubr (&Sfile_symlink_p
);
3441 defsubr (&Sfile_directory_p
);
3442 defsubr (&Sfile_accessible_directory_p
);
3443 defsubr (&Sfile_modes
);
3444 defsubr (&Sset_file_modes
);
3445 defsubr (&Sset_default_file_modes
);
3446 defsubr (&Sdefault_file_modes
);
3447 defsubr (&Sfile_newer_than_file_p
);
3448 defsubr (&Sinsert_file_contents
);
3449 defsubr (&Swrite_region
);
3450 defsubr (&Sverify_visited_file_modtime
);
3451 defsubr (&Sclear_visited_file_modtime
);
3452 defsubr (&Svisited_file_modtime
);
3453 defsubr (&Sset_visited_file_modtime
);
3454 defsubr (&Sdo_auto_save
);
3455 defsubr (&Sset_buffer_auto_saved
);
3456 defsubr (&Srecent_auto_save_p
);
3458 defsubr (&Sread_file_name_internal
);
3459 defsubr (&Sread_file_name
);
3462 defsubr (&Sunix_sync
);