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