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