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