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