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