(ange-ftp-binary-file-name-regexp): Handle .gz.
[emacs.git] / src / fileio.c
blob714c41410f7d66e20d596dd6b408066671c657b9
1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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. */
20 #include "config.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
25 #ifdef VMS
26 #include "vms-pwd.h"
27 #else
28 #include <pwd.h>
29 #endif
31 #include <ctype.h>
33 #ifdef VMS
34 #include "dir.h"
35 #include <perror.h>
36 #include <stddef.h>
37 #include <string.h>
38 #endif
40 #include <errno.h>
42 #ifndef vax11c
43 extern int errno;
44 extern char *sys_errlist[];
45 extern int sys_nerr;
46 #endif
48 #define err_str(a) ((a) < sys_nerr ? sys_errlist[a] : "unknown error")
50 #ifdef APOLLO
51 #include <sys/time.h>
52 #endif
54 #ifndef USG
55 #ifndef VMS
56 #ifndef BSD4_1
57 #define HAVE_FSYNC
58 #endif
59 #endif
60 #endif
62 #include "lisp.h"
63 #include "intervals.h"
64 #include "buffer.h"
65 #include "window.h"
67 #ifdef VMS
68 #include <file.h>
69 #include <rmsdef.h>
70 #include <fab.h>
71 #include <nam.h>
72 #endif
74 #include "systime.h"
76 #ifdef HPUX
77 #include <netio.h>
78 #ifndef HPUX8
79 #ifndef HPUX9
80 #include <errnet.h>
81 #endif
82 #endif
83 #endif
85 #ifndef O_WRONLY
86 #define O_WRONLY 1
87 #endif
89 #define min(a, b) ((a) < (b) ? (a) : (b))
90 #define max(a, b) ((a) > (b) ? (a) : (b))
92 /* Nonzero during writing of auto-save files */
93 int auto_saving;
95 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
96 a new file with the same mode as the original */
97 int auto_save_mode_bits;
99 /* Alist of elements (REGEXP . HANDLER) for file names
100 whose I/O is done with a special handler. */
101 Lisp_Object Vfile_name_handler_alist;
103 /* Nonzero means, when reading a filename in the minibuffer,
104 start out by inserting the default directory into the minibuffer. */
105 int insert_default_directory;
107 /* On VMS, nonzero means write new files with record format stmlf.
108 Zero means use var format. */
109 int vms_stmlf_recfm;
111 Lisp_Object Qfile_error, Qfile_already_exists;
113 Lisp_Object Qfile_name_history;
115 report_file_error (string, data)
116 char *string;
117 Lisp_Object data;
119 Lisp_Object errstring;
121 if (errno >= 0 && errno < sys_nerr)
122 errstring = build_string (sys_errlist[errno]);
123 else
124 errstring = build_string ("undocumented error code");
126 /* System error messages are capitalized. Downcase the initial
127 unless it is followed by a slash. */
128 if (XSTRING (errstring)->data[1] != '/')
129 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
131 while (1)
132 Fsignal (Qfile_error,
133 Fcons (build_string (string), Fcons (errstring, data)));
136 close_file_unwind (fd)
137 Lisp_Object fd;
139 close (XFASTINT (fd));
142 Lisp_Object Qexpand_file_name;
143 Lisp_Object Qdirectory_file_name;
144 Lisp_Object Qfile_name_directory;
145 Lisp_Object Qfile_name_nondirectory;
146 Lisp_Object Qunhandled_file_name_directory;
147 Lisp_Object Qfile_name_as_directory;
148 Lisp_Object Qcopy_file;
149 Lisp_Object Qmake_directory;
150 Lisp_Object Qdelete_directory;
151 Lisp_Object Qdelete_file;
152 Lisp_Object Qrename_file;
153 Lisp_Object Qadd_name_to_file;
154 Lisp_Object Qmake_symbolic_link;
155 Lisp_Object Qfile_exists_p;
156 Lisp_Object Qfile_executable_p;
157 Lisp_Object Qfile_readable_p;
158 Lisp_Object Qfile_symlink_p;
159 Lisp_Object Qfile_writable_p;
160 Lisp_Object Qfile_directory_p;
161 Lisp_Object Qfile_accessible_directory_p;
162 Lisp_Object Qfile_modes;
163 Lisp_Object Qset_file_modes;
164 Lisp_Object Qfile_newer_than_file_p;
165 Lisp_Object Qinsert_file_contents;
166 Lisp_Object Qwrite_region;
167 Lisp_Object Qverify_visited_file_modtime;
169 DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 1, 1, 0,
170 "Return FILENAME's handler function, if its syntax is handled specially.\n\
171 Otherwise, return nil.\n\
172 A file name is handled if one of the regular expressions in\n\
173 `file-name-handler-alist' matches it.")
174 (filename)
175 Lisp_Object filename;
177 /* This function must not munge the match data. */
178 Lisp_Object chain;
180 CHECK_STRING (filename, 0);
182 for (chain = Vfile_name_handler_alist; XTYPE (chain) == Lisp_Cons;
183 chain = XCONS (chain)->cdr)
185 Lisp_Object elt;
186 elt = XCONS (chain)->car;
187 if (XTYPE (elt) == Lisp_Cons)
189 Lisp_Object string;
190 string = XCONS (elt)->car;
191 if (XTYPE (string) == Lisp_String
192 && fast_string_match (string, filename) >= 0)
193 return XCONS (elt)->cdr;
196 QUIT;
198 return Qnil;
201 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
202 1, 1, 0,
203 "Return the directory component in file name NAME.\n\
204 Return nil if NAME does not include a directory.\n\
205 Otherwise return a directory spec.\n\
206 Given a Unix syntax file name, returns a string ending in slash;\n\
207 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
208 (file)
209 Lisp_Object file;
211 register unsigned char *beg;
212 register unsigned char *p;
213 Lisp_Object handler;
215 CHECK_STRING (file, 0);
217 /* If the file name has special constructs in it,
218 call the corresponding file handler. */
219 handler = Ffind_file_name_handler (file);
220 if (!NILP (handler))
221 return call2 (handler, Qfile_name_directory, file);
223 beg = XSTRING (file)->data;
224 p = beg + XSTRING (file)->size;
226 while (p != beg && p[-1] != '/'
227 #ifdef VMS
228 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
229 #endif /* VMS */
230 ) p--;
232 if (p == beg)
233 return Qnil;
234 return make_string (beg, p - beg);
237 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
238 1, 1, 0,
239 "Return file name NAME sans its directory.\n\
240 For example, in a Unix-syntax file name,\n\
241 this is everything after the last slash,\n\
242 or the entire name if it contains no slash.")
243 (file)
244 Lisp_Object file;
246 register unsigned char *beg, *p, *end;
247 Lisp_Object handler;
249 CHECK_STRING (file, 0);
251 /* If the file name has special constructs in it,
252 call the corresponding file handler. */
253 handler = Ffind_file_name_handler (file);
254 if (!NILP (handler))
255 return call2 (handler, Qfile_name_nondirectory, file);
257 beg = XSTRING (file)->data;
258 end = p = beg + XSTRING (file)->size;
260 while (p != beg && p[-1] != '/'
261 #ifdef VMS
262 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
263 #endif /* VMS */
264 ) p--;
266 return make_string (p, end - p);
269 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
270 "Return a directly usable directory name somehow associated with FILENAME.\n\
271 A `directly usable' directory name is one that may be used without the\n\
272 intervention of any file handler.\n\
273 If FILENAME is a directly usable file itself, return\n\
274 (file-name-directory FILENAME).\n\
275 The `call-process' and `start-process' functions use this function to\n\
276 get a current directory to run processes in.")
277 (filename)
278 Lisp_Object filename;
280 Lisp_Object handler;
282 /* If the file name has special constructs in it,
283 call the corresponding file handler. */
284 handler = Ffind_file_name_handler (filename);
285 if (!NILP (handler))
286 return call2 (handler, Qunhandled_file_name_directory, filename);
288 return Ffile_name_directory (filename);
292 char *
293 file_name_as_directory (out, in)
294 char *out, *in;
296 int size = strlen (in) - 1;
298 strcpy (out, in);
300 #ifdef VMS
301 /* Is it already a directory string? */
302 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
303 return out;
304 /* Is it a VMS directory file name? If so, hack VMS syntax. */
305 else if (! index (in, '/')
306 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
307 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
308 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
309 || ! strncmp (&in[size - 5], ".dir", 4))
310 && (in[size - 1] == '.' || in[size - 1] == ';')
311 && in[size] == '1')))
313 register char *p, *dot;
314 char brack;
316 /* x.dir -> [.x]
317 dir:x.dir --> dir:[x]
318 dir:[x]y.dir --> dir:[x.y] */
319 p = in + size;
320 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
321 if (p != in)
323 strncpy (out, in, p - in);
324 out[p - in] = '\0';
325 if (*p == ':')
327 brack = ']';
328 strcat (out, ":[");
330 else
332 brack = *p;
333 strcat (out, ".");
335 p++;
337 else
339 brack = ']';
340 strcpy (out, "[.");
342 dot = index (p, '.');
343 if (dot)
345 /* blindly remove any extension */
346 size = strlen (out) + (dot - p);
347 strncat (out, p, dot - p);
349 else
351 strcat (out, p);
352 size = strlen (out);
354 out[size++] = brack;
355 out[size] = '\0';
357 #else /* not VMS */
358 /* For Unix syntax, Append a slash if necessary */
359 if (out[size] != '/')
360 strcat (out, "/");
361 #endif /* not VMS */
362 return out;
365 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
366 Sfile_name_as_directory, 1, 1, 0,
367 "Return a string representing file FILENAME interpreted as a directory.\n\
368 This operation exists because a directory is also a file, but its name as\n\
369 a directory is different from its name as a file.\n\
370 The result can be used as the value of `default-directory'\n\
371 or passed as second argument to `expand-file-name'.\n\
372 For a Unix-syntax file name, just appends a slash.\n\
373 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
374 (file)
375 Lisp_Object file;
377 char *buf;
378 Lisp_Object handler;
380 CHECK_STRING (file, 0);
381 if (NILP (file))
382 return Qnil;
384 /* If the file name has special constructs in it,
385 call the corresponding file handler. */
386 handler = Ffind_file_name_handler (file);
387 if (!NILP (handler))
388 return call2 (handler, Qfile_name_as_directory, file);
390 buf = (char *) alloca (XSTRING (file)->size + 10);
391 return build_string (file_name_as_directory (buf, XSTRING (file)->data));
395 * Convert from directory name to filename.
396 * On VMS:
397 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
398 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
399 * On UNIX, it's simple: just make sure there is a terminating /
401 * Value is nonzero if the string output is different from the input.
404 directory_file_name (src, dst)
405 char *src, *dst;
407 long slen;
408 #ifdef VMS
409 long rlen;
410 char * ptr, * rptr;
411 char bracket;
412 struct FAB fab = cc$rms_fab;
413 struct NAM nam = cc$rms_nam;
414 char esa[NAM$C_MAXRSS];
415 #endif /* VMS */
417 slen = strlen (src);
418 #ifdef VMS
419 if (! index (src, '/')
420 && (src[slen - 1] == ']'
421 || src[slen - 1] == ':'
422 || src[slen - 1] == '>'))
424 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
425 fab.fab$l_fna = src;
426 fab.fab$b_fns = slen;
427 fab.fab$l_nam = &nam;
428 fab.fab$l_fop = FAB$M_NAM;
430 nam.nam$l_esa = esa;
431 nam.nam$b_ess = sizeof esa;
432 nam.nam$b_nop |= NAM$M_SYNCHK;
434 /* We call SYS$PARSE to handle such things as [--] for us. */
435 if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
437 slen = nam.nam$b_esl;
438 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
439 slen -= 2;
440 esa[slen] = '\0';
441 src = esa;
443 if (src[slen - 1] != ']' && src[slen - 1] != '>')
445 /* what about when we have logical_name:???? */
446 if (src[slen - 1] == ':')
447 { /* Xlate logical name and see what we get */
448 ptr = strcpy (dst, src); /* upper case for getenv */
449 while (*ptr)
451 if ('a' <= *ptr && *ptr <= 'z')
452 *ptr -= 040;
453 ptr++;
455 dst[slen - 1] = 0; /* remove colon */
456 if (!(src = egetenv (dst)))
457 return 0;
458 /* should we jump to the beginning of this procedure?
459 Good points: allows us to use logical names that xlate
460 to Unix names,
461 Bad points: can be a problem if we just translated to a device
462 name...
463 For now, I'll punt and always expect VMS names, and hope for
464 the best! */
465 slen = strlen (src);
466 if (src[slen - 1] != ']' && src[slen - 1] != '>')
467 { /* no recursion here! */
468 strcpy (dst, src);
469 return 0;
472 else
473 { /* not a directory spec */
474 strcpy (dst, src);
475 return 0;
478 bracket = src[slen - 1];
480 /* If bracket is ']' or '>', bracket - 2 is the corresponding
481 opening bracket. */
482 ptr = index (src, bracket - 2);
483 if (ptr == 0)
484 { /* no opening bracket */
485 strcpy (dst, src);
486 return 0;
488 if (!(rptr = rindex (src, '.')))
489 rptr = ptr;
490 slen = rptr - src;
491 strncpy (dst, src, slen);
492 dst[slen] = '\0';
493 if (*rptr == '.')
495 dst[slen++] = bracket;
496 dst[slen] = '\0';
498 else
500 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
501 then translate the device and recurse. */
502 if (dst[slen - 1] == ':'
503 && dst[slen - 2] != ':' /* skip decnet nodes */
504 && strcmp(src + slen, "[000000]") == 0)
506 dst[slen - 1] = '\0';
507 if ((ptr = egetenv (dst))
508 && (rlen = strlen (ptr) - 1) > 0
509 && (ptr[rlen] == ']' || ptr[rlen] == '>')
510 && ptr[rlen - 1] == '.')
512 char * buf = (char *) alloca (strlen (ptr) + 1);
513 strcpy (buf, ptr);
514 buf[rlen - 1] = ']';
515 buf[rlen] = '\0';
516 return directory_file_name (buf, dst);
518 else
519 dst[slen - 1] = ':';
521 strcat (dst, "[000000]");
522 slen += 8;
524 rptr++;
525 rlen = strlen (rptr) - 1;
526 strncat (dst, rptr, rlen);
527 dst[slen + rlen] = '\0';
528 strcat (dst, ".DIR.1");
529 return 1;
531 #endif /* VMS */
532 /* Process as Unix format: just remove any final slash.
533 But leave "/" unchanged; do not change it to "". */
534 strcpy (dst, src);
535 if (slen > 1 && dst[slen - 1] == '/')
536 dst[slen - 1] = 0;
537 return 1;
540 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
541 1, 1, 0,
542 "Returns the file name of the directory named DIR.\n\
543 This is the name of the file that holds the data for the directory DIR.\n\
544 This operation exists because a directory is also a file, but its name as\n\
545 a directory is different from its name as a file.\n\
546 In Unix-syntax, this function just removes the final slash.\n\
547 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
548 it returns a file name such as \"[X]Y.DIR.1\".")
549 (directory)
550 Lisp_Object directory;
552 char *buf;
553 Lisp_Object handler;
555 CHECK_STRING (directory, 0);
557 if (NILP (directory))
558 return Qnil;
560 /* If the file name has special constructs in it,
561 call the corresponding file handler. */
562 handler = Ffind_file_name_handler (directory);
563 if (!NILP (handler))
564 return call2 (handler, Qdirectory_file_name, directory);
566 #ifdef VMS
567 /* 20 extra chars is insufficient for VMS, since we might perform a
568 logical name translation. an equivalence string can be up to 255
569 chars long, so grab that much extra space... - sss */
570 buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
571 #else
572 buf = (char *) alloca (XSTRING (directory)->size + 20);
573 #endif
574 directory_file_name (XSTRING (directory)->data, buf);
575 return build_string (buf);
578 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
579 "Generate temporary file name (string) starting with PREFIX (a string).\n\
580 The Emacs process number forms part of the result,\n\
581 so there is no danger of generating a name being used by another process.")
582 (prefix)
583 Lisp_Object prefix;
585 Lisp_Object val;
586 val = concat2 (prefix, build_string ("XXXXXX"));
587 mktemp (XSTRING (val)->data);
588 return val;
591 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
592 "Convert FILENAME to absolute, and canonicalize it.\n\
593 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
594 (does not start with slash); if DEFAULT is nil or missing,\n\
595 the current buffer's value of default-directory is used.\n\
596 Path components that are `.' are removed, and \n\
597 path components followed by `..' are removed, along with the `..' itself;\n\
598 note that these simplifications are done without checking the resulting\n\
599 paths in the file system.\n\
600 An initial `~/' expands to your home directory.\n\
601 An initial `~USER/' expands to USER's home directory.\n\
602 See also the function `substitute-in-file-name'.")
603 (name, defalt)
604 Lisp_Object name, defalt;
606 unsigned char *nm;
608 register unsigned char *newdir, *p, *o;
609 int tlen;
610 unsigned char *target;
611 struct passwd *pw;
612 #ifdef VMS
613 unsigned char * colon = 0;
614 unsigned char * close = 0;
615 unsigned char * slash = 0;
616 unsigned char * brack = 0;
617 int lbrack = 0, rbrack = 0;
618 int dots = 0;
619 #endif /* VMS */
620 Lisp_Object handler;
622 CHECK_STRING (name, 0);
624 /* If the file name has special constructs in it,
625 call the corresponding file handler. */
626 handler = Ffind_file_name_handler (name);
627 if (!NILP (handler))
628 return call3 (handler, Qexpand_file_name, name, defalt);
630 /* Use the buffer's default-directory if DEFALT is omitted. */
631 if (NILP (defalt))
632 defalt = current_buffer->directory;
633 CHECK_STRING (defalt, 1);
635 /* Make sure DEFALT is properly expanded.
636 It would be better to do this down below where we actually use
637 defalt. Unfortunately, calling Fexpand_file_name recursively
638 could invoke GC, and the strings might be relocated. This would
639 be annoying because we have pointers into strings lying around
640 that would need adjusting, and people would add new pointers to
641 the code and forget to adjust them, resulting in intermittent bugs.
642 Putting this call here avoids all that crud.
644 The EQ test avoids infinite recursion. */
645 if (! NILP (defalt) && !EQ (defalt, name)
646 /* This saves time in a common case. */
647 && XSTRING (defalt)->data[0] != '/')
649 struct gcpro gcpro1;
651 GCPRO1 (name);
652 defalt = Fexpand_file_name (defalt, Qnil);
653 UNGCPRO;
656 #ifdef VMS
657 /* Filenames on VMS are always upper case. */
658 name = Fupcase (name);
659 #endif
661 nm = XSTRING (name)->data;
663 /* If nm is absolute, flush ...// and detect /./ and /../.
664 If no /./ or /../ we can return right away. */
665 if (
666 nm[0] == '/'
667 #ifdef VMS
668 || index (nm, ':')
669 #endif /* VMS */
672 /* If it turns out that the filename we want to return is just a
673 suffix of FILENAME, we don't need to go through and edit
674 things; we just need to construct a new string using data
675 starting at the middle of FILENAME. If we set lose to a
676 non-zero value, that means we've discovered that we can't do
677 that cool trick. */
678 int lose = 0;
680 p = nm;
681 while (*p)
683 /* Since we know the path is absolute, we can assume that each
684 element starts with a "/". */
686 /* "//" anywhere isn't necessarily hairy; we just start afresh
687 with the second slash. */
688 if (p[0] == '/' && p[1] == '/'
689 #ifdef APOLLO
690 /* // at start of filename is meaningful on Apollo system */
691 && nm != p
692 #endif /* APOLLO */
694 nm = p + 1;
696 /* "~" is hairy as the start of any path element. */
697 if (p[0] == '/' && p[1] == '~')
698 nm = p + 1, lose = 1;
700 /* "." and ".." are hairy. */
701 if (p[0] == '/'
702 && p[1] == '.'
703 && (p[2] == '/'
704 || p[2] == 0
705 || (p[2] == '.' && (p[3] == '/'
706 || p[3] == 0))))
707 lose = 1;
708 #ifdef VMS
709 if (p[0] == '\\')
710 lose = 1;
711 if (p[0] == '/') {
712 /* if dev:[dir]/, move nm to / */
713 if (!slash && p > nm && (brack || colon)) {
714 nm = (brack ? brack + 1 : colon + 1);
715 lbrack = rbrack = 0;
716 brack = 0;
717 colon = 0;
719 slash = p;
721 if (p[0] == '-')
722 #ifndef VMS4_4
723 /* VMS pre V4.4,convert '-'s in filenames. */
724 if (lbrack == rbrack)
726 if (dots < 2) /* this is to allow negative version numbers */
727 p[0] = '_';
729 else
730 #endif /* VMS4_4 */
731 if (lbrack > rbrack &&
732 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
733 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
734 lose = 1;
735 #ifndef VMS4_4
736 else
737 p[0] = '_';
738 #endif /* VMS4_4 */
739 /* count open brackets, reset close bracket pointer */
740 if (p[0] == '[' || p[0] == '<')
741 lbrack++, brack = 0;
742 /* count close brackets, set close bracket pointer */
743 if (p[0] == ']' || p[0] == '>')
744 rbrack++, brack = p;
745 /* detect ][ or >< */
746 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
747 lose = 1;
748 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
749 nm = p + 1, lose = 1;
750 if (p[0] == ':' && (colon || slash))
751 /* if dev1:[dir]dev2:, move nm to dev2: */
752 if (brack)
754 nm = brack + 1;
755 brack = 0;
757 /* if /pathname/dev:, move nm to dev: */
758 else if (slash)
759 nm = slash + 1;
760 /* if node::dev:, move colon following dev */
761 else if (colon && colon[-1] == ':')
762 colon = p;
763 /* if dev1:dev2:, move nm to dev2: */
764 else if (colon && colon[-1] != ':')
766 nm = colon + 1;
767 colon = 0;
769 if (p[0] == ':' && !colon)
771 if (p[1] == ':')
772 p++;
773 colon = p;
775 if (lbrack == rbrack)
776 if (p[0] == ';')
777 dots = 2;
778 else if (p[0] == '.')
779 dots++;
780 #endif /* VMS */
781 p++;
783 if (!lose)
785 #ifdef VMS
786 if (index (nm, '/'))
787 return build_string (sys_translate_unix (nm));
788 #endif /* VMS */
789 if (nm == XSTRING (name)->data)
790 return name;
791 return build_string (nm);
795 /* Now determine directory to start with and put it in newdir */
797 newdir = 0;
799 if (nm[0] == '~') /* prefix ~ */
801 if (nm[1] == '/'
802 #ifdef VMS
803 || nm[1] == ':'
804 #endif /* VMS */
805 || nm[1] == 0) /* ~ by itself */
807 if (!(newdir = (unsigned char *) egetenv ("HOME")))
808 newdir = (unsigned char *) "";
809 nm++;
810 #ifdef VMS
811 nm++; /* Don't leave the slash in nm. */
812 #endif /* VMS */
814 else /* ~user/filename */
816 for (p = nm; *p && (*p != '/'
817 #ifdef VMS
818 && *p != ':'
819 #endif /* VMS */
820 ); p++);
821 o = (unsigned char *) alloca (p - nm + 1);
822 bcopy ((char *) nm, o, p - nm);
823 o [p - nm] = 0;
825 pw = (struct passwd *) getpwnam (o + 1);
826 if (pw)
828 newdir = (unsigned char *) pw -> pw_dir;
829 #ifdef VMS
830 nm = p + 1; /* skip the terminator */
831 #else
832 nm = p;
833 #endif /* VMS */
836 /* If we don't find a user of that name, leave the name
837 unchanged; don't move nm forward to p. */
841 if (nm[0] != '/'
842 #ifdef VMS
843 && !index (nm, ':')
844 #endif /* not VMS */
845 && !newdir)
847 newdir = XSTRING (defalt)->data;
850 if (newdir != 0)
852 /* Get rid of any slash at the end of newdir. */
853 int length = strlen (newdir);
854 /* Adding `length > 1 &&' makes ~ expand into / when homedir
855 is the root dir. People disagree about whether that is right.
856 Anyway, we can't take the risk of this change now. */
857 if (newdir[length - 1] == '/')
859 unsigned char *temp = (unsigned char *) alloca (length);
860 bcopy (newdir, temp, length - 1);
861 temp[length - 1] = 0;
862 newdir = temp;
864 tlen = length + 1;
866 else
867 tlen = 0;
869 /* Now concatenate the directory and name to new space in the stack frame */
870 tlen += strlen (nm) + 1;
871 target = (unsigned char *) alloca (tlen);
872 *target = 0;
874 if (newdir)
876 #ifndef VMS
877 if (nm[0] == 0 || nm[0] == '/')
878 strcpy (target, newdir);
879 else
880 #endif
881 file_name_as_directory (target, newdir);
884 strcat (target, nm);
885 #ifdef VMS
886 if (index (target, '/'))
887 strcpy (target, sys_translate_unix (target));
888 #endif /* VMS */
890 /* Now canonicalize by removing /. and /foo/.. if they appear. */
892 p = target;
893 o = target;
895 while (*p)
897 #ifdef VMS
898 if (*p != ']' && *p != '>' && *p != '-')
900 if (*p == '\\')
901 p++;
902 *o++ = *p++;
904 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
905 /* brackets are offset from each other by 2 */
907 p += 2;
908 if (*p != '.' && *p != '-' && o[-1] != '.')
909 /* convert [foo][bar] to [bar] */
910 while (o[-1] != '[' && o[-1] != '<')
911 o--;
912 else if (*p == '-' && *o != '.')
913 *--p = '.';
915 else if (p[0] == '-' && o[-1] == '.' &&
916 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
917 /* flush .foo.- ; leave - if stopped by '[' or '<' */
920 o--;
921 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
922 if (p[1] == '.') /* foo.-.bar ==> bar*/
923 p += 2;
924 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
925 p++, o--;
926 /* else [foo.-] ==> [-] */
928 else
930 #ifndef VMS4_4
931 if (*p == '-' &&
932 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
933 p[1] != ']' && p[1] != '>' && p[1] != '.')
934 *p = '_';
935 #endif /* VMS4_4 */
936 *o++ = *p++;
938 #else /* not VMS */
939 if (*p != '/')
941 *o++ = *p++;
943 else if (!strncmp (p, "//", 2)
944 #ifdef APOLLO
945 /* // at start of filename is meaningful in Apollo system */
946 && o != target
947 #endif /* APOLLO */
950 o = target;
951 p++;
953 else if (p[0] == '/'
954 && p[1] == '.'
955 && (p[2] == '/'
956 || p[2] == 0))
958 /* If "/." is the entire filename, keep the "/". Otherwise,
959 just delete the whole "/.". */
960 if (o == target && p[2] == '\0')
961 *o++ = *p;
962 p += 2;
964 else if (!strncmp (p, "/..", 3)
965 /* `/../' is the "superroot" on certain file systems. */
966 && o != target
967 && (p[3] == '/' || p[3] == 0))
969 while (o != target && *--o != '/')
971 #ifdef APOLLO
972 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
973 ++o;
974 else
975 #endif /* APOLLO */
976 if (o == target && *o == '/')
977 ++o;
978 p += 3;
980 else
982 *o++ = *p++;
984 #endif /* not VMS */
987 return make_string (target, o - target);
989 #if 0
990 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'.
991 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
992 "Convert FILENAME to absolute, and canonicalize it.\n\
993 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
994 (does not start with slash); if DEFAULT is nil or missing,\n\
995 the current buffer's value of default-directory is used.\n\
996 Filenames containing `.' or `..' as components are simplified;\n\
997 initial `~/' expands to your home directory.\n\
998 See also the function `substitute-in-file-name'.")
999 (name, defalt)
1000 Lisp_Object name, defalt;
1002 unsigned char *nm;
1004 register unsigned char *newdir, *p, *o;
1005 int tlen;
1006 unsigned char *target;
1007 struct passwd *pw;
1008 int lose;
1009 #ifdef VMS
1010 unsigned char * colon = 0;
1011 unsigned char * close = 0;
1012 unsigned char * slash = 0;
1013 unsigned char * brack = 0;
1014 int lbrack = 0, rbrack = 0;
1015 int dots = 0;
1016 #endif /* VMS */
1018 CHECK_STRING (name, 0);
1020 #ifdef VMS
1021 /* Filenames on VMS are always upper case. */
1022 name = Fupcase (name);
1023 #endif
1025 nm = XSTRING (name)->data;
1027 /* If nm is absolute, flush ...// and detect /./ and /../.
1028 If no /./ or /../ we can return right away. */
1029 if (
1030 nm[0] == '/'
1031 #ifdef VMS
1032 || index (nm, ':')
1033 #endif /* VMS */
1036 p = nm;
1037 lose = 0;
1038 while (*p)
1040 if (p[0] == '/' && p[1] == '/'
1041 #ifdef APOLLO
1042 /* // at start of filename is meaningful on Apollo system */
1043 && nm != p
1044 #endif /* APOLLO */
1046 nm = p + 1;
1047 if (p[0] == '/' && p[1] == '~')
1048 nm = p + 1, lose = 1;
1049 if (p[0] == '/' && p[1] == '.'
1050 && (p[2] == '/' || p[2] == 0
1051 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
1052 lose = 1;
1053 #ifdef VMS
1054 if (p[0] == '\\')
1055 lose = 1;
1056 if (p[0] == '/') {
1057 /* if dev:[dir]/, move nm to / */
1058 if (!slash && p > nm && (brack || colon)) {
1059 nm = (brack ? brack + 1 : colon + 1);
1060 lbrack = rbrack = 0;
1061 brack = 0;
1062 colon = 0;
1064 slash = p;
1066 if (p[0] == '-')
1067 #ifndef VMS4_4
1068 /* VMS pre V4.4,convert '-'s in filenames. */
1069 if (lbrack == rbrack)
1071 if (dots < 2) /* this is to allow negative version numbers */
1072 p[0] = '_';
1074 else
1075 #endif /* VMS4_4 */
1076 if (lbrack > rbrack &&
1077 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1078 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1079 lose = 1;
1080 #ifndef VMS4_4
1081 else
1082 p[0] = '_';
1083 #endif /* VMS4_4 */
1084 /* count open brackets, reset close bracket pointer */
1085 if (p[0] == '[' || p[0] == '<')
1086 lbrack++, brack = 0;
1087 /* count close brackets, set close bracket pointer */
1088 if (p[0] == ']' || p[0] == '>')
1089 rbrack++, brack = p;
1090 /* detect ][ or >< */
1091 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1092 lose = 1;
1093 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1094 nm = p + 1, lose = 1;
1095 if (p[0] == ':' && (colon || slash))
1096 /* if dev1:[dir]dev2:, move nm to dev2: */
1097 if (brack)
1099 nm = brack + 1;
1100 brack = 0;
1102 /* if /pathname/dev:, move nm to dev: */
1103 else if (slash)
1104 nm = slash + 1;
1105 /* if node::dev:, move colon following dev */
1106 else if (colon && colon[-1] == ':')
1107 colon = p;
1108 /* if dev1:dev2:, move nm to dev2: */
1109 else if (colon && colon[-1] != ':')
1111 nm = colon + 1;
1112 colon = 0;
1114 if (p[0] == ':' && !colon)
1116 if (p[1] == ':')
1117 p++;
1118 colon = p;
1120 if (lbrack == rbrack)
1121 if (p[0] == ';')
1122 dots = 2;
1123 else if (p[0] == '.')
1124 dots++;
1125 #endif /* VMS */
1126 p++;
1128 if (!lose)
1130 #ifdef VMS
1131 if (index (nm, '/'))
1132 return build_string (sys_translate_unix (nm));
1133 #endif /* VMS */
1134 if (nm == XSTRING (name)->data)
1135 return name;
1136 return build_string (nm);
1140 /* Now determine directory to start with and put it in NEWDIR */
1142 newdir = 0;
1144 if (nm[0] == '~') /* prefix ~ */
1145 if (nm[1] == '/'
1146 #ifdef VMS
1147 || nm[1] == ':'
1148 #endif /* VMS */
1149 || nm[1] == 0)/* ~/filename */
1151 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1152 newdir = (unsigned char *) "";
1153 nm++;
1154 #ifdef VMS
1155 nm++; /* Don't leave the slash in nm. */
1156 #endif /* VMS */
1158 else /* ~user/filename */
1160 /* Get past ~ to user */
1161 unsigned char *user = nm + 1;
1162 /* Find end of name. */
1163 unsigned char *ptr = (unsigned char *) index (user, '/');
1164 int len = ptr ? ptr - user : strlen (user);
1165 #ifdef VMS
1166 unsigned char *ptr1 = index (user, ':');
1167 if (ptr1 != 0 && ptr1 - user < len)
1168 len = ptr1 - user;
1169 #endif /* VMS */
1170 /* Copy the user name into temp storage. */
1171 o = (unsigned char *) alloca (len + 1);
1172 bcopy ((char *) user, o, len);
1173 o[len] = 0;
1175 /* Look up the user name. */
1176 pw = (struct passwd *) getpwnam (o + 1);
1177 if (!pw)
1178 error ("\"%s\" isn't a registered user", o + 1);
1180 newdir = (unsigned char *) pw->pw_dir;
1182 /* Discard the user name from NM. */
1183 nm += len;
1186 if (nm[0] != '/'
1187 #ifdef VMS
1188 && !index (nm, ':')
1189 #endif /* not VMS */
1190 && !newdir)
1192 if (NILP (defalt))
1193 defalt = current_buffer->directory;
1194 CHECK_STRING (defalt, 1);
1195 newdir = XSTRING (defalt)->data;
1198 /* Now concatenate the directory and name to new space in the stack frame */
1200 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1201 target = (unsigned char *) alloca (tlen);
1202 *target = 0;
1204 if (newdir)
1206 #ifndef VMS
1207 if (nm[0] == 0 || nm[0] == '/')
1208 strcpy (target, newdir);
1209 else
1210 #endif
1211 file_name_as_directory (target, newdir);
1214 strcat (target, nm);
1215 #ifdef VMS
1216 if (index (target, '/'))
1217 strcpy (target, sys_translate_unix (target));
1218 #endif /* VMS */
1220 /* Now canonicalize by removing /. and /foo/.. if they appear */
1222 p = target;
1223 o = target;
1225 while (*p)
1227 #ifdef VMS
1228 if (*p != ']' && *p != '>' && *p != '-')
1230 if (*p == '\\')
1231 p++;
1232 *o++ = *p++;
1234 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1235 /* brackets are offset from each other by 2 */
1237 p += 2;
1238 if (*p != '.' && *p != '-' && o[-1] != '.')
1239 /* convert [foo][bar] to [bar] */
1240 while (o[-1] != '[' && o[-1] != '<')
1241 o--;
1242 else if (*p == '-' && *o != '.')
1243 *--p = '.';
1245 else if (p[0] == '-' && o[-1] == '.' &&
1246 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1247 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1250 o--;
1251 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1252 if (p[1] == '.') /* foo.-.bar ==> bar*/
1253 p += 2;
1254 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1255 p++, o--;
1256 /* else [foo.-] ==> [-] */
1258 else
1260 #ifndef VMS4_4
1261 if (*p == '-' &&
1262 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1263 p[1] != ']' && p[1] != '>' && p[1] != '.')
1264 *p = '_';
1265 #endif /* VMS4_4 */
1266 *o++ = *p++;
1268 #else /* not VMS */
1269 if (*p != '/')
1271 *o++ = *p++;
1273 else if (!strncmp (p, "//", 2)
1274 #ifdef APOLLO
1275 /* // at start of filename is meaningful in Apollo system */
1276 && o != target
1277 #endif /* APOLLO */
1280 o = target;
1281 p++;
1283 else if (p[0] == '/' && p[1] == '.' &&
1284 (p[2] == '/' || p[2] == 0))
1285 p += 2;
1286 else if (!strncmp (p, "/..", 3)
1287 /* `/../' is the "superroot" on certain file systems. */
1288 && o != target
1289 && (p[3] == '/' || p[3] == 0))
1291 while (o != target && *--o != '/')
1293 #ifdef APOLLO
1294 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1295 ++o;
1296 else
1297 #endif /* APOLLO */
1298 if (o == target && *o == '/')
1299 ++o;
1300 p += 3;
1302 else
1304 *o++ = *p++;
1306 #endif /* not VMS */
1309 return make_string (target, o - target);
1311 #endif
1313 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
1314 Ssubstitute_in_file_name, 1, 1, 0,
1315 "Substitute environment variables referred to in FILENAME.\n\
1316 `$FOO' where FOO is an environment variable name means to substitute\n\
1317 the value of that variable. The variable name should be terminated\n\
1318 with a character not a letter, digit or underscore; otherwise, enclose\n\
1319 the entire variable name in braces.\n\
1320 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1321 On VMS, `$' substitution is not done; this function does little and only\n\
1322 duplicates what `expand-file-name' does.")
1323 (string)
1324 Lisp_Object string;
1326 unsigned char *nm;
1328 register unsigned char *s, *p, *o, *x, *endp;
1329 unsigned char *target;
1330 int total = 0;
1331 int substituted = 0;
1332 unsigned char *xnm;
1334 CHECK_STRING (string, 0);
1336 nm = XSTRING (string)->data;
1337 endp = nm + XSTRING (string)->size;
1339 /* If /~ or // appears, discard everything through first slash. */
1341 for (p = nm; p != endp; p++)
1343 if ((p[0] == '~' ||
1344 #ifdef APOLLO
1345 /* // at start of file name is meaningful in Apollo system */
1346 (p[0] == '/' && p - 1 != nm)
1347 #else /* not APOLLO */
1348 p[0] == '/'
1349 #endif /* not APOLLO */
1351 && p != nm &&
1352 #ifdef VMS
1353 (p[-1] == ':' || p[-1] == ']' || p[-1] == '>' ||
1354 #endif /* VMS */
1355 p[-1] == '/')
1356 #ifdef VMS
1358 #endif /* VMS */
1360 nm = p;
1361 substituted = 1;
1365 #ifdef VMS
1366 return build_string (nm);
1367 #else
1369 /* See if any variables are substituted into the string
1370 and find the total length of their values in `total' */
1372 for (p = nm; p != endp;)
1373 if (*p != '$')
1374 p++;
1375 else
1377 p++;
1378 if (p == endp)
1379 goto badsubst;
1380 else if (*p == '$')
1382 /* "$$" means a single "$" */
1383 p++;
1384 total -= 1;
1385 substituted = 1;
1386 continue;
1388 else if (*p == '{')
1390 o = ++p;
1391 while (p != endp && *p != '}') p++;
1392 if (*p != '}') goto missingclose;
1393 s = p;
1395 else
1397 o = p;
1398 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1399 s = p;
1402 /* Copy out the variable name */
1403 target = (unsigned char *) alloca (s - o + 1);
1404 strncpy (target, o, s - o);
1405 target[s - o] = 0;
1407 /* Get variable value */
1408 o = (unsigned char *) egetenv (target);
1409 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1410 #if 0
1411 #ifdef USG
1412 if (!o && !strcmp (target, "USER"))
1413 o = egetenv ("LOGNAME");
1414 #endif /* USG */
1415 #endif /* 0 */
1416 if (!o) goto badvar;
1417 total += strlen (o);
1418 substituted = 1;
1421 if (!substituted)
1422 return string;
1424 /* If substitution required, recopy the string and do it */
1425 /* Make space in stack frame for the new copy */
1426 xnm = (unsigned char *) alloca (XSTRING (string)->size + total + 1);
1427 x = xnm;
1429 /* Copy the rest of the name through, replacing $ constructs with values */
1430 for (p = nm; *p;)
1431 if (*p != '$')
1432 *x++ = *p++;
1433 else
1435 p++;
1436 if (p == endp)
1437 goto badsubst;
1438 else if (*p == '$')
1440 *x++ = *p++;
1441 continue;
1443 else if (*p == '{')
1445 o = ++p;
1446 while (p != endp && *p != '}') p++;
1447 if (*p != '}') goto missingclose;
1448 s = p++;
1450 else
1452 o = p;
1453 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1454 s = p;
1457 /* Copy out the variable name */
1458 target = (unsigned char *) alloca (s - o + 1);
1459 strncpy (target, o, s - o);
1460 target[s - o] = 0;
1462 /* Get variable value */
1463 o = (unsigned char *) egetenv (target);
1464 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1465 #if 0
1466 #ifdef USG
1467 if (!o && !strcmp (target, "USER"))
1468 o = egetenv ("LOGNAME");
1469 #endif /* USG */
1470 #endif /* 0 */
1471 if (!o)
1472 goto badvar;
1474 strcpy (x, o);
1475 x += strlen (o);
1478 *x = 0;
1480 /* If /~ or // appears, discard everything through first slash. */
1482 for (p = xnm; p != x; p++)
1483 if ((p[0] == '~' ||
1484 #ifdef APOLLO
1485 /* // at start of file name is meaningful in Apollo system */
1486 (p[0] == '/' && p - 1 != xnm)
1487 #else /* not APOLLO */
1488 p[0] == '/'
1489 #endif /* not APOLLO */
1491 && p != nm && p[-1] == '/')
1492 xnm = p;
1494 return make_string (xnm, x - xnm);
1496 badsubst:
1497 error ("Bad format environment-variable substitution");
1498 missingclose:
1499 error ("Missing \"}\" in environment-variable substitution");
1500 badvar:
1501 error ("Substituting nonexistent environment variable \"%s\"", target);
1503 /* NOTREACHED */
1504 #endif /* not VMS */
1507 /* A slightly faster and more convenient way to get
1508 (directory-file-name (expand-file-name FOO)). The return value may
1509 have had its last character zapped with a '\0' character, meaning
1510 that it is acceptable to system calls, but not to other lisp
1511 functions. Callers should make sure that the return value doesn't
1512 escape. */
1514 Lisp_Object
1515 expand_and_dir_to_file (filename, defdir)
1516 Lisp_Object filename, defdir;
1518 register Lisp_Object abspath;
1520 abspath = Fexpand_file_name (filename, defdir);
1521 #ifdef VMS
1523 register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1];
1524 if (c == ':' || c == ']' || c == '>')
1525 abspath = Fdirectory_file_name (abspath);
1527 #else
1528 /* Remove final slash, if any (unless path is root).
1529 stat behaves differently depending! */
1530 if (XSTRING (abspath)->size > 1
1531 && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/')
1533 if (EQ (abspath, filename))
1534 abspath = Fcopy_sequence (abspath);
1535 XSTRING (abspath)->data[XSTRING (abspath)->size - 1] = 0;
1537 #endif
1538 return abspath;
1541 barf_or_query_if_file_exists (absname, querystring, interactive)
1542 Lisp_Object absname;
1543 unsigned char *querystring;
1544 int interactive;
1546 register Lisp_Object tem;
1547 struct gcpro gcpro1;
1549 if (access (XSTRING (absname)->data, 4) >= 0)
1551 if (! interactive)
1552 Fsignal (Qfile_already_exists,
1553 Fcons (build_string ("File already exists"),
1554 Fcons (absname, Qnil)));
1555 GCPRO1 (absname);
1556 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1557 XSTRING (absname)->data, querystring));
1558 UNGCPRO;
1559 if (NILP (tem))
1560 Fsignal (Qfile_already_exists,
1561 Fcons (build_string ("File already exists"),
1562 Fcons (absname, Qnil)));
1564 return;
1567 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
1568 "fCopy file: \nFCopy %s to file: \np\nP",
1569 "Copy FILE to NEWNAME. Both args must be strings.\n\
1570 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1571 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1572 A number as third arg means request confirmation if NEWNAME already exists.\n\
1573 This is what happens in interactive use with M-x.\n\
1574 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1575 last-modified time as the old one. (This works on only some systems.)\n\
1576 A prefix arg makes KEEP-TIME non-nil.")
1577 (filename, newname, ok_if_already_exists, keep_date)
1578 Lisp_Object filename, newname, ok_if_already_exists, keep_date;
1580 int ifd, ofd, n;
1581 char buf[16 * 1024];
1582 struct stat st;
1583 Lisp_Object handler;
1584 struct gcpro gcpro1, gcpro2;
1585 int count = specpdl_ptr - specpdl;
1587 GCPRO2 (filename, newname);
1588 CHECK_STRING (filename, 0);
1589 CHECK_STRING (newname, 1);
1590 filename = Fexpand_file_name (filename, Qnil);
1591 newname = Fexpand_file_name (newname, Qnil);
1593 /* If the input file name has special constructs in it,
1594 call the corresponding file handler. */
1595 handler = Ffind_file_name_handler (filename);
1596 if (!NILP (handler))
1597 return call3 (handler, Qcopy_file, filename, newname);
1598 /* Likewise for output file name. */
1599 handler = Ffind_file_name_handler (newname);
1600 if (!NILP (handler))
1601 return call3 (handler, Qcopy_file, filename, newname);
1603 if (NILP (ok_if_already_exists)
1604 || XTYPE (ok_if_already_exists) == Lisp_Int)
1605 barf_or_query_if_file_exists (newname, "copy to it",
1606 XTYPE (ok_if_already_exists) == Lisp_Int);
1608 ifd = open (XSTRING (filename)->data, 0);
1609 if (ifd < 0)
1610 report_file_error ("Opening input file", Fcons (filename, Qnil));
1612 record_unwind_protect (close_file_unwind, make_number (ifd));
1614 #ifdef VMS
1615 /* Create the copy file with the same record format as the input file */
1616 ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
1617 #else
1618 ofd = creat (XSTRING (newname)->data, 0666);
1619 #endif /* VMS */
1620 if (ofd < 0)
1621 report_file_error ("Opening output file", Fcons (newname, Qnil));
1623 record_unwind_protect (close_file_unwind, make_number (ofd));
1625 immediate_quit = 1;
1626 QUIT;
1627 while ((n = read (ifd, buf, sizeof buf)) > 0)
1628 if (write (ofd, buf, n) != n)
1629 report_file_error ("I/O error", Fcons (newname, Qnil));
1630 immediate_quit = 0;
1632 if (fstat (ifd, &st) >= 0)
1634 if (!NILP (keep_date))
1636 EMACS_TIME atime, mtime;
1637 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
1638 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
1639 EMACS_SET_UTIMES (XSTRING (newname)->data, atime, mtime);
1641 #ifdef APOLLO
1642 if (!egetenv ("USE_DOMAIN_ACLS"))
1643 #endif
1644 chmod (XSTRING (newname)->data, st.st_mode & 07777);
1647 /* Discard the unwind protects. */
1648 specpdl_ptr = specpdl + count;
1650 close (ifd);
1651 if (close (ofd) < 0)
1652 report_file_error ("I/O error", Fcons (newname, Qnil));
1654 UNGCPRO;
1655 return Qnil;
1658 DEFUN ("make-directory-internal", Fmake_directory_internal,
1659 Smake_directory_internal, 1, 1, 0,
1660 "Create a directory. One argument, a file name string.")
1661 (dirname)
1662 Lisp_Object dirname;
1664 unsigned char *dir;
1665 Lisp_Object handler;
1667 CHECK_STRING (dirname, 0);
1668 dirname = Fexpand_file_name (dirname, Qnil);
1670 handler = Ffind_file_name_handler (dirname);
1671 if (!NILP (handler))
1672 return call3 (handler, Qmake_directory, dirname, Qnil);
1674 dir = XSTRING (dirname)->data;
1676 if (mkdir (dir, 0777) != 0)
1677 report_file_error ("Creating directory", Flist (1, &dirname));
1679 return Qnil;
1682 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
1683 "Delete a directory. One argument, a file name string.")
1684 (dirname)
1685 Lisp_Object dirname;
1687 unsigned char *dir;
1688 Lisp_Object handler;
1690 CHECK_STRING (dirname, 0);
1691 dirname = Fexpand_file_name (dirname, Qnil);
1692 dir = XSTRING (dirname)->data;
1694 handler = Ffind_file_name_handler (dirname);
1695 if (!NILP (handler))
1696 return call2 (handler, Qdelete_directory, dirname);
1698 if (rmdir (dir) != 0)
1699 report_file_error ("Removing directory", Flist (1, &dirname));
1701 return Qnil;
1704 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
1705 "Delete specified file. One argument, a file name string.\n\
1706 If file has multiple names, it continues to exist with the other names.")
1707 (filename)
1708 Lisp_Object filename;
1710 Lisp_Object handler;
1711 CHECK_STRING (filename, 0);
1712 filename = Fexpand_file_name (filename, Qnil);
1714 handler = Ffind_file_name_handler (filename);
1715 if (!NILP (handler))
1716 return call2 (handler, Qdelete_file, filename);
1718 if (0 > unlink (XSTRING (filename)->data))
1719 report_file_error ("Removing old name", Flist (1, &filename));
1720 return Qnil;
1723 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
1724 "fRename file: \nFRename %s to file: \np",
1725 "Rename FILE as NEWNAME. Both args strings.\n\
1726 If file has names other than FILE, it continues to have those names.\n\
1727 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1728 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1729 A number as third arg means request confirmation if NEWNAME already exists.\n\
1730 This is what happens in interactive use with M-x.")
1731 (filename, newname, ok_if_already_exists)
1732 Lisp_Object filename, newname, ok_if_already_exists;
1734 #ifdef NO_ARG_ARRAY
1735 Lisp_Object args[2];
1736 #endif
1737 Lisp_Object handler;
1738 struct gcpro gcpro1, gcpro2;
1740 GCPRO2 (filename, newname);
1741 CHECK_STRING (filename, 0);
1742 CHECK_STRING (newname, 1);
1743 filename = Fexpand_file_name (filename, Qnil);
1744 newname = Fexpand_file_name (newname, Qnil);
1746 /* If the file name has special constructs in it,
1747 call the corresponding file handler. */
1748 handler = Ffind_file_name_handler (filename);
1749 if (!NILP (handler))
1750 return call3 (handler, Qrename_file, filename, newname);
1752 if (NILP (ok_if_already_exists)
1753 || XTYPE (ok_if_already_exists) == Lisp_Int)
1754 barf_or_query_if_file_exists (newname, "rename to it",
1755 XTYPE (ok_if_already_exists) == Lisp_Int);
1756 #ifndef BSD4_1
1757 if (0 > rename (XSTRING (filename)->data, XSTRING (newname)->data))
1758 #else
1759 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data)
1760 || 0 > unlink (XSTRING (filename)->data))
1761 #endif
1763 if (errno == EXDEV)
1765 Fcopy_file (filename, newname, ok_if_already_exists, Qt);
1766 Fdelete_file (filename);
1768 else
1769 #ifdef NO_ARG_ARRAY
1771 args[0] = filename;
1772 args[1] = newname;
1773 report_file_error ("Renaming", Flist (2, args));
1775 #else
1776 report_file_error ("Renaming", Flist (2, &filename));
1777 #endif
1779 UNGCPRO;
1780 return Qnil;
1783 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
1784 "fAdd name to file: \nFName to add to %s: \np",
1785 "Give FILE additional name NEWNAME. Both args strings.\n\
1786 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1787 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1788 A number as third arg means request confirmation if NEWNAME already exists.\n\
1789 This is what happens in interactive use with M-x.")
1790 (filename, newname, ok_if_already_exists)
1791 Lisp_Object filename, newname, ok_if_already_exists;
1793 #ifdef NO_ARG_ARRAY
1794 Lisp_Object args[2];
1795 #endif
1796 Lisp_Object handler;
1797 struct gcpro gcpro1, gcpro2;
1799 GCPRO2 (filename, newname);
1800 CHECK_STRING (filename, 0);
1801 CHECK_STRING (newname, 1);
1802 filename = Fexpand_file_name (filename, Qnil);
1803 newname = Fexpand_file_name (newname, Qnil);
1805 /* If the file name has special constructs in it,
1806 call the corresponding file handler. */
1807 handler = Ffind_file_name_handler (filename);
1808 if (!NILP (handler))
1809 return call3 (handler, Qadd_name_to_file, filename, newname);
1811 if (NILP (ok_if_already_exists)
1812 || XTYPE (ok_if_already_exists) == Lisp_Int)
1813 barf_or_query_if_file_exists (newname, "make it a new name",
1814 XTYPE (ok_if_already_exists) == Lisp_Int);
1815 unlink (XSTRING (newname)->data);
1816 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data))
1818 #ifdef NO_ARG_ARRAY
1819 args[0] = filename;
1820 args[1] = newname;
1821 report_file_error ("Adding new name", Flist (2, args));
1822 #else
1823 report_file_error ("Adding new name", Flist (2, &filename));
1824 #endif
1827 UNGCPRO;
1828 return Qnil;
1831 #ifdef S_IFLNK
1832 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
1833 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
1834 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
1835 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1836 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1837 A number as third arg means request confirmation if NEWNAME already exists.\n\
1838 This happens for interactive use with M-x.")
1839 (filename, linkname, ok_if_already_exists)
1840 Lisp_Object filename, linkname, ok_if_already_exists;
1842 #ifdef NO_ARG_ARRAY
1843 Lisp_Object args[2];
1844 #endif
1845 Lisp_Object handler;
1846 struct gcpro gcpro1, gcpro2;
1848 GCPRO2 (filename, linkname);
1849 CHECK_STRING (filename, 0);
1850 CHECK_STRING (linkname, 1);
1851 #if 0 /* This made it impossible to make a link to a relative name. */
1852 filename = Fexpand_file_name (filename, Qnil);
1853 #endif
1854 linkname = Fexpand_file_name (linkname, Qnil);
1856 /* If the file name has special constructs in it,
1857 call the corresponding file handler. */
1858 handler = Ffind_file_name_handler (filename);
1859 if (!NILP (handler))
1860 return call3 (handler, Qmake_symbolic_link, filename, linkname);
1862 if (NILP (ok_if_already_exists)
1863 || XTYPE (ok_if_already_exists) == Lisp_Int)
1864 barf_or_query_if_file_exists (linkname, "make it a link",
1865 XTYPE (ok_if_already_exists) == Lisp_Int);
1866 if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
1868 /* If we didn't complain already, silently delete existing file. */
1869 if (errno == EEXIST)
1871 unlink (XSTRING (linkname)->data);
1872 if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
1873 return Qnil;
1876 #ifdef NO_ARG_ARRAY
1877 args[0] = filename;
1878 args[1] = linkname;
1879 report_file_error ("Making symbolic link", Flist (2, args));
1880 #else
1881 report_file_error ("Making symbolic link", Flist (2, &filename));
1882 #endif
1884 UNGCPRO;
1885 return Qnil;
1887 #endif /* S_IFLNK */
1889 #ifdef VMS
1891 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
1892 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
1893 "Define the job-wide logical name NAME to have the value STRING.\n\
1894 If STRING is nil or a null string, the logical name NAME is deleted.")
1895 (varname, string)
1896 Lisp_Object varname;
1897 Lisp_Object string;
1899 CHECK_STRING (varname, 0);
1900 if (NILP (string))
1901 delete_logical_name (XSTRING (varname)->data);
1902 else
1904 CHECK_STRING (string, 1);
1906 if (XSTRING (string)->size == 0)
1907 delete_logical_name (XSTRING (varname)->data);
1908 else
1909 define_logical_name (XSTRING (varname)->data, XSTRING (string)->data);
1912 return string;
1914 #endif /* VMS */
1916 #ifdef HPUX_NET
1918 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
1919 "Open a network connection to PATH using LOGIN as the login string.")
1920 (path, login)
1921 Lisp_Object path, login;
1923 int netresult;
1925 CHECK_STRING (path, 0);
1926 CHECK_STRING (login, 0);
1928 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
1930 if (netresult == -1)
1931 return Qnil;
1932 else
1933 return Qt;
1935 #endif /* HPUX_NET */
1937 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
1938 1, 1, 0,
1939 "Return t if file FILENAME specifies an absolute path name.\n\
1940 On Unix, this is a name starting with a `/' or a `~'.")
1941 (filename)
1942 Lisp_Object filename;
1944 unsigned char *ptr;
1946 CHECK_STRING (filename, 0);
1947 ptr = XSTRING (filename)->data;
1948 if (*ptr == '/' || *ptr == '~'
1949 #ifdef VMS
1950 /* ??? This criterion is probably wrong for '<'. */
1951 || index (ptr, ':') || index (ptr, '<')
1952 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
1953 && ptr[1] != '.')
1954 #endif /* VMS */
1956 return Qt;
1957 else
1958 return Qnil;
1961 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
1962 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
1963 See also `file-readable-p' and `file-attributes'.")
1964 (filename)
1965 Lisp_Object filename;
1967 Lisp_Object abspath;
1968 Lisp_Object handler;
1970 CHECK_STRING (filename, 0);
1971 abspath = Fexpand_file_name (filename, Qnil);
1973 /* If the file name has special constructs in it,
1974 call the corresponding file handler. */
1975 handler = Ffind_file_name_handler (abspath);
1976 if (!NILP (handler))
1977 return call2 (handler, Qfile_exists_p, abspath);
1979 return (access (XSTRING (abspath)->data, 0) >= 0) ? Qt : Qnil;
1982 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
1983 "Return t if FILENAME can be executed by you.\n\
1984 For a directory, this means you can access files in that directory.")
1985 (filename)
1986 Lisp_Object filename;
1989 Lisp_Object abspath;
1990 Lisp_Object handler;
1992 CHECK_STRING (filename, 0);
1993 abspath = Fexpand_file_name (filename, Qnil);
1995 /* If the file name has special constructs in it,
1996 call the corresponding file handler. */
1997 handler = Ffind_file_name_handler (abspath);
1998 if (!NILP (handler))
1999 return call2 (handler, Qfile_executable_p, abspath);
2001 return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
2004 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2005 "Return t if file FILENAME exists and you can read it.\n\
2006 See also `file-exists-p' and `file-attributes'.")
2007 (filename)
2008 Lisp_Object filename;
2010 Lisp_Object abspath;
2011 Lisp_Object handler;
2013 CHECK_STRING (filename, 0);
2014 abspath = Fexpand_file_name (filename, Qnil);
2016 /* If the file name has special constructs in it,
2017 call the corresponding file handler. */
2018 handler = Ffind_file_name_handler (abspath);
2019 if (!NILP (handler))
2020 return call2 (handler, Qfile_readable_p, abspath);
2022 return (access (XSTRING (abspath)->data, 4) >= 0) ? Qt : Qnil;
2025 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2026 "If file FILENAME is the name of a symbolic link\n\
2027 returns the name of the file to which it is linked.\n\
2028 Otherwise returns NIL.")
2029 (filename)
2030 Lisp_Object filename;
2032 #ifdef S_IFLNK
2033 char *buf;
2034 int bufsize;
2035 int valsize;
2036 Lisp_Object val;
2037 Lisp_Object handler;
2039 CHECK_STRING (filename, 0);
2040 filename = Fexpand_file_name (filename, Qnil);
2042 /* If the file name has special constructs in it,
2043 call the corresponding file handler. */
2044 handler = Ffind_file_name_handler (filename);
2045 if (!NILP (handler))
2046 return call2 (handler, Qfile_symlink_p, filename);
2048 bufsize = 100;
2049 while (1)
2051 buf = (char *) xmalloc (bufsize);
2052 bzero (buf, bufsize);
2053 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
2054 if (valsize < bufsize) break;
2055 /* Buffer was not long enough */
2056 xfree (buf);
2057 bufsize *= 2;
2059 if (valsize == -1)
2061 xfree (buf);
2062 return Qnil;
2064 val = make_string (buf, valsize);
2065 xfree (buf);
2066 return val;
2067 #else /* not S_IFLNK */
2068 return Qnil;
2069 #endif /* not S_IFLNK */
2072 #ifdef SOLARIS_BROKEN_ACCESS
2073 /* In Solaris 2.1, the readonly-ness of the filesystem is not
2074 considered by the access system call. This is Sun's bug, but we
2075 still have to make Emacs work. */
2077 #include <sys/statvfs.h>
2079 static int
2080 ro_fsys (path)
2081 char *path;
2083 struct statvfs statvfsb;
2085 if (statvfs(path, &statvfsb))
2086 return 1; /* error from statvfs, be conservative and say not wrtable */
2087 else
2088 /* Otherwise, fsys is ro if bit is set. */
2089 return statvfsb.f_flag & ST_RDONLY;
2091 #else
2092 /* But on every other os, access has already done the right thing. */
2093 #define ro_fsys(path) 0
2094 #endif
2096 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2097 on the RT/PC. */
2098 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2099 "Return t if file FILENAME can be written or created by you.")
2100 (filename)
2101 Lisp_Object filename;
2103 Lisp_Object abspath, dir;
2104 Lisp_Object handler;
2106 CHECK_STRING (filename, 0);
2107 abspath = Fexpand_file_name (filename, Qnil);
2109 /* If the file name has special constructs in it,
2110 call the corresponding file handler. */
2111 handler = Ffind_file_name_handler (abspath);
2112 if (!NILP (handler))
2113 return call2 (handler, Qfile_writable_p, abspath);
2115 if (access (XSTRING (abspath)->data, 0) >= 0)
2116 return ((access (XSTRING (abspath)->data, 2) >= 0
2117 && ! ro_fsys ((char *) XSTRING (abspath)->data))
2118 ? Qt : Qnil);
2119 dir = Ffile_name_directory (abspath);
2120 #ifdef VMS
2121 if (!NILP (dir))
2122 dir = Fdirectory_file_name (dir);
2123 #endif /* VMS */
2124 return ((access (!NILP (dir) ? (char *) XSTRING (dir)->data : "", 2) >= 0
2125 && ! ro_fsys ((char *) XSTRING (dir)->data))
2126 ? Qt : Qnil);
2129 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2130 "Return t if file FILENAME is the name of a directory as a file.\n\
2131 A directory name spec may be given instead; then the value is t\n\
2132 if the directory so specified exists and really is a directory.")
2133 (filename)
2134 Lisp_Object filename;
2136 register Lisp_Object abspath;
2137 struct stat st;
2138 Lisp_Object handler;
2140 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2142 /* If the file name has special constructs in it,
2143 call the corresponding file handler. */
2144 handler = Ffind_file_name_handler (abspath);
2145 if (!NILP (handler))
2146 return call2 (handler, Qfile_directory_p, abspath);
2148 if (stat (XSTRING (abspath)->data, &st) < 0)
2149 return Qnil;
2150 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2153 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
2154 "Return t if file FILENAME is the name of a directory as a file,\n\
2155 and files in that directory can be opened by you. In order to use a\n\
2156 directory as a buffer's current directory, this predicate must return true.\n\
2157 A directory name spec may be given instead; then the value is t\n\
2158 if the directory so specified exists and really is a readable and\n\
2159 searchable directory.")
2160 (filename)
2161 Lisp_Object filename;
2163 Lisp_Object handler;
2165 /* If the file name has special constructs in it,
2166 call the corresponding file handler. */
2167 handler = Ffind_file_name_handler (filename);
2168 if (!NILP (handler))
2169 return call2 (handler, Qfile_accessible_directory_p, filename);
2171 if (NILP (Ffile_directory_p (filename))
2172 || NILP (Ffile_executable_p (filename)))
2173 return Qnil;
2174 else
2175 return Qt;
2178 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2179 "Return mode bits of FILE, as an integer.")
2180 (filename)
2181 Lisp_Object filename;
2183 Lisp_Object abspath;
2184 struct stat st;
2185 Lisp_Object handler;
2187 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
2189 /* If the file name has special constructs in it,
2190 call the corresponding file handler. */
2191 handler = Ffind_file_name_handler (abspath);
2192 if (!NILP (handler))
2193 return call2 (handler, Qfile_modes, abspath);
2195 if (stat (XSTRING (abspath)->data, &st) < 0)
2196 return Qnil;
2197 return make_number (st.st_mode & 07777);
2200 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
2201 "Set mode bits of FILE to MODE (an integer).\n\
2202 Only the 12 low bits of MODE are used.")
2203 (filename, mode)
2204 Lisp_Object filename, mode;
2206 Lisp_Object abspath;
2207 Lisp_Object handler;
2209 abspath = Fexpand_file_name (filename, current_buffer->directory);
2210 CHECK_NUMBER (mode, 1);
2212 /* If the file name has special constructs in it,
2213 call the corresponding file handler. */
2214 handler = Ffind_file_name_handler (abspath);
2215 if (!NILP (handler))
2216 return call3 (handler, Qset_file_modes, abspath, mode);
2218 #ifndef APOLLO
2219 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2220 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2221 #else /* APOLLO */
2222 if (!egetenv ("USE_DOMAIN_ACLS"))
2224 struct stat st;
2225 struct timeval tvp[2];
2227 /* chmod on apollo also change the file's modtime; need to save the
2228 modtime and then restore it. */
2229 if (stat (XSTRING (abspath)->data, &st) < 0)
2231 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2232 return (Qnil);
2235 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
2236 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
2238 /* reset the old accessed and modified times. */
2239 tvp[0].tv_sec = st.st_atime + 1; /* +1 due to an Apollo roundoff bug */
2240 tvp[0].tv_usec = 0;
2241 tvp[1].tv_sec = st.st_mtime + 1; /* +1 due to an Apollo roundoff bug */
2242 tvp[1].tv_usec = 0;
2244 if (utimes (XSTRING (abspath)->data, tvp) < 0)
2245 report_file_error ("Doing utimes", Fcons (abspath, Qnil));
2247 #endif /* APOLLO */
2249 return Qnil;
2252 DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
2253 "Set the file permission bits for newly created files.\n\
2254 The argument MODE should be an integer; only the low 9 bits are used.\n\
2255 This setting is inherited by subprocesses.")
2256 (mode)
2257 Lisp_Object mode;
2259 CHECK_NUMBER (mode, 0);
2261 umask ((~ XINT (mode)) & 0777);
2263 return Qnil;
2266 DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
2267 "Return the default file protection for created files.\n\
2268 The value is an integer.")
2271 int realmask;
2272 Lisp_Object value;
2274 realmask = umask (0);
2275 umask (realmask);
2277 XSET (value, Lisp_Int, (~ realmask) & 0777);
2278 return value;
2281 #ifdef unix
2283 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
2284 "Tell Unix to finish all pending disk updates.")
2287 sync ();
2288 return Qnil;
2291 #endif /* unix */
2293 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
2294 "Return t if file FILE1 is newer than file FILE2.\n\
2295 If FILE1 does not exist, the answer is nil;\n\
2296 otherwise, if FILE2 does not exist, the answer is t.")
2297 (file1, file2)
2298 Lisp_Object file1, file2;
2300 Lisp_Object abspath1, abspath2;
2301 struct stat st;
2302 int mtime1;
2303 Lisp_Object handler;
2304 struct gcpro gcpro1, gcpro2;
2306 CHECK_STRING (file1, 0);
2307 CHECK_STRING (file2, 0);
2309 abspath1 = Qnil;
2310 GCPRO2 (abspath1, file2);
2311 abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
2312 abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
2313 UNGCPRO;
2315 /* If the file name has special constructs in it,
2316 call the corresponding file handler. */
2317 handler = Ffind_file_name_handler (abspath1);
2318 if (!NILP (handler))
2319 return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2);
2321 if (stat (XSTRING (abspath1)->data, &st) < 0)
2322 return Qnil;
2324 mtime1 = st.st_mtime;
2326 if (stat (XSTRING (abspath2)->data, &st) < 0)
2327 return Qt;
2329 return (mtime1 > st.st_mtime) ? Qt : Qnil;
2332 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
2333 1, 2, 0,
2334 "Insert contents of file FILENAME after point.\n\
2335 Returns list of absolute pathname and length of data inserted.\n\
2336 If second argument VISIT is non-nil, the buffer's visited filename\n\
2337 and last save file modtime are set, and it is marked unmodified.\n\
2338 If visiting and the file does not exist, visiting is completed\n\
2339 before the error is signaled.")
2340 (filename, visit)
2341 Lisp_Object filename, visit;
2343 struct stat st;
2344 register int fd;
2345 register int inserted = 0;
2346 register int how_much;
2347 int count = specpdl_ptr - specpdl;
2348 struct gcpro gcpro1;
2349 Lisp_Object handler, val;
2351 val = Qnil;
2353 GCPRO1 (filename);
2354 if (!NILP (current_buffer->read_only))
2355 Fbarf_if_buffer_read_only();
2357 CHECK_STRING (filename, 0);
2358 filename = Fexpand_file_name (filename, Qnil);
2360 /* If the file name has special constructs in it,
2361 call the corresponding file handler. */
2362 handler = Ffind_file_name_handler (filename);
2363 if (!NILP (handler))
2365 val = call3 (handler, Qinsert_file_contents, filename, visit);
2366 st.st_mtime = 0;
2367 goto handled;
2370 fd = -1;
2372 #ifndef APOLLO
2373 if (stat (XSTRING (filename)->data, &st) < 0
2374 || (fd = open (XSTRING (filename)->data, 0)) < 0)
2375 #else
2376 if ((fd = open (XSTRING (filename)->data, 0)) < 0
2377 || fstat (fd, &st) < 0)
2378 #endif /* not APOLLO */
2380 if (fd >= 0) close (fd);
2381 if (NILP (visit))
2382 report_file_error ("Opening input file", Fcons (filename, Qnil));
2383 st.st_mtime = -1;
2384 how_much = 0;
2385 goto notfound;
2388 record_unwind_protect (close_file_unwind, make_number (fd));
2390 #ifdef S_IFSOCK
2391 /* This code will need to be changed in order to work on named
2392 pipes, and it's probably just not worth it. So we should at
2393 least signal an error. */
2394 if ((st.st_mode & S_IFMT) == S_IFSOCK)
2395 Fsignal (Qfile_error,
2396 Fcons (build_string ("reading from named pipe"),
2397 Fcons (filename, Qnil)));
2398 #endif
2400 /* Supposedly happens on VMS. */
2401 if (st.st_size < 0)
2402 error ("File size is negative");
2405 register Lisp_Object temp;
2407 /* Make sure point-max won't overflow after this insertion. */
2408 XSET (temp, Lisp_Int, st.st_size + Z);
2409 if (st.st_size + Z != XINT (temp))
2410 error ("maximum buffer size exceeded");
2413 if (NILP (visit))
2414 prepare_to_modify_buffer (point, point);
2416 move_gap (point);
2417 if (GAP_SIZE < st.st_size)
2418 make_gap (st.st_size - GAP_SIZE);
2420 while (1)
2422 int try = min (st.st_size - inserted, 64 << 10);
2423 int this;
2425 /* Allow quitting out of the actual I/O. */
2426 immediate_quit = 1;
2427 QUIT;
2428 this = read (fd, &FETCH_CHAR (point + inserted - 1) + 1, try);
2429 immediate_quit = 0;
2431 if (this <= 0)
2433 how_much = this;
2434 break;
2437 GPT += this;
2438 GAP_SIZE -= this;
2439 ZV += this;
2440 Z += this;
2441 inserted += this;
2444 if (inserted > 0)
2446 record_insert (point, inserted);
2448 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
2449 offset_intervals (current_buffer, point, inserted);
2450 MODIFF++;
2453 close (fd);
2455 /* Discard the unwind protect */
2456 specpdl_ptr = specpdl + count;
2458 if (how_much < 0)
2459 error ("IO error reading %s: %s",
2460 XSTRING (filename)->data, err_str (errno));
2462 notfound:
2463 handled:
2465 if (!NILP (visit))
2467 current_buffer->undo_list = Qnil;
2468 #ifdef APOLLO
2469 stat (XSTRING (filename)->data, &st);
2470 #endif
2471 current_buffer->modtime = st.st_mtime;
2472 current_buffer->save_modified = MODIFF;
2473 current_buffer->auto_save_modified = MODIFF;
2474 XFASTINT (current_buffer->save_length) = Z - BEG;
2475 #ifdef CLASH_DETECTION
2476 if (NILP (handler))
2478 if (!NILP (current_buffer->filename))
2479 unlock_file (current_buffer->filename);
2480 unlock_file (filename);
2482 #endif /* CLASH_DETECTION */
2483 current_buffer->filename = filename;
2484 /* If visiting nonexistent file, return nil. */
2485 if (current_buffer->modtime == -1)
2486 report_file_error ("Opening input file", Fcons (filename, Qnil));
2489 signal_after_change (point, 0, inserted);
2491 if (!NILP (val))
2492 RETURN_UNGCPRO (val);
2493 RETURN_UNGCPRO (Fcons (filename,
2494 Fcons (make_number (inserted),
2495 Qnil)));
2498 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
2499 "r\nFWrite region to file: ",
2500 "Write current region into specified file.\n\
2501 When called from a program, takes three arguments:\n\
2502 START, END and FILENAME. START and END are buffer positions.\n\
2503 Optional fourth argument APPEND if non-nil means\n\
2504 append to existing file contents (if any).\n\
2505 Optional fifth argument VISIT if t means\n\
2506 set the last-save-file-modtime of buffer to this file's modtime\n\
2507 and mark buffer not modified.\n\
2508 If VISIT is a string, it is a second file name;\n\
2509 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
2510 VISIT is also the file name to lock and unlock for clash detection.\n\
2511 If VISIT is neither t nor nil nor a string,\n\
2512 that means do not print the \"Wrote file\" message.\n\
2513 Kludgy feature: if START is a string, then that string is written\n\
2514 to the file, instead of any buffer contents, and END is ignored.")
2515 (start, end, filename, append, visit)
2516 Lisp_Object start, end, filename, append, visit;
2518 register int desc;
2519 int failure;
2520 int save_errno;
2521 unsigned char *fn;
2522 struct stat st;
2523 int tem;
2524 int count = specpdl_ptr - specpdl;
2525 #ifdef VMS
2526 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
2527 #endif /* VMS */
2528 Lisp_Object handler;
2529 Lisp_Object visit_file;
2530 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2532 /* Special kludge to simplify auto-saving */
2533 if (NILP (start))
2535 XFASTINT (start) = BEG;
2536 XFASTINT (end) = Z;
2538 else if (XTYPE (start) != Lisp_String)
2539 validate_region (&start, &end);
2541 filename = Fexpand_file_name (filename, Qnil);
2542 if (XTYPE (visit) == Lisp_String)
2543 visit_file = Fexpand_file_name (visit, Qnil);
2544 else
2545 visit_file = filename;
2547 GCPRO4 (start, filename, visit, visit_file);
2549 /* If the file name has special constructs in it,
2550 call the corresponding file handler. */
2551 handler = Ffind_file_name_handler (filename);
2553 if (!NILP (handler))
2555 Lisp_Object args[7];
2556 Lisp_Object val;
2557 args[0] = handler;
2558 args[1] = Qwrite_region;
2559 args[2] = start;
2560 args[3] = end;
2561 args[4] = filename;
2562 args[5] = append;
2563 args[6] = visit;
2564 val = Ffuncall (7, args);
2566 /* Do this before reporting IO error
2567 to avoid a "file has changed on disk" warning on
2568 next attempt to save. */
2569 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
2571 current_buffer->modtime = 0;
2572 current_buffer->save_modified = MODIFF;
2573 XFASTINT (current_buffer->save_length) = Z - BEG;
2574 current_buffer->filename = visit_file;
2576 UNGCPRO;
2577 return val;
2580 #ifdef CLASH_DETECTION
2581 if (!auto_saving)
2582 lock_file (visit_file);
2583 #endif /* CLASH_DETECTION */
2585 fn = XSTRING (filename)->data;
2586 desc = -1;
2587 if (!NILP (append))
2588 desc = open (fn, O_WRONLY);
2590 if (desc < 0)
2591 #ifdef VMS
2592 if (auto_saving) /* Overwrite any previous version of autosave file */
2594 vms_truncate (fn); /* if fn exists, truncate to zero length */
2595 desc = open (fn, O_RDWR);
2596 if (desc < 0)
2597 desc = creat_copy_attrs (XTYPE (current_buffer->filename) == Lisp_String
2598 ? XSTRING (current_buffer->filename)->data : 0,
2599 fn);
2601 else /* Write to temporary name and rename if no errors */
2603 Lisp_Object temp_name;
2604 temp_name = Ffile_name_directory (filename);
2606 if (!NILP (temp_name))
2608 temp_name = Fmake_temp_name (concat2 (temp_name,
2609 build_string ("$$SAVE$$")));
2610 fname = XSTRING (filename)->data;
2611 fn = XSTRING (temp_name)->data;
2612 desc = creat_copy_attrs (fname, fn);
2613 if (desc < 0)
2615 /* If we can't open the temporary file, try creating a new
2616 version of the original file. VMS "creat" creates a
2617 new version rather than truncating an existing file. */
2618 fn = fname;
2619 fname = 0;
2620 desc = creat (fn, 0666);
2621 #if 0 /* This can clobber an existing file and fail to replace it,
2622 if the user runs out of space. */
2623 if (desc < 0)
2625 /* We can't make a new version;
2626 try to truncate and rewrite existing version if any. */
2627 vms_truncate (fn);
2628 desc = open (fn, O_RDWR);
2630 #endif
2633 else
2634 desc = creat (fn, 0666);
2636 #else /* not VMS */
2637 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
2638 #endif /* not VMS */
2640 UNGCPRO;
2642 if (desc < 0)
2644 #ifdef CLASH_DETECTION
2645 save_errno = errno;
2646 if (!auto_saving) unlock_file (visit_file);
2647 errno = save_errno;
2648 #endif /* CLASH_DETECTION */
2649 report_file_error ("Opening output file", Fcons (filename, Qnil));
2652 record_unwind_protect (close_file_unwind, make_number (desc));
2654 if (!NILP (append))
2655 if (lseek (desc, 0, 2) < 0)
2657 #ifdef CLASH_DETECTION
2658 if (!auto_saving) unlock_file (visit_file);
2659 #endif /* CLASH_DETECTION */
2660 report_file_error ("Lseek error", Fcons (filename, Qnil));
2663 #ifdef VMS
2665 * Kludge Warning: The VMS C RTL likes to insert carriage returns
2666 * if we do writes that don't end with a carriage return. Furthermore
2667 * it cannot handle writes of more then 16K. The modified
2668 * version of "sys_write" in SYSDEP.C (see comment there) copes with
2669 * this EXCEPT for the last record (iff it doesn't end with a carriage
2670 * return). This implies that if your buffer doesn't end with a carriage
2671 * return, you get one free... tough. However it also means that if
2672 * we make two calls to sys_write (a la the following code) you can
2673 * get one at the gap as well. The easiest way to fix this (honest)
2674 * is to move the gap to the next newline (or the end of the buffer).
2675 * Thus this change.
2677 * Yech!
2679 if (GPT > BEG && GPT_ADDR[-1] != '\n')
2680 move_gap (find_next_newline (GPT, 1));
2681 #endif
2683 failure = 0;
2684 immediate_quit = 1;
2686 if (XTYPE (start) == Lisp_String)
2688 failure = 0 > e_write (desc, XSTRING (start)->data,
2689 XSTRING (start)->size);
2690 save_errno = errno;
2692 else if (XINT (start) != XINT (end))
2694 if (XINT (start) < GPT)
2696 register int end1 = XINT (end);
2697 tem = XINT (start);
2698 failure = 0 > e_write (desc, &FETCH_CHAR (tem),
2699 min (GPT, end1) - tem);
2700 save_errno = errno;
2703 if (XINT (end) > GPT && !failure)
2705 tem = XINT (start);
2706 tem = max (tem, GPT);
2707 failure = 0 > e_write (desc, &FETCH_CHAR (tem), XINT (end) - tem);
2708 save_errno = errno;
2712 immediate_quit = 0;
2714 #ifdef HAVE_FSYNC
2715 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
2716 Disk full in NFS may be reported here. */
2717 /* mib says that closing the file will try to write as fast as NFS can do
2718 it, and that means the fsync here is not crucial for autosave files. */
2719 if (!auto_saving && fsync (desc) < 0)
2720 failure = 1, save_errno = errno;
2721 #endif
2723 /* Spurious "file has changed on disk" warnings have been
2724 observed on Suns as well.
2725 It seems that `close' can change the modtime, under nfs.
2727 (This has supposedly been fixed in Sunos 4,
2728 but who knows about all the other machines with NFS?) */
2729 #if 0
2731 /* On VMS and APOLLO, must do the stat after the close
2732 since closing changes the modtime. */
2733 #ifndef VMS
2734 #ifndef APOLLO
2735 /* Recall that #if defined does not work on VMS. */
2736 #define FOO
2737 fstat (desc, &st);
2738 #endif
2739 #endif
2740 #endif
2742 /* NFS can report a write failure now. */
2743 if (close (desc) < 0)
2744 failure = 1, save_errno = errno;
2746 #ifdef VMS
2747 /* If we wrote to a temporary name and had no errors, rename to real name. */
2748 if (fname)
2750 if (!failure)
2751 failure = (rename (fn, fname) != 0), save_errno = errno;
2752 fn = fname;
2754 #endif /* VMS */
2756 #ifndef FOO
2757 stat (fn, &st);
2758 #endif
2759 /* Discard the unwind protect */
2760 specpdl_ptr = specpdl + count;
2762 #ifdef CLASH_DETECTION
2763 if (!auto_saving)
2764 unlock_file (visit_file);
2765 #endif /* CLASH_DETECTION */
2767 /* Do this before reporting IO error
2768 to avoid a "file has changed on disk" warning on
2769 next attempt to save. */
2770 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
2771 current_buffer->modtime = st.st_mtime;
2773 if (failure)
2774 error ("IO error writing %s: %s", fn, err_str (save_errno));
2776 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
2778 current_buffer->save_modified = MODIFF;
2779 XFASTINT (current_buffer->save_length) = Z - BEG;
2780 current_buffer->filename = visit_file;
2782 else if (!NILP (visit))
2783 return Qnil;
2785 if (!auto_saving)
2786 message ("Wrote %s", XSTRING (visit_file)->data);
2788 return Qnil;
2792 e_write (desc, addr, len)
2793 int desc;
2794 register char *addr;
2795 register int len;
2797 char buf[16 * 1024];
2798 register char *p, *end;
2800 if (!EQ (current_buffer->selective_display, Qt))
2801 return write (desc, addr, len) - len;
2802 else
2804 p = buf;
2805 end = p + sizeof buf;
2806 while (len--)
2808 if (p == end)
2810 if (write (desc, buf, sizeof buf) != sizeof buf)
2811 return -1;
2812 p = buf;
2814 *p = *addr++;
2815 if (*p++ == '\015')
2816 p[-1] = '\n';
2818 if (p != buf)
2819 if (write (desc, buf, p - buf) != p - buf)
2820 return -1;
2822 return 0;
2825 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
2826 Sverify_visited_file_modtime, 1, 1, 0,
2827 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
2828 This means that the file has not been changed since it was visited or saved.")
2829 (buf)
2830 Lisp_Object buf;
2832 struct buffer *b;
2833 struct stat st;
2834 Lisp_Object handler;
2836 CHECK_BUFFER (buf, 0);
2837 b = XBUFFER (buf);
2839 if (XTYPE (b->filename) != Lisp_String) return Qt;
2840 if (b->modtime == 0) return Qt;
2842 /* If the file name has special constructs in it,
2843 call the corresponding file handler. */
2844 handler = Ffind_file_name_handler (b->filename);
2845 if (!NILP (handler))
2846 return call2 (handler, Qverify_visited_file_modtime, buf);
2848 if (stat (XSTRING (b->filename)->data, &st) < 0)
2850 /* If the file doesn't exist now and didn't exist before,
2851 we say that it isn't modified, provided the error is a tame one. */
2852 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
2853 st.st_mtime = -1;
2854 else
2855 st.st_mtime = 0;
2857 if (st.st_mtime == b->modtime
2858 /* If both are positive, accept them if they are off by one second. */
2859 || (st.st_mtime > 0 && b->modtime > 0
2860 && (st.st_mtime == b->modtime + 1
2861 || st.st_mtime == b->modtime - 1)))
2862 return Qt;
2863 return Qnil;
2866 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
2867 Sclear_visited_file_modtime, 0, 0, 0,
2868 "Clear out records of last mod time of visited file.\n\
2869 Next attempt to save will certainly not complain of a discrepancy.")
2872 current_buffer->modtime = 0;
2873 return Qnil;
2876 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
2877 Svisited_file_modtime, 0, 0, 0,
2878 "Return the current buffer's recorded visited file modification time.\n\
2879 The value is a list of the form (HIGH . LOW), like the time values\n\
2880 that `file-attributes' returns.")
2883 return long_to_cons (current_buffer->modtime);
2886 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
2887 Sset_visited_file_modtime, 0, 1, 0,
2888 "Update buffer's recorded modification time from the visited file's time.\n\
2889 Useful if the buffer was not read from the file normally\n\
2890 or if the file itself has been changed for some known benign reason.\n\
2891 An argument specifies the modification time value to use\n\
2892 \(instead of that of the visited file), in the form of a list\n\
2893 \(HIGH . LOW) or (HIGH LOW).")
2894 (time_list)
2895 Lisp_Object time_list;
2897 if (!NILP (time_list))
2898 current_buffer->modtime = cons_to_long (time_list);
2899 else
2901 register Lisp_Object filename;
2902 struct stat st;
2903 Lisp_Object handler;
2905 filename = Fexpand_file_name (current_buffer->filename, Qnil);
2907 /* If the file name has special constructs in it,
2908 call the corresponding file handler. */
2909 handler = Ffind_file_name_handler (filename);
2910 if (!NILP (handler))
2911 return call3 (handler, Qfile_name_directory, filename, Qnil);
2912 else if (stat (XSTRING (filename)->data, &st) >= 0)
2913 current_buffer->modtime = st.st_mtime;
2916 return Qnil;
2919 Lisp_Object
2920 auto_save_error ()
2922 unsigned char *name = XSTRING (current_buffer->name)->data;
2924 ring_bell ();
2925 message ("Autosaving...error for %s", name);
2926 Fsleep_for (make_number (1), Qnil);
2927 message ("Autosaving...error!for %s", name);
2928 Fsleep_for (make_number (1), Qnil);
2929 message ("Autosaving...error for %s", name);
2930 Fsleep_for (make_number (1), Qnil);
2931 return Qnil;
2934 Lisp_Object
2935 auto_save_1 ()
2937 unsigned char *fn;
2938 struct stat st;
2940 /* Get visited file's mode to become the auto save file's mode. */
2941 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
2942 /* But make sure we can overwrite it later! */
2943 auto_save_mode_bits = st.st_mode | 0600;
2944 else
2945 auto_save_mode_bits = 0666;
2947 return
2948 Fwrite_region (Qnil, Qnil,
2949 current_buffer->auto_save_file_name,
2950 Qnil, Qlambda);
2953 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
2954 "Auto-save all buffers that need it.\n\
2955 This is all buffers that have auto-saving enabled\n\
2956 and are changed since last auto-saved.\n\
2957 Auto-saving writes the buffer into a file\n\
2958 so that your editing is not lost if the system crashes.\n\
2959 This file is not the file you visited; that changes only when you save.\n\n\
2960 Non-nil first argument means do not print any message if successful.\n\
2961 Non-nil second argument means save only current buffer.")
2962 (no_message, current_only)
2963 Lisp_Object no_message, current_only;
2965 struct buffer *old = current_buffer, *b;
2966 Lisp_Object tail, buf;
2967 int auto_saved = 0;
2968 char *omessage = echo_area_glyphs;
2969 extern int minibuf_level;
2970 int do_handled_files;
2972 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
2973 point to non-strings reached from Vbuffer_alist. */
2975 auto_saving = 1;
2976 if (minibuf_level)
2977 no_message = Qt;
2979 /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
2980 eventually call do-auto-save, so don't err here in that case. */
2981 if (!NILP (Vrun_hooks))
2982 call1 (Vrun_hooks, intern ("auto-save-hook"));
2984 /* First, save all files which don't have handlers. If Emacs is
2985 crashing, the handlers may tweak what is causing Emacs to crash
2986 in the first place, and it would be a shame if Emacs failed to
2987 autosave perfectly ordinary files because it couldn't handle some
2988 ange-ftp'd file. */
2989 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
2990 for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
2991 tail = XCONS (tail)->cdr)
2993 buf = XCONS (XCONS (tail)->car)->cdr;
2994 b = XBUFFER (buf);
2996 if (!NILP (current_only)
2997 && b != current_buffer)
2998 continue;
3000 /* Check for auto save enabled
3001 and file changed since last auto save
3002 and file changed since last real save. */
3003 if (XTYPE (b->auto_save_file_name) == Lisp_String
3004 && b->save_modified < BUF_MODIFF (b)
3005 && b->auto_save_modified < BUF_MODIFF (b)
3006 && (do_handled_files
3007 || NILP (Ffind_file_name_handler (b->auto_save_file_name))))
3009 if ((XFASTINT (b->save_length) * 10
3010 > (BUF_Z (b) - BUF_BEG (b)) * 13)
3011 /* A short file is likely to change a large fraction;
3012 spare the user annoying messages. */
3013 && XFASTINT (b->save_length) > 5000
3014 /* These messages are frequent and annoying for `*mail*'. */
3015 && !EQ (b->filename, Qnil)
3016 && NILP (no_message))
3018 /* It has shrunk too much; turn off auto-saving here. */
3019 message ("Buffer %s has shrunk a lot; auto save turned off there",
3020 XSTRING (b->name)->data);
3021 /* User can reenable saving with M-x auto-save. */
3022 b->auto_save_file_name = Qnil;
3023 /* Prevent warning from repeating if user does so. */
3024 XFASTINT (b->save_length) = 0;
3025 Fsleep_for (make_number (1), Qnil);
3026 continue;
3028 set_buffer_internal (b);
3029 if (!auto_saved && NILP (no_message))
3030 message1 ("Auto-saving...");
3031 internal_condition_case (auto_save_1, Qt, auto_save_error);
3032 auto_saved++;
3033 b->auto_save_modified = BUF_MODIFF (b);
3034 XFASTINT (current_buffer->save_length) = Z - BEG;
3035 set_buffer_internal (old);
3039 /* Prevent another auto save till enough input events come in. */
3040 record_auto_save ();
3042 if (auto_saved && NILP (no_message))
3043 message1 (omessage ? omessage : "Auto-saving...done");
3045 auto_saving = 0;
3046 return Qnil;
3049 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
3050 Sset_buffer_auto_saved, 0, 0, 0,
3051 "Mark current buffer as auto-saved with its current text.\n\
3052 No auto-save file will be written until the buffer changes again.")
3055 current_buffer->auto_save_modified = MODIFF;
3056 XFASTINT (current_buffer->save_length) = Z - BEG;
3057 return Qnil;
3060 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
3061 0, 0, 0,
3062 "Return t if buffer has been auto-saved since last read in or saved.")
3065 return (current_buffer->save_modified < current_buffer->auto_save_modified) ? Qt : Qnil;
3068 /* Reading and completing file names */
3069 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
3071 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
3072 3, 3, 0,
3073 "Internal subroutine for read-file-name. Do not call this.")
3074 (string, dir, action)
3075 Lisp_Object string, dir, action;
3076 /* action is nil for complete, t for return list of completions,
3077 lambda for verify final value */
3079 Lisp_Object name, specdir, realdir, val, orig_string;
3080 int changed;
3081 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3083 realdir = dir;
3084 name = string;
3085 orig_string = Qnil;
3086 specdir = Qnil;
3087 changed = 0;
3088 /* No need to protect ACTION--we only compare it with t and nil. */
3089 GCPRO4 (string, realdir, name, specdir);
3091 if (XSTRING (string)->size == 0)
3093 if (EQ (action, Qlambda))
3095 UNGCPRO;
3096 return Qnil;
3099 else
3101 orig_string = string;
3102 string = Fsubstitute_in_file_name (string);
3103 changed = NILP (Fstring_equal (string, orig_string));
3104 name = Ffile_name_nondirectory (string);
3105 val = Ffile_name_directory (string);
3106 if (! NILP (val))
3107 realdir = Fexpand_file_name (val, realdir);
3110 if (NILP (action))
3112 specdir = Ffile_name_directory (string);
3113 val = Ffile_name_completion (name, realdir);
3114 UNGCPRO;
3115 if (XTYPE (val) != Lisp_String)
3117 if (changed)
3118 return string;
3119 return val;
3122 if (!NILP (specdir))
3123 val = concat2 (specdir, val);
3124 #ifndef VMS
3126 register unsigned char *old, *new;
3127 register int n;
3128 int osize, count;
3130 osize = XSTRING (val)->size;
3131 /* Quote "$" as "$$" to get it past substitute-in-file-name */
3132 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
3133 if (*old++ == '$') count++;
3134 if (count > 0)
3136 old = XSTRING (val)->data;
3137 val = Fmake_string (make_number (osize + count), make_number (0));
3138 new = XSTRING (val)->data;
3139 for (n = osize; n > 0; n--)
3140 if (*old != '$')
3141 *new++ = *old++;
3142 else
3144 *new++ = '$';
3145 *new++ = '$';
3146 old++;
3150 #endif /* Not VMS */
3151 return val;
3153 UNGCPRO;
3155 if (EQ (action, Qt))
3156 return Ffile_name_all_completions (name, realdir);
3157 /* Only other case actually used is ACTION = lambda */
3158 #ifdef VMS
3159 /* Supposedly this helps commands such as `cd' that read directory names,
3160 but can someone explain how it helps them? -- RMS */
3161 if (XSTRING (name)->size == 0)
3162 return Qt;
3163 #endif /* VMS */
3164 return Ffile_exists_p (string);
3167 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
3168 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3169 Value is not expanded---you must call `expand-file-name' yourself.\n\
3170 Default name to DEFAULT if user enters a null string.\n\
3171 (If DEFAULT is omitted, the visited file name is used.)\n\
3172 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3173 Non-nil and non-t means also require confirmation after completion.\n\
3174 Fifth arg INITIAL specifies text to start with.\n\
3175 DIR defaults to current buffer's directory default.")
3176 (prompt, dir, defalt, mustmatch, initial)
3177 Lisp_Object prompt, dir, defalt, mustmatch, initial;
3179 Lisp_Object val, insdef, insdef1, tem;
3180 struct gcpro gcpro1, gcpro2;
3181 register char *homedir;
3182 int count;
3184 if (NILP (dir))
3185 dir = current_buffer->directory;
3186 if (NILP (defalt))
3187 defalt = current_buffer->filename;
3189 /* If dir starts with user's homedir, change that to ~. */
3190 homedir = (char *) egetenv ("HOME");
3191 if (homedir != 0
3192 && XTYPE (dir) == Lisp_String
3193 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
3194 && XSTRING (dir)->data[strlen (homedir)] == '/')
3196 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
3197 XSTRING (dir)->size - strlen (homedir) + 1);
3198 XSTRING (dir)->data[0] = '~';
3201 if (insert_default_directory)
3203 insdef = dir;
3204 insdef1 = dir;
3205 if (!NILP (initial))
3207 Lisp_Object args[2], pos;
3209 args[0] = insdef;
3210 args[1] = initial;
3211 insdef = Fconcat (2, args);
3212 pos = make_number (XSTRING (dir)->size);
3213 insdef1 = Fcons (insdef, pos);
3216 else
3217 insdef = Qnil, insdef1 = Qnil;
3219 #ifdef VMS
3220 count = specpdl_ptr - specpdl;
3221 specbind (intern ("completion-ignore-case"), Qt);
3222 #endif
3224 GCPRO2 (insdef, defalt);
3225 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
3226 dir, mustmatch, insdef1,
3227 Qfile_name_history);
3229 #ifdef VMS
3230 unbind_to (count, Qnil);
3231 #endif
3233 UNGCPRO;
3234 if (NILP (val))
3235 error ("No file name specified");
3236 tem = Fstring_equal (val, insdef);
3237 if (!NILP (tem) && !NILP (defalt))
3238 return defalt;
3239 if (XSTRING (val)->size == 0 && NILP (insdef))
3240 return defalt;
3241 return Fsubstitute_in_file_name (val);
3244 #if 0 /* Old version */
3245 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
3246 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
3247 Value is not expanded---you must call `expand-file-name' yourself.\n\
3248 Default name to DEFAULT if user enters a null string.\n\
3249 (If DEFAULT is omitted, the visited file name is used.)\n\
3250 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
3251 Non-nil and non-t means also require confirmation after completion.\n\
3252 Fifth arg INITIAL specifies text to start with.\n\
3253 DIR defaults to current buffer's directory default.")
3254 (prompt, dir, defalt, mustmatch, initial)
3255 Lisp_Object prompt, dir, defalt, mustmatch, initial;
3257 Lisp_Object val, insdef, tem;
3258 struct gcpro gcpro1, gcpro2;
3259 register char *homedir;
3260 int count;
3262 if (NILP (dir))
3263 dir = current_buffer->directory;
3264 if (NILP (defalt))
3265 defalt = current_buffer->filename;
3267 /* If dir starts with user's homedir, change that to ~. */
3268 homedir = (char *) egetenv ("HOME");
3269 if (homedir != 0
3270 && XTYPE (dir) == Lisp_String
3271 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
3272 && XSTRING (dir)->data[strlen (homedir)] == '/')
3274 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
3275 XSTRING (dir)->size - strlen (homedir) + 1);
3276 XSTRING (dir)->data[0] = '~';
3279 if (!NILP (initial))
3280 insdef = initial;
3281 else if (insert_default_directory)
3282 insdef = dir;
3283 else
3284 insdef = build_string ("");
3286 #ifdef VMS
3287 count = specpdl_ptr - specpdl;
3288 specbind (intern ("completion-ignore-case"), Qt);
3289 #endif
3291 GCPRO2 (insdef, defalt);
3292 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
3293 dir, mustmatch,
3294 insert_default_directory ? insdef : Qnil,
3295 Qfile_name_history);
3297 #ifdef VMS
3298 unbind_to (count, Qnil);
3299 #endif
3301 UNGCPRO;
3302 if (NILP (val))
3303 error ("No file name specified");
3304 tem = Fstring_equal (val, insdef);
3305 if (!NILP (tem) && !NILP (defalt))
3306 return defalt;
3307 return Fsubstitute_in_file_name (val);
3309 #endif /* Old version */
3311 syms_of_fileio ()
3313 Qexpand_file_name = intern ("expand-file-name");
3314 Qdirectory_file_name = intern ("directory-file-name");
3315 Qfile_name_directory = intern ("file-name-directory");
3316 Qfile_name_nondirectory = intern ("file-name-nondirectory");
3317 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
3318 Qfile_name_as_directory = intern ("file-name-as-directory");
3319 Qcopy_file = intern ("copy-file");
3320 Qmake_directory = intern ("make-directory");
3321 Qdelete_directory = intern ("delete-directory");
3322 Qdelete_file = intern ("delete-file");
3323 Qrename_file = intern ("rename-file");
3324 Qadd_name_to_file = intern ("add-name-to-file");
3325 Qmake_symbolic_link = intern ("make-symbolic-link");
3326 Qfile_exists_p = intern ("file-exists-p");
3327 Qfile_executable_p = intern ("file-executable-p");
3328 Qfile_readable_p = intern ("file-readable-p");
3329 Qfile_symlink_p = intern ("file-symlink-p");
3330 Qfile_writable_p = intern ("file-writable-p");
3331 Qfile_directory_p = intern ("file-directory-p");
3332 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
3333 Qfile_modes = intern ("file-modes");
3334 Qset_file_modes = intern ("set-file-modes");
3335 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
3336 Qinsert_file_contents = intern ("insert-file-contents");
3337 Qwrite_region = intern ("write-region");
3338 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
3340 staticpro (&Qexpand_file_name);
3341 staticpro (&Qdirectory_file_name);
3342 staticpro (&Qfile_name_directory);
3343 staticpro (&Qfile_name_nondirectory);
3344 staticpro (&Qunhandled_file_name_directory);
3345 staticpro (&Qfile_name_as_directory);
3346 staticpro (&Qcopy_file);
3347 staticpro (&Qmake_directory);
3348 staticpro (&Qdelete_directory);
3349 staticpro (&Qdelete_file);
3350 staticpro (&Qrename_file);
3351 staticpro (&Qadd_name_to_file);
3352 staticpro (&Qmake_symbolic_link);
3353 staticpro (&Qfile_exists_p);
3354 staticpro (&Qfile_executable_p);
3355 staticpro (&Qfile_readable_p);
3356 staticpro (&Qfile_symlink_p);
3357 staticpro (&Qfile_writable_p);
3358 staticpro (&Qfile_directory_p);
3359 staticpro (&Qfile_accessible_directory_p);
3360 staticpro (&Qfile_modes);
3361 staticpro (&Qset_file_modes);
3362 staticpro (&Qfile_newer_than_file_p);
3363 staticpro (&Qinsert_file_contents);
3364 staticpro (&Qwrite_region);
3365 staticpro (&Qverify_visited_file_modtime);
3367 Qfile_name_history = intern ("file-name-history");
3368 Fset (Qfile_name_history, Qnil);
3369 staticpro (&Qfile_name_history);
3371 Qfile_error = intern ("file-error");
3372 staticpro (&Qfile_error);
3373 Qfile_already_exists = intern("file-already-exists");
3374 staticpro (&Qfile_already_exists);
3376 Fput (Qfile_error, Qerror_conditions,
3377 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
3378 Fput (Qfile_error, Qerror_message,
3379 build_string ("File error"));
3381 Fput (Qfile_already_exists, Qerror_conditions,
3382 Fcons (Qfile_already_exists,
3383 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
3384 Fput (Qfile_already_exists, Qerror_message,
3385 build_string ("File already exists"));
3387 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
3388 "*Non-nil means when reading a filename start with default dir in minibuffer.");
3389 insert_default_directory = 1;
3391 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
3392 "*Non-nil means write new files with record format `stmlf'.\n\
3393 nil means use format `var'. This variable is meaningful only on VMS.");
3394 vms_stmlf_recfm = 0;
3396 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
3397 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
3398 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
3399 HANDLER.\n\
3401 The first argument given to HANDLER is the name of the I/O primitive\n\
3402 to be handled; the remaining arguments are the arguments that were\n\
3403 passed to that primitive. For example, if you do\n\
3404 (file-exists-p FILENAME)\n\
3405 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
3406 (funcall HANDLER 'file-exists-p FILENAME)\n\
3407 The function `find-file-name-handler' checks this list for a handler\n\
3408 for its argument.");
3409 Vfile_name_handler_alist = Qnil;
3411 defsubr (&Sfind_file_name_handler);
3412 defsubr (&Sfile_name_directory);
3413 defsubr (&Sfile_name_nondirectory);
3414 defsubr (&Sunhandled_file_name_directory);
3415 defsubr (&Sfile_name_as_directory);
3416 defsubr (&Sdirectory_file_name);
3417 defsubr (&Smake_temp_name);
3418 defsubr (&Sexpand_file_name);
3419 defsubr (&Ssubstitute_in_file_name);
3420 defsubr (&Scopy_file);
3421 defsubr (&Smake_directory_internal);
3422 defsubr (&Sdelete_directory);
3423 defsubr (&Sdelete_file);
3424 defsubr (&Srename_file);
3425 defsubr (&Sadd_name_to_file);
3426 #ifdef S_IFLNK
3427 defsubr (&Smake_symbolic_link);
3428 #endif /* S_IFLNK */
3429 #ifdef VMS
3430 defsubr (&Sdefine_logical_name);
3431 #endif /* VMS */
3432 #ifdef HPUX_NET
3433 defsubr (&Ssysnetunam);
3434 #endif /* HPUX_NET */
3435 defsubr (&Sfile_name_absolute_p);
3436 defsubr (&Sfile_exists_p);
3437 defsubr (&Sfile_executable_p);
3438 defsubr (&Sfile_readable_p);
3439 defsubr (&Sfile_writable_p);
3440 defsubr (&Sfile_symlink_p);
3441 defsubr (&Sfile_directory_p);
3442 defsubr (&Sfile_accessible_directory_p);
3443 defsubr (&Sfile_modes);
3444 defsubr (&Sset_file_modes);
3445 defsubr (&Sset_default_file_modes);
3446 defsubr (&Sdefault_file_modes);
3447 defsubr (&Sfile_newer_than_file_p);
3448 defsubr (&Sinsert_file_contents);
3449 defsubr (&Swrite_region);
3450 defsubr (&Sverify_visited_file_modtime);
3451 defsubr (&Sclear_visited_file_modtime);
3452 defsubr (&Svisited_file_modtime);
3453 defsubr (&Sset_visited_file_modtime);
3454 defsubr (&Sdo_auto_save);
3455 defsubr (&Sset_buffer_auto_saved);
3456 defsubr (&Srecent_auto_save_p);
3458 defsubr (&Sread_file_name_internal);
3459 defsubr (&Sread_file_name);
3461 #ifdef unix
3462 defsubr (&Sunix_sync);
3463 #endif