comparison src/fileio.c @ 0:376386a54a3c r19-14

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