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