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