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