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