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