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