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