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