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