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