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