]> code.delx.au - gnu-emacs/blob - src/fileio.c
(Finsert_file_contents): Fix previous change.
[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 /* Encode the file name NAME using the specified coding system
156 for file names, if any. */
157 #define ENCODE_FILE(name) \
158 (! NILP (Vfile_name_coding_system) \
159 && XFASTINT (Vfile_name_coding_system) != 0 \
160 ? Fencode_coding_string (name, Vfile_name_coding_system, Qt) \
161 : name)
162
163 /* Nonzero during writing of auto-save files */
164 int auto_saving;
165
166 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
167 a new file with the same mode as the original */
168 int auto_save_mode_bits;
169
170 /* Coding system for file names, or nil if none. */
171 Lisp_Object Vfile_name_coding_system;
172
173 /* Alist of elements (REGEXP . HANDLER) for file names
174 whose I/O is done with a special handler. */
175 Lisp_Object Vfile_name_handler_alist;
176
177 /* Format for auto-save files */
178 Lisp_Object Vauto_save_file_format;
179
180 /* Lisp functions for translating file formats */
181 Lisp_Object Qformat_decode, Qformat_annotate_function;
182
183 /* Function to be called to decide a coding system of a reading file. */
184 Lisp_Object Vset_auto_coding_function;
185
186 /* Functions to be called to process text properties in inserted file. */
187 Lisp_Object Vafter_insert_file_functions;
188
189 /* Functions to be called to create text property annotations for file. */
190 Lisp_Object Vwrite_region_annotate_functions;
191
192 /* During build_annotations, each time an annotation function is called,
193 this holds the annotations made by the previous functions. */
194 Lisp_Object Vwrite_region_annotations_so_far;
195
196 /* File name in which we write a list of all our auto save files. */
197 Lisp_Object Vauto_save_list_file_name;
198
199 /* Nonzero means, when reading a filename in the minibuffer,
200 start out by inserting the default directory into the minibuffer. */
201 int insert_default_directory;
202
203 /* On VMS, nonzero means write new files with record format stmlf.
204 Zero means use var format. */
205 int vms_stmlf_recfm;
206
207 /* On NT, specifies the directory separator character, used (eg.) when
208 expanding file names. This can be bound to / or \. */
209 Lisp_Object Vdirectory_sep_char;
210
211 extern Lisp_Object Vuser_login_name;
212
213 extern int minibuf_level;
214
215 extern int minibuffer_auto_raise;
216
217 /* These variables describe handlers that have "already" had a chance
218 to handle the current operation.
219
220 Vinhibit_file_name_handlers is a list of file name handlers.
221 Vinhibit_file_name_operation is the operation being handled.
222 If we try to handle that operation, we ignore those handlers. */
223
224 static Lisp_Object Vinhibit_file_name_handlers;
225 static Lisp_Object Vinhibit_file_name_operation;
226
227 Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
228
229 Lisp_Object Qfile_name_history;
230
231 Lisp_Object Qcar_less_than_car;
232
233 static int a_write P_ ((int, char *, int, int,
234 Lisp_Object *, struct coding_system *));
235 static int e_write P_ ((int, char *, int, struct coding_system *));
236 \f
237 void
238 report_file_error (string, data)
239 char *string;
240 Lisp_Object data;
241 {
242 Lisp_Object errstring;
243
244 errstring = build_string (strerror (errno));
245
246 /* System error messages are capitalized. Downcase the initial
247 unless it is followed by a slash. */
248 if (XSTRING (errstring)->data[1] != '/')
249 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
250
251 while (1)
252 Fsignal (Qfile_error,
253 Fcons (build_string (string), Fcons (errstring, data)));
254 }
255
256 Lisp_Object
257 close_file_unwind (fd)
258 Lisp_Object fd;
259 {
260 close (XFASTINT (fd));
261 return Qnil;
262 }
263
264 /* Restore point, having saved it as a marker. */
265
266 static Lisp_Object
267 restore_point_unwind (location)
268 Lisp_Object location;
269 {
270 Fgoto_char (location);
271 Fset_marker (location, Qnil, Qnil);
272 return Qnil;
273 }
274 \f
275 Lisp_Object Qexpand_file_name;
276 Lisp_Object Qsubstitute_in_file_name;
277 Lisp_Object Qdirectory_file_name;
278 Lisp_Object Qfile_name_directory;
279 Lisp_Object Qfile_name_nondirectory;
280 Lisp_Object Qunhandled_file_name_directory;
281 Lisp_Object Qfile_name_as_directory;
282 Lisp_Object Qcopy_file;
283 Lisp_Object Qmake_directory_internal;
284 Lisp_Object Qdelete_directory;
285 Lisp_Object Qdelete_file;
286 Lisp_Object Qrename_file;
287 Lisp_Object Qadd_name_to_file;
288 Lisp_Object Qmake_symbolic_link;
289 Lisp_Object Qfile_exists_p;
290 Lisp_Object Qfile_executable_p;
291 Lisp_Object Qfile_readable_p;
292 Lisp_Object Qfile_writable_p;
293 Lisp_Object Qfile_symlink_p;
294 Lisp_Object Qaccess_file;
295 Lisp_Object Qfile_directory_p;
296 Lisp_Object Qfile_regular_p;
297 Lisp_Object Qfile_accessible_directory_p;
298 Lisp_Object Qfile_modes;
299 Lisp_Object Qset_file_modes;
300 Lisp_Object Qfile_newer_than_file_p;
301 Lisp_Object Qinsert_file_contents;
302 Lisp_Object Qwrite_region;
303 Lisp_Object Qverify_visited_file_modtime;
304 Lisp_Object Qset_visited_file_modtime;
305
306 DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
307 "Return FILENAME's handler function for OPERATION, if it has one.\n\
308 Otherwise, return nil.\n\
309 A file name is handled if one of the regular expressions in\n\
310 `file-name-handler-alist' matches it.\n\n\
311 If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
312 any handlers that are members of `inhibit-file-name-handlers',\n\
313 but we still do run any other handlers. This lets handlers\n\
314 use the standard functions without calling themselves recursively.")
315 (filename, operation)
316 Lisp_Object filename, operation;
317 {
318 /* This function must not munge the match data. */
319 Lisp_Object chain, inhibited_handlers;
320
321 CHECK_STRING (filename, 0);
322
323 if (EQ (operation, Vinhibit_file_name_operation))
324 inhibited_handlers = Vinhibit_file_name_handlers;
325 else
326 inhibited_handlers = Qnil;
327
328 for (chain = Vfile_name_handler_alist; CONSP (chain);
329 chain = XCONS (chain)->cdr)
330 {
331 Lisp_Object elt;
332 elt = XCONS (chain)->car;
333 if (CONSP (elt))
334 {
335 Lisp_Object string;
336 string = XCONS (elt)->car;
337 if (STRINGP (string) && fast_string_match (string, filename) >= 0)
338 {
339 Lisp_Object handler, tem;
340
341 handler = XCONS (elt)->cdr;
342 tem = Fmemq (handler, inhibited_handlers);
343 if (NILP (tem))
344 return handler;
345 }
346 }
347
348 QUIT;
349 }
350 return Qnil;
351 }
352 \f
353 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
354 1, 1, 0,
355 "Return the directory component in file name FILENAME.\n\
356 Return nil if FILENAME does not include a directory.\n\
357 Otherwise return a directory spec.\n\
358 Given a Unix syntax file name, returns a string ending in slash;\n\
359 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
360 (filename)
361 Lisp_Object filename;
362 {
363 register unsigned char *beg;
364 register unsigned char *p;
365 Lisp_Object handler;
366
367 CHECK_STRING (filename, 0);
368
369 /* If the file name has special constructs in it,
370 call the corresponding file handler. */
371 handler = Ffind_file_name_handler (filename, Qfile_name_directory);
372 if (!NILP (handler))
373 return call2 (handler, Qfile_name_directory, filename);
374
375 #ifdef FILE_SYSTEM_CASE
376 filename = FILE_SYSTEM_CASE (filename);
377 #endif
378 beg = XSTRING (filename)->data;
379 #ifdef DOS_NT
380 beg = strcpy (alloca (strlen (beg) + 1), beg);
381 #endif
382 p = beg + XSTRING (filename)->size;
383
384 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
385 #ifdef VMS
386 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
387 #endif /* VMS */
388 #ifdef DOS_NT
389 /* only recognise drive specifier at beginning */
390 && !(p[-1] == ':' && p == beg + 2)
391 #endif
392 ) p--;
393
394 if (p == beg)
395 return Qnil;
396 #ifdef DOS_NT
397 /* Expansion of "c:" to drive and default directory. */
398 if (p == beg + 2 && beg[1] == ':')
399 {
400 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
401 unsigned char *res = alloca (MAXPATHLEN + 1);
402 if (getdefdir (toupper (*beg) - 'A' + 1, res))
403 {
404 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
405 strcat (res, "/");
406 beg = res;
407 p = beg + strlen (beg);
408 }
409 }
410 CORRECT_DIR_SEPS (beg);
411 #endif /* DOS_NT */
412
413 if (STRING_MULTIBYTE (filename))
414 return make_string (beg, p - beg);
415 return make_unibyte_string (beg, p - beg);
416 }
417
418 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory,
419 Sfile_name_nondirectory, 1, 1, 0,
420 "Return file name FILENAME sans its directory.\n\
421 For example, in a Unix-syntax file name,\n\
422 this is everything after the last slash,\n\
423 or the entire name if it contains no slash.")
424 (filename)
425 Lisp_Object filename;
426 {
427 register unsigned char *beg, *p, *end;
428 Lisp_Object handler;
429
430 CHECK_STRING (filename, 0);
431
432 /* If the file name has special constructs in it,
433 call the corresponding file handler. */
434 handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory);
435 if (!NILP (handler))
436 return call2 (handler, Qfile_name_nondirectory, filename);
437
438 beg = XSTRING (filename)->data;
439 end = p = beg + XSTRING (filename)->size;
440
441 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
442 #ifdef VMS
443 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
444 #endif /* VMS */
445 #ifdef DOS_NT
446 /* only recognise drive specifier at beginning */
447 && !(p[-1] == ':' && p == beg + 2)
448 #endif
449 )
450 p--;
451
452 if (STRING_MULTIBYTE (filename))
453 return make_string (p, end - p);
454 return make_unibyte_string (p, end - p);
455 }
456
457 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
458 Sunhandled_file_name_directory, 1, 1, 0,
459 "Return a directly usable directory name somehow associated with FILENAME.\n\
460 A `directly usable' directory name is one that may be used without the\n\
461 intervention of any file handler.\n\
462 If FILENAME is a directly usable file itself, return\n\
463 \(file-name-directory FILENAME).\n\
464 The `call-process' and `start-process' functions use this function to\n\
465 get a current directory to run processes in.")
466 (filename)
467 Lisp_Object filename;
468 {
469 Lisp_Object handler;
470
471 /* If the file name has special constructs in it,
472 call the corresponding file handler. */
473 handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
474 if (!NILP (handler))
475 return call2 (handler, Qunhandled_file_name_directory, filename);
476
477 return Ffile_name_directory (filename);
478 }
479
480 \f
481 char *
482 file_name_as_directory (out, in)
483 char *out, *in;
484 {
485 int size = strlen (in) - 1;
486
487 if (size < 0)
488 error ("Empty file name");
489
490 strcpy (out, in);
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 + 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 + 20 + 255);
784 #else
785 buf = (char *) alloca (XSTRING (directory)->size + 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;
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 + 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 - 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 - 1])
2029 && !IS_DEVICE_SEP (XSTRING (absname)->data[XSTRING (absname)->size-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 *STATPTR is used to store the stat information if the file exists.
2042 If the file does not exist, STATPTR->st_mode is set to 0. */
2043
2044 void
2045 barf_or_query_if_file_exists (absname, querystring, interactive, statptr)
2046 Lisp_Object absname;
2047 unsigned char *querystring;
2048 int interactive;
2049 struct stat *statptr;
2050 {
2051 register Lisp_Object tem;
2052 struct stat statbuf;
2053 struct gcpro gcpro1;
2054
2055 /* stat is a good way to tell whether the file exists,
2056 regardless of what access permissions it has. */
2057 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
2058 {
2059 if (! interactive)
2060 Fsignal (Qfile_already_exists,
2061 Fcons (build_string ("File already exists"),
2062 Fcons (absname, Qnil)));
2063 GCPRO1 (absname);
2064 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
2065 XSTRING (absname)->data, querystring));
2066 UNGCPRO;
2067 if (NILP (tem))
2068 Fsignal (Qfile_already_exists,
2069 Fcons (build_string ("File already exists"),
2070 Fcons (absname, Qnil)));
2071 if (statptr)
2072 *statptr = statbuf;
2073 }
2074 else
2075 {
2076 if (statptr)
2077 statptr->st_mode = 0;
2078 }
2079 return;
2080 }
2081
2082 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
2083 "fCopy file: \nFCopy %s to file: \np\nP",
2084 "Copy FILE to NEWNAME. Both args must be strings.\n\
2085 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
2086 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
2087 A number as third arg means request confirmation if NEWNAME already exists.\n\
2088 This is what happens in interactive use with M-x.\n\
2089 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
2090 last-modified time as the old one. (This works on only some systems.)\n\
2091 A prefix arg makes KEEP-TIME non-nil.")
2092 (file, newname, ok_if_already_exists, keep_date)
2093 Lisp_Object file, newname, ok_if_already_exists, keep_date;
2094 {
2095 int ifd, ofd, n;
2096 char buf[16 * 1024];
2097 struct stat st, out_st;
2098 Lisp_Object handler;
2099 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2100 int count = specpdl_ptr - specpdl;
2101 int input_file_statable_p;
2102 Lisp_Object encoded_file, encoded_newname;
2103
2104 encoded_file = encoded_newname = Qnil;
2105 GCPRO4 (file, newname, encoded_file, encoded_newname);
2106 CHECK_STRING (file, 0);
2107 CHECK_STRING (newname, 1);
2108
2109 file = Fexpand_file_name (file, Qnil);
2110 newname = Fexpand_file_name (newname, Qnil);
2111
2112 /* If the input file name has special constructs in it,
2113 call the corresponding file handler. */
2114 handler = Ffind_file_name_handler (file, Qcopy_file);
2115 /* Likewise for output file name. */
2116 if (NILP (handler))
2117 handler = Ffind_file_name_handler (newname, Qcopy_file);
2118 if (!NILP (handler))
2119 RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
2120 ok_if_already_exists, keep_date));
2121
2122 encoded_file = ENCODE_FILE (file);
2123 encoded_newname = ENCODE_FILE (newname);
2124
2125 if (NILP (ok_if_already_exists)
2126 || INTEGERP (ok_if_already_exists))
2127 barf_or_query_if_file_exists (encoded_newname, "copy to it",
2128 INTEGERP (ok_if_already_exists), &out_st);
2129 else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
2130 out_st.st_mode = 0;
2131
2132 ifd = open (XSTRING (encoded_file)->data, O_RDONLY);
2133 if (ifd < 0)
2134 report_file_error ("Opening input file", Fcons (file, Qnil));
2135
2136 record_unwind_protect (close_file_unwind, make_number (ifd));
2137
2138 /* We can only copy regular files and symbolic links. Other files are not
2139 copyable by us. */
2140 input_file_statable_p = (fstat (ifd, &st) >= 0);
2141
2142 #if !defined (MSDOS) || __DJGPP__ > 1
2143 if (out_st.st_mode != 0
2144 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2145 {
2146 errno = 0;
2147 report_file_error ("Input and output files are the same",
2148 Fcons (file, Fcons (newname, Qnil)));
2149 }
2150 #endif
2151
2152 #if defined (S_ISREG) && defined (S_ISLNK)
2153 if (input_file_statable_p)
2154 {
2155 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
2156 {
2157 #if defined (EISDIR)
2158 /* Get a better looking error message. */
2159 errno = EISDIR;
2160 #endif /* EISDIR */
2161 report_file_error ("Non-regular file", Fcons (file, Qnil));
2162 }
2163 }
2164 #endif /* S_ISREG && S_ISLNK */
2165
2166 #ifdef VMS
2167 /* Create the copy file with the same record format as the input file */
2168 ofd = sys_creat (XSTRING (encoded_newname)->data, 0666, ifd);
2169 #else
2170 #ifdef MSDOS
2171 /* System's default file type was set to binary by _fmode in emacs.c. */
2172 ofd = creat (XSTRING (encoded_newname)->data, S_IREAD | S_IWRITE);
2173 #else /* not MSDOS */
2174 ofd = creat (XSTRING (encoded_newname)->data, 0666);
2175 #endif /* not MSDOS */
2176 #endif /* VMS */
2177 if (ofd < 0)
2178 report_file_error ("Opening output file", Fcons (newname, Qnil));
2179
2180 record_unwind_protect (close_file_unwind, make_number (ofd));
2181
2182 immediate_quit = 1;
2183 QUIT;
2184 while ((n = read (ifd, buf, sizeof buf)) > 0)
2185 if (write (ofd, buf, n) != n)
2186 report_file_error ("I/O error", Fcons (newname, Qnil));
2187 immediate_quit = 0;
2188
2189 /* Closing the output clobbers the file times on some systems. */
2190 if (close (ofd) < 0)
2191 report_file_error ("I/O error", Fcons (newname, Qnil));
2192
2193 if (input_file_statable_p)
2194 {
2195 if (!NILP (keep_date))
2196 {
2197 EMACS_TIME atime, mtime;
2198 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
2199 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
2200 if (set_file_times (XSTRING (encoded_newname)->data,
2201 atime, mtime))
2202 Fsignal (Qfile_date_error,
2203 Fcons (build_string ("Cannot set file date"),
2204 Fcons (newname, Qnil)));
2205 }
2206 #ifndef MSDOS
2207 chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
2208 #else /* MSDOS */
2209 #if defined (__DJGPP__) && __DJGPP__ > 1
2210 /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
2211 and if it can't, it tells so. Otherwise, under MSDOS we usually
2212 get only the READ bit, which will make the copied file read-only,
2213 so it's better not to chmod at all. */
2214 if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
2215 chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
2216 #endif /* DJGPP version 2 or newer */
2217 #endif /* MSDOS */
2218 }
2219
2220 close (ifd);
2221
2222 /* Discard the unwind protects. */
2223 specpdl_ptr = specpdl + count;
2224
2225 UNGCPRO;
2226 return Qnil;
2227 }
2228 \f
2229 DEFUN ("make-directory-internal", Fmake_directory_internal,
2230 Smake_directory_internal, 1, 1, 0,
2231 "Create a new directory named DIRECTORY.")
2232 (directory)
2233 Lisp_Object directory;
2234 {
2235 unsigned char *dir;
2236 Lisp_Object handler;
2237 Lisp_Object encoded_dir;
2238
2239 CHECK_STRING (directory, 0);
2240 directory = Fexpand_file_name (directory, Qnil);
2241
2242 handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
2243 if (!NILP (handler))
2244 return call2 (handler, Qmake_directory_internal, directory);
2245
2246 encoded_dir = ENCODE_FILE (directory);
2247
2248 dir = XSTRING (encoded_dir)->data;
2249
2250 #ifdef WINDOWSNT
2251 if (mkdir (dir) != 0)
2252 #else
2253 if (mkdir (dir, 0777) != 0)
2254 #endif
2255 report_file_error ("Creating directory", Flist (1, &directory));
2256
2257 return Qnil;
2258 }
2259
2260 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
2261 "Delete the directory named DIRECTORY.")
2262 (directory)
2263 Lisp_Object directory;
2264 {
2265 unsigned char *dir;
2266 Lisp_Object handler;
2267 Lisp_Object encoded_dir;
2268
2269 CHECK_STRING (directory, 0);
2270 directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
2271
2272 handler = Ffind_file_name_handler (directory, Qdelete_directory);
2273 if (!NILP (handler))
2274 return call2 (handler, Qdelete_directory, directory);
2275
2276 encoded_dir = ENCODE_FILE (directory);
2277
2278 dir = XSTRING (encoded_dir)->data;
2279
2280 if (rmdir (dir) != 0)
2281 report_file_error ("Removing directory", Flist (1, &directory));
2282
2283 return Qnil;
2284 }
2285
2286 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
2287 "Delete file named FILENAME.\n\
2288 If file has multiple names, it continues to exist with the other names.")
2289 (filename)
2290 Lisp_Object filename;
2291 {
2292 Lisp_Object handler;
2293 Lisp_Object encoded_file;
2294
2295 CHECK_STRING (filename, 0);
2296 filename = Fexpand_file_name (filename, Qnil);
2297
2298 handler = Ffind_file_name_handler (filename, Qdelete_file);
2299 if (!NILP (handler))
2300 return call2 (handler, Qdelete_file, filename);
2301
2302 encoded_file = ENCODE_FILE (filename);
2303
2304 if (0 > unlink (XSTRING (encoded_file)->data))
2305 report_file_error ("Removing old name", Flist (1, &filename));
2306 return Qnil;
2307 }
2308
2309 static Lisp_Object
2310 internal_delete_file_1 (ignore)
2311 Lisp_Object ignore;
2312 {
2313 return Qt;
2314 }
2315
2316 /* Delete file FILENAME, returning 1 if successful and 0 if failed. */
2317
2318 int
2319 internal_delete_file (filename)
2320 Lisp_Object filename;
2321 {
2322 return NILP (internal_condition_case_1 (Fdelete_file, filename,
2323 Qt, internal_delete_file_1));
2324 }
2325 \f
2326 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2327 "fRename file: \nFRename %s to file: \np",
2328 "Rename FILE as NEWNAME. Both args strings.\n\
2329 If file has names other than FILE, it continues to have those names.\n\
2330 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2331 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2332 A number as third arg means request confirmation if NEWNAME already exists.\n\
2333 This is what happens in interactive use with M-x.")
2334 (file, newname, ok_if_already_exists)
2335 Lisp_Object file, newname, ok_if_already_exists;
2336 {
2337 #ifdef NO_ARG_ARRAY
2338 Lisp_Object args[2];
2339 #endif
2340 Lisp_Object handler;
2341 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2342 Lisp_Object encoded_file, encoded_newname;
2343
2344 encoded_file = encoded_newname = Qnil;
2345 GCPRO4 (file, newname, encoded_file, encoded_newname);
2346 CHECK_STRING (file, 0);
2347 CHECK_STRING (newname, 1);
2348 file = Fexpand_file_name (file, Qnil);
2349 newname = Fexpand_file_name (newname, Qnil);
2350
2351 /* If the file name has special constructs in it,
2352 call the corresponding file handler. */
2353 handler = Ffind_file_name_handler (file, Qrename_file);
2354 if (NILP (handler))
2355 handler = Ffind_file_name_handler (newname, Qrename_file);
2356 if (!NILP (handler))
2357 RETURN_UNGCPRO (call4 (handler, Qrename_file,
2358 file, newname, ok_if_already_exists));
2359
2360 encoded_file = ENCODE_FILE (file);
2361 encoded_newname = ENCODE_FILE (newname);
2362
2363 if (NILP (ok_if_already_exists)
2364 || INTEGERP (ok_if_already_exists))
2365 barf_or_query_if_file_exists (encoded_newname, "rename to it",
2366 INTEGERP (ok_if_already_exists), 0);
2367 #ifndef BSD4_1
2368 if (0 > rename (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
2369 #else
2370 if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data)
2371 || 0 > unlink (XSTRING (encoded_file)->data))
2372 #endif
2373 {
2374 if (errno == EXDEV)
2375 {
2376 Fcopy_file (file, newname,
2377 /* We have already prompted if it was an integer,
2378 so don't have copy-file prompt again. */
2379 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
2380 Fdelete_file (file);
2381 }
2382 else
2383 #ifdef NO_ARG_ARRAY
2384 {
2385 args[0] = file;
2386 args[1] = newname;
2387 report_file_error ("Renaming", Flist (2, args));
2388 }
2389 #else
2390 report_file_error ("Renaming", Flist (2, &file));
2391 #endif
2392 }
2393 UNGCPRO;
2394 return Qnil;
2395 }
2396
2397 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
2398 "fAdd name to file: \nFName to add to %s: \np",
2399 "Give FILE additional name NEWNAME. Both args strings.\n\
2400 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2401 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2402 A number as third arg means request confirmation if NEWNAME already exists.\n\
2403 This is what happens in interactive use with M-x.")
2404 (file, newname, ok_if_already_exists)
2405 Lisp_Object file, newname, ok_if_already_exists;
2406 {
2407 #ifdef NO_ARG_ARRAY
2408 Lisp_Object args[2];
2409 #endif
2410 Lisp_Object handler;
2411 Lisp_Object encoded_file, encoded_newname;
2412 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2413
2414 GCPRO4 (file, newname, encoded_file, encoded_newname);
2415 encoded_file = encoded_newname = Qnil;
2416 CHECK_STRING (file, 0);
2417 CHECK_STRING (newname, 1);
2418 file = Fexpand_file_name (file, Qnil);
2419 newname = Fexpand_file_name (newname, Qnil);
2420
2421 /* If the file name has special constructs in it,
2422 call the corresponding file handler. */
2423 handler = Ffind_file_name_handler (file, Qadd_name_to_file);
2424 if (!NILP (handler))
2425 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
2426 newname, ok_if_already_exists));
2427
2428 /* If the new name has special constructs in it,
2429 call the corresponding file handler. */
2430 handler = Ffind_file_name_handler (newname, Qadd_name_to_file);
2431 if (!NILP (handler))
2432 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
2433 newname, ok_if_already_exists));
2434
2435 encoded_file = ENCODE_FILE (file);
2436 encoded_newname = ENCODE_FILE (newname);
2437
2438 if (NILP (ok_if_already_exists)
2439 || INTEGERP (ok_if_already_exists))
2440 barf_or_query_if_file_exists (encoded_newname, "make it a new name",
2441 INTEGERP (ok_if_already_exists), 0);
2442
2443 unlink (XSTRING (newname)->data);
2444 if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
2445 {
2446 #ifdef NO_ARG_ARRAY
2447 args[0] = file;
2448 args[1] = newname;
2449 report_file_error ("Adding new name", Flist (2, args));
2450 #else
2451 report_file_error ("Adding new name", Flist (2, &file));
2452 #endif
2453 }
2454
2455 UNGCPRO;
2456 return Qnil;
2457 }
2458
2459 #ifdef S_IFLNK
2460 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2461 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2462 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
2463 Signals a `file-already-exists' error if a file LINKNAME already exists\n\
2464 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2465 A number as third arg means request confirmation if LINKNAME already exists.\n\
2466 This happens for interactive use with M-x.")
2467 (filename, linkname, ok_if_already_exists)
2468 Lisp_Object filename, linkname, ok_if_already_exists;
2469 {
2470 #ifdef NO_ARG_ARRAY
2471 Lisp_Object args[2];
2472 #endif
2473 Lisp_Object handler;
2474 Lisp_Object encoded_filename, encoded_linkname;
2475 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2476
2477 GCPRO4 (filename, linkname, encoded_filename, encoded_linkname);
2478 encoded_filename = encoded_linkname = Qnil;
2479 CHECK_STRING (filename, 0);
2480 CHECK_STRING (linkname, 1);
2481 /* If the link target has a ~, we must expand it to get
2482 a truly valid file name. Otherwise, do not expand;
2483 we want to permit links to relative file names. */
2484 if (XSTRING (filename)->data[0] == '~')
2485 filename = Fexpand_file_name (filename, Qnil);
2486 linkname = Fexpand_file_name (linkname, Qnil);
2487
2488 /* If the file name has special constructs in it,
2489 call the corresponding file handler. */
2490 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
2491 if (!NILP (handler))
2492 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2493 linkname, ok_if_already_exists));
2494
2495 /* If the new link name has special constructs in it,
2496 call the corresponding file handler. */
2497 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
2498 if (!NILP (handler))
2499 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2500 linkname, ok_if_already_exists));
2501
2502 encoded_filename = ENCODE_FILE (filename);
2503 encoded_linkname = ENCODE_FILE (linkname);
2504
2505 if (NILP (ok_if_already_exists)
2506 || INTEGERP (ok_if_already_exists))
2507 barf_or_query_if_file_exists (encoded_linkname, "make it a link",
2508 INTEGERP (ok_if_already_exists), 0);
2509 if (0 > symlink (XSTRING (encoded_filename)->data,
2510 XSTRING (encoded_linkname)->data))
2511 {
2512 /* If we didn't complain already, silently delete existing file. */
2513 if (errno == EEXIST)
2514 {
2515 unlink (XSTRING (encoded_linkname)->data);
2516 if (0 <= symlink (XSTRING (encoded_filename)->data,
2517 XSTRING (encoded_linkname)->data))
2518 {
2519 UNGCPRO;
2520 return Qnil;
2521 }
2522 }
2523
2524 #ifdef NO_ARG_ARRAY
2525 args[0] = filename;
2526 args[1] = linkname;
2527 report_file_error ("Making symbolic link", Flist (2, args));
2528 #else
2529 report_file_error ("Making symbolic link", Flist (2, &filename));
2530 #endif
2531 }
2532 UNGCPRO;
2533 return Qnil;
2534 }
2535 #endif /* S_IFLNK */
2536
2537 #ifdef VMS
2538
2539 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2540 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
2541 "Define the job-wide logical name NAME to have the value STRING.\n\
2542 If STRING is nil or a null string, the logical name NAME is deleted.")
2543 (name, string)
2544 Lisp_Object name;
2545 Lisp_Object string;
2546 {
2547 CHECK_STRING (name, 0);
2548 if (NILP (string))
2549 delete_logical_name (XSTRING (name)->data);
2550 else
2551 {
2552 CHECK_STRING (string, 1);
2553
2554 if (XSTRING (string)->size == 0)
2555 delete_logical_name (XSTRING (name)->data);
2556 else
2557 define_logical_name (XSTRING (name)->data, XSTRING (string)->data);
2558 }
2559
2560 return string;
2561 }
2562 #endif /* VMS */
2563
2564 #ifdef HPUX_NET
2565
2566 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2567 "Open a network connection to PATH using LOGIN as the login string.")
2568 (path, login)
2569 Lisp_Object path, login;
2570 {
2571 int netresult;
2572
2573 CHECK_STRING (path, 0);
2574 CHECK_STRING (login, 0);
2575
2576 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2577
2578 if (netresult == -1)
2579 return Qnil;
2580 else
2581 return Qt;
2582 }
2583 #endif /* HPUX_NET */
2584 \f
2585 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2586 1, 1, 0,
2587 "Return t if file FILENAME specifies an absolute file name.\n\
2588 On Unix, this is a name starting with a `/' or a `~'.")
2589 (filename)
2590 Lisp_Object filename;
2591 {
2592 unsigned char *ptr;
2593
2594 CHECK_STRING (filename, 0);
2595 ptr = XSTRING (filename)->data;
2596 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
2597 #ifdef VMS
2598 /* ??? This criterion is probably wrong for '<'. */
2599 || index (ptr, ':') || index (ptr, '<')
2600 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2601 && ptr[1] != '.')
2602 #endif /* VMS */
2603 #ifdef DOS_NT
2604 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
2605 #endif
2606 )
2607 return Qt;
2608 else
2609 return Qnil;
2610 }
2611 \f
2612 /* Return nonzero if file FILENAME exists and can be executed. */
2613
2614 static int
2615 check_executable (filename)
2616 char *filename;
2617 {
2618 #ifdef DOS_NT
2619 int len = strlen (filename);
2620 char *suffix;
2621 struct stat st;
2622 if (stat (filename, &st) < 0)
2623 return 0;
2624 #if defined (WINDOWSNT) || (defined (MSDOS) && __DJGPP__ > 1)
2625 return ((st.st_mode & S_IEXEC) != 0);
2626 #else
2627 return (S_ISREG (st.st_mode)
2628 && len >= 5
2629 && (stricmp ((suffix = filename + len-4), ".com") == 0
2630 || stricmp (suffix, ".exe") == 0
2631 || stricmp (suffix, ".bat") == 0)
2632 || (st.st_mode & S_IFMT) == S_IFDIR);
2633 #endif /* not WINDOWSNT */
2634 #else /* not DOS_NT */
2635 #ifdef HAVE_EUIDACCESS
2636 return (euidaccess (filename, 1) >= 0);
2637 #else
2638 /* Access isn't quite right because it uses the real uid
2639 and we really want to test with the effective uid.
2640 But Unix doesn't give us a right way to do it. */
2641 return (access (filename, 1) >= 0);
2642 #endif
2643 #endif /* not DOS_NT */
2644 }
2645
2646 /* Return nonzero if file FILENAME exists and can be written. */
2647
2648 static int
2649 check_writable (filename)
2650 char *filename;
2651 {
2652 #ifdef MSDOS
2653 struct stat st;
2654 if (stat (filename, &st) < 0)
2655 return 0;
2656 return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR);
2657 #else /* not MSDOS */
2658 #ifdef HAVE_EUIDACCESS
2659 return (euidaccess (filename, 2) >= 0);
2660 #else
2661 /* Access isn't quite right because it uses the real uid
2662 and we really want to test with the effective uid.
2663 But Unix doesn't give us a right way to do it.
2664 Opening with O_WRONLY could work for an ordinary file,
2665 but would lose for directories. */
2666 return (access (filename, 2) >= 0);
2667 #endif
2668 #endif /* not MSDOS */
2669 }
2670
2671 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2672 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
2673 See also `file-readable-p' and `file-attributes'.")
2674 (filename)
2675 Lisp_Object filename;
2676 {
2677 Lisp_Object absname;
2678 Lisp_Object handler;
2679 struct stat statbuf;
2680
2681 CHECK_STRING (filename, 0);
2682 absname = Fexpand_file_name (filename, Qnil);
2683
2684 /* If the file name has special constructs in it,
2685 call the corresponding file handler. */
2686 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2687 if (!NILP (handler))
2688 return call2 (handler, Qfile_exists_p, absname);
2689
2690 absname = ENCODE_FILE (absname);
2691
2692 return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
2693 }
2694
2695 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
2696 "Return t if FILENAME can be executed by you.\n\
2697 For a directory, this means you can access files in that directory.")
2698 (filename)
2699 Lisp_Object filename;
2700
2701 {
2702 Lisp_Object absname;
2703 Lisp_Object handler;
2704
2705 CHECK_STRING (filename, 0);
2706 absname = Fexpand_file_name (filename, Qnil);
2707
2708 /* If the file name has special constructs in it,
2709 call the corresponding file handler. */
2710 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
2711 if (!NILP (handler))
2712 return call2 (handler, Qfile_executable_p, absname);
2713
2714 absname = ENCODE_FILE (absname);
2715
2716 return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
2717 }
2718
2719 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2720 "Return t if file FILENAME exists and you can read it.\n\
2721 See also `file-exists-p' and `file-attributes'.")
2722 (filename)
2723 Lisp_Object filename;
2724 {
2725 Lisp_Object absname;
2726 Lisp_Object handler;
2727 int desc;
2728 int flags;
2729 struct stat statbuf;
2730
2731 CHECK_STRING (filename, 0);
2732 absname = Fexpand_file_name (filename, Qnil);
2733
2734 /* If the file name has special constructs in it,
2735 call the corresponding file handler. */
2736 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
2737 if (!NILP (handler))
2738 return call2 (handler, Qfile_readable_p, absname);
2739
2740 absname = ENCODE_FILE (absname);
2741
2742 #ifdef DOS_NT
2743 /* Under MS-DOS and Windows, open does not work for directories. */
2744 if (access (XSTRING (absname)->data, 0) == 0)
2745 return Qt;
2746 return Qnil;
2747 #else /* not DOS_NT */
2748 flags = O_RDONLY;
2749 #if defined (S_ISFIFO) && defined (O_NONBLOCK)
2750 /* Opening a fifo without O_NONBLOCK can wait.
2751 We don't want to wait. But we don't want to mess wth O_NONBLOCK
2752 except in the case of a fifo, on a system which handles it. */
2753 desc = stat (XSTRING (absname)->data, &statbuf);
2754 if (desc < 0)
2755 return Qnil;
2756 if (S_ISFIFO (statbuf.st_mode))
2757 flags |= O_NONBLOCK;
2758 #endif
2759 desc = open (XSTRING (absname)->data, flags);
2760 if (desc < 0)
2761 return Qnil;
2762 close (desc);
2763 return Qt;
2764 #endif /* not DOS_NT */
2765 }
2766
2767 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2768 on the RT/PC. */
2769 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2770 "Return t if file FILENAME can be written or created by you.")
2771 (filename)
2772 Lisp_Object filename;
2773 {
2774 Lisp_Object absname, dir, encoded;
2775 Lisp_Object handler;
2776 struct stat statbuf;
2777
2778 CHECK_STRING (filename, 0);
2779 absname = Fexpand_file_name (filename, Qnil);
2780
2781 /* If the file name has special constructs in it,
2782 call the corresponding file handler. */
2783 handler = Ffind_file_name_handler (absname, Qfile_writable_p);
2784 if (!NILP (handler))
2785 return call2 (handler, Qfile_writable_p, absname);
2786
2787 encoded = ENCODE_FILE (absname);
2788 if (stat (XSTRING (encoded)->data, &statbuf) >= 0)
2789 return (check_writable (XSTRING (encoded)->data)
2790 ? Qt : Qnil);
2791
2792 dir = Ffile_name_directory (absname);
2793 #ifdef VMS
2794 if (!NILP (dir))
2795 dir = Fdirectory_file_name (dir);
2796 #endif /* VMS */
2797 #ifdef MSDOS
2798 if (!NILP (dir))
2799 dir = Fdirectory_file_name (dir);
2800 #endif /* MSDOS */
2801
2802 dir = ENCODE_FILE (dir);
2803 return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
2804 ? Qt : Qnil);
2805 }
2806 \f
2807 DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
2808 "Access file FILENAME, and get an error if that does not work.\n\
2809 The second argument STRING is used in the error message.\n\
2810 If there is no error, we return nil.")
2811 (filename, string)
2812 Lisp_Object filename, string;
2813 {
2814 Lisp_Object handler, encoded_filename;
2815 int fd;
2816
2817 CHECK_STRING (filename, 0);
2818
2819 /* If the file name has special constructs in it,
2820 call the corresponding file handler. */
2821 handler = Ffind_file_name_handler (filename, Qaccess_file);
2822 if (!NILP (handler))
2823 return call3 (handler, Qaccess_file, filename, string);
2824
2825 encoded_filename = ENCODE_FILE (filename);
2826
2827 fd = open (XSTRING (encoded_filename)->data, O_RDONLY);
2828 if (fd < 0)
2829 report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
2830 close (fd);
2831
2832 return Qnil;
2833 }
2834 \f
2835 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2836 "Return non-nil if file FILENAME is the name of a symbolic link.\n\
2837 The value is the name of the file to which it is linked.\n\
2838 Otherwise returns nil.")
2839 (filename)
2840 Lisp_Object filename;
2841 {
2842 #ifdef S_IFLNK
2843 char *buf;
2844 int bufsize;
2845 int valsize;
2846 Lisp_Object val;
2847 Lisp_Object handler;
2848
2849 CHECK_STRING (filename, 0);
2850 filename = Fexpand_file_name (filename, Qnil);
2851
2852 /* If the file name has special constructs in it,
2853 call the corresponding file handler. */
2854 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
2855 if (!NILP (handler))
2856 return call2 (handler, Qfile_symlink_p, filename);
2857
2858 filename = ENCODE_FILE (filename);
2859
2860 bufsize = 100;
2861 while (1)
2862 {
2863 buf = (char *) xmalloc (bufsize);
2864 bzero (buf, bufsize);
2865 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
2866 if (valsize < bufsize) break;
2867 /* Buffer was not long enough */
2868 xfree (buf);
2869 bufsize *= 2;
2870 }
2871 if (valsize == -1)
2872 {
2873 xfree (buf);
2874 return Qnil;
2875 }
2876 val = make_string (buf, valsize);
2877 xfree (buf);
2878 return Fdecode_coding_string (val, Vfile_name_coding_system, Qt);
2879 #else /* not S_IFLNK */
2880 return Qnil;
2881 #endif /* not S_IFLNK */
2882 }
2883
2884 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2885 "Return t if FILENAME names an existing directory.")
2886 (filename)
2887 Lisp_Object filename;
2888 {
2889 register Lisp_Object absname;
2890 struct stat st;
2891 Lisp_Object handler;
2892
2893 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2894
2895 /* If the file name has special constructs in it,
2896 call the corresponding file handler. */
2897 handler = Ffind_file_name_handler (absname, Qfile_directory_p);
2898 if (!NILP (handler))
2899 return call2 (handler, Qfile_directory_p, absname);
2900
2901 absname = ENCODE_FILE (absname);
2902
2903 if (stat (XSTRING (absname)->data, &st) < 0)
2904 return Qnil;
2905 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2906 }
2907
2908 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
2909 "Return t if file FILENAME is the name of a directory as a file,\n\
2910 and files in that directory can be opened by you. In order to use a\n\
2911 directory as a buffer's current directory, this predicate must return true.\n\
2912 A directory name spec may be given instead; then the value is t\n\
2913 if the directory so specified exists and really is a readable and\n\
2914 searchable directory.")
2915 (filename)
2916 Lisp_Object filename;
2917 {
2918 Lisp_Object handler;
2919 int tem;
2920 struct gcpro gcpro1;
2921
2922 /* If the file name has special constructs in it,
2923 call the corresponding file handler. */
2924 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2925 if (!NILP (handler))
2926 return call2 (handler, Qfile_accessible_directory_p, filename);
2927
2928 /* It's an unlikely combination, but yes we really do need to gcpro:
2929 Suppose that file-accessible-directory-p has no handler, but
2930 file-directory-p does have a handler; this handler causes a GC which
2931 relocates the string in `filename'; and finally file-directory-p
2932 returns non-nil. Then we would end up passing a garbaged string
2933 to file-executable-p. */
2934 GCPRO1 (filename);
2935 tem = (NILP (Ffile_directory_p (filename))
2936 || NILP (Ffile_executable_p (filename)));
2937 UNGCPRO;
2938 return tem ? Qnil : Qt;
2939 }
2940
2941 DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
2942 "Return t if file FILENAME is the name of a regular file.\n\
2943 This is the sort of file that holds an ordinary stream of data bytes.")
2944 (filename)
2945 Lisp_Object filename;
2946 {
2947 register Lisp_Object absname;
2948 struct stat st;
2949 Lisp_Object handler;
2950
2951 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2952
2953 /* If the file name has special constructs in it,
2954 call the corresponding file handler. */
2955 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
2956 if (!NILP (handler))
2957 return call2 (handler, Qfile_regular_p, absname);
2958
2959 absname = ENCODE_FILE (absname);
2960
2961 if (stat (XSTRING (absname)->data, &st) < 0)
2962 return Qnil;
2963 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
2964 }
2965 \f
2966 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2967 "Return mode bits of file named FILENAME, as an integer.")
2968 (filename)
2969 Lisp_Object filename;
2970 {
2971 Lisp_Object absname;
2972 struct stat st;
2973 Lisp_Object handler;
2974
2975 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2976
2977 /* If the file name has special constructs in it,
2978 call the corresponding file handler. */
2979 handler = Ffind_file_name_handler (absname, Qfile_modes);
2980 if (!NILP (handler))
2981 return call2 (handler, Qfile_modes, absname);
2982
2983 absname = ENCODE_FILE (absname);
2984
2985 if (stat (XSTRING (absname)->data, &st) < 0)
2986 return Qnil;
2987 #if defined (MSDOS) && __DJGPP__ < 2
2988 if (check_executable (XSTRING (absname)->data))
2989 st.st_mode |= S_IEXEC;
2990 #endif /* MSDOS && __DJGPP__ < 2 */
2991
2992 return make_number (st.st_mode & 07777);
2993 }
2994
2995 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
2996 "Set mode bits of file named FILENAME to MODE (an integer).\n\
2997 Only the 12 low bits of MODE are used.")
2998 (filename, mode)
2999 Lisp_Object filename, mode;
3000 {
3001 Lisp_Object absname, encoded_absname;
3002 Lisp_Object handler;
3003
3004 absname = Fexpand_file_name (filename, current_buffer->directory);
3005 CHECK_NUMBER (mode, 1);
3006
3007 /* If the file name has special constructs in it,
3008 call the corresponding file handler. */
3009 handler = Ffind_file_name_handler (absname, Qset_file_modes);
3010 if (!NILP (handler))
3011 return call3 (handler, Qset_file_modes, absname, mode);
3012
3013 encoded_absname = ENCODE_FILE (absname);
3014
3015 if (chmod (XSTRING (encoded_absname)->data, XINT (mode)) < 0)
3016 report_file_error ("Doing chmod", Fcons (absname, Qnil));
3017
3018 return Qnil;
3019 }
3020
3021 DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
3022 "Set the file permission bits for newly created files.\n\
3023 The argument MODE should be an integer; only the low 9 bits are used.\n\
3024 This setting is inherited by subprocesses.")
3025 (mode)
3026 Lisp_Object mode;
3027 {
3028 CHECK_NUMBER (mode, 0);
3029
3030 umask ((~ XINT (mode)) & 0777);
3031
3032 return Qnil;
3033 }
3034
3035 DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
3036 "Return the default file protection for created files.\n\
3037 The value is an integer.")
3038 ()
3039 {
3040 int realmask;
3041 Lisp_Object value;
3042
3043 realmask = umask (0);
3044 umask (realmask);
3045
3046 XSETINT (value, (~ realmask) & 0777);
3047 return value;
3048 }
3049 \f
3050 #ifdef unix
3051
3052 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
3053 "Tell Unix to finish all pending disk updates.")
3054 ()
3055 {
3056 sync ();
3057 return Qnil;
3058 }
3059
3060 #endif /* unix */
3061
3062 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
3063 "Return t if file FILE1 is newer than file FILE2.\n\
3064 If FILE1 does not exist, the answer is nil;\n\
3065 otherwise, if FILE2 does not exist, the answer is t.")
3066 (file1, file2)
3067 Lisp_Object file1, file2;
3068 {
3069 Lisp_Object absname1, absname2;
3070 struct stat st;
3071 int mtime1;
3072 Lisp_Object handler;
3073 struct gcpro gcpro1, gcpro2;
3074
3075 CHECK_STRING (file1, 0);
3076 CHECK_STRING (file2, 0);
3077
3078 absname1 = Qnil;
3079 GCPRO2 (absname1, file2);
3080 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
3081 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
3082 UNGCPRO;
3083
3084 /* If the file name has special constructs in it,
3085 call the corresponding file handler. */
3086 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
3087 if (NILP (handler))
3088 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
3089 if (!NILP (handler))
3090 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
3091
3092 GCPRO2 (absname1, absname2);
3093 absname1 = ENCODE_FILE (absname1);
3094 absname2 = ENCODE_FILE (absname2);
3095 UNGCPRO;
3096
3097 if (stat (XSTRING (absname1)->data, &st) < 0)
3098 return Qnil;
3099
3100 mtime1 = st.st_mtime;
3101
3102 if (stat (XSTRING (absname2)->data, &st) < 0)
3103 return Qt;
3104
3105 return (mtime1 > st.st_mtime) ? Qt : Qnil;
3106 }
3107 \f
3108 #ifdef DOS_NT
3109 Lisp_Object Qfind_buffer_file_type;
3110 #endif /* DOS_NT */
3111
3112 #ifndef READ_BUF_SIZE
3113 #define READ_BUF_SIZE (64 << 10)
3114 #endif
3115
3116 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
3117 1, 5, 0,
3118 "Insert contents of file FILENAME after point.\n\
3119 Returns list of absolute file name and number of bytes inserted.\n\
3120 If second argument VISIT is non-nil, the buffer's visited filename\n\
3121 and last save file modtime are set, and it is marked unmodified.\n\
3122 If visiting and the file does not exist, visiting is completed\n\
3123 before the error is signaled.\n\
3124 The optional third and fourth arguments BEG and END\n\
3125 specify what portion of the file to insert.\n\
3126 These arguments count bytes in the file, not characters in the buffer.\n\
3127 If VISIT is non-nil, BEG and END must be nil.\n\
3128 \n\
3129 If optional fifth argument REPLACE is non-nil,\n\
3130 it means replace the current buffer contents (in the accessible portion)\n\
3131 with the file contents. This is better than simply deleting and inserting\n\
3132 the whole thing because (1) it preserves some marker positions\n\
3133 and (2) it puts less data in the undo list.\n\
3134 When REPLACE is non-nil, the value is the number of characters actually read,\n\
3135 which is often less than the number of characters to be read.\n\
3136 This does code conversion according to the value of\n\
3137 `coding-system-for-read' or `file-coding-system-alist',\n\
3138 and sets the variable `last-coding-system-used' to the coding system\n\
3139 actually used.")
3140 (filename, visit, beg, end, replace)
3141 Lisp_Object filename, visit, beg, end, replace;
3142 {
3143 struct stat st;
3144 register int fd;
3145 int inserted = 0;
3146 register int how_much;
3147 register int unprocessed;
3148 int count = specpdl_ptr - specpdl;
3149 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3150 Lisp_Object handler, val, insval, orig_filename;
3151 Lisp_Object p;
3152 int total;
3153 int not_regular = 0;
3154 char read_buf[READ_BUF_SIZE];
3155 struct coding_system coding;
3156 unsigned char buffer[1 << 14];
3157 int replace_handled = 0;
3158 int set_coding_system = 0;
3159
3160 if (current_buffer->base_buffer && ! NILP (visit))
3161 error ("Cannot do file visiting in an indirect buffer");
3162
3163 if (!NILP (current_buffer->read_only))
3164 Fbarf_if_buffer_read_only ();
3165
3166 val = Qnil;
3167 p = Qnil;
3168 orig_filename = Qnil;
3169
3170 GCPRO4 (filename, val, p, orig_filename);
3171
3172 CHECK_STRING (filename, 0);
3173 filename = Fexpand_file_name (filename, Qnil);
3174
3175 /* If the file name has special constructs in it,
3176 call the corresponding file handler. */
3177 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
3178 if (!NILP (handler))
3179 {
3180 val = call6 (handler, Qinsert_file_contents, filename,
3181 visit, beg, end, replace);
3182 goto handled;
3183 }
3184
3185 orig_filename = filename;
3186 filename = ENCODE_FILE (filename);
3187
3188 fd = -1;
3189
3190 #ifndef APOLLO
3191 if (stat (XSTRING (filename)->data, &st) < 0)
3192 #else
3193 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
3194 || fstat (fd, &st) < 0)
3195 #endif /* not APOLLO */
3196 {
3197 if (fd >= 0) close (fd);
3198 badopen:
3199 if (NILP (visit))
3200 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
3201 st.st_mtime = -1;
3202 how_much = 0;
3203 if (!NILP (Vcoding_system_for_read))
3204 current_buffer->buffer_file_coding_system = Vcoding_system_for_read;
3205 goto notfound;
3206 }
3207
3208 #ifdef S_IFREG
3209 /* This code will need to be changed in order to work on named
3210 pipes, and it's probably just not worth it. So we should at
3211 least signal an error. */
3212 if (!S_ISREG (st.st_mode))
3213 {
3214 not_regular = 1;
3215
3216 if (! NILP (visit))
3217 goto notfound;
3218
3219 if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
3220 Fsignal (Qfile_error,
3221 Fcons (build_string ("not a regular file"),
3222 Fcons (orig_filename, Qnil)));
3223 }
3224 #endif
3225
3226 if (fd < 0)
3227 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
3228 goto badopen;
3229
3230 /* Replacement should preserve point as it preserves markers. */
3231 if (!NILP (replace))
3232 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3233
3234 record_unwind_protect (close_file_unwind, make_number (fd));
3235
3236 /* Supposedly happens on VMS. */
3237 if (! not_regular && st.st_size < 0)
3238 error ("File size is negative");
3239
3240 if (!NILP (beg) || !NILP (end))
3241 if (!NILP (visit))
3242 error ("Attempt to visit less than an entire file");
3243
3244 if (!NILP (beg))
3245 CHECK_NUMBER (beg, 0);
3246 else
3247 XSETFASTINT (beg, 0);
3248
3249 if (!NILP (end))
3250 CHECK_NUMBER (end, 0);
3251 else
3252 {
3253 if (! not_regular)
3254 {
3255 XSETINT (end, st.st_size);
3256 if (XINT (end) != st.st_size)
3257 error ("Maximum buffer size exceeded");
3258 }
3259 }
3260
3261 /* Decide the coding-system of the file. */
3262 {
3263 Lisp_Object val = Qnil;
3264
3265 if (!NILP (Vcoding_system_for_read))
3266 val = Vcoding_system_for_read;
3267 else
3268 {
3269 if (! NILP (Vset_auto_coding_function))
3270 {
3271 /* Find a coding system specified in the heading two lines
3272 or in the tailing several lines of the file. We assume
3273 that the 1K-byte and 3K-byte for heading and tailing
3274 respectively are sufficient fot this purpose. */
3275 int how_many, nread;
3276
3277 if (st.st_size <= (1024 * 4))
3278 nread = read (fd, read_buf, 1024 * 4);
3279 else
3280 {
3281 nread = read (fd, read_buf, 1024);
3282 if (nread >= 0)
3283 {
3284 if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
3285 report_file_error ("Setting file position",
3286 Fcons (orig_filename, Qnil));
3287 nread += read (fd, read_buf + nread, 1024 * 3);
3288 }
3289 }
3290
3291 if (nread < 0)
3292 error ("IO error reading %s: %s",
3293 XSTRING (orig_filename)->data, strerror (errno));
3294 else if (nread > 0)
3295 {
3296 Lisp_Object tem;
3297 /* Always make this a unibyte string
3298 because we have not yet decoded it. */
3299 tem = make_unibyte_string (read_buf, nread);
3300 val = call1 (Vset_auto_coding_function, tem);
3301 /* Rewind the file for the actual read done later. */
3302 if (lseek (fd, 0, 0) < 0)
3303 report_file_error ("Setting file position",
3304 Fcons (orig_filename, Qnil));
3305 }
3306 }
3307 if (NILP (val))
3308 {
3309 Lisp_Object args[6], coding_systems;
3310
3311 args[0] = Qinsert_file_contents, args[1] = orig_filename,
3312 args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
3313 coding_systems = Ffind_operation_coding_system (6, args);
3314 if (CONSP (coding_systems)) val = XCONS (coding_systems)->car;
3315 }
3316 }
3317
3318 if (NILP (Vcoding_system_for_read)
3319 && NILP (current_buffer->enable_multibyte_characters))
3320 {
3321 /* We must suppress all text conversion except for end-of-line
3322 conversion. */
3323 struct coding_system coding_temp;
3324
3325 setup_coding_system (Fcheck_coding_system (val), &coding_temp);
3326 setup_coding_system (Qraw_text, &coding);
3327 coding.eol_type = coding_temp.eol_type;
3328 }
3329 else
3330 setup_coding_system (Fcheck_coding_system (val), &coding);
3331 }
3332
3333 /* If requested, replace the accessible part of the buffer
3334 with the file contents. Avoid replacing text at the
3335 beginning or end of the buffer that matches the file contents;
3336 that preserves markers pointing to the unchanged parts.
3337
3338 Here we implement this feature in an optimized way
3339 for the case where code conversion is NOT needed.
3340 The following if-statement handles the case of conversion
3341 in a less optimal way.
3342
3343 If the code conversion is "automatic" then we try using this
3344 method and hope for the best.
3345 But if we discover the need for conversion, we give up on this method
3346 and let the following if-statement handle the replace job. */
3347 if (!NILP (replace)
3348 && ! CODING_REQUIRE_DECODING (&coding))
3349 {
3350 /* same_at_start and same_at_end count bytes,
3351 because file access counts bytes
3352 and BEG and END count bytes. */
3353 int same_at_start = BEGV_BYTE;
3354 int same_at_end = ZV_BYTE;
3355 int overlap;
3356 /* There is still a possibility we will find the need to do code
3357 conversion. If that happens, we set this variable to 1 to
3358 give up on handling REPLACE in the optimized way. */
3359 int giveup_match_end = 0;
3360
3361 if (XINT (beg) != 0)
3362 {
3363 if (lseek (fd, XINT (beg), 0) < 0)
3364 report_file_error ("Setting file position",
3365 Fcons (orig_filename, Qnil));
3366 }
3367
3368 immediate_quit = 1;
3369 QUIT;
3370 /* Count how many chars at the start of the file
3371 match the text at the beginning of the buffer. */
3372 while (1)
3373 {
3374 int nread, bufpos;
3375
3376 nread = read (fd, buffer, sizeof buffer);
3377 if (nread < 0)
3378 error ("IO error reading %s: %s",
3379 XSTRING (orig_filename)->data, strerror (errno));
3380 else if (nread == 0)
3381 break;
3382
3383 if (coding.type == coding_type_undecided)
3384 detect_coding (&coding, buffer, nread);
3385 if (CODING_REQUIRE_DECODING (&coding))
3386 /* We found that the file should be decoded somehow.
3387 Let's give up here. */
3388 {
3389 giveup_match_end = 1;
3390 break;
3391 }
3392
3393 if (coding.eol_type == CODING_EOL_UNDECIDED)
3394 detect_eol (&coding, buffer, nread);
3395 if (coding.eol_type != CODING_EOL_UNDECIDED
3396 && coding.eol_type != CODING_EOL_LF)
3397 /* We found that the format of eol should be decoded.
3398 Let's give up here. */
3399 {
3400 giveup_match_end = 1;
3401 break;
3402 }
3403
3404 bufpos = 0;
3405 while (bufpos < nread && same_at_start < ZV_BYTE
3406 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3407 same_at_start++, bufpos++;
3408 /* If we found a discrepancy, stop the scan.
3409 Otherwise loop around and scan the next bufferful. */
3410 if (bufpos != nread)
3411 break;
3412 }
3413 immediate_quit = 0;
3414 /* If the file matches the buffer completely,
3415 there's no need to replace anything. */
3416 if (same_at_start - BEGV_BYTE == XINT (end))
3417 {
3418 close (fd);
3419 specpdl_ptr--;
3420 /* Truncate the buffer to the size of the file. */
3421 del_range_1 (same_at_start, same_at_end, 0);
3422 goto handled;
3423 }
3424 immediate_quit = 1;
3425 QUIT;
3426 /* Count how many chars at the end of the file
3427 match the text at the end of the buffer. But, if we have
3428 already found that decoding is necessary, don't waste time. */
3429 while (!giveup_match_end)
3430 {
3431 int total_read, nread, bufpos, curpos, trial;
3432
3433 /* At what file position are we now scanning? */
3434 curpos = XINT (end) - (ZV_BYTE - same_at_end);
3435 /* If the entire file matches the buffer tail, stop the scan. */
3436 if (curpos == 0)
3437 break;
3438 /* How much can we scan in the next step? */
3439 trial = min (curpos, sizeof buffer);
3440 if (lseek (fd, curpos - trial, 0) < 0)
3441 report_file_error ("Setting file position",
3442 Fcons (orig_filename, Qnil));
3443
3444 total_read = 0;
3445 while (total_read < trial)
3446 {
3447 nread = read (fd, buffer + total_read, trial - total_read);
3448 if (nread <= 0)
3449 error ("IO error reading %s: %s",
3450 XSTRING (orig_filename)->data, strerror (errno));
3451 total_read += nread;
3452 }
3453 /* Scan this bufferful from the end, comparing with
3454 the Emacs buffer. */
3455 bufpos = total_read;
3456 /* Compare with same_at_start to avoid counting some buffer text
3457 as matching both at the file's beginning and at the end. */
3458 while (bufpos > 0 && same_at_end > same_at_start
3459 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3460 same_at_end--, bufpos--;
3461
3462 /* If we found a discrepancy, stop the scan.
3463 Otherwise loop around and scan the preceding bufferful. */
3464 if (bufpos != 0)
3465 {
3466 /* If this discrepancy is because of code conversion,
3467 we cannot use this method; giveup and try the other. */
3468 if (same_at_end > same_at_start
3469 && FETCH_BYTE (same_at_end - 1) >= 0200
3470 && ! NILP (current_buffer->enable_multibyte_characters)
3471 && (CODING_MAY_REQUIRE_DECODING (&coding)))
3472 giveup_match_end = 1;
3473 break;
3474 }
3475 }
3476 immediate_quit = 0;
3477
3478 if (! giveup_match_end)
3479 {
3480 int temp;
3481
3482 /* We win! We can handle REPLACE the optimized way. */
3483
3484 /* Extends the end of non-matching text area to multibyte
3485 character boundary. */
3486 if (! NILP (current_buffer->enable_multibyte_characters))
3487 while (same_at_end < ZV_BYTE
3488 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
3489 same_at_end++;
3490
3491 /* Don't try to reuse the same piece of text twice. */
3492 overlap = (same_at_start - BEGV_BYTE
3493 - (same_at_end + st.st_size - ZV));
3494 if (overlap > 0)
3495 same_at_end += overlap;
3496
3497 /* Arrange to read only the nonmatching middle part of the file. */
3498 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
3499 XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
3500
3501 del_range_byte (same_at_start, same_at_end, 0);
3502 /* Insert from the file at the proper position. */
3503 temp = BYTE_TO_CHAR (same_at_start);
3504 SET_PT_BOTH (temp, same_at_start);
3505
3506 /* If display currently starts at beginning of line,
3507 keep it that way. */
3508 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3509 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3510
3511 replace_handled = 1;
3512 }
3513 }
3514
3515 /* If requested, replace the accessible part of the buffer
3516 with the file contents. Avoid replacing text at the
3517 beginning or end of the buffer that matches the file contents;
3518 that preserves markers pointing to the unchanged parts.
3519
3520 Here we implement this feature for the case where code conversion
3521 is needed, in a simple way that needs a lot of memory.
3522 The preceding if-statement handles the case of no conversion
3523 in a more optimized way. */
3524 if (!NILP (replace) && ! replace_handled)
3525 {
3526 int same_at_start = BEGV_BYTE;
3527 int same_at_end = ZV_BYTE;
3528 int overlap;
3529 int bufpos;
3530 /* Make sure that the gap is large enough. */
3531 int bufsize = 2 * st.st_size;
3532 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
3533 int temp;
3534
3535 /* First read the whole file, performing code conversion into
3536 CONVERSION_BUFFER. */
3537
3538 if (lseek (fd, XINT (beg), 0) < 0)
3539 {
3540 free (conversion_buffer);
3541 report_file_error ("Setting file position",
3542 Fcons (orig_filename, Qnil));
3543 }
3544
3545 total = st.st_size; /* Total bytes in the file. */
3546 how_much = 0; /* Bytes read from file so far. */
3547 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
3548 unprocessed = 0; /* Bytes not processed in previous loop. */
3549
3550 while (how_much < total)
3551 {
3552 /* try is reserved in some compilers (Microsoft C) */
3553 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
3554 char *destination = read_buf + unprocessed;
3555 int this;
3556
3557 /* Allow quitting out of the actual I/O. */
3558 immediate_quit = 1;
3559 QUIT;
3560 this = read (fd, destination, trytry);
3561 immediate_quit = 0;
3562
3563 if (this < 0 || this + unprocessed == 0)
3564 {
3565 how_much = this;
3566 break;
3567 }
3568
3569 how_much += this;
3570
3571 if (CODING_MAY_REQUIRE_DECODING (&coding))
3572 {
3573 int require, result;
3574
3575 this += unprocessed;
3576
3577 /* If we are using more space than estimated,
3578 make CONVERSION_BUFFER bigger. */
3579 require = decoding_buffer_size (&coding, this);
3580 if (inserted + require + 2 * (total - how_much) > bufsize)
3581 {
3582 bufsize = inserted + require + 2 * (total - how_much);
3583 conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
3584 }
3585
3586 /* Convert this batch with results in CONVERSION_BUFFER. */
3587 if (how_much >= total) /* This is the last block. */
3588 coding.mode |= CODING_MODE_LAST_BLOCK;
3589 result = decode_coding (&coding, read_buf,
3590 conversion_buffer + inserted,
3591 this, bufsize - inserted);
3592
3593 /* Save for next iteration whatever we didn't convert. */
3594 unprocessed = this - coding.consumed;
3595 bcopy (read_buf + coding.consumed, read_buf, unprocessed);
3596 this = coding.produced;
3597 }
3598
3599 inserted += this;
3600 }
3601
3602 /* At this point, INSERTED is how many characters (i.e. bytes)
3603 are present in CONVERSION_BUFFER.
3604 HOW_MUCH should equal TOTAL,
3605 or should be <= 0 if we couldn't read the file. */
3606
3607 if (how_much < 0)
3608 {
3609 free (conversion_buffer);
3610
3611 if (how_much == -1)
3612 error ("IO error reading %s: %s",
3613 XSTRING (orig_filename)->data, strerror (errno));
3614 else if (how_much == -2)
3615 error ("maximum buffer size exceeded");
3616 }
3617
3618 /* Compare the beginning of the converted file
3619 with the buffer text. */
3620
3621 bufpos = 0;
3622 while (bufpos < inserted && same_at_start < same_at_end
3623 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
3624 same_at_start++, bufpos++;
3625
3626 /* If the file matches the buffer completely,
3627 there's no need to replace anything. */
3628
3629 if (bufpos == inserted)
3630 {
3631 free (conversion_buffer);
3632 close (fd);
3633 specpdl_ptr--;
3634 /* Truncate the buffer to the size of the file. */
3635 del_range_1 (same_at_start, same_at_end, 0);
3636 goto handled;
3637 }
3638
3639 /* Scan this bufferful from the end, comparing with
3640 the Emacs buffer. */
3641 bufpos = inserted;
3642
3643 /* Compare with same_at_start to avoid counting some buffer text
3644 as matching both at the file's beginning and at the end. */
3645 while (bufpos > 0 && same_at_end > same_at_start
3646 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
3647 same_at_end--, bufpos--;
3648
3649 /* Don't try to reuse the same piece of text twice. */
3650 overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
3651 if (overlap > 0)
3652 same_at_end += overlap;
3653
3654 /* If display currently starts at beginning of line,
3655 keep it that way. */
3656 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3657 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3658
3659 /* Replace the chars that we need to replace,
3660 and update INSERTED to equal the number of bytes
3661 we are taking from the file. */
3662 inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
3663 del_range_byte (same_at_start, same_at_end, 0);
3664 SET_PT_BOTH (GPT, GPT_BYTE);
3665
3666 insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
3667 0, 0, 0);
3668
3669 free (conversion_buffer);
3670 close (fd);
3671 specpdl_ptr--;
3672
3673 goto handled;
3674 }
3675
3676 if (! not_regular)
3677 {
3678 register Lisp_Object temp;
3679
3680 total = XINT (end) - XINT (beg);
3681
3682 /* Make sure point-max won't overflow after this insertion. */
3683 XSETINT (temp, total);
3684 if (total != XINT (temp))
3685 error ("Maximum buffer size exceeded");
3686 }
3687 else
3688 /* For a special file, all we can do is guess. */
3689 total = READ_BUF_SIZE;
3690
3691 if (NILP (visit) && total > 0)
3692 prepare_to_modify_buffer (PT, PT, NULL);
3693
3694 move_gap (PT);
3695 if (GAP_SIZE < total)
3696 make_gap (total - GAP_SIZE);
3697
3698 if (XINT (beg) != 0 || !NILP (replace))
3699 {
3700 if (lseek (fd, XINT (beg), 0) < 0)
3701 report_file_error ("Setting file position",
3702 Fcons (orig_filename, Qnil));
3703 }
3704
3705 /* In the following loop, HOW_MUCH contains the total bytes read so
3706 far for a regular file, and not changed for a special file. But,
3707 before exiting the loop, it is set to a negative value if I/O
3708 error occurs. */
3709 how_much = 0;
3710 /* Total bytes inserted. */
3711 inserted = 0;
3712 /* Here, we don't do code conversion in the loop. It is done by
3713 code_convert_region after all data are read into the buffer. */
3714 while (how_much < total)
3715 {
3716 /* try is reserved in some compilers (Microsoft C) */
3717 int trytry = min (total - how_much, READ_BUF_SIZE);
3718 int this;
3719
3720 /* For a special file, GAP_SIZE should be checked every time. */
3721 if (not_regular && GAP_SIZE < trytry)
3722 make_gap (total - GAP_SIZE);
3723
3724 /* Allow quitting out of the actual I/O. */
3725 immediate_quit = 1;
3726 QUIT;
3727 this = read (fd, BYTE_POS_ADDR (PT + inserted - 1) + 1, trytry);
3728 immediate_quit = 0;
3729
3730 if (this <= 0)
3731 {
3732 how_much = this;
3733 break;
3734 }
3735
3736 GAP_SIZE -= this;
3737 GPT_BYTE += this;
3738 ZV_BYTE += this;
3739 Z_BYTE += this;
3740 GPT += this;
3741 ZV += this;
3742 Z += this;
3743
3744 /* For a regular file, where TOTAL is the real size,
3745 count HOW_MUCH to compare with it.
3746 For a special file, where TOTAL is just a buffer size,
3747 so don't bother counting in HOW_MUCH.
3748 (INSERTED is where we count the number of characters inserted.) */
3749 if (! not_regular)
3750 how_much += this;
3751 inserted += this;
3752 }
3753
3754 if (GAP_SIZE > 0)
3755 /* Put an anchor to ensure multi-byte form ends at gap. */
3756 *GPT_ADDR = 0;
3757
3758 close (fd);
3759
3760 /* Discard the unwind protect for closing the file. */
3761 specpdl_ptr--;
3762
3763 if (how_much < 0)
3764 error ("IO error reading %s: %s",
3765 XSTRING (orig_filename)->data, strerror (errno));
3766
3767 if (inserted > 0)
3768 {
3769 if (CODING_MAY_REQUIRE_DECODING (&coding))
3770 inserted = code_convert_region (PT, PT + inserted, &coding, 0, 0);
3771
3772 #ifdef DOS_NT
3773 /* Use the conversion type to determine buffer-file-type
3774 (find-buffer-file-type is now used to help determine the
3775 conversion). */
3776 if (coding.eol_type != CODING_EOL_UNDECIDED
3777 && coding.eol_type != CODING_EOL_LF)
3778 current_buffer->buffer_file_type = Qnil;
3779 else
3780 current_buffer->buffer_file_type = Qt;
3781 #endif
3782
3783 record_insert (PT, inserted);
3784
3785 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3786 offset_intervals (current_buffer, PT, inserted);
3787 MODIFF++;
3788
3789 if (! NILP (coding.post_read_conversion))
3790 {
3791 Lisp_Object val;
3792
3793 val = call1 (coding.post_read_conversion, make_number (inserted));
3794 if (!NILP (val))
3795 {
3796 CHECK_NUMBER (val, 0);
3797 inserted = XFASTINT (val);
3798 }
3799 }
3800 }
3801
3802 set_coding_system = 1;
3803
3804 notfound:
3805 handled:
3806
3807 if (!NILP (visit))
3808 {
3809 if (!EQ (current_buffer->undo_list, Qt))
3810 current_buffer->undo_list = Qnil;
3811 #ifdef APOLLO
3812 stat (XSTRING (filename)->data, &st);
3813 #endif
3814
3815 if (NILP (handler))
3816 {
3817 current_buffer->modtime = st.st_mtime;
3818 current_buffer->filename = orig_filename;
3819 }
3820
3821 SAVE_MODIFF = MODIFF;
3822 current_buffer->auto_save_modified = MODIFF;
3823 XSETFASTINT (current_buffer->save_length, Z - BEG);
3824 #ifdef CLASH_DETECTION
3825 if (NILP (handler))
3826 {
3827 if (!NILP (current_buffer->file_truename))
3828 unlock_file (current_buffer->file_truename);
3829 unlock_file (filename);
3830 }
3831 #endif /* CLASH_DETECTION */
3832 if (not_regular)
3833 Fsignal (Qfile_error,
3834 Fcons (build_string ("not a regular file"),
3835 Fcons (orig_filename, Qnil)));
3836
3837 /* If visiting nonexistent file, return nil. */
3838 if (current_buffer->modtime == -1)
3839 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
3840 }
3841
3842 /* Decode file format */
3843 if (inserted > 0)
3844 {
3845 insval = call3 (Qformat_decode,
3846 Qnil, make_number (inserted), visit);
3847 CHECK_NUMBER (insval, 0);
3848 inserted = XFASTINT (insval);
3849 }
3850
3851 /* Call after-change hooks for the inserted text, aside from the case
3852 of normal visiting (not with REPLACE), which is done in a new buffer
3853 "before" the buffer is changed. */
3854 if (inserted > 0 && total > 0
3855 && (NILP (visit) || !NILP (replace)))
3856 signal_after_change (PT, 0, inserted);
3857
3858 if (set_coding_system)
3859 Vlast_coding_system_used = coding.symbol;
3860
3861 if (inserted > 0)
3862 {
3863 p = Vafter_insert_file_functions;
3864 while (!NILP (p))
3865 {
3866 insval = call1 (Fcar (p), make_number (inserted));
3867 if (!NILP (insval))
3868 {
3869 CHECK_NUMBER (insval, 0);
3870 inserted = XFASTINT (insval);
3871 }
3872 QUIT;
3873 p = Fcdr (p);
3874 }
3875 }
3876
3877 /* ??? Retval needs to be dealt with in all cases consistently. */
3878 if (NILP (val))
3879 val = Fcons (orig_filename,
3880 Fcons (make_number (inserted),
3881 Qnil));
3882
3883 RETURN_UNGCPRO (unbind_to (count, val));
3884 }
3885 \f
3886 static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
3887 Lisp_Object));
3888
3889 /* If build_annotations switched buffers, switch back to BUF.
3890 Kill the temporary buffer that was selected in the meantime.
3891
3892 Since this kill only the last temporary buffer, some buffers remain
3893 not killed if build_annotations switched buffers more than once.
3894 -- K.Handa */
3895
3896 static Lisp_Object
3897 build_annotations_unwind (buf)
3898 Lisp_Object buf;
3899 {
3900 Lisp_Object tembuf;
3901
3902 if (XBUFFER (buf) == current_buffer)
3903 return Qnil;
3904 tembuf = Fcurrent_buffer ();
3905 Fset_buffer (buf);
3906 Fkill_buffer (tembuf);
3907 return Qnil;
3908 }
3909
3910 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 6,
3911 "r\nFWrite region to file: ",
3912 "Write current region into specified file.\n\
3913 When called from a program, takes three arguments:\n\
3914 START, END and FILENAME. START and END are buffer positions.\n\
3915 Optional fourth argument APPEND if non-nil means\n\
3916 append to existing file contents (if any).\n\
3917 Optional fifth argument VISIT if t means\n\
3918 set the last-save-file-modtime of buffer to this file's modtime\n\
3919 and mark buffer not modified.\n\
3920 If VISIT is a string, it is a second file name;\n\
3921 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
3922 VISIT is also the file name to lock and unlock for clash detection.\n\
3923 If VISIT is neither t nor nil nor a string,\n\
3924 that means do not print the \"Wrote file\" message.\n\
3925 The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
3926 use for locking and unlocking, overriding FILENAME and VISIT.\n\
3927 Kludgy feature: if START is a string, then that string is written\n\
3928 to the file, instead of any buffer contents, and END is ignored.")
3929 (start, end, filename, append, visit, lockname)
3930 Lisp_Object start, end, filename, append, visit, lockname;
3931 {
3932 register int desc;
3933 int failure;
3934 int save_errno;
3935 unsigned char *fn;
3936 struct stat st;
3937 int tem;
3938 int count = specpdl_ptr - specpdl;
3939 int count1;
3940 #ifdef VMS
3941 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
3942 #endif /* VMS */
3943 Lisp_Object handler;
3944 Lisp_Object visit_file;
3945 Lisp_Object annotations;
3946 Lisp_Object encoded_filename;
3947 int visiting, quietly;
3948 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
3949 struct buffer *given_buffer;
3950 #ifdef DOS_NT
3951 int buffer_file_type = O_BINARY;
3952 #endif /* DOS_NT */
3953 struct coding_system coding;
3954
3955 if (current_buffer->base_buffer && ! NILP (visit))
3956 error ("Cannot do file visiting in an indirect buffer");
3957
3958 if (!NILP (start) && !STRINGP (start))
3959 validate_region (&start, &end);
3960
3961 GCPRO4 (start, filename, visit, lockname);
3962
3963 /* Decide the coding-system to encode the data with. */
3964 {
3965 Lisp_Object val;
3966
3967 if (auto_saving)
3968 val = Qnil;
3969 else if (!NILP (Vcoding_system_for_write))
3970 val = Vcoding_system_for_write;
3971 else if (NILP (current_buffer->enable_multibyte_characters))
3972 {
3973 /* If the variable `buffer-file-coding-system' is set locally,
3974 it means that the file was read with some kind of code
3975 conversion or the varialbe is explicitely set by users. We
3976 had better write it out with the same coding system even if
3977 `enable-multibyte-characters' is nil.
3978
3979 If it is not set locally, we anyway have to convert EOL
3980 format if the default value of `buffer-file-coding-system'
3981 tells that it is not Unix-like (LF only) format. */
3982 val = current_buffer->buffer_file_coding_system;
3983 if (NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
3984 {
3985 struct coding_system coding_temp;
3986
3987 setup_coding_system (Fcheck_coding_system (val), &coding_temp);
3988 if (coding_temp.eol_type == CODING_EOL_CRLF
3989 || coding_temp.eol_type == CODING_EOL_CR)
3990 {
3991 setup_coding_system (Qraw_text, &coding);
3992 coding.eol_type = coding_temp.eol_type;
3993 goto done_setup_coding;
3994 }
3995 val = Qnil;
3996 }
3997 }
3998 else
3999 {
4000 Lisp_Object args[7], coding_systems;
4001
4002 args[0] = Qwrite_region; args[1] = start; args[2] = end;
4003 args[3] = filename; args[4] = append; args[5] = visit;
4004 args[6] = lockname;
4005 coding_systems = Ffind_operation_coding_system (7, args);
4006 val = (CONSP (coding_systems) && !NILP (XCONS (coding_systems)->cdr)
4007 ? XCONS (coding_systems)->cdr
4008 : current_buffer->buffer_file_coding_system);
4009 /* Confirm that VAL can surely encode the current region. */
4010 if (Ffboundp (Vselect_safe_coding_system_function))
4011 val = call3 (Vselect_safe_coding_system_function, start, end, val);
4012 }
4013 setup_coding_system (Fcheck_coding_system (val), &coding);
4014
4015 done_setup_coding:
4016 if (!STRINGP (start) && !NILP (current_buffer->selective_display))
4017 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
4018 }
4019
4020 Vlast_coding_system_used = coding.symbol;
4021
4022 filename = Fexpand_file_name (filename, Qnil);
4023 if (STRINGP (visit))
4024 visit_file = Fexpand_file_name (visit, Qnil);
4025 else
4026 visit_file = filename;
4027 UNGCPRO;
4028
4029 visiting = (EQ (visit, Qt) || STRINGP (visit));
4030 quietly = !NILP (visit);
4031
4032 annotations = Qnil;
4033
4034 if (NILP (lockname))
4035 lockname = visit_file;
4036
4037 GCPRO5 (start, filename, annotations, visit_file, lockname);
4038
4039 /* If the file name has special constructs in it,
4040 call the corresponding file handler. */
4041 handler = Ffind_file_name_handler (filename, Qwrite_region);
4042 /* If FILENAME has no handler, see if VISIT has one. */
4043 if (NILP (handler) && STRINGP (visit))
4044 handler = Ffind_file_name_handler (visit, Qwrite_region);
4045
4046 if (!NILP (handler))
4047 {
4048 Lisp_Object val;
4049 val = call6 (handler, Qwrite_region, start, end,
4050 filename, append, visit);
4051
4052 if (visiting)
4053 {
4054 SAVE_MODIFF = MODIFF;
4055 XSETFASTINT (current_buffer->save_length, Z - BEG);
4056 current_buffer->filename = visit_file;
4057 }
4058 UNGCPRO;
4059 return val;
4060 }
4061
4062 /* Special kludge to simplify auto-saving. */
4063 if (NILP (start))
4064 {
4065 XSETFASTINT (start, BEG);
4066 XSETFASTINT (end, Z);
4067 }
4068
4069 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
4070 count1 = specpdl_ptr - specpdl;
4071
4072 given_buffer = current_buffer;
4073 annotations = build_annotations (start, end, coding.pre_write_conversion);
4074 if (current_buffer != given_buffer)
4075 {
4076 XSETFASTINT (start, BEGV);
4077 XSETFASTINT (end, ZV);
4078 }
4079
4080 #ifdef CLASH_DETECTION
4081 if (!auto_saving)
4082 {
4083 #if 0 /* This causes trouble for GNUS. */
4084 /* If we've locked this file for some other buffer,
4085 query before proceeding. */
4086 if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
4087 call2 (intern ("ask-user-about-lock"), filename, Vuser_login_name);
4088 #endif
4089
4090 lock_file (lockname);
4091 }
4092 #endif /* CLASH_DETECTION */
4093
4094 encoded_filename = ENCODE_FILE (filename);
4095
4096 fn = XSTRING (encoded_filename)->data;
4097 desc = -1;
4098 if (!NILP (append))
4099 #ifdef DOS_NT
4100 desc = open (fn, O_WRONLY | buffer_file_type);
4101 #else /* not DOS_NT */
4102 desc = open (fn, O_WRONLY);
4103 #endif /* not DOS_NT */
4104
4105 if (desc < 0 && (NILP (append) || errno == ENOENT))
4106 #ifdef VMS
4107 if (auto_saving) /* Overwrite any previous version of autosave file */
4108 {
4109 vms_truncate (fn); /* if fn exists, truncate to zero length */
4110 desc = open (fn, O_RDWR);
4111 if (desc < 0)
4112 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
4113 ? XSTRING (current_buffer->filename)->data : 0,
4114 fn);
4115 }
4116 else /* Write to temporary name and rename if no errors */
4117 {
4118 Lisp_Object temp_name;
4119 temp_name = Ffile_name_directory (filename);
4120
4121 if (!NILP (temp_name))
4122 {
4123 temp_name = Fmake_temp_name (concat2 (temp_name,
4124 build_string ("$$SAVE$$")));
4125 fname = XSTRING (filename)->data;
4126 fn = XSTRING (temp_name)->data;
4127 desc = creat_copy_attrs (fname, fn);
4128 if (desc < 0)
4129 {
4130 /* If we can't open the temporary file, try creating a new
4131 version of the original file. VMS "creat" creates a
4132 new version rather than truncating an existing file. */
4133 fn = fname;
4134 fname = 0;
4135 desc = creat (fn, 0666);
4136 #if 0 /* This can clobber an existing file and fail to replace it,
4137 if the user runs out of space. */
4138 if (desc < 0)
4139 {
4140 /* We can't make a new version;
4141 try to truncate and rewrite existing version if any. */
4142 vms_truncate (fn);
4143 desc = open (fn, O_RDWR);
4144 }
4145 #endif
4146 }
4147 }
4148 else
4149 desc = creat (fn, 0666);
4150 }
4151 #else /* not VMS */
4152 #ifdef DOS_NT
4153 desc = open (fn,
4154 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
4155 S_IREAD | S_IWRITE);
4156 #else /* not DOS_NT */
4157 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
4158 #endif /* not DOS_NT */
4159 #endif /* not VMS */
4160
4161 UNGCPRO;
4162
4163 if (desc < 0)
4164 {
4165 #ifdef CLASH_DETECTION
4166 save_errno = errno;
4167 if (!auto_saving) unlock_file (lockname);
4168 errno = save_errno;
4169 #endif /* CLASH_DETECTION */
4170 report_file_error ("Opening output file", Fcons (filename, Qnil));
4171 }
4172
4173 record_unwind_protect (close_file_unwind, make_number (desc));
4174
4175 if (!NILP (append))
4176 if (lseek (desc, 0, 2) < 0)
4177 {
4178 #ifdef CLASH_DETECTION
4179 if (!auto_saving) unlock_file (lockname);
4180 #endif /* CLASH_DETECTION */
4181 report_file_error ("Lseek error", Fcons (filename, Qnil));
4182 }
4183
4184 #ifdef VMS
4185 /*
4186 * Kludge Warning: The VMS C RTL likes to insert carriage returns
4187 * if we do writes that don't end with a carriage return. Furthermore
4188 * it cannot handle writes of more then 16K. The modified
4189 * version of "sys_write" in SYSDEP.C (see comment there) copes with
4190 * this EXCEPT for the last record (iff it doesn't end with a carriage
4191 * return). This implies that if your buffer doesn't end with a carriage
4192 * return, you get one free... tough. However it also means that if
4193 * we make two calls to sys_write (a la the following code) you can
4194 * get one at the gap as well. The easiest way to fix this (honest)
4195 * is to move the gap to the next newline (or the end of the buffer).
4196 * Thus this change.
4197 *
4198 * Yech!
4199 */
4200 if (GPT > BEG && GPT_ADDR[-1] != '\n')
4201 move_gap (find_next_newline (GPT, 1));
4202 #else
4203 /* Whether VMS or not, we must move the gap to the next of newline
4204 when we must put designation sequences at beginning of line. */
4205 if (INTEGERP (start)
4206 && coding.type == coding_type_iso2022
4207 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
4208 && GPT > BEG && GPT_ADDR[-1] != '\n')
4209 {
4210 int opoint = PT, opoint_byte = PT_BYTE;
4211 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
4212 move_gap_both (PT, PT_BYTE);
4213 SET_PT_BOTH (opoint, opoint_byte);
4214 }
4215 #endif
4216
4217 failure = 0;
4218 immediate_quit = 1;
4219
4220 if (STRINGP (start))
4221 {
4222 failure = 0 > a_write (desc, XSTRING (start)->data,
4223 XSTRING (start)->size, 0, &annotations, &coding);
4224 save_errno = errno;
4225 }
4226 else if (XINT (start) != XINT (end))
4227 {
4228 register int end1 = CHAR_TO_BYTE (XINT (end));
4229
4230 tem = CHAR_TO_BYTE (XINT (start));
4231
4232 if (XINT (start) < GPT)
4233 {
4234 failure = 0 > a_write (desc, BYTE_POS_ADDR (tem),
4235 min (GPT_BYTE, end1) - tem, tem, &annotations,
4236 &coding);
4237 save_errno = errno;
4238 }
4239
4240 if (XINT (end) > GPT && !failure)
4241 {
4242 tem = max (tem, GPT_BYTE);
4243 failure = 0 > a_write (desc, BYTE_POS_ADDR (tem), end1 - tem,
4244 tem, &annotations, &coding);
4245 save_errno = errno;
4246 }
4247 }
4248 else
4249 {
4250 /* If file was empty, still need to write the annotations */
4251 coding.mode |= CODING_MODE_LAST_BLOCK;
4252 failure = 0 > a_write (desc, "", 0, XINT (start), &annotations, &coding);
4253 save_errno = errno;
4254 }
4255
4256 if (CODING_REQUIRE_FLUSHING (&coding)
4257 && !(coding.mode & CODING_MODE_LAST_BLOCK)
4258 && ! failure)
4259 {
4260 /* We have to flush out a data. */
4261 coding.mode |= CODING_MODE_LAST_BLOCK;
4262 failure = 0 > e_write (desc, "", 0, &coding);
4263 save_errno = errno;
4264 }
4265
4266 immediate_quit = 0;
4267
4268 #ifdef HAVE_FSYNC
4269 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
4270 Disk full in NFS may be reported here. */
4271 /* mib says that closing the file will try to write as fast as NFS can do
4272 it, and that means the fsync here is not crucial for autosave files. */
4273 if (!auto_saving && fsync (desc) < 0)
4274 {
4275 /* If fsync fails with EINTR, don't treat that as serious. */
4276 if (errno != EINTR)
4277 failure = 1, save_errno = errno;
4278 }
4279 #endif
4280
4281 /* Spurious "file has changed on disk" warnings have been
4282 observed on Suns as well.
4283 It seems that `close' can change the modtime, under nfs.
4284
4285 (This has supposedly been fixed in Sunos 4,
4286 but who knows about all the other machines with NFS?) */
4287 #if 0
4288
4289 /* On VMS and APOLLO, must do the stat after the close
4290 since closing changes the modtime. */
4291 #ifndef VMS
4292 #ifndef APOLLO
4293 /* Recall that #if defined does not work on VMS. */
4294 #define FOO
4295 fstat (desc, &st);
4296 #endif
4297 #endif
4298 #endif
4299
4300 /* NFS can report a write failure now. */
4301 if (close (desc) < 0)
4302 failure = 1, save_errno = errno;
4303
4304 #ifdef VMS
4305 /* If we wrote to a temporary name and had no errors, rename to real name. */
4306 if (fname)
4307 {
4308 if (!failure)
4309 failure = (rename (fn, fname) != 0), save_errno = errno;
4310 fn = fname;
4311 }
4312 #endif /* VMS */
4313
4314 #ifndef FOO
4315 stat (fn, &st);
4316 #endif
4317 /* Discard the unwind protect for close_file_unwind. */
4318 specpdl_ptr = specpdl + count1;
4319 /* Restore the original current buffer. */
4320 visit_file = unbind_to (count, visit_file);
4321
4322 #ifdef CLASH_DETECTION
4323 if (!auto_saving)
4324 unlock_file (lockname);
4325 #endif /* CLASH_DETECTION */
4326
4327 /* Do this before reporting IO error
4328 to avoid a "file has changed on disk" warning on
4329 next attempt to save. */
4330 if (visiting)
4331 current_buffer->modtime = st.st_mtime;
4332
4333 if (failure)
4334 error ("IO error writing %s: %s", XSTRING (filename)->data,
4335 strerror (save_errno));
4336
4337 if (visiting)
4338 {
4339 SAVE_MODIFF = MODIFF;
4340 XSETFASTINT (current_buffer->save_length, Z - BEG);
4341 current_buffer->filename = visit_file;
4342 update_mode_lines++;
4343 }
4344 else if (quietly)
4345 return Qnil;
4346
4347 if (!auto_saving)
4348 message_with_string ("Wrote %s", visit_file, 1);
4349
4350 return Qnil;
4351 }
4352 \f
4353 Lisp_Object merge ();
4354
4355 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
4356 "Return t if (car A) is numerically less than (car B).")
4357 (a, b)
4358 Lisp_Object a, b;
4359 {
4360 return Flss (Fcar (a), Fcar (b));
4361 }
4362
4363 /* Build the complete list of annotations appropriate for writing out
4364 the text between START and END, by calling all the functions in
4365 write-region-annotate-functions and merging the lists they return.
4366 If one of these functions switches to a different buffer, we assume
4367 that buffer contains altered text. Therefore, the caller must
4368 make sure to restore the current buffer in all cases,
4369 as save-excursion would do. */
4370
4371 static Lisp_Object
4372 build_annotations (start, end, pre_write_conversion)
4373 Lisp_Object start, end, pre_write_conversion;
4374 {
4375 Lisp_Object annotations;
4376 Lisp_Object p, res;
4377 struct gcpro gcpro1, gcpro2;
4378 Lisp_Object original_buffer;
4379
4380 XSETBUFFER (original_buffer, current_buffer);
4381
4382 annotations = Qnil;
4383 p = Vwrite_region_annotate_functions;
4384 GCPRO2 (annotations, p);
4385 while (!NILP (p))
4386 {
4387 struct buffer *given_buffer = current_buffer;
4388 Vwrite_region_annotations_so_far = annotations;
4389 res = call2 (Fcar (p), start, end);
4390 /* If the function makes a different buffer current,
4391 assume that means this buffer contains altered text to be output.
4392 Reset START and END from the buffer bounds
4393 and discard all previous annotations because they should have
4394 been dealt with by this function. */
4395 if (current_buffer != given_buffer)
4396 {
4397 XSETFASTINT (start, BEGV);
4398 XSETFASTINT (end, ZV);
4399 annotations = Qnil;
4400 }
4401 Flength (res); /* Check basic validity of return value */
4402 annotations = merge (annotations, res, Qcar_less_than_car);
4403 p = Fcdr (p);
4404 }
4405
4406 /* Now do the same for annotation functions implied by the file-format */
4407 if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
4408 p = Vauto_save_file_format;
4409 else
4410 p = current_buffer->file_format;
4411 while (!NILP (p))
4412 {
4413 struct buffer *given_buffer = current_buffer;
4414 Vwrite_region_annotations_so_far = annotations;
4415 res = call4 (Qformat_annotate_function, Fcar (p), start, end,
4416 original_buffer);
4417 if (current_buffer != given_buffer)
4418 {
4419 XSETFASTINT (start, BEGV);
4420 XSETFASTINT (end, ZV);
4421 annotations = Qnil;
4422 }
4423 Flength (res);
4424 annotations = merge (annotations, res, Qcar_less_than_car);
4425 p = Fcdr (p);
4426 }
4427
4428 /* At last, do the same for the function PRE_WRITE_CONVERSION
4429 implied by the current coding-system. */
4430 if (!NILP (pre_write_conversion))
4431 {
4432 struct buffer *given_buffer = current_buffer;
4433 Vwrite_region_annotations_so_far = annotations;
4434 res = call2 (pre_write_conversion, start, end);
4435 Flength (res);
4436 annotations = (current_buffer != given_buffer
4437 ? res
4438 : merge (annotations, res, Qcar_less_than_car));
4439 }
4440
4441 UNGCPRO;
4442 return annotations;
4443 }
4444 \f
4445 /* Write to descriptor DESC the NBYTES bytes starting at ADDR,
4446 assuming they start at byte position BYTEPOS in the buffer.
4447 Intersperse with them the annotations from *ANNOT
4448 which fall within the range of byte positions BYTEPOS to BYTEPOS + NBYTES,
4449 each at its appropriate position.
4450
4451 We modify *ANNOT by discarding elements as we use them up.
4452
4453 The return value is negative in case of system call failure. */
4454
4455 static int
4456 a_write (desc, addr, nbytes, bytepos, annot, coding)
4457 int desc;
4458 register char *addr;
4459 register int nbytes;
4460 int bytepos;
4461 Lisp_Object *annot;
4462 struct coding_system *coding;
4463 {
4464 Lisp_Object tem;
4465 int nextpos;
4466 int lastpos = bytepos + nbytes;
4467
4468 while (NILP (*annot) || CONSP (*annot))
4469 {
4470 tem = Fcar_safe (Fcar (*annot));
4471 nextpos = 0;
4472 if (INTEGERP (tem))
4473 nextpos = CHAR_TO_BYTE (XFASTINT (tem));
4474
4475 /* If there are no more annotations in this range,
4476 output the rest of the range all at once. */
4477 if (! (nextpos >= bytepos && nextpos <= lastpos))
4478 return e_write (desc, addr, lastpos - bytepos, coding);
4479
4480 /* Output buffer text up to the next annotation's position. */
4481 if (nextpos > bytepos)
4482 {
4483 if (0 > e_write (desc, addr, nextpos - bytepos, coding))
4484 return -1;
4485 addr += nextpos - bytepos;
4486 bytepos = nextpos;
4487 }
4488 /* Output the annotation. */
4489 tem = Fcdr (Fcar (*annot));
4490 if (STRINGP (tem))
4491 {
4492 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size,
4493 coding))
4494 return -1;
4495 }
4496 *annot = Fcdr (*annot);
4497 }
4498 }
4499
4500 #ifndef WRITE_BUF_SIZE
4501 #define WRITE_BUF_SIZE (16 * 1024)
4502 #endif
4503
4504 /* Write NBYTES bytes starting at ADDR into descriptor DESC,
4505 encoding them with coding system CODING. */
4506
4507 static int
4508 e_write (desc, addr, nbytes, coding)
4509 int desc;
4510 register char *addr;
4511 register int nbytes;
4512 struct coding_system *coding;
4513 {
4514 char buf[WRITE_BUF_SIZE];
4515
4516 /* We used to have a code for handling selective display here. But,
4517 now it is handled within encode_coding. */
4518 while (1)
4519 {
4520 encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
4521 nbytes -= coding->consumed, addr += coding->consumed;
4522 if (coding->produced > 0)
4523 {
4524 coding->produced -= write (desc, buf, coding->produced);
4525 if (coding->produced) return -1;
4526 }
4527 if (nbytes <= 0)
4528 break;
4529 }
4530 return 0;
4531 }
4532 \f
4533 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
4534 Sverify_visited_file_modtime, 1, 1, 0,
4535 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
4536 This means that the file has not been changed since it was visited or saved.")
4537 (buf)
4538 Lisp_Object buf;
4539 {
4540 struct buffer *b;
4541 struct stat st;
4542 Lisp_Object handler;
4543 Lisp_Object filename;
4544
4545 CHECK_BUFFER (buf, 0);
4546 b = XBUFFER (buf);
4547
4548 if (!STRINGP (b->filename)) return Qt;
4549 if (b->modtime == 0) return Qt;
4550
4551 /* If the file name has special constructs in it,
4552 call the corresponding file handler. */
4553 handler = Ffind_file_name_handler (b->filename,
4554 Qverify_visited_file_modtime);
4555 if (!NILP (handler))
4556 return call2 (handler, Qverify_visited_file_modtime, buf);
4557
4558 filename = ENCODE_FILE (b->filename);
4559
4560 if (stat (XSTRING (filename)->data, &st) < 0)
4561 {
4562 /* If the file doesn't exist now and didn't exist before,
4563 we say that it isn't modified, provided the error is a tame one. */
4564 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
4565 st.st_mtime = -1;
4566 else
4567 st.st_mtime = 0;
4568 }
4569 if (st.st_mtime == b->modtime
4570 /* If both are positive, accept them if they are off by one second. */
4571 || (st.st_mtime > 0 && b->modtime > 0
4572 && (st.st_mtime == b->modtime + 1
4573 || st.st_mtime == b->modtime - 1)))
4574 return Qt;
4575 return Qnil;
4576 }
4577
4578 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
4579 Sclear_visited_file_modtime, 0, 0, 0,
4580 "Clear out records of last mod time of visited file.\n\
4581 Next attempt to save will certainly not complain of a discrepancy.")
4582 ()
4583 {
4584 current_buffer->modtime = 0;
4585 return Qnil;
4586 }
4587
4588 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
4589 Svisited_file_modtime, 0, 0, 0,
4590 "Return the current buffer's recorded visited file modification time.\n\
4591 The value is a list of the form (HIGH . LOW), like the time values\n\
4592 that `file-attributes' returns.")
4593 ()
4594 {
4595 return long_to_cons ((unsigned long) current_buffer->modtime);
4596 }
4597
4598 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
4599 Sset_visited_file_modtime, 0, 1, 0,
4600 "Update buffer's recorded modification time from the visited file's time.\n\
4601 Useful if the buffer was not read from the file normally\n\
4602 or if the file itself has been changed for some known benign reason.\n\
4603 An argument specifies the modification time value to use\n\
4604 \(instead of that of the visited file), in the form of a list\n\
4605 \(HIGH . LOW) or (HIGH LOW).")
4606 (time_list)
4607 Lisp_Object time_list;
4608 {
4609 if (!NILP (time_list))
4610 current_buffer->modtime = cons_to_long (time_list);
4611 else
4612 {
4613 register Lisp_Object filename;
4614 struct stat st;
4615 Lisp_Object handler;
4616
4617 filename = Fexpand_file_name (current_buffer->filename, Qnil);
4618
4619 /* If the file name has special constructs in it,
4620 call the corresponding file handler. */
4621 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
4622 if (!NILP (handler))
4623 /* The handler can find the file name the same way we did. */
4624 return call2 (handler, Qset_visited_file_modtime, Qnil);
4625
4626 filename = ENCODE_FILE (filename);
4627
4628 if (stat (XSTRING (filename)->data, &st) >= 0)
4629 current_buffer->modtime = st.st_mtime;
4630 }
4631
4632 return Qnil;
4633 }
4634 \f
4635 Lisp_Object
4636 auto_save_error ()
4637 {
4638 ring_bell ();
4639 message_with_string ("Autosaving...error for %s", current_buffer->name, 1);
4640 Fsleep_for (make_number (1), Qnil);
4641 message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
4642 Fsleep_for (make_number (1), Qnil);
4643 message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
4644 Fsleep_for (make_number (1), Qnil);
4645 return Qnil;
4646 }
4647
4648 Lisp_Object
4649 auto_save_1 ()
4650 {
4651 unsigned char *fn;
4652 struct stat st;
4653
4654 /* Get visited file's mode to become the auto save file's mode. */
4655 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
4656 /* But make sure we can overwrite it later! */
4657 auto_save_mode_bits = st.st_mode | 0600;
4658 else
4659 auto_save_mode_bits = 0666;
4660
4661 return
4662 Fwrite_region (Qnil, Qnil,
4663 current_buffer->auto_save_file_name,
4664 Qnil, Qlambda, Qnil);
4665 }
4666
4667 static Lisp_Object
4668 do_auto_save_unwind (stream) /* used as unwind-protect function */
4669 Lisp_Object stream;
4670 {
4671 auto_saving = 0;
4672 if (!NILP (stream))
4673 fclose ((FILE *) (XFASTINT (XCONS (stream)->car) << 16
4674 | XFASTINT (XCONS (stream)->cdr)));
4675 return Qnil;
4676 }
4677
4678 static Lisp_Object
4679 do_auto_save_unwind_1 (value) /* used as unwind-protect function */
4680 Lisp_Object value;
4681 {
4682 minibuffer_auto_raise = XINT (value);
4683 return Qnil;
4684 }
4685
4686 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
4687 "Auto-save all buffers that need it.\n\
4688 This is all buffers that have auto-saving enabled\n\
4689 and are changed since last auto-saved.\n\
4690 Auto-saving writes the buffer into a file\n\
4691 so that your editing is not lost if the system crashes.\n\
4692 This file is not the file you visited; that changes only when you save.\n\
4693 Normally we run the normal hook `auto-save-hook' before saving.\n\n\
4694 A non-nil NO-MESSAGE argument means do not print any message if successful.\n\
4695 A non-nil CURRENT-ONLY argument means save only current buffer.")
4696 (no_message, current_only)
4697 Lisp_Object no_message, current_only;
4698 {
4699 struct buffer *old = current_buffer, *b;
4700 Lisp_Object tail, buf;
4701 int auto_saved = 0;
4702 char *omessage = echo_area_glyphs;
4703 int omessage_length = echo_area_glyphs_length;
4704 int oldmultibyte = message_enable_multibyte;
4705 int do_handled_files;
4706 Lisp_Object oquit;
4707 FILE *stream;
4708 Lisp_Object lispstream;
4709 int count = specpdl_ptr - specpdl;
4710 int *ptr;
4711 int orig_minibuffer_auto_raise = minibuffer_auto_raise;
4712
4713 /* Ordinarily don't quit within this function,
4714 but don't make it impossible to quit (in case we get hung in I/O). */
4715 oquit = Vquit_flag;
4716 Vquit_flag = Qnil;
4717
4718 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
4719 point to non-strings reached from Vbuffer_alist. */
4720
4721 if (minibuf_level)
4722 no_message = Qt;
4723
4724 if (!NILP (Vrun_hooks))
4725 call1 (Vrun_hooks, intern ("auto-save-hook"));
4726
4727 if (STRINGP (Vauto_save_list_file_name))
4728 {
4729 Lisp_Object listfile;
4730 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
4731 stream = fopen (XSTRING (listfile)->data, "w");
4732 if (stream != NULL)
4733 {
4734 /* Arrange to close that file whether or not we get an error.
4735 Also reset auto_saving to 0. */
4736 lispstream = Fcons (Qnil, Qnil);
4737 XSETFASTINT (XCONS (lispstream)->car, (EMACS_UINT)stream >> 16);
4738 XSETFASTINT (XCONS (lispstream)->cdr, (EMACS_UINT)stream & 0xffff);
4739 }
4740 else
4741 lispstream = Qnil;
4742 }
4743 else
4744 {
4745 stream = NULL;
4746 lispstream = Qnil;
4747 }
4748
4749 record_unwind_protect (do_auto_save_unwind, lispstream);
4750 record_unwind_protect (do_auto_save_unwind_1,
4751 make_number (minibuffer_auto_raise));
4752 minibuffer_auto_raise = 0;
4753 auto_saving = 1;
4754
4755 /* First, save all files which don't have handlers. If Emacs is
4756 crashing, the handlers may tweak what is causing Emacs to crash
4757 in the first place, and it would be a shame if Emacs failed to
4758 autosave perfectly ordinary files because it couldn't handle some
4759 ange-ftp'd file. */
4760 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
4761 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
4762 {
4763 buf = XCONS (XCONS (tail)->car)->cdr;
4764 b = XBUFFER (buf);
4765
4766 /* Record all the buffers that have auto save mode
4767 in the special file that lists them. For each of these buffers,
4768 Record visited name (if any) and auto save name. */
4769 if (STRINGP (b->auto_save_file_name)
4770 && stream != NULL && do_handled_files == 0)
4771 {
4772 if (!NILP (b->filename))
4773 {
4774 fwrite (XSTRING (b->filename)->data, 1,
4775 XSTRING (b->filename)->size, stream);
4776 }
4777 putc ('\n', stream);
4778 fwrite (XSTRING (b->auto_save_file_name)->data, 1,
4779 XSTRING (b->auto_save_file_name)->size, stream);
4780 putc ('\n', stream);
4781 }
4782
4783 if (!NILP (current_only)
4784 && b != current_buffer)
4785 continue;
4786
4787 /* Don't auto-save indirect buffers.
4788 The base buffer takes care of it. */
4789 if (b->base_buffer)
4790 continue;
4791
4792 /* Check for auto save enabled
4793 and file changed since last auto save
4794 and file changed since last real save. */
4795 if (STRINGP (b->auto_save_file_name)
4796 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
4797 && b->auto_save_modified < BUF_MODIFF (b)
4798 /* -1 means we've turned off autosaving for a while--see below. */
4799 && XINT (b->save_length) >= 0
4800 && (do_handled_files
4801 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
4802 Qwrite_region))))
4803 {
4804 EMACS_TIME before_time, after_time;
4805
4806 EMACS_GET_TIME (before_time);
4807
4808 /* If we had a failure, don't try again for 20 minutes. */
4809 if (b->auto_save_failure_time >= 0
4810 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
4811 continue;
4812
4813 if ((XFASTINT (b->save_length) * 10
4814 > (BUF_Z (b) - BUF_BEG (b)) * 13)
4815 /* A short file is likely to change a large fraction;
4816 spare the user annoying messages. */
4817 && XFASTINT (b->save_length) > 5000
4818 /* These messages are frequent and annoying for `*mail*'. */
4819 && !EQ (b->filename, Qnil)
4820 && NILP (no_message))
4821 {
4822 /* It has shrunk too much; turn off auto-saving here. */
4823 minibuffer_auto_raise = orig_minibuffer_auto_raise;
4824 message_with_string ("Buffer %s has shrunk a lot; auto save turned off there",
4825 b->name, 1);
4826 minibuffer_auto_raise = 0;
4827 /* Turn off auto-saving until there's a real save,
4828 and prevent any more warnings. */
4829 XSETINT (b->save_length, -1);
4830 Fsleep_for (make_number (1), Qnil);
4831 continue;
4832 }
4833 set_buffer_internal (b);
4834 if (!auto_saved && NILP (no_message))
4835 message1 ("Auto-saving...");
4836 internal_condition_case (auto_save_1, Qt, auto_save_error);
4837 auto_saved++;
4838 b->auto_save_modified = BUF_MODIFF (b);
4839 XSETFASTINT (current_buffer->save_length, Z - BEG);
4840 set_buffer_internal (old);
4841
4842 EMACS_GET_TIME (after_time);
4843
4844 /* If auto-save took more than 60 seconds,
4845 assume it was an NFS failure that got a timeout. */
4846 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
4847 b->auto_save_failure_time = EMACS_SECS (after_time);
4848 }
4849 }
4850
4851 /* Prevent another auto save till enough input events come in. */
4852 record_auto_save ();
4853
4854 if (auto_saved && NILP (no_message))
4855 {
4856 if (omessage)
4857 {
4858 sit_for (1, 0, 0, 0, 0);
4859 message2 (omessage, omessage_length, oldmultibyte);
4860 }
4861 else
4862 message1 ("Auto-saving...done");
4863 }
4864
4865 Vquit_flag = oquit;
4866
4867 unbind_to (count, Qnil);
4868 return Qnil;
4869 }
4870
4871 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
4872 Sset_buffer_auto_saved, 0, 0, 0,
4873 "Mark current buffer as auto-saved with its current text.\n\
4874 No auto-save file will be written until the buffer changes again.")
4875 ()
4876 {
4877 current_buffer->auto_save_modified = MODIFF;
4878 XSETFASTINT (current_buffer->save_length, Z - BEG);
4879 current_buffer->auto_save_failure_time = -1;
4880 return Qnil;
4881 }
4882
4883 DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
4884 Sclear_buffer_auto_save_failure, 0, 0, 0,
4885 "Clear any record of a recent auto-save failure in the current buffer.")
4886 ()
4887 {
4888 current_buffer->auto_save_failure_time = -1;
4889 return Qnil;
4890 }
4891
4892 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
4893 0, 0, 0,
4894 "Return t if buffer has been auto-saved since last read in or saved.")
4895 ()
4896 {
4897 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
4898 }
4899 \f
4900 /* Reading and completing file names */
4901 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
4902
4903 /* In the string VAL, change each $ to $$ and return the result. */
4904
4905 static Lisp_Object
4906 double_dollars (val)
4907 Lisp_Object val;
4908 {
4909 register unsigned char *old, *new;
4910 register int n;
4911 int osize, count;
4912
4913 osize = XSTRING (val)->size_byte;
4914
4915 /* Count the number of $ characters. */
4916 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
4917 if (*old++ == '$') count++;
4918 if (count > 0)
4919 {
4920 old = XSTRING (val)->data;
4921 val = make_uninit_multibyte_string (XSTRING (val)->size + count,
4922 osize + count);
4923 new = XSTRING (val)->data;
4924 for (n = osize; n > 0; n--)
4925 if (*old != '$')
4926 *new++ = *old++;
4927 else
4928 {
4929 *new++ = '$';
4930 *new++ = '$';
4931 old++;
4932 }
4933 }
4934 return val;
4935 }
4936
4937 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
4938 3, 3, 0,
4939 "Internal subroutine for read-file-name. Do not call this.")
4940 (string, dir, action)
4941 Lisp_Object string, dir, action;
4942 /* action is nil for complete, t for return list of completions,
4943 lambda for verify final value */
4944 {
4945 Lisp_Object name, specdir, realdir, val, orig_string;
4946 int changed;
4947 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4948
4949 CHECK_STRING (string, 0);
4950
4951 realdir = dir;
4952 name = string;
4953 orig_string = Qnil;
4954 specdir = Qnil;
4955 changed = 0;
4956 /* No need to protect ACTION--we only compare it with t and nil. */
4957 GCPRO5 (string, realdir, name, specdir, orig_string);
4958
4959 if (XSTRING (string)->size == 0)
4960 {
4961 if (EQ (action, Qlambda))
4962 {
4963 UNGCPRO;
4964 return Qnil;
4965 }
4966 }
4967 else
4968 {
4969 orig_string = string;
4970 string = Fsubstitute_in_file_name (string);
4971 changed = NILP (Fstring_equal (string, orig_string));
4972 name = Ffile_name_nondirectory (string);
4973 val = Ffile_name_directory (string);
4974 if (! NILP (val))
4975 realdir = Fexpand_file_name (val, realdir);
4976 }
4977
4978 if (NILP (action))
4979 {
4980 specdir = Ffile_name_directory (string);
4981 val = Ffile_name_completion (name, realdir);
4982 UNGCPRO;
4983 if (!STRINGP (val))
4984 {
4985 if (changed)
4986 return double_dollars (string);
4987 return val;
4988 }
4989
4990 if (!NILP (specdir))
4991 val = concat2 (specdir, val);
4992 #ifndef VMS
4993 return double_dollars (val);
4994 #else /* not VMS */
4995 return val;
4996 #endif /* not VMS */
4997 }
4998 UNGCPRO;
4999
5000 if (EQ (action, Qt))
5001 return Ffile_name_all_completions (name, realdir);
5002 /* Only other case actually used is ACTION = lambda */
5003 #ifdef VMS
5004 /* Supposedly this helps commands such as `cd' that read directory names,
5005 but can someone explain how it helps them? -- RMS */
5006 if (XSTRING (name)->size == 0)
5007 return Qt;
5008 #endif /* VMS */
5009 return Ffile_exists_p (string);
5010 }
5011
5012 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
5013 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
5014 Value is not expanded---you must call `expand-file-name' yourself.\n\
5015 Default name to DEFAULT-FILENAME if user enters a null string.\n\
5016 (If DEFAULT-FILENAME is omitted, the visited file name is used,\n\
5017 except that if INITIAL is specified, that combined with DIR is used.)\n\
5018 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
5019 Non-nil and non-t means also require confirmation after completion.\n\
5020 Fifth arg INITIAL specifies text to start with.\n\
5021 DIR defaults to current buffer's directory default.")
5022 (prompt, dir, default_filename, mustmatch, initial)
5023 Lisp_Object prompt, dir, default_filename, mustmatch, initial;
5024 {
5025 Lisp_Object val, insdef, insdef1, tem;
5026 struct gcpro gcpro1, gcpro2;
5027 register char *homedir;
5028 int count;
5029
5030 if (NILP (dir))
5031 dir = current_buffer->directory;
5032 if (NILP (default_filename))
5033 {
5034 if (! NILP (initial))
5035 default_filename = Fexpand_file_name (initial, dir);
5036 else
5037 default_filename = current_buffer->filename;
5038 }
5039
5040 /* If dir starts with user's homedir, change that to ~. */
5041 homedir = (char *) egetenv ("HOME");
5042 #ifdef DOS_NT
5043 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
5044 CORRECT_DIR_SEPS (homedir);
5045 #endif
5046 if (homedir != 0
5047 && STRINGP (dir)
5048 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
5049 && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
5050 {
5051 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
5052 XSTRING (dir)->size - strlen (homedir) + 1);
5053 XSTRING (dir)->data[0] = '~';
5054 }
5055
5056 if (insert_default_directory && STRINGP (dir))
5057 {
5058 insdef = dir;
5059 if (!NILP (initial))
5060 {
5061 Lisp_Object args[2], pos;
5062
5063 args[0] = insdef;
5064 args[1] = initial;
5065 insdef = Fconcat (2, args);
5066 pos = make_number (XSTRING (double_dollars (dir))->size);
5067 insdef1 = Fcons (double_dollars (insdef), pos);
5068 }
5069 else
5070 insdef1 = double_dollars (insdef);
5071 }
5072 else if (STRINGP (initial))
5073 {
5074 insdef = initial;
5075 insdef1 = Fcons (double_dollars (insdef), make_number (0));
5076 }
5077 else
5078 insdef = Qnil, insdef1 = Qnil;
5079
5080 #ifdef VMS
5081 count = specpdl_ptr - specpdl;
5082 specbind (intern ("completion-ignore-case"), Qt);
5083 #endif
5084
5085 GCPRO2 (insdef, default_filename);
5086 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
5087 dir, mustmatch, insdef1,
5088 Qfile_name_history, default_filename, Qnil);
5089 /* If Fcompleting_read returned the default string itself
5090 (rather than a new string with the same contents),
5091 it has to mean that the user typed RET with the minibuffer empty.
5092 In that case, we really want to return ""
5093 so that commands such as set-visited-file-name can distinguish. */
5094 if (EQ (val, default_filename))
5095 val = build_string ("");
5096
5097 #ifdef VMS
5098 unbind_to (count, Qnil);
5099 #endif
5100
5101 UNGCPRO;
5102 if (NILP (val))
5103 error ("No file name specified");
5104 tem = Fstring_equal (val, insdef);
5105 if (!NILP (tem) && !NILP (default_filename))
5106 return default_filename;
5107 if (XSTRING (val)->size == 0 && NILP (insdef))
5108 {
5109 if (!NILP (default_filename))
5110 return default_filename;
5111 else
5112 error ("No default file name");
5113 }
5114 return Fsubstitute_in_file_name (val);
5115 }
5116
5117 #if 0 /* Old version */
5118 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
5119 /* Don't confuse make-docfile by having two doc strings for this function.
5120 make-docfile does not pay attention to #if, for good reason! */
5121 0)
5122 (prompt, dir, defalt, mustmatch, initial)
5123 Lisp_Object prompt, dir, defalt, mustmatch, initial;
5124 {
5125 Lisp_Object val, insdef, tem;
5126 struct gcpro gcpro1, gcpro2;
5127 register char *homedir;
5128 int count;
5129
5130 if (NILP (dir))
5131 dir = current_buffer->directory;
5132 if (NILP (defalt))
5133 defalt = current_buffer->filename;
5134
5135 /* If dir starts with user's homedir, change that to ~. */
5136 homedir = (char *) egetenv ("HOME");
5137 if (homedir != 0
5138 && STRINGP (dir)
5139 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
5140 && XSTRING (dir)->data[strlen (homedir)] == '/')
5141 {
5142 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
5143 XSTRING (dir)->size - strlen (homedir) + 1);
5144 XSTRING (dir)->data[0] = '~';
5145 }
5146
5147 if (!NILP (initial))
5148 insdef = initial;
5149 else if (insert_default_directory)
5150 insdef = dir;
5151 else
5152 insdef = build_string ("");
5153
5154 #ifdef VMS
5155 count = specpdl_ptr - specpdl;
5156 specbind (intern ("completion-ignore-case"), Qt);
5157 #endif
5158
5159 GCPRO2 (insdef, defalt);
5160 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
5161 dir, mustmatch,
5162 insert_default_directory ? insdef : Qnil,
5163 Qfile_name_history, Qnil, Qnil);
5164
5165 #ifdef VMS
5166 unbind_to (count, Qnil);
5167 #endif
5168
5169 UNGCPRO;
5170 if (NILP (val))
5171 error ("No file name specified");
5172 tem = Fstring_equal (val, insdef);
5173 if (!NILP (tem) && !NILP (defalt))
5174 return defalt;
5175 return Fsubstitute_in_file_name (val);
5176 }
5177 #endif /* Old version */
5178 \f
5179 syms_of_fileio ()
5180 {
5181 Qexpand_file_name = intern ("expand-file-name");
5182 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
5183 Qdirectory_file_name = intern ("directory-file-name");
5184 Qfile_name_directory = intern ("file-name-directory");
5185 Qfile_name_nondirectory = intern ("file-name-nondirectory");
5186 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
5187 Qfile_name_as_directory = intern ("file-name-as-directory");
5188 Qcopy_file = intern ("copy-file");
5189 Qmake_directory_internal = intern ("make-directory-internal");
5190 Qdelete_directory = intern ("delete-directory");
5191 Qdelete_file = intern ("delete-file");
5192 Qrename_file = intern ("rename-file");
5193 Qadd_name_to_file = intern ("add-name-to-file");
5194 Qmake_symbolic_link = intern ("make-symbolic-link");
5195 Qfile_exists_p = intern ("file-exists-p");
5196 Qfile_executable_p = intern ("file-executable-p");
5197 Qfile_readable_p = intern ("file-readable-p");
5198 Qfile_writable_p = intern ("file-writable-p");
5199 Qfile_symlink_p = intern ("file-symlink-p");
5200 Qaccess_file = intern ("access-file");
5201 Qfile_directory_p = intern ("file-directory-p");
5202 Qfile_regular_p = intern ("file-regular-p");
5203 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
5204 Qfile_modes = intern ("file-modes");
5205 Qset_file_modes = intern ("set-file-modes");
5206 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
5207 Qinsert_file_contents = intern ("insert-file-contents");
5208 Qwrite_region = intern ("write-region");
5209 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
5210 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
5211
5212 staticpro (&Qexpand_file_name);
5213 staticpro (&Qsubstitute_in_file_name);
5214 staticpro (&Qdirectory_file_name);
5215 staticpro (&Qfile_name_directory);
5216 staticpro (&Qfile_name_nondirectory);
5217 staticpro (&Qunhandled_file_name_directory);
5218 staticpro (&Qfile_name_as_directory);
5219 staticpro (&Qcopy_file);
5220 staticpro (&Qmake_directory_internal);
5221 staticpro (&Qdelete_directory);
5222 staticpro (&Qdelete_file);
5223 staticpro (&Qrename_file);
5224 staticpro (&Qadd_name_to_file);
5225 staticpro (&Qmake_symbolic_link);
5226 staticpro (&Qfile_exists_p);
5227 staticpro (&Qfile_executable_p);
5228 staticpro (&Qfile_readable_p);
5229 staticpro (&Qfile_writable_p);
5230 staticpro (&Qaccess_file);
5231 staticpro (&Qfile_symlink_p);
5232 staticpro (&Qfile_directory_p);
5233 staticpro (&Qfile_regular_p);
5234 staticpro (&Qfile_accessible_directory_p);
5235 staticpro (&Qfile_modes);
5236 staticpro (&Qset_file_modes);
5237 staticpro (&Qfile_newer_than_file_p);
5238 staticpro (&Qinsert_file_contents);
5239 staticpro (&Qwrite_region);
5240 staticpro (&Qverify_visited_file_modtime);
5241 staticpro (&Qset_visited_file_modtime);
5242
5243 Qfile_name_history = intern ("file-name-history");
5244 Fset (Qfile_name_history, Qnil);
5245 staticpro (&Qfile_name_history);
5246
5247 Qfile_error = intern ("file-error");
5248 staticpro (&Qfile_error);
5249 Qfile_already_exists = intern ("file-already-exists");
5250 staticpro (&Qfile_already_exists);
5251 Qfile_date_error = intern ("file-date-error");
5252 staticpro (&Qfile_date_error);
5253
5254 #ifdef DOS_NT
5255 Qfind_buffer_file_type = intern ("find-buffer-file-type");
5256 staticpro (&Qfind_buffer_file_type);
5257 #endif /* DOS_NT */
5258
5259 DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
5260 "*Coding system for encoding file names.");
5261 Vfile_name_coding_system = Qnil;
5262
5263 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
5264 "*Format in which to write auto-save files.\n\
5265 Should be a list of symbols naming formats that are defined in `format-alist'.\n\
5266 If it is t, which is the default, auto-save files are written in the\n\
5267 same format as a regular save would use.");
5268 Vauto_save_file_format = Qt;
5269
5270 Qformat_decode = intern ("format-decode");
5271 staticpro (&Qformat_decode);
5272 Qformat_annotate_function = intern ("format-annotate-function");
5273 staticpro (&Qformat_annotate_function);
5274
5275 Qcar_less_than_car = intern ("car-less-than-car");
5276 staticpro (&Qcar_less_than_car);
5277
5278 Fput (Qfile_error, Qerror_conditions,
5279 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
5280 Fput (Qfile_error, Qerror_message,
5281 build_string ("File error"));
5282
5283 Fput (Qfile_already_exists, Qerror_conditions,
5284 Fcons (Qfile_already_exists,
5285 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5286 Fput (Qfile_already_exists, Qerror_message,
5287 build_string ("File already exists"));
5288
5289 Fput (Qfile_date_error, Qerror_conditions,
5290 Fcons (Qfile_date_error,
5291 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5292 Fput (Qfile_date_error, Qerror_message,
5293 build_string ("Cannot set file date"));
5294
5295 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
5296 "*Non-nil means when reading a filename start with default dir in minibuffer.");
5297 insert_default_directory = 1;
5298
5299 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
5300 "*Non-nil means write new files with record format `stmlf'.\n\
5301 nil means use format `var'. This variable is meaningful only on VMS.");
5302 vms_stmlf_recfm = 0;
5303
5304 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
5305 "Directory separator character for built-in functions that return file names.\n\
5306 The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
5307 This variable affects the built-in functions only on Windows,\n\
5308 on other platforms, it is initialized so that Lisp code can find out\n\
5309 what the normal separator is.");
5310 XSETFASTINT (Vdirectory_sep_char, '/');
5311
5312 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
5313 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
5314 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
5315 HANDLER.\n\
5316 \n\
5317 The first argument given to HANDLER is the name of the I/O primitive\n\
5318 to be handled; the remaining arguments are the arguments that were\n\
5319 passed to that primitive. For example, if you do\n\
5320 (file-exists-p FILENAME)\n\
5321 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
5322 (funcall HANDLER 'file-exists-p FILENAME)\n\
5323 The function `find-file-name-handler' checks this list for a handler\n\
5324 for its argument.");
5325 Vfile_name_handler_alist = Qnil;
5326
5327 DEFVAR_LISP ("set-auto-coding-function",
5328 &Vset_auto_coding_function,
5329 "If non-nil, a function to call to decide a coding system of file.\n\
5330 One argument is passed to this function: the string of concatination\n\
5331 or the heading 1K-byte and the tailing 3K-byte of a file to be read.\n\
5332 This function should return a coding system to decode the file contents\n\
5333 specified in the heading lines with the format:\n\
5334 -*- ... coding: CODING-SYSTEM; ... -*-\n\
5335 or local variable spec of the tailing lines with `coding:' tag.");
5336 Vset_auto_coding_function = Qnil;
5337
5338 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
5339 "A list of functions to be called at the end of `insert-file-contents'.\n\
5340 Each is passed one argument, the number of bytes inserted. It should return\n\
5341 the new byte count, and leave point the same. If `insert-file-contents' is\n\
5342 intercepted by a handler from `file-name-handler-alist', that handler is\n\
5343 responsible for calling the after-insert-file-functions if appropriate.");
5344 Vafter_insert_file_functions = Qnil;
5345
5346 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
5347 "A list of functions to be called at the start of `write-region'.\n\
5348 Each is passed two arguments, START and END as for `write-region'.\n\
5349 These are usually two numbers but not always; see the documentation\n\
5350 for `write-region'. The function should return a list of pairs\n\
5351 of the form (POSITION . STRING), consisting of strings to be effectively\n\
5352 inserted at the specified positions of the file being written (1 means to\n\
5353 insert before the first byte written). The POSITIONs must be sorted into\n\
5354 increasing order. If there are several functions in the list, the several\n\
5355 lists are merged destructively.");
5356 Vwrite_region_annotate_functions = Qnil;
5357
5358 DEFVAR_LISP ("write-region-annotations-so-far",
5359 &Vwrite_region_annotations_so_far,
5360 "When an annotation function is called, this holds the previous annotations.\n\
5361 These are the annotations made by other annotation functions\n\
5362 that were already called. See also `write-region-annotate-functions'.");
5363 Vwrite_region_annotations_so_far = Qnil;
5364
5365 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
5366 "A list of file name handlers that temporarily should not be used.\n\
5367 This applies only to the operation `inhibit-file-name-operation'.");
5368 Vinhibit_file_name_handlers = Qnil;
5369
5370 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
5371 "The operation for which `inhibit-file-name-handlers' is applicable.");
5372 Vinhibit_file_name_operation = Qnil;
5373
5374 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
5375 "File name in which we write a list of all auto save file names.\n\
5376 This variable is initialized automatically from `auto-save-list-file-prefix'\n\
5377 shortly after Emacs reads your `.emacs' file, if you have not yet given it\n\
5378 a non-nil value.");
5379 Vauto_save_list_file_name = Qnil;
5380
5381 defsubr (&Sfind_file_name_handler);
5382 defsubr (&Sfile_name_directory);
5383 defsubr (&Sfile_name_nondirectory);
5384 defsubr (&Sunhandled_file_name_directory);
5385 defsubr (&Sfile_name_as_directory);
5386 defsubr (&Sdirectory_file_name);
5387 defsubr (&Smake_temp_name);
5388 defsubr (&Sexpand_file_name);
5389 defsubr (&Ssubstitute_in_file_name);
5390 defsubr (&Scopy_file);
5391 defsubr (&Smake_directory_internal);
5392 defsubr (&Sdelete_directory);
5393 defsubr (&Sdelete_file);
5394 defsubr (&Srename_file);
5395 defsubr (&Sadd_name_to_file);
5396 #ifdef S_IFLNK
5397 defsubr (&Smake_symbolic_link);
5398 #endif /* S_IFLNK */
5399 #ifdef VMS
5400 defsubr (&Sdefine_logical_name);
5401 #endif /* VMS */
5402 #ifdef HPUX_NET
5403 defsubr (&Ssysnetunam);
5404 #endif /* HPUX_NET */
5405 defsubr (&Sfile_name_absolute_p);
5406 defsubr (&Sfile_exists_p);
5407 defsubr (&Sfile_executable_p);
5408 defsubr (&Sfile_readable_p);
5409 defsubr (&Sfile_writable_p);
5410 defsubr (&Saccess_file);
5411 defsubr (&Sfile_symlink_p);
5412 defsubr (&Sfile_directory_p);
5413 defsubr (&Sfile_accessible_directory_p);
5414 defsubr (&Sfile_regular_p);
5415 defsubr (&Sfile_modes);
5416 defsubr (&Sset_file_modes);
5417 defsubr (&Sset_default_file_modes);
5418 defsubr (&Sdefault_file_modes);
5419 defsubr (&Sfile_newer_than_file_p);
5420 defsubr (&Sinsert_file_contents);
5421 defsubr (&Swrite_region);
5422 defsubr (&Scar_less_than_car);
5423 defsubr (&Sverify_visited_file_modtime);
5424 defsubr (&Sclear_visited_file_modtime);
5425 defsubr (&Svisited_file_modtime);
5426 defsubr (&Sset_visited_file_modtime);
5427 defsubr (&Sdo_auto_save);
5428 defsubr (&Sset_buffer_auto_saved);
5429 defsubr (&Sclear_buffer_auto_save_failure);
5430 defsubr (&Srecent_auto_save_p);
5431
5432 defsubr (&Sread_file_name_internal);
5433 defsubr (&Sread_file_name);
5434
5435 #ifdef unix
5436 defsubr (&Sunix_sync);
5437 #endif
5438 }