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