entered into RCS
[emacs.git] / src / fileio.c
blob4ff7dfeee8777e137e4b8309ef9f056a4f39f0c6
1 /* File IO for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988, 1992 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 #else
39 #include <sys/dir.h>
40 #endif
42 #include <errno.h>
44 #ifndef vax11c
45 extern int errno;
46 extern char *sys_errlist[];
47 extern int sys_nerr;
48 #endif
50 #define err_str(a) ((a) < sys_nerr ? sys_errlist[a] : "unknown error")
52 #ifdef APOLLO
53 #include <sys/time.h>
54 #endif
56 #include "lisp.h"
57 #include "buffer.h"
58 #include "window.h"
60 #ifdef VMS
61 #include <file.h>
62 #include <rmsdef.h>
63 #include <fab.h>
64 #include <nam.h>
65 #endif
67 #include "systime.h"
69 #ifdef HPUX
70 #include <netio.h>
71 #ifndef HPUX8
72 #include <errnet.h>
73 #endif
74 #endif
76 #ifndef O_WRONLY
77 #define O_WRONLY 1
78 #endif
80 #define min(a, b) ((a) < (b) ? (a) : (b))
81 #define max(a, b) ((a) > (b) ? (a) : (b))
83 /* Nonzero during writing of auto-save files */
84 int auto_saving;
86 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
87 a new file with the same mode as the original */
88 int auto_save_mode_bits;
90 /* Nonzero means, when reading a filename in the minibuffer,
91 start out by inserting the default directory into the minibuffer. */
92 int insert_default_directory;
94 /* On VMS, nonzero means write new files with record format stmlf.
95 Zero means use var format. */
96 int vms_stmlf_recfm;
98 Lisp_Object Qfile_error, Qfile_already_exists;
100 report_file_error (string, data)
101 char *string;
102 Lisp_Object data;
104 Lisp_Object errstring;
106 if (errno >= 0 && errno < sys_nerr)
107 errstring = build_string (sys_errlist[errno]);
108 else
109 errstring = build_string ("undocumented error code");
111 /* System error messages are capitalized. Downcase the initial
112 unless it is followed by a slash. */
113 if (XSTRING (errstring)->data[1] != '/')
114 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
116 while (1)
117 Fsignal (Qfile_error,
118 Fcons (build_string (string), Fcons (errstring, data)));
121 close_file_unwind (fd)
122 Lisp_Object fd;
124 close (XFASTINT (fd));
127 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
128 1, 1, 0,
129 "Return the directory component in file name NAME.\n\
130 Return nil if NAME does not include a directory.\n\
131 Otherwise return a directory spec.\n\
132 Given a Unix syntax file name, returns a string ending in slash;\n\
133 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
134 (file)
135 Lisp_Object file;
137 register unsigned char *beg;
138 register unsigned char *p;
140 CHECK_STRING (file, 0);
142 beg = XSTRING (file)->data;
143 p = beg + XSTRING (file)->size;
145 while (p != beg && p[-1] != '/'
146 #ifdef VMS
147 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
148 #endif /* VMS */
149 ) p--;
151 if (p == beg)
152 return Qnil;
153 return make_string (beg, p - beg);
156 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
157 1, 1, 0,
158 "Return file name NAME sans its directory.\n\
159 For example, in a Unix-syntax file name,\n\
160 this is everything after the last slash,\n\
161 or the entire name if it contains no slash.")
162 (file)
163 Lisp_Object file;
165 register unsigned char *beg, *p, *end;
167 CHECK_STRING (file, 0);
169 beg = XSTRING (file)->data;
170 end = p = beg + XSTRING (file)->size;
172 while (p != beg && p[-1] != '/'
173 #ifdef VMS
174 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
175 #endif /* VMS */
176 ) p--;
178 return make_string (p, end - p);
181 char *
182 file_name_as_directory (out, in)
183 char *out, *in;
185 int size = strlen (in) - 1;
187 strcpy (out, in);
189 #ifdef VMS
190 /* Is it already a directory string? */
191 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
192 return out;
193 /* Is it a VMS directory file name? If so, hack VMS syntax. */
194 else if (! index (in, '/')
195 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
196 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
197 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
198 || ! strncmp (&in[size - 5], ".dir", 4))
199 && (in[size - 1] == '.' || in[size - 1] == ';')
200 && in[size] == '1')))
202 register char *p, *dot;
203 char brack;
205 /* x.dir -> [.x]
206 dir:x.dir --> dir:[x]
207 dir:[x]y.dir --> dir:[x.y] */
208 p = in + size;
209 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
210 if (p != in)
212 strncpy (out, in, p - in);
213 out[p - in] = '\0';
214 if (*p == ':')
216 brack = ']';
217 strcat (out, ":[");
219 else
221 brack = *p;
222 strcat (out, ".");
224 p++;
226 else
228 brack = ']';
229 strcpy (out, "[.");
231 dot = index (p, '.');
232 if (dot)
234 /* blindly remove any extension */
235 size = strlen (out) + (dot - p);
236 strncat (out, p, dot - p);
238 else
240 strcat (out, p);
241 size = strlen (out);
243 out[size++] = brack;
244 out[size] = '\0';
246 #else /* not VMS */
247 /* For Unix syntax, Append a slash if necessary */
248 if (out[size] != '/')
249 strcat (out, "/");
250 #endif /* not VMS */
251 return out;
254 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
255 Sfile_name_as_directory, 1, 1, 0,
256 "Return a string representing file FILENAME interpreted as a directory.\n\
257 This operation exists because a directory is also a file, but its name as\n\
258 a directory is different from its name as a file.\n\
259 The result can be used as the value of `default-directory'\n\
260 or passed as second argument to `expand-file-name'.\n\
261 For a Unix-syntax file name, just appends a slash.\n\
262 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
263 (file)
264 Lisp_Object file;
266 char *buf;
268 CHECK_STRING (file, 0);
269 if (NILP (file))
270 return Qnil;
271 buf = (char *) alloca (XSTRING (file)->size + 10);
272 return build_string (file_name_as_directory (buf, XSTRING (file)->data));
276 * Convert from directory name to filename.
277 * On VMS:
278 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
279 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
280 * On UNIX, it's simple: just make sure there is a terminating /
282 * Value is nonzero if the string output is different from the input.
285 directory_file_name (src, dst)
286 char *src, *dst;
288 long slen;
289 #ifdef VMS
290 long rlen;
291 char * ptr, * rptr;
292 char bracket;
293 struct FAB fab = cc$rms_fab;
294 struct NAM nam = cc$rms_nam;
295 char esa[NAM$C_MAXRSS];
296 #endif /* VMS */
298 slen = strlen (src);
299 #ifdef VMS
300 if (! index (src, '/')
301 && (src[slen - 1] == ']'
302 || src[slen - 1] == ':'
303 || src[slen - 1] == '>'))
305 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
306 fab.fab$l_fna = src;
307 fab.fab$b_fns = slen;
308 fab.fab$l_nam = &nam;
309 fab.fab$l_fop = FAB$M_NAM;
311 nam.nam$l_esa = esa;
312 nam.nam$b_ess = sizeof esa;
313 nam.nam$b_nop |= NAM$M_SYNCHK;
315 /* We call SYS$PARSE to handle such things as [--] for us. */
316 if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
318 slen = nam.nam$b_esl;
319 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
320 slen -= 2;
321 esa[slen] = '\0';
322 src = esa;
324 if (src[slen - 1] != ']' && src[slen - 1] != '>')
326 /* what about when we have logical_name:???? */
327 if (src[slen - 1] == ':')
328 { /* Xlate logical name and see what we get */
329 ptr = strcpy (dst, src); /* upper case for getenv */
330 while (*ptr)
332 if ('a' <= *ptr && *ptr <= 'z')
333 *ptr -= 040;
334 ptr++;
336 dst[slen - 1] = 0; /* remove colon */
337 if (!(src = egetenv (dst)))
338 return 0;
339 /* should we jump to the beginning of this procedure?
340 Good points: allows us to use logical names that xlate
341 to Unix names,
342 Bad points: can be a problem if we just translated to a device
343 name...
344 For now, I'll punt and always expect VMS names, and hope for
345 the best! */
346 slen = strlen (src);
347 if (src[slen - 1] != ']' && src[slen - 1] != '>')
348 { /* no recursion here! */
349 strcpy (dst, src);
350 return 0;
353 else
354 { /* not a directory spec */
355 strcpy (dst, src);
356 return 0;
359 bracket = src[slen - 1];
361 /* If bracket is ']' or '>', bracket - 2 is the corresponding
362 opening bracket. */
363 ptr = index (src, bracket - 2);
364 if (ptr == 0)
365 { /* no opening bracket */
366 strcpy (dst, src);
367 return 0;
369 if (!(rptr = rindex (src, '.')))
370 rptr = ptr;
371 slen = rptr - src;
372 strncpy (dst, src, slen);
373 dst[slen] = '\0';
374 if (*rptr == '.')
376 dst[slen++] = bracket;
377 dst[slen] = '\0';
379 else
381 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
382 then translate the device and recurse. */
383 if (dst[slen - 1] == ':'
384 && dst[slen - 2] != ':' /* skip decnet nodes */
385 && strcmp(src + slen, "[000000]") == 0)
387 dst[slen - 1] = '\0';
388 if ((ptr = egetenv (dst))
389 && (rlen = strlen (ptr) - 1) > 0
390 && (ptr[rlen] == ']' || ptr[rlen] == '>')
391 && ptr[rlen - 1] == '.')
393 ptr[rlen - 1] = ']';
394 ptr[rlen] = '\0';
395 return directory_file_name (ptr, dst);
397 else
398 dst[slen - 1] = ':';
400 strcat (dst, "[000000]");
401 slen += 8;
403 rptr++;
404 rlen = strlen (rptr) - 1;
405 strncat (dst, rptr, rlen);
406 dst[slen + rlen] = '\0';
407 strcat (dst, ".DIR.1");
408 return 1;
410 #endif /* VMS */
411 /* Process as Unix format: just remove any final slash.
412 But leave "/" unchanged; do not change it to "". */
413 strcpy (dst, src);
414 if (slen > 1 && dst[slen - 1] == '/')
415 dst[slen - 1] = 0;
416 return 1;
419 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
420 1, 1, 0,
421 "Returns the file name of the directory named DIR.\n\
422 This is the name of the file that holds the data for the directory DIR.\n\
423 This operation exists because a directory is also a file, but its name as\n\
424 a directory is different from its name as a file.\n\
425 In Unix-syntax, this function just removes the final slash.\n\
426 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
427 it returns a file name such as \"[X]Y.DIR.1\".")
428 (directory)
429 Lisp_Object directory;
431 char *buf;
433 CHECK_STRING (directory, 0);
435 if (NILP (directory))
436 return Qnil;
437 #ifdef VMS
438 /* 20 extra chars is insufficient for VMS, since we might perform a
439 logical name translation. an equivalence string can be up to 255
440 chars long, so grab that much extra space... - sss */
441 buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
442 #else
443 buf = (char *) alloca (XSTRING (directory)->size + 20);
444 #endif
445 directory_file_name (XSTRING (directory)->data, buf);
446 return build_string (buf);
449 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
450 "Generate temporary file name (string) starting with PREFIX (a string).\n\
451 The Emacs process number forms part of the result,\n\
452 so there is no danger of generating a name being used by another process.")
453 (prefix)
454 Lisp_Object prefix;
456 Lisp_Object val;
457 val = concat2 (prefix, build_string ("XXXXXX"));
458 mktemp (XSTRING (val)->data);
459 return val;
462 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
463 "Convert FILENAME to absolute, and canonicalize it.\n\
464 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
465 (does not start with slash); if DEFAULT is nil or missing,\n\
466 the current buffer's value of default-directory is used.\n\
467 Path components that are `.' are removed, and \n\
468 path components followed by `..' are removed, along with the `..' itself;\n\
469 note that these simplifications are done without checking the resulting\n\
470 paths in the file system.\n\
471 An initial `~/' expands to your home directory.\n\
472 An initial `~USER/' expands to USER's home directory.\n\
473 See also the function `substitute-in-file-name'.")
474 (name, defalt)
475 Lisp_Object name, defalt;
477 unsigned char *nm;
479 register unsigned char *newdir, *p, *o;
480 int tlen;
481 unsigned char *target;
482 struct passwd *pw;
483 int lose;
484 #ifdef VMS
485 unsigned char * colon = 0;
486 unsigned char * close = 0;
487 unsigned char * slash = 0;
488 unsigned char * brack = 0;
489 int lbrack = 0, rbrack = 0;
490 int dots = 0;
491 #endif /* VMS */
493 CHECK_STRING (name, 0);
495 #ifdef VMS
496 /* Filenames on VMS are always upper case. */
497 name = Fupcase (name);
498 #endif
500 nm = XSTRING (name)->data;
502 /* If nm is absolute, flush ...// and detect /./ and /../.
503 If no /./ or /../ we can return right away. */
504 if (
505 nm[0] == '/'
506 #ifdef VMS
507 || index (nm, ':')
508 #endif /* VMS */
511 p = nm;
512 lose = 0;
513 while (*p)
515 if (p[0] == '/' && p[1] == '/'
516 #ifdef APOLLO
517 /* // at start of filename is meaningful on Apollo system */
518 && nm != p
519 #endif /* APOLLO */
521 nm = p + 1;
522 if (p[0] == '/' && p[1] == '~')
523 nm = p + 1, lose = 1;
524 if (p[0] == '/' && p[1] == '.'
525 && (p[2] == '/' || p[2] == 0
526 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
527 lose = 1;
528 #ifdef VMS
529 if (p[0] == '\\')
530 lose = 1;
531 if (p[0] == '/') {
532 /* if dev:[dir]/, move nm to / */
533 if (!slash && p > nm && (brack || colon)) {
534 nm = (brack ? brack + 1 : colon + 1);
535 lbrack = rbrack = 0;
536 brack = 0;
537 colon = 0;
539 slash = p;
541 if (p[0] == '-')
542 #ifndef VMS4_4
543 /* VMS pre V4.4,convert '-'s in filenames. */
544 if (lbrack == rbrack)
546 if (dots < 2) /* this is to allow negative version numbers */
547 p[0] = '_';
549 else
550 #endif /* VMS4_4 */
551 if (lbrack > rbrack &&
552 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
553 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
554 lose = 1;
555 #ifndef VMS4_4
556 else
557 p[0] = '_';
558 #endif /* VMS4_4 */
559 /* count open brackets, reset close bracket pointer */
560 if (p[0] == '[' || p[0] == '<')
561 lbrack++, brack = 0;
562 /* count close brackets, set close bracket pointer */
563 if (p[0] == ']' || p[0] == '>')
564 rbrack++, brack = p;
565 /* detect ][ or >< */
566 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
567 lose = 1;
568 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
569 nm = p + 1, lose = 1;
570 if (p[0] == ':' && (colon || slash))
571 /* if dev1:[dir]dev2:, move nm to dev2: */
572 if (brack)
574 nm = brack + 1;
575 brack = 0;
577 /* if /pathname/dev:, move nm to dev: */
578 else if (slash)
579 nm = slash + 1;
580 /* if node::dev:, move colon following dev */
581 else if (colon && colon[-1] == ':')
582 colon = p;
583 /* if dev1:dev2:, move nm to dev2: */
584 else if (colon && colon[-1] != ':')
586 nm = colon + 1;
587 colon = 0;
589 if (p[0] == ':' && !colon)
591 if (p[1] == ':')
592 p++;
593 colon = p;
595 if (lbrack == rbrack)
596 if (p[0] == ';')
597 dots = 2;
598 else if (p[0] == '.')
599 dots++;
600 #endif /* VMS */
601 p++;
603 if (!lose)
605 #ifdef VMS
606 if (index (nm, '/'))
607 return build_string (sys_translate_unix (nm));
608 #endif /* VMS */
609 if (nm == XSTRING (name)->data)
610 return name;
611 return build_string (nm);
615 /* Now determine directory to start with and put it in newdir */
617 newdir = 0;
619 if (nm[0] == '~') /* prefix ~ */
620 if (nm[1] == '/'
621 #ifdef VMS
622 || nm[1] == ':'
623 #endif /* VMS */
624 || nm[1] == 0)/* ~ by itself */
626 if (!(newdir = (unsigned char *) egetenv ("HOME")))
627 newdir = (unsigned char *) "";
628 nm++;
629 #ifdef VMS
630 nm++; /* Don't leave the slash in nm. */
631 #endif /* VMS */
633 else /* ~user/filename */
635 for (p = nm; *p && (*p != '/'
636 #ifdef VMS
637 && *p != ':'
638 #endif /* VMS */
639 ); p++);
640 o = (unsigned char *) alloca (p - nm + 1);
641 bcopy ((char *) nm, o, p - nm);
642 o [p - nm] = 0;
644 pw = (struct passwd *) getpwnam (o + 1);
645 if (pw)
647 newdir = (unsigned char *) pw -> pw_dir;
648 #ifdef VMS
649 nm = p + 1; /* skip the terminator */
650 #else
651 nm = p;
652 #endif /* VMS */
655 /* If we don't find a user of that name, leave the name
656 unchanged; don't move nm forward to p. */
659 if (nm[0] != '/'
660 #ifdef VMS
661 && !index (nm, ':')
662 #endif /* not VMS */
663 && !newdir)
665 if (NILP (defalt))
666 defalt = current_buffer->directory;
667 CHECK_STRING (defalt, 1);
668 newdir = XSTRING (defalt)->data;
671 if (newdir != 0)
673 /* Get rid of any slash at the end of newdir. */
674 int length = strlen (newdir);
675 if (newdir[length - 1] == '/')
677 unsigned char *temp = (unsigned char *) alloca (length);
678 bcopy (newdir, temp, length - 1);
679 temp[length - 1] = 0;
680 newdir = temp;
682 tlen = length + 1;
684 else
685 tlen = 0;
687 /* Now concatenate the directory and name to new space in the stack frame */
688 tlen += strlen (nm) + 1;
689 target = (unsigned char *) alloca (tlen);
690 *target = 0;
692 if (newdir)
694 #ifndef VMS
695 if (nm[0] == 0 || nm[0] == '/')
696 strcpy (target, newdir);
697 else
698 #endif
699 file_name_as_directory (target, newdir);
702 strcat (target, nm);
703 #ifdef VMS
704 if (index (target, '/'))
705 strcpy (target, sys_translate_unix (target));
706 #endif /* VMS */
708 /* Now canonicalize by removing /. and /foo/.. if they appear */
710 p = target;
711 o = target;
713 while (*p)
715 #ifdef VMS
716 if (*p != ']' && *p != '>' && *p != '-')
718 if (*p == '\\')
719 p++;
720 *o++ = *p++;
722 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
723 /* brackets are offset from each other by 2 */
725 p += 2;
726 if (*p != '.' && *p != '-' && o[-1] != '.')
727 /* convert [foo][bar] to [bar] */
728 while (o[-1] != '[' && o[-1] != '<')
729 o--;
730 else if (*p == '-' && *o != '.')
731 *--p = '.';
733 else if (p[0] == '-' && o[-1] == '.' &&
734 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
735 /* flush .foo.- ; leave - if stopped by '[' or '<' */
738 o--;
739 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
740 if (p[1] == '.') /* foo.-.bar ==> bar*/
741 p += 2;
742 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
743 p++, o--;
744 /* else [foo.-] ==> [-] */
746 else
748 #ifndef VMS4_4
749 if (*p == '-' &&
750 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
751 p[1] != ']' && p[1] != '>' && p[1] != '.')
752 *p = '_';
753 #endif /* VMS4_4 */
754 *o++ = *p++;
756 #else /* not VMS */
757 if (*p != '/')
759 *o++ = *p++;
761 else if (!strncmp (p, "//", 2)
762 #ifdef APOLLO
763 /* // at start of filename is meaningful in Apollo system */
764 && o != target
765 #endif /* APOLLO */
768 o = target;
769 p++;
771 else if (p[0] == '/' && p[1] == '.' &&
772 (p[2] == '/' || p[2] == 0))
773 p += 2;
774 else if (!strncmp (p, "/..", 3)
775 /* `/../' is the "superroot" on certain file systems. */
776 && o != target
777 && (p[3] == '/' || p[3] == 0))
779 while (o != target && *--o != '/')
781 #ifdef APOLLO
782 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
783 ++o;
784 else
785 #endif /* APOLLO */
786 if (o == target && *o == '/')
787 ++o;
788 p += 3;
790 else
792 *o++ = *p++;
794 #endif /* not VMS */
797 return make_string (target, o - target);
799 #if 0
800 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'.
801 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
802 "Convert FILENAME to absolute, and canonicalize it.\n\
803 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
804 (does not start with slash); if DEFAULT is nil or missing,\n\
805 the current buffer's value of default-directory is used.\n\
806 Filenames containing `.' or `..' as components are simplified;\n\
807 initial `~/' expands to your home directory.\n\
808 See also the function `substitute-in-file-name'.")
809 (name, defalt)
810 Lisp_Object name, defalt;
812 unsigned char *nm;
814 register unsigned char *newdir, *p, *o;
815 int tlen;
816 unsigned char *target;
817 struct passwd *pw;
818 int lose;
819 #ifdef VMS
820 unsigned char * colon = 0;
821 unsigned char * close = 0;
822 unsigned char * slash = 0;
823 unsigned char * brack = 0;
824 int lbrack = 0, rbrack = 0;
825 int dots = 0;
826 #endif /* VMS */
828 CHECK_STRING (name, 0);
830 #ifdef VMS
831 /* Filenames on VMS are always upper case. */
832 name = Fupcase (name);
833 #endif
835 nm = XSTRING (name)->data;
837 /* If nm is absolute, flush ...// and detect /./ and /../.
838 If no /./ or /../ we can return right away. */
839 if (
840 nm[0] == '/'
841 #ifdef VMS
842 || index (nm, ':')
843 #endif /* VMS */
846 p = nm;
847 lose = 0;
848 while (*p)
850 if (p[0] == '/' && p[1] == '/'
851 #ifdef APOLLO
852 /* // at start of filename is meaningful on Apollo system */
853 && nm != p
854 #endif /* APOLLO */
856 nm = p + 1;
857 if (p[0] == '/' && p[1] == '~')
858 nm = p + 1, lose = 1;
859 if (p[0] == '/' && p[1] == '.'
860 && (p[2] == '/' || p[2] == 0
861 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
862 lose = 1;
863 #ifdef VMS
864 if (p[0] == '\\')
865 lose = 1;
866 if (p[0] == '/') {
867 /* if dev:[dir]/, move nm to / */
868 if (!slash && p > nm && (brack || colon)) {
869 nm = (brack ? brack + 1 : colon + 1);
870 lbrack = rbrack = 0;
871 brack = 0;
872 colon = 0;
874 slash = p;
876 if (p[0] == '-')
877 #ifndef VMS4_4
878 /* VMS pre V4.4,convert '-'s in filenames. */
879 if (lbrack == rbrack)
881 if (dots < 2) /* this is to allow negative version numbers */
882 p[0] = '_';
884 else
885 #endif /* VMS4_4 */
886 if (lbrack > rbrack &&
887 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
888 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
889 lose = 1;
890 #ifndef VMS4_4
891 else
892 p[0] = '_';
893 #endif /* VMS4_4 */
894 /* count open brackets, reset close bracket pointer */
895 if (p[0] == '[' || p[0] == '<')
896 lbrack++, brack = 0;
897 /* count close brackets, set close bracket pointer */
898 if (p[0] == ']' || p[0] == '>')
899 rbrack++, brack = p;
900 /* detect ][ or >< */
901 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
902 lose = 1;
903 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
904 nm = p + 1, lose = 1;
905 if (p[0] == ':' && (colon || slash))
906 /* if dev1:[dir]dev2:, move nm to dev2: */
907 if (brack)
909 nm = brack + 1;
910 brack = 0;
912 /* if /pathname/dev:, move nm to dev: */
913 else if (slash)
914 nm = slash + 1;
915 /* if node::dev:, move colon following dev */
916 else if (colon && colon[-1] == ':')
917 colon = p;
918 /* if dev1:dev2:, move nm to dev2: */
919 else if (colon && colon[-1] != ':')
921 nm = colon + 1;
922 colon = 0;
924 if (p[0] == ':' && !colon)
926 if (p[1] == ':')
927 p++;
928 colon = p;
930 if (lbrack == rbrack)
931 if (p[0] == ';')
932 dots = 2;
933 else if (p[0] == '.')
934 dots++;
935 #endif /* VMS */
936 p++;
938 if (!lose)
940 #ifdef VMS
941 if (index (nm, '/'))
942 return build_string (sys_translate_unix (nm));
943 #endif /* VMS */
944 if (nm == XSTRING (name)->data)
945 return name;
946 return build_string (nm);
950 /* Now determine directory to start with and put it in NEWDIR */
952 newdir = 0;
954 if (nm[0] == '~') /* prefix ~ */
955 if (nm[1] == '/'
956 #ifdef VMS
957 || nm[1] == ':'
958 #endif /* VMS */
959 || nm[1] == 0)/* ~/filename */
961 if (!(newdir = (unsigned char *) egetenv ("HOME")))
962 newdir = (unsigned char *) "";
963 nm++;
964 #ifdef VMS
965 nm++; /* Don't leave the slash in nm. */
966 #endif /* VMS */
968 else /* ~user/filename */
970 /* Get past ~ to user */
971 unsigned char *user = nm + 1;
972 /* Find end of name. */
973 unsigned char *ptr = (unsigned char *) index (user, '/');
974 int len = ptr ? ptr - user : strlen (user);
975 #ifdef VMS
976 unsigned char *ptr1 = index (user, ':');
977 if (ptr1 != 0 && ptr1 - user < len)
978 len = ptr1 - user;
979 #endif /* VMS */
980 /* Copy the user name into temp storage. */
981 o = (unsigned char *) alloca (len + 1);
982 bcopy ((char *) user, o, len);
983 o[len] = 0;
985 /* Look up the user name. */
986 pw = (struct passwd *) getpwnam (o + 1);
987 if (!pw)
988 error ("\"%s\" isn't a registered user", o + 1);
990 newdir = (unsigned char *) pw->pw_dir;
992 /* Discard the user name from NM. */
993 nm += len;
996 if (nm[0] != '/'
997 #ifdef VMS
998 && !index (nm, ':')
999 #endif /* not VMS */
1000 && !newdir)
1002 if (NILP (defalt))
1003 defalt = current_buffer->directory;
1004 CHECK_STRING (defalt, 1);
1005 newdir = XSTRING (defalt)->data;
1008 /* Now concatenate the directory and name to new space in the stack frame */
1010 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1011 target = (unsigned char *) alloca (tlen);
1012 *target = 0;
1014 if (newdir)
1016 #ifndef VMS
1017 if (nm[0] == 0 || nm[0] == '/')
1018 strcpy (target, newdir);
1019 else
1020 #endif
1021 file_name_as_directory (target, newdir);
1024 strcat (target, nm);
1025 #ifdef VMS
1026 if (index (target, '/'))
1027 strcpy (target, sys_translate_unix (target));
1028 #endif /* VMS */
1030 /* Now canonicalize by removing /. and /foo/.. if they appear */
1032 p = target;
1033 o = target;
1035 while (*p)
1037 #ifdef VMS
1038 if (*p != ']' && *p != '>' && *p != '-')
1040 if (*p == '\\')
1041 p++;
1042 *o++ = *p++;
1044 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1045 /* brackets are offset from each other by 2 */
1047 p += 2;
1048 if (*p != '.' && *p != '-' && o[-1] != '.')
1049 /* convert [foo][bar] to [bar] */
1050 while (o[-1] != '[' && o[-1] != '<')
1051 o--;
1052 else if (*p == '-' && *o != '.')
1053 *--p = '.';
1055 else if (p[0] == '-' && o[-1] == '.' &&
1056 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1057 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1060 o--;
1061 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1062 if (p[1] == '.') /* foo.-.bar ==> bar*/
1063 p += 2;
1064 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1065 p++, o--;
1066 /* else [foo.-] ==> [-] */
1068 else
1070 #ifndef VMS4_4
1071 if (*p == '-' &&
1072 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1073 p[1] != ']' && p[1] != '>' && p[1] != '.')
1074 *p = '_';
1075 #endif /* VMS4_4 */
1076 *o++ = *p++;
1078 #else /* not VMS */
1079 if (*p != '/')
1081 *o++ = *p++;
1083 else if (!strncmp (p, "//", 2)
1084 #ifdef APOLLO
1085 /* // at start of filename is meaningful in Apollo system */
1086 && o != target
1087 #endif /* APOLLO */
1090 o = target;
1091 p++;
1093 else if (p[0] == '/' && p[1] == '.' &&
1094 (p[2] == '/' || p[2] == 0))
1095 p += 2;
1096 else if (!strncmp (p, "/..", 3)
1097 /* `/../' is the "superroot" on certain file systems. */
1098 && o != target
1099 && (p[3] == '/' || p[3] == 0))
1101 while (o != target && *--o != '/')
1103 #ifdef APOLLO
1104 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1105 ++o;
1106 else
1107 #endif /* APOLLO */
1108 if (o == target && *o == '/')
1109 ++o;
1110 p += 3;
1112 else
1114 *o++ = *p++;
1116 #endif /* not VMS */
1119 return make_string (target, o - target);
1121 #endif
1123 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
1124 Ssubstitute_in_file_name, 1, 1, 0,
1125 "Substitute environment variables referred to in FILENAME.\n\
1126 `$FOO' where FOO is an environment variable name means to substitute\n\
1127 the value of that variable. The variable name should be terminated\n\
1128 with a character not a letter, digit or underscore; otherwise, enclose\n\
1129 the entire variable name in braces.\n\
1130 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1131 On VMS, `$' substitution is not done; this function does little and only\n\
1132 duplicates what `expand-file-name' does.")
1133 (string)
1134 Lisp_Object string;
1136 unsigned char *nm;
1138 register unsigned char *s, *p, *o, *x, *endp;
1139 unsigned char *target;
1140 int total = 0;
1141 int substituted = 0;
1142 unsigned char *xnm;
1144 CHECK_STRING (string, 0);
1146 nm = XSTRING (string)->data;
1147 endp = nm + XSTRING (string)->size;
1149 /* If /~ or // appears, discard everything through first slash. */
1151 for (p = nm; p != endp; p++)
1153 if ((p[0] == '~' ||
1154 #ifdef APOLLO
1155 /* // at start of file name is meaningful in Apollo system */
1156 (p[0] == '/' && p - 1 != nm)
1157 #else /* not APOLLO */
1158 p[0] == '/'
1159 #endif /* not APOLLO */
1161 && p != nm &&
1162 #ifdef VMS
1163 (p[-1] == ':' || p[-1] == ']' || p[-1] == '>' ||
1164 #endif /* VMS */
1165 p[-1] == '/')
1166 #ifdef VMS
1168 #endif /* VMS */
1170 nm = p;
1171 substituted = 1;
1175 #ifdef VMS
1176 return build_string (nm);
1177 #else
1179 /* See if any variables are substituted into the string
1180 and find the total length of their values in `total' */
1182 for (p = nm; p != endp;)
1183 if (*p != '$')
1184 p++;
1185 else
1187 p++;
1188 if (p == endp)
1189 goto badsubst;
1190 else if (*p == '$')
1192 /* "$$" means a single "$" */
1193 p++;
1194 total -= 1;
1195 substituted = 1;
1196 continue;
1198 else if (*p == '{')
1200 o = ++p;
1201 while (p != endp && *p != '}') p++;
1202 if (*p != '}') goto missingclose;
1203 s = p;
1205 else
1207 o = p;
1208 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1209 s = p;
1212 /* Copy out the variable name */
1213 target = (unsigned char *) alloca (s - o + 1);
1214 strncpy (target, o, s - o);
1215 target[s - o] = 0;
1217 /* Get variable value */
1218 o = (unsigned char *) egetenv (target);
1219 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1220 #if 0
1221 #ifdef USG
1222 if (!o && !strcmp (target, "USER"))
1223 o = egetenv ("LOGNAME");
1224 #endif /* USG */
1225 #endif /* 0 */
1226 if (!o) goto badvar;
1227 total += strlen (o);
1228 substituted = 1;
1231 if (!substituted)
1232 return string;
1234 /* If substitution required, recopy the string and do it */
1235 /* Make space in stack frame for the new copy */
1236 xnm = (unsigned char *) alloca (XSTRING (string)->size + total + 1);
1237 x = xnm;
1239 /* Copy the rest of the name through, replacing $ constructs with values */
1240 for (p = nm; *p;)
1241 if (*p != '$')
1242 *x++ = *p++;
1243 else
1245 p++;
1246 if (p == endp)
1247 goto badsubst;
1248 else if (*p == '$')
1250 *x++ = *p++;
1251 continue;
1253 else if (*p == '{')
1255 o = ++p;
1256 while (p != endp && *p != '}') p++;
1257 if (*p != '}') goto missingclose;
1258 s = p++;
1260 else
1262 o = p;
1263 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1264 s = p;
1267 /* Copy out the variable name */
1268 target = (unsigned char *) alloca (s - o + 1);
1269 strncpy (target, o, s - o);
1270 target[s - o] = 0;
1272 /* Get variable value */
1273 o = (unsigned char *) egetenv (target);
1274 /* The presence of this code makes vax 5.0 crash, for reasons yet unknown */
1275 #if 0
1276 #ifdef USG
1277 if (!o && !strcmp (target, "USER"))
1278 o = egetenv ("LOGNAME");
1279 #endif /* USG */
1280 #endif /* 0 */
1281 if (!o)
1282 goto badvar;
1284 strcpy (x, o);
1285 x += strlen (o);
1288 *x = 0;
1290 /* If /~ or // appears, discard everything through first slash. */
1292 for (p = xnm; p != x; p++)
1293 if ((p[0] == '~' ||
1294 #ifdef APOLLO
1295 /* // at start of file name is meaningful in Apollo system */
1296 (p[0] == '/' && p - 1 != xnm)
1297 #else /* not APOLLO */
1298 p[0] == '/'
1299 #endif /* not APOLLO */
1301 && p != nm && p[-1] == '/')
1302 xnm = p;
1304 return make_string (xnm, x - xnm);
1306 badsubst:
1307 error ("Bad format environment-variable substitution");
1308 missingclose:
1309 error ("Missing \"}\" in environment-variable substitution");
1310 badvar:
1311 error ("Substituting nonexistent environment variable \"%s\"", target);
1313 /* NOTREACHED */
1314 #endif /* not VMS */
1317 Lisp_Object
1318 expand_and_dir_to_file (filename, defdir)
1319 Lisp_Object filename, defdir;
1321 register Lisp_Object abspath;
1323 abspath = Fexpand_file_name (filename, defdir);
1324 #ifdef VMS
1326 register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1];
1327 if (c == ':' || c == ']' || c == '>')
1328 abspath = Fdirectory_file_name (abspath);
1330 #else
1331 /* Remove final slash, if any (unless path is root).
1332 stat behaves differently depending! */
1333 if (XSTRING (abspath)->size > 1
1334 && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/')
1336 if (EQ (abspath, filename))
1337 abspath = Fcopy_sequence (abspath);
1338 XSTRING (abspath)->data[XSTRING (abspath)->size - 1] = 0;
1340 #endif
1341 return abspath;
1344 barf_or_query_if_file_exists (absname, querystring, interactive)
1345 Lisp_Object absname;
1346 unsigned char *querystring;
1347 int interactive;
1349 register Lisp_Object tem;
1350 struct gcpro gcpro1;
1352 if (access (XSTRING (absname)->data, 4) >= 0)
1354 if (! interactive)
1355 Fsignal (Qfile_already_exists,
1356 Fcons (build_string ("File already exists"),
1357 Fcons (absname, Qnil)));
1358 GCPRO1 (absname);
1359 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
1360 XSTRING (absname)->data, querystring));
1361 UNGCPRO;
1362 if (NILP (tem))
1363 Fsignal (Qfile_already_exists,
1364 Fcons (build_string ("File already exists"),
1365 Fcons (absname, Qnil)));
1367 return;
1370 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
1371 "fCopy file: \nFCopy %s to file: \np\nP",
1372 "Copy FILE to NEWNAME. Both args must be strings.\n\
1373 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
1374 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
1375 A number as third arg means request confirmation if NEWNAME already exists.\n\
1376 This is what happens in interactive use with M-x.\n\
1377 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
1378 last-modified time as the old one. (This works on only some systems.)\n\
1379 A prefix arg makes KEEP-TIME non-nil.")
1380 (filename, newname, ok_if_already_exists, keep_date)
1381 Lisp_Object filename, newname, ok_if_already_exists, keep_date;
1383 int ifd, ofd, n;
1384 char buf[16 * 1024];
1385 struct stat st;
1386 struct gcpro gcpro1, gcpro2;
1387 int count = specpdl_ptr - specpdl;
1389 GCPRO2 (filename, newname);
1390 CHECK_STRING (filename, 0);
1391 CHECK_STRING (newname, 1);
1392 filename = Fexpand_file_name (filename, Qnil);
1393 newname = Fexpand_file_name (newname, Qnil);
1394 if (NILP (ok_if_already_exists)
1395 || XTYPE (ok_if_already_exists) == Lisp_Int)
1396 barf_or_query_if_file_exists (newname, "copy to it",
1397 XTYPE (ok_if_already_exists) == Lisp_Int);
1399 ifd = open (XSTRING (filename)->data, 0);
1400 if (ifd < 0)
1401 report_file_error ("Opening input file", Fcons (filename, Qnil));
1403 record_unwind_protect (close_file_unwind, make_number (ifd));
1405 #ifdef VMS
1406 /* Create the copy file with the same record format as the input file */
1407 ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
1408 #else
1409 ofd = creat (XSTRING (newname)->data, 0666);
1410 #endif /* VMS */
1411 if (ofd < 0)
1412 report_file_error ("Opening output file", Fcons (newname, Qnil));
1414 record_unwind_protect (close_file_unwind, make_number (ofd));
1416 immediate_quit = 1;
1417 QUIT;
1418 while ((n = read (ifd, buf, sizeof buf)) > 0)
1419 if (write (ofd, buf, n) != n)
1420 report_file_error ("I/O error", Fcons (newname, Qnil));
1421 immediate_quit = 0;
1423 if (fstat (ifd, &st) >= 0)
1425 if (!NILP (keep_date))
1427 EMACS_TIME atime, mtime;
1428 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
1429 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
1430 EMACS_SET_UTIMES (XSTRING (newname)->data, atime, mtime);
1432 #ifdef APOLLO
1433 if (!egetenv ("USE_DOMAIN_ACLS"))
1434 #endif
1435 chmod (XSTRING (newname)->data, st.st_mode & 07777);
1438 /* Discard the unwind protects. */
1439 specpdl_ptr = specpdl + count;
1441 close (ifd);
1442 if (close (ofd) < 0)
1443 report_file_error ("I/O error", Fcons (newname, Qnil));
1445 UNGCPRO;
1446 return Qnil;
1449 DEFUN ("make-directory", Fmake_directory, Smake_directory, 1, 1, "FMake directory: ",
1450 "Create a directory. One argument, a file name string.")
1451 (dirname)
1452 Lisp_Object dirname;
1454 unsigned char *dir;
1456 CHECK_STRING (dirname, 0);
1457 dirname = Fexpand_file_name (dirname, Qnil);
1458 dir = XSTRING (dirname)->data;
1460 if (mkdir (dir, 0777) != 0)
1461 report_file_error ("Creating directory", Flist (1, &dirname));
1463 return Qnil;
1466 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
1467 "Delete a directory. One argument, a file name string.")
1468 (dirname)
1469 Lisp_Object dirname;
1471 unsigned char *dir;
1473 CHECK_STRING (dirname, 0);
1474 dirname = Fexpand_file_name (dirname, Qnil);
1475 dir = XSTRING (dirname)->data;
1477 if (rmdir (dir) != 0)
1478 report_file_error ("Removing directory", Flist (1, &dirname));
1480 return Qnil;
1483 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
1484 "Delete specified file. One argument, a file name string.\n\
1485 If file has multiple names, it continues to exist with the other names.")
1486 (filename)
1487 Lisp_Object filename;
1489 CHECK_STRING (filename, 0);
1490 filename = Fexpand_file_name (filename, Qnil);
1491 if (0 > unlink (XSTRING (filename)->data))
1492 report_file_error ("Removing old name", Flist (1, &filename));
1493 return Qnil;
1496 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
1497 "fRename file: \nFRename %s to file: \np",
1498 "Rename FILE as NEWNAME. Both args strings.\n\
1499 If file has names other than FILE, it continues to have those names.\n\
1500 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1501 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1502 A number as third arg means request confirmation if NEWNAME already exists.\n\
1503 This is what happens in interactive use with M-x.")
1504 (filename, newname, ok_if_already_exists)
1505 Lisp_Object filename, newname, ok_if_already_exists;
1507 #ifdef NO_ARG_ARRAY
1508 Lisp_Object args[2];
1509 #endif
1510 struct gcpro gcpro1, gcpro2;
1512 GCPRO2 (filename, newname);
1513 CHECK_STRING (filename, 0);
1514 CHECK_STRING (newname, 1);
1515 filename = Fexpand_file_name (filename, Qnil);
1516 newname = Fexpand_file_name (newname, Qnil);
1517 if (NILP (ok_if_already_exists)
1518 || XTYPE (ok_if_already_exists) == Lisp_Int)
1519 barf_or_query_if_file_exists (newname, "rename to it",
1520 XTYPE (ok_if_already_exists) == Lisp_Int);
1521 #ifndef BSD4_1
1522 if (0 > rename (XSTRING (filename)->data, XSTRING (newname)->data))
1523 #else
1524 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data)
1525 || 0 > unlink (XSTRING (filename)->data))
1526 #endif
1528 if (errno == EXDEV)
1530 Fcopy_file (filename, newname, ok_if_already_exists, Qt);
1531 Fdelete_file (filename);
1533 else
1534 #ifdef NO_ARG_ARRAY
1536 args[0] = filename;
1537 args[1] = newname;
1538 report_file_error ("Renaming", Flist (2, args));
1540 #else
1541 report_file_error ("Renaming", Flist (2, &filename));
1542 #endif
1544 UNGCPRO;
1545 return Qnil;
1548 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
1549 "fAdd name to file: \nFName to add to %s: \np",
1550 "Give FILE additional name NEWNAME. Both args strings.\n\
1551 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1552 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1553 A number as third arg means request confirmation if NEWNAME already exists.\n\
1554 This is what happens in interactive use with M-x.")
1555 (filename, newname, ok_if_already_exists)
1556 Lisp_Object filename, newname, ok_if_already_exists;
1558 #ifdef NO_ARG_ARRAY
1559 Lisp_Object args[2];
1560 #endif
1561 struct gcpro gcpro1, gcpro2;
1563 GCPRO2 (filename, newname);
1564 CHECK_STRING (filename, 0);
1565 CHECK_STRING (newname, 1);
1566 filename = Fexpand_file_name (filename, Qnil);
1567 newname = Fexpand_file_name (newname, Qnil);
1568 if (NILP (ok_if_already_exists)
1569 || XTYPE (ok_if_already_exists) == Lisp_Int)
1570 barf_or_query_if_file_exists (newname, "make it a new name",
1571 XTYPE (ok_if_already_exists) == Lisp_Int);
1572 unlink (XSTRING (newname)->data);
1573 if (0 > link (XSTRING (filename)->data, XSTRING (newname)->data))
1575 #ifdef NO_ARG_ARRAY
1576 args[0] = filename;
1577 args[1] = newname;
1578 report_file_error ("Adding new name", Flist (2, args));
1579 #else
1580 report_file_error ("Adding new name", Flist (2, &filename));
1581 #endif
1584 UNGCPRO;
1585 return Qnil;
1588 #ifdef S_IFLNK
1589 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
1590 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
1591 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
1592 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
1593 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
1594 A number as third arg means request confirmation if NEWNAME already exists.\n\
1595 This happens for interactive use with M-x.")
1596 (filename, linkname, ok_if_already_exists)
1597 Lisp_Object filename, linkname, ok_if_already_exists;
1599 #ifdef NO_ARG_ARRAY
1600 Lisp_Object args[2];
1601 #endif
1602 struct gcpro gcpro1, gcpro2;
1604 GCPRO2 (filename, linkname);
1605 CHECK_STRING (filename, 0);
1606 CHECK_STRING (linkname, 1);
1607 #if 0 /* This made it impossible to make a link to a relative name. */
1608 filename = Fexpand_file_name (filename, Qnil);
1609 #endif
1610 linkname = Fexpand_file_name (linkname, Qnil);
1611 if (NILP (ok_if_already_exists)
1612 || XTYPE (ok_if_already_exists) == Lisp_Int)
1613 barf_or_query_if_file_exists (linkname, "make it a link",
1614 XTYPE (ok_if_already_exists) == Lisp_Int);
1615 if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
1617 /* If we didn't complain already, silently delete existing file. */
1618 if (errno == EEXIST)
1620 unlink (XSTRING (filename)->data);
1621 if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
1622 return Qnil;
1625 #ifdef NO_ARG_ARRAY
1626 args[0] = filename;
1627 args[1] = linkname;
1628 report_file_error ("Making symbolic link", Flist (2, args));
1629 #else
1630 report_file_error ("Making symbolic link", Flist (2, &filename));
1631 #endif
1633 UNGCPRO;
1634 return Qnil;
1636 #endif /* S_IFLNK */
1638 #ifdef VMS
1640 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
1641 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
1642 "Define the job-wide logical name NAME to have the value STRING.\n\
1643 If STRING is nil or a null string, the logical name NAME is deleted.")
1644 (varname, string)
1645 Lisp_Object varname;
1646 Lisp_Object string;
1648 CHECK_STRING (varname, 0);
1649 if (NILP (string))
1650 delete_logical_name (XSTRING (varname)->data);
1651 else
1653 CHECK_STRING (string, 1);
1655 if (XSTRING (string)->size == 0)
1656 delete_logical_name (XSTRING (varname)->data);
1657 else
1658 define_logical_name (XSTRING (varname)->data, XSTRING (string)->data);
1661 return string;
1663 #endif /* VMS */
1665 #ifdef HPUX_NET
1667 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
1668 "Open a network connection to PATH using LOGIN as the login string.")
1669 (path, login)
1670 Lisp_Object path, login;
1672 int netresult;
1674 CHECK_STRING (path, 0);
1675 CHECK_STRING (login, 0);
1677 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
1679 if (netresult == -1)
1680 return Qnil;
1681 else
1682 return Qt;
1684 #endif /* HPUX_NET */
1686 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
1687 1, 1, 0,
1688 "Return t if file FILENAME specifies an absolute path name.\n\
1689 On Unix, this is a name starting with a `/' or a `~'.")
1690 (filename)
1691 Lisp_Object filename;
1693 unsigned char *ptr;
1695 CHECK_STRING (filename, 0);
1696 ptr = XSTRING (filename)->data;
1697 if (*ptr == '/' || *ptr == '~'
1698 #ifdef VMS
1699 /* ??? This criterion is probably wrong for '<'. */
1700 || index (ptr, ':') || index (ptr, '<')
1701 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
1702 && ptr[1] != '.')
1703 #endif /* VMS */
1705 return Qt;
1706 else
1707 return Qnil;
1710 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
1711 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
1712 See also `file-readable-p' and `file-attributes'.")
1713 (filename)
1714 Lisp_Object filename;
1716 Lisp_Object abspath;
1718 CHECK_STRING (filename, 0);
1719 abspath = Fexpand_file_name (filename, Qnil);
1720 return (access (XSTRING (abspath)->data, 0) >= 0) ? Qt : Qnil;
1723 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
1724 "Return t if FILENAME can be executed by you.\n\
1725 For directories this means you can change to that directory.")
1726 (filename)
1727 Lisp_Object filename;
1730 Lisp_Object abspath;
1732 CHECK_STRING (filename, 0);
1733 abspath = Fexpand_file_name (filename, Qnil);
1734 return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
1737 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
1738 "Return t if file FILENAME exists and you can read it.\n\
1739 See also `file-exists-p' and `file-attributes'.")
1740 (filename)
1741 Lisp_Object filename;
1743 Lisp_Object abspath;
1745 CHECK_STRING (filename, 0);
1746 abspath = Fexpand_file_name (filename, Qnil);
1747 return (access (XSTRING (abspath)->data, 4) >= 0) ? Qt : Qnil;
1750 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
1751 "If file FILENAME is the name of a symbolic link\n\
1752 returns the name of the file to which it is linked.\n\
1753 Otherwise returns NIL.")
1754 (filename)
1755 Lisp_Object filename;
1757 #ifdef S_IFLNK
1758 char *buf;
1759 int bufsize;
1760 int valsize;
1761 Lisp_Object val;
1763 CHECK_STRING (filename, 0);
1764 filename = Fexpand_file_name (filename, Qnil);
1766 bufsize = 100;
1767 while (1)
1769 buf = (char *) xmalloc (bufsize);
1770 bzero (buf, bufsize);
1771 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
1772 if (valsize < bufsize) break;
1773 /* Buffer was not long enough */
1774 free (buf);
1775 bufsize *= 2;
1777 if (valsize == -1)
1779 free (buf);
1780 return Qnil;
1782 val = make_string (buf, valsize);
1783 free (buf);
1784 return val;
1785 #else /* not S_IFLNK */
1786 return Qnil;
1787 #endif /* not S_IFLNK */
1790 /* Having this before file-symlink-p mysteriously caused it to be forgotten
1791 on the RT/PC. */
1792 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
1793 "Return t if file FILENAME can be written or created by you.")
1794 (filename)
1795 Lisp_Object filename;
1797 Lisp_Object abspath, dir;
1799 CHECK_STRING (filename, 0);
1800 abspath = Fexpand_file_name (filename, Qnil);
1801 if (access (XSTRING (abspath)->data, 0) >= 0)
1802 return (access (XSTRING (abspath)->data, 2) >= 0) ? Qt : Qnil;
1803 dir = Ffile_name_directory (abspath);
1804 #ifdef VMS
1805 if (!NILP (dir))
1806 dir = Fdirectory_file_name (dir);
1807 #endif /* VMS */
1808 return (access (!NILP (dir) ? (char *) XSTRING (dir)->data : "", 2) >= 0
1809 ? Qt : Qnil);
1812 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
1813 "Return t if file FILENAME is the name of a directory as a file.\n\
1814 A directory name spec may be given instead; then the value is t\n\
1815 if the directory so specified exists and really is a directory.")
1816 (filename)
1817 Lisp_Object filename;
1819 register Lisp_Object abspath;
1820 struct stat st;
1822 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
1824 if (stat (XSTRING (abspath)->data, &st) < 0)
1825 return Qnil;
1826 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
1829 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
1830 "Return t if file FILENAME is the name of a directory as a file,\n\
1831 and files in that directory can be opened by you. In order to use a\n\
1832 directory as a buffer's current directory, this predicate must return true.\n\
1833 A directory name spec may be given instead; then the value is t\n\
1834 if the directory so specified exists and really is a readable and\n\
1835 searchable directory.")
1836 (filename)
1837 Lisp_Object filename;
1839 if (NILP (Ffile_directory_p (filename))
1840 || NILP (Ffile_executable_p (filename)))
1841 return Qnil;
1842 else
1843 return Qt;
1846 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
1847 "Return mode bits of FILE, as an integer.")
1848 (filename)
1849 Lisp_Object filename;
1851 Lisp_Object abspath;
1852 struct stat st;
1854 abspath = expand_and_dir_to_file (filename, current_buffer->directory);
1856 if (stat (XSTRING (abspath)->data, &st) < 0)
1857 return Qnil;
1858 return make_number (st.st_mode & 07777);
1861 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
1862 "Set mode bits of FILE to MODE (an integer).\n\
1863 Only the 12 low bits of MODE are used.")
1864 (filename, mode)
1865 Lisp_Object filename, mode;
1867 Lisp_Object abspath;
1869 abspath = Fexpand_file_name (filename, current_buffer->directory);
1870 CHECK_NUMBER (mode, 1);
1872 #ifndef APOLLO
1873 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
1874 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
1875 #else /* APOLLO */
1876 if (!egetenv ("USE_DOMAIN_ACLS"))
1878 struct stat st;
1879 struct timeval tvp[2];
1881 /* chmod on apollo also change the file's modtime; need to save the
1882 modtime and then restore it. */
1883 if (stat (XSTRING (abspath)->data, &st) < 0)
1885 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
1886 return (Qnil);
1889 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
1890 report_file_error ("Doing chmod", Fcons (abspath, Qnil));
1892 /* reset the old accessed and modified times. */
1893 tvp[0].tv_sec = st.st_atime + 1; /* +1 due to an Apollo roundoff bug */
1894 tvp[0].tv_usec = 0;
1895 tvp[1].tv_sec = st.st_mtime + 1; /* +1 due to an Apollo roundoff bug */
1896 tvp[1].tv_usec = 0;
1898 if (utimes (XSTRING (abspath)->data, tvp) < 0)
1899 report_file_error ("Doing utimes", Fcons (abspath, Qnil));
1901 #endif /* APOLLO */
1903 return Qnil;
1906 DEFUN ("set-umask", Fset_umask, Sset_umask, 1, 1, 0,
1907 "Select which permission bits to disable in newly created files.\n\
1908 MASK should be an integer; if a permission's bit in MASK is 1,\n\
1909 subsequently created files will not have that permission enabled.\n\
1910 Only the low 9 bits are used.\n\
1911 This setting is inherited by subprocesses.")
1912 (mask)
1913 Lisp_Object mask;
1915 CHECK_NUMBER (mask, 0);
1917 umask (XINT (mask) & 0777);
1919 return Qnil;
1922 DEFUN ("umask", Fumask, Sumask, 0, 0, 0,
1923 "Return the current umask value.\n\
1924 The umask value determines which permissions are enabled in newly\n\
1925 created files. If a permission's bit in the umask is 1, subsequently\n\
1926 created files will not have that permission enabled.")
1929 Lisp_Object mask;
1931 XSET (mask, Lisp_Int, umask (0));
1932 umask (XINT (mask));
1934 return mask;
1937 #ifdef unix
1939 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
1940 "Tell Unix to finish all pending disk updates.")
1943 sync ();
1944 return Qnil;
1947 #endif /* unix */
1949 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
1950 "Return t if file FILE1 is newer than file FILE2.\n\
1951 If FILE1 does not exist, the answer is nil;\n\
1952 otherwise, if FILE2 does not exist, the answer is t.")
1953 (file1, file2)
1954 Lisp_Object file1, file2;
1956 Lisp_Object abspath;
1957 struct stat st;
1958 int mtime1;
1960 CHECK_STRING (file1, 0);
1961 CHECK_STRING (file2, 0);
1963 abspath = expand_and_dir_to_file (file1, current_buffer->directory);
1965 if (stat (XSTRING (abspath)->data, &st) < 0)
1966 return Qnil;
1968 mtime1 = st.st_mtime;
1970 abspath = expand_and_dir_to_file (file2, current_buffer->directory);
1972 if (stat (XSTRING (abspath)->data, &st) < 0)
1973 return Qt;
1975 return (mtime1 > st.st_mtime) ? Qt : Qnil;
1978 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
1979 1, 2, 0,
1980 "Insert contents of file FILENAME after point.\n\
1981 Returns list of absolute pathname and length of data inserted.\n\
1982 If second argument VISIT is non-nil, the buffer's visited filename\n\
1983 and last save file modtime are set, and it is marked unmodified.\n\
1984 If visiting and the file does not exist, visiting is completed\n\
1985 before the error is signaled.")
1986 (filename, visit)
1987 Lisp_Object filename, visit;
1989 struct stat st;
1990 register int fd;
1991 register int inserted = 0;
1992 register int how_much;
1993 int count = specpdl_ptr - specpdl;
1994 struct gcpro gcpro1;
1996 GCPRO1 (filename);
1997 if (!NILP (current_buffer->read_only))
1998 Fbarf_if_buffer_read_only();
2000 CHECK_STRING (filename, 0);
2001 filename = Fexpand_file_name (filename, Qnil);
2003 fd = -1;
2005 #ifndef APOLLO
2006 if (stat (XSTRING (filename)->data, &st) < 0
2007 || (fd = open (XSTRING (filename)->data, 0)) < 0)
2008 #else
2009 if ((fd = open (XSTRING (filename)->data, 0)) < 0
2010 || fstat (fd, &st) < 0)
2011 #endif /* not APOLLO */
2013 if (fd >= 0) close (fd);
2014 if (NILP (visit))
2015 report_file_error ("Opening input file", Fcons (filename, Qnil));
2016 st.st_mtime = -1;
2017 how_much = 0;
2018 goto notfound;
2021 record_unwind_protect (close_file_unwind, make_number (fd));
2023 #ifdef S_IFSOCK
2024 /* This code will need to be changed in order to work on named
2025 pipes, and it's probably just not worth it. So we should at
2026 least signal an error. */
2027 if ((st.st_mode & S_IFMT) == S_IFSOCK)
2028 Fsignal (Qfile_error,
2029 Fcons (build_string ("reading from named pipe"),
2030 Fcons (filename, Qnil)));
2031 #endif
2033 /* Supposedly happens on VMS. */
2034 if (st.st_size < 0)
2035 error ("File size is negative");
2038 register Lisp_Object temp;
2040 /* Make sure point-max won't overflow after this insertion. */
2041 XSET (temp, Lisp_Int, st.st_size + Z);
2042 if (st.st_size + Z != XINT (temp))
2043 error ("maximum buffer size exceeded");
2046 if (NILP (visit))
2047 prepare_to_modify_buffer (point, point);
2049 move_gap (point);
2050 if (GAP_SIZE < st.st_size)
2051 make_gap (st.st_size - GAP_SIZE);
2053 while (1)
2055 int try = min (st.st_size - inserted, 64 << 10);
2056 int this;
2058 /* Allow quitting out of the actual I/O. */
2059 immediate_quit = 1;
2060 QUIT;
2061 this = read (fd, &FETCH_CHAR (point + inserted - 1) + 1, try);
2062 immediate_quit = 0;
2064 if (this <= 0)
2066 how_much = this;
2067 break;
2070 GPT += this;
2071 GAP_SIZE -= this;
2072 ZV += this;
2073 Z += this;
2074 inserted += this;
2077 if (inserted > 0)
2078 MODIFF++;
2079 record_insert (point, inserted);
2081 close (fd);
2083 /* Discard the unwind protect */
2084 specpdl_ptr = specpdl + count;
2086 if (how_much < 0)
2087 error ("IO error reading %s: %s",
2088 XSTRING (filename)->data, err_str (errno));
2090 notfound:
2092 if (!NILP (visit))
2094 current_buffer->undo_list = Qnil;
2095 #ifdef APOLLO
2096 stat (XSTRING (filename)->data, &st);
2097 #endif
2098 current_buffer->modtime = st.st_mtime;
2099 current_buffer->save_modified = MODIFF;
2100 current_buffer->auto_save_modified = MODIFF;
2101 XFASTINT (current_buffer->save_length) = Z - BEG;
2102 #ifdef CLASH_DETECTION
2103 if (!NILP (current_buffer->filename))
2104 unlock_file (current_buffer->filename);
2105 unlock_file (filename);
2106 #endif /* CLASH_DETECTION */
2107 current_buffer->filename = filename;
2108 /* If visiting nonexistent file, return nil. */
2109 if (st.st_mtime == -1)
2110 report_file_error ("Opening input file", Fcons (filename, Qnil));
2113 signal_after_change (point, 0, inserted);
2115 RETURN_UNGCPRO (Fcons (filename,
2116 Fcons (make_number (inserted),
2117 Qnil)));
2120 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
2121 "r\nFWrite region to file: ",
2122 "Write current region into specified file.\n\
2123 When called from a program, takes three arguments:\n\
2124 START, END and FILENAME. START and END are buffer positions.\n\
2125 Optional fourth argument APPEND if non-nil means\n\
2126 append to existing file contents (if any).\n\
2127 Optional fifth argument VISIT if t means\n\
2128 set the last-save-file-modtime of buffer to this file's modtime\n\
2129 and mark buffer not modified.\n\
2130 If VISIT is neither t nor nil, it means do not print\n\
2131 the \"Wrote file\" message.\n\
2132 Kludgy feature: if START is a string, then that string is written\n\
2133 to the file, instead of any buffer contents, and END is ignored.")
2134 (start, end, filename, append, visit)
2135 Lisp_Object start, end, filename, append, visit;
2137 register int desc;
2138 int failure;
2139 int save_errno;
2140 unsigned char *fn;
2141 struct stat st;
2142 int tem;
2143 int count = specpdl_ptr - specpdl;
2144 #ifdef VMS
2145 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
2146 #endif /* VMS */
2148 /* Special kludge to simplify auto-saving */
2149 if (NILP (start))
2151 XFASTINT (start) = BEG;
2152 XFASTINT (end) = Z;
2154 else if (XTYPE (start) != Lisp_String)
2155 validate_region (&start, &end);
2157 filename = Fexpand_file_name (filename, Qnil);
2158 fn = XSTRING (filename)->data;
2160 #ifdef CLASH_DETECTION
2161 if (!auto_saving)
2162 lock_file (filename);
2163 #endif /* CLASH_DETECTION */
2165 desc = -1;
2166 if (!NILP (append))
2167 desc = open (fn, O_WRONLY);
2169 if (desc < 0)
2170 #ifdef VMS
2171 if (auto_saving) /* Overwrite any previous version of autosave file */
2173 vms_truncate (fn); /* if fn exists, truncate to zero length */
2174 desc = open (fn, O_RDWR);
2175 if (desc < 0)
2176 desc = creat_copy_attrs (XTYPE (current_buffer->filename) == Lisp_String
2177 ? XSTRING (current_buffer->filename)->data : 0,
2178 fn);
2180 else /* Write to temporary name and rename if no errors */
2182 Lisp_Object temp_name;
2183 temp_name = Ffile_name_directory (filename);
2185 if (!NILP (temp_name))
2187 temp_name = Fmake_temp_name (concat2 (temp_name,
2188 build_string ("$$SAVE$$")));
2189 fname = XSTRING (filename)->data;
2190 fn = XSTRING (temp_name)->data;
2191 desc = creat_copy_attrs (fname, fn);
2192 if (desc < 0)
2194 /* If we can't open the temporary file, try creating a new
2195 version of the original file. VMS "creat" creates a
2196 new version rather than truncating an existing file. */
2197 fn = fname;
2198 fname = 0;
2199 desc = creat (fn, 0666);
2200 #if 0 /* This can clobber an existing file and fail to replace it,
2201 if the user runs out of space. */
2202 if (desc < 0)
2204 /* We can't make a new version;
2205 try to truncate and rewrite existing version if any. */
2206 vms_truncate (fn);
2207 desc = open (fn, O_RDWR);
2209 #endif
2212 else
2213 desc = creat (fn, 0666);
2215 #else /* not VMS */
2216 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
2217 #endif /* not VMS */
2219 if (desc < 0)
2221 #ifdef CLASH_DETECTION
2222 save_errno = errno;
2223 if (!auto_saving) unlock_file (filename);
2224 errno = save_errno;
2225 #endif /* CLASH_DETECTION */
2226 report_file_error ("Opening output file", Fcons (filename, Qnil));
2229 record_unwind_protect (close_file_unwind, make_number (desc));
2231 if (!NILP (append))
2232 if (lseek (desc, 0, 2) < 0)
2234 #ifdef CLASH_DETECTION
2235 if (!auto_saving) unlock_file (filename);
2236 #endif /* CLASH_DETECTION */
2237 report_file_error ("Lseek error", Fcons (filename, Qnil));
2240 #ifdef VMS
2242 * Kludge Warning: The VMS C RTL likes to insert carriage returns
2243 * if we do writes that don't end with a carriage return. Furthermore
2244 * it cannot handle writes of more then 16K. The modified
2245 * version of "sys_write" in SYSDEP.C (see comment there) copes with
2246 * this EXCEPT for the last record (iff it doesn't end with a carriage
2247 * return). This implies that if your buffer doesn't end with a carriage
2248 * return, you get one free... tough. However it also means that if
2249 * we make two calls to sys_write (a la the following code) you can
2250 * get one at the gap as well. The easiest way to fix this (honest)
2251 * is to move the gap to the next newline (or the end of the buffer).
2252 * Thus this change.
2254 * Yech!
2256 if (GPT > BEG && GPT_ADDR[-1] != '\n')
2257 move_gap (find_next_newline (GPT, 1));
2258 #endif
2260 failure = 0;
2261 immediate_quit = 1;
2263 if (XTYPE (start) == Lisp_String)
2265 failure = 0 > e_write (desc, XSTRING (start)->data,
2266 XSTRING (start)->size);
2267 save_errno = errno;
2269 else if (XINT (start) != XINT (end))
2271 if (XINT (start) < GPT)
2273 register int end1 = XINT (end);
2274 tem = XINT (start);
2275 failure = 0 > e_write (desc, &FETCH_CHAR (tem),
2276 min (GPT, end1) - tem);
2277 save_errno = errno;
2280 if (XINT (end) > GPT && !failure)
2282 tem = XINT (start);
2283 tem = max (tem, GPT);
2284 failure = 0 > e_write (desc, &FETCH_CHAR (tem), XINT (end) - tem);
2285 save_errno = errno;
2289 immediate_quit = 0;
2291 #ifndef USG
2292 #ifndef VMS
2293 #ifndef BSD4_1
2294 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
2295 Disk full in NFS may be reported here. */
2296 if (fsync (desc) < 0)
2297 failure = 1, save_errno = errno;
2298 #endif
2299 #endif
2300 #endif
2302 /* Spurious "file has changed on disk" warnings have been
2303 observed on Suns as well.
2304 It seems that `close' can change the modtime, under nfs.
2306 (This has supposedly been fixed in Sunos 4,
2307 but who knows about all the other machines with NFS?) */
2308 #if 0
2310 /* On VMS and APOLLO, must do the stat after the close
2311 since closing changes the modtime. */
2312 #ifndef VMS
2313 #ifndef APOLLO
2314 /* Recall that #if defined does not work on VMS. */
2315 #define FOO
2316 fstat (desc, &st);
2317 #endif
2318 #endif
2319 #endif
2321 /* NFS can report a write failure now. */
2322 if (close (desc) < 0)
2323 failure = 1, save_errno = errno;
2325 #ifdef VMS
2326 /* If we wrote to a temporary name and had no errors, rename to real name. */
2327 if (fname)
2329 if (!failure)
2330 failure = (rename (fn, fname) != 0), save_errno = errno;
2331 fn = fname;
2333 #endif /* VMS */
2335 #ifndef FOO
2336 stat (fn, &st);
2337 #endif
2338 /* Discard the unwind protect */
2339 specpdl_ptr = specpdl + count;
2341 #ifdef CLASH_DETECTION
2342 if (!auto_saving)
2343 unlock_file (filename);
2344 #endif /* CLASH_DETECTION */
2346 /* Do this before reporting IO error
2347 to avoid a "file has changed on disk" warning on
2348 next attempt to save. */
2349 if (EQ (visit, Qt))
2350 current_buffer->modtime = st.st_mtime;
2352 if (failure)
2353 error ("IO error writing %s: %s", fn, err_str (save_errno));
2355 if (EQ (visit, Qt))
2357 current_buffer->save_modified = MODIFF;
2358 XFASTINT (current_buffer->save_length) = Z - BEG;
2359 current_buffer->filename = filename;
2361 else if (!NILP (visit))
2362 return Qnil;
2364 if (!auto_saving)
2365 message ("Wrote %s", fn);
2367 return Qnil;
2371 e_write (desc, addr, len)
2372 int desc;
2373 register char *addr;
2374 register int len;
2376 char buf[16 * 1024];
2377 register char *p, *end;
2379 if (!EQ (current_buffer->selective_display, Qt))
2380 return write (desc, addr, len) - len;
2381 else
2383 p = buf;
2384 end = p + sizeof buf;
2385 while (len--)
2387 if (p == end)
2389 if (write (desc, buf, sizeof buf) != sizeof buf)
2390 return -1;
2391 p = buf;
2393 *p = *addr++;
2394 if (*p++ == '\015')
2395 p[-1] = '\n';
2397 if (p != buf)
2398 if (write (desc, buf, p - buf) != p - buf)
2399 return -1;
2401 return 0;
2404 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
2405 Sverify_visited_file_modtime, 1, 1, 0,
2406 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
2407 This means that the file has not been changed since it was visited or saved.")
2408 (buf)
2409 Lisp_Object buf;
2411 struct buffer *b;
2412 struct stat st;
2414 CHECK_BUFFER (buf, 0);
2415 b = XBUFFER (buf);
2417 if (XTYPE (b->filename) != Lisp_String) return Qt;
2418 if (b->modtime == 0) return Qt;
2420 if (stat (XSTRING (b->filename)->data, &st) < 0)
2422 /* If the file doesn't exist now and didn't exist before,
2423 we say that it isn't modified, provided the error is a tame one. */
2424 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
2425 st.st_mtime = -1;
2426 else
2427 st.st_mtime = 0;
2429 if (st.st_mtime == b->modtime
2430 /* If both are positive, accept them if they are off by one second. */
2431 || (st.st_mtime > 0 && b->modtime > 0
2432 && (st.st_mtime == b->modtime + 1
2433 || st.st_mtime == b->modtime - 1)))
2434 return Qt;
2435 return Qnil;
2438 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
2439 Sclear_visited_file_modtime, 0, 0, 0,
2440 "Clear out records of last mod time of visited file.\n\
2441 Next attempt to save will certainly not complain of a discrepancy.")
2444 current_buffer->modtime = 0;
2445 return Qnil;
2448 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
2449 Sset_visited_file_modtime, 0, 0, 0,
2450 "Update buffer's recorded modification time from the visited file's time.\n\
2451 Useful if the buffer was not read from the file normally\n\
2452 or if the file itself has been changed for some known benign reason.")
2455 register Lisp_Object filename;
2456 struct stat st;
2458 filename = Fexpand_file_name (current_buffer->filename, Qnil);
2460 if (stat (XSTRING (filename)->data, &st) >= 0)
2461 current_buffer->modtime = st.st_mtime;
2463 return Qnil;
2466 Lisp_Object
2467 auto_save_error ()
2469 unsigned char *name = XSTRING (current_buffer->name)->data;
2471 ring_bell ();
2472 message ("Autosaving...error for %s", name);
2473 Fsleep_for (make_number (1), Qnil);
2474 message ("Autosaving...error!for %s", name);
2475 Fsleep_for (make_number (1), Qnil);
2476 message ("Autosaving...error for %s", name);
2477 Fsleep_for (make_number (1), Qnil);
2478 return Qnil;
2481 Lisp_Object
2482 auto_save_1 ()
2484 unsigned char *fn;
2485 struct stat st;
2487 /* Get visited file's mode to become the auto save file's mode. */
2488 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
2489 /* But make sure we can overwrite it later! */
2490 auto_save_mode_bits = st.st_mode | 0600;
2491 else
2492 auto_save_mode_bits = 0666;
2494 return
2495 Fwrite_region (Qnil, Qnil,
2496 current_buffer->auto_save_file_name,
2497 Qnil, Qlambda);
2500 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
2501 "Auto-save all buffers that need it.\n\
2502 This is all buffers that have auto-saving enabled\n\
2503 and are changed since last auto-saved.\n\
2504 Auto-saving writes the buffer into a file\n\
2505 so that your editing is not lost if the system crashes.\n\
2506 This file is not the file you visited; that changes only when you save.\n\n\
2507 Non-nil first argument means do not print any message if successful.\n\
2508 Non-nil second argument means save only current buffer.")
2509 (nomsg)
2510 Lisp_Object nomsg;
2512 struct buffer *old = current_buffer, *b;
2513 Lisp_Object tail, buf;
2514 int auto_saved = 0;
2515 char *omessage = echo_area_glyphs;
2516 extern minibuf_level;
2518 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
2519 point to non-strings reached from Vbuffer_alist. */
2521 auto_saving = 1;
2522 if (minibuf_level)
2523 nomsg = Qt;
2525 /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
2526 eventually call do-auto-save, so don't err here in that case. */
2527 if (!NILP (Vrun_hooks))
2528 call1 (Vrun_hooks, intern ("auto-save-hook"));
2530 for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
2531 tail = XCONS (tail)->cdr)
2533 buf = XCONS (XCONS (tail)->car)->cdr;
2534 b = XBUFFER (buf);
2535 /* Check for auto save enabled
2536 and file changed since last auto save
2537 and file changed since last real save. */
2538 if (XTYPE (b->auto_save_file_name) == Lisp_String
2539 && b->save_modified < BUF_MODIFF (b)
2540 && b->auto_save_modified < BUF_MODIFF (b))
2542 if ((XFASTINT (b->save_length) * 10
2543 > (BUF_Z (b) - BUF_BEG (b)) * 13)
2544 /* A short file is likely to change a large fraction;
2545 spare the user annoying messages. */
2546 && XFASTINT (b->save_length) > 5000
2547 /* These messages are frequent and annoying for `*mail*'. */
2548 && !EQ (b->filename, Qnil))
2550 /* It has shrunk too much; turn off auto-saving here. */
2551 message ("Buffer %s has shrunk a lot; auto save turned off there",
2552 XSTRING (b->name)->data);
2553 /* User can reenable saving with M-x auto-save. */
2554 b->auto_save_file_name = Qnil;
2555 /* Prevent warning from repeating if user does so. */
2556 XFASTINT (b->save_length) = 0;
2557 Fsleep_for (make_number (1));
2558 continue;
2560 set_buffer_internal (b);
2561 if (!auto_saved && NILP (nomsg))
2562 message1 ("Auto-saving...");
2563 internal_condition_case (auto_save_1, Qt, auto_save_error);
2564 auto_saved++;
2565 b->auto_save_modified = BUF_MODIFF (b);
2566 XFASTINT (current_buffer->save_length) = Z - BEG;
2567 set_buffer_internal (old);
2571 if (auto_saved)
2572 record_auto_save ();
2574 if (auto_saved && NILP (nomsg))
2575 message1 (omessage ? omessage : "Auto-saving...done");
2577 auto_saving = 0;
2578 return Qnil;
2581 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
2582 Sset_buffer_auto_saved, 0, 0, 0,
2583 "Mark current buffer as auto-saved with its current text.\n\
2584 No auto-save file will be written until the buffer changes again.")
2587 current_buffer->auto_save_modified = MODIFF;
2588 XFASTINT (current_buffer->save_length) = Z - BEG;
2589 return Qnil;
2592 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
2593 0, 0, 0,
2594 "Return t if buffer has been auto-saved since last read in or saved.")
2597 return (current_buffer->save_modified < current_buffer->auto_save_modified) ? Qt : Qnil;
2600 /* Reading and completing file names */
2601 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
2603 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
2604 3, 3, 0,
2605 "Internal subroutine for read-file-name. Do not call this.")
2606 (string, dir, action)
2607 Lisp_Object string, dir, action;
2608 /* action is nil for complete, t for return list of completions,
2609 lambda for verify final value */
2611 Lisp_Object name, specdir, realdir, val, orig_string;
2613 if (XSTRING (string)->size == 0)
2615 orig_string = Qnil;
2616 name = string;
2617 realdir = dir;
2618 if (EQ (action, Qlambda))
2619 return Qnil;
2621 else
2623 orig_string = string;
2624 string = Fsubstitute_in_file_name (string);
2625 name = Ffile_name_nondirectory (string);
2626 realdir = Ffile_name_directory (string);
2627 if (NILP (realdir))
2628 realdir = dir;
2629 else
2630 realdir = Fexpand_file_name (realdir, dir);
2633 if (NILP (action))
2635 specdir = Ffile_name_directory (string);
2636 val = Ffile_name_completion (name, realdir);
2637 if (XTYPE (val) != Lisp_String)
2639 if (NILP (Fstring_equal (string, orig_string)))
2640 return string;
2641 return (val);
2644 if (!NILP (specdir))
2645 val = concat2 (specdir, val);
2646 #ifndef VMS
2648 register unsigned char *old, *new;
2649 register int n;
2650 int osize, count;
2652 osize = XSTRING (val)->size;
2653 /* Quote "$" as "$$" to get it past substitute-in-file-name */
2654 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
2655 if (*old++ == '$') count++;
2656 if (count > 0)
2658 old = XSTRING (val)->data;
2659 val = Fmake_string (make_number (osize + count), make_number (0));
2660 new = XSTRING (val)->data;
2661 for (n = osize; n > 0; n--)
2662 if (*old != '$')
2663 *new++ = *old++;
2664 else
2666 *new++ = '$';
2667 *new++ = '$';
2668 old++;
2672 #endif /* Not VMS */
2673 return (val);
2676 if (EQ (action, Qt))
2677 return Ffile_name_all_completions (name, realdir);
2678 /* Only other case actually used is ACTION = lambda */
2679 #ifdef VMS
2680 /* Supposedly this helps commands such as `cd' that read directory names,
2681 but can someone explain how it helps them? -- RMS */
2682 if (XSTRING (name)->size == 0)
2683 return Qt;
2684 #endif /* VMS */
2685 return Ffile_exists_p (string);
2688 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
2689 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
2690 Value is not expanded---you must call `expand-file-name' yourself.\n\
2691 Default name to DEFAULT if user enters a null string.\n\
2692 (If DEFAULT is omitted, the visited file name is used.)\n\
2693 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
2694 Non-nil and non-t means also require confirmation after completion.\n\
2695 Fifth arg INITIAL specifies text to start with.\n\
2696 DIR defaults to current buffer's directory default.")
2697 (prompt, dir, defalt, mustmatch, initial)
2698 Lisp_Object prompt, dir, defalt, mustmatch, initial;
2700 Lisp_Object val, insdef, tem, backup_n;
2701 struct gcpro gcpro1, gcpro2;
2702 register char *homedir;
2703 int count;
2705 if (NILP (dir))
2706 dir = current_buffer->directory;
2707 if (NILP (defalt))
2708 defalt = current_buffer->filename;
2710 /* If dir starts with user's homedir, change that to ~. */
2711 homedir = (char *) egetenv ("HOME");
2712 if (homedir != 0
2713 && XTYPE (dir) == Lisp_String
2714 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
2715 && XSTRING (dir)->data[strlen (homedir)] == '/')
2717 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
2718 XSTRING (dir)->size - strlen (homedir) + 1);
2719 XSTRING (dir)->data[0] = '~';
2722 if (insert_default_directory)
2724 insdef = dir;
2725 if (!NILP (initial))
2727 Lisp_Object args[2];
2729 args[0] = insdef;
2730 args[1] = initial;
2731 insdef = Fconcat (2, args);
2732 backup_n = make_number (- (XSTRING (initial)->size));
2734 else
2735 backup_n = Qnil;
2737 else
2739 insdef = build_string ("");
2740 backup_n = Qnil;
2743 #ifdef VMS
2744 count = specpdl_ptr - specpdl;
2745 specbind (intern ("completion-ignore-case"), Qt);
2746 #endif
2748 GCPRO2 (insdef, defalt);
2749 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
2750 dir, mustmatch,
2751 insert_default_directory ? insdef : Qnil, backup_n);
2753 #ifdef VMS
2754 unbind_to (count, Qnil);
2755 #endif
2757 UNGCPRO;
2758 if (NILP (val))
2759 error ("No file name specified");
2760 tem = Fstring_equal (val, insdef);
2761 if (!NILP (tem) && !NILP (defalt))
2762 return defalt;
2763 return Fsubstitute_in_file_name (val);
2766 #if 0 /* Old version */
2767 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
2768 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
2769 Value is not expanded---you must call `expand-file-name' yourself.\n\
2770 Default name to DEFAULT if user enters a null string.\n\
2771 (If DEFAULT is omitted, the visited file name is used.)\n\
2772 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
2773 Non-nil and non-t means also require confirmation after completion.\n\
2774 Fifth arg INITIAL specifies text to start with.\n\
2775 DIR defaults to current buffer's directory default.")
2776 (prompt, dir, defalt, mustmatch, initial)
2777 Lisp_Object prompt, dir, defalt, mustmatch, initial;
2779 Lisp_Object val, insdef, tem;
2780 struct gcpro gcpro1, gcpro2;
2781 register char *homedir;
2782 int count;
2784 if (NILP (dir))
2785 dir = current_buffer->directory;
2786 if (NILP (defalt))
2787 defalt = current_buffer->filename;
2789 /* If dir starts with user's homedir, change that to ~. */
2790 homedir = (char *) egetenv ("HOME");
2791 if (homedir != 0
2792 && XTYPE (dir) == Lisp_String
2793 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
2794 && XSTRING (dir)->data[strlen (homedir)] == '/')
2796 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
2797 XSTRING (dir)->size - strlen (homedir) + 1);
2798 XSTRING (dir)->data[0] = '~';
2801 if (!NILP (initial))
2802 insdef = initial;
2803 else if (insert_default_directory)
2804 insdef = dir;
2805 else
2806 insdef = build_string ("");
2808 #ifdef VMS
2809 count = specpdl_ptr - specpdl;
2810 specbind (intern ("completion-ignore-case"), Qt);
2811 #endif
2813 GCPRO2 (insdef, defalt);
2814 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
2815 dir, mustmatch,
2816 insert_default_directory ? insdef : Qnil, Qnil);
2818 #ifdef VMS
2819 unbind_to (count, Qnil);
2820 #endif
2822 UNGCPRO;
2823 if (NILP (val))
2824 error ("No file name specified");
2825 tem = Fstring_equal (val, insdef);
2826 if (!NILP (tem) && !NILP (defalt))
2827 return defalt;
2828 return Fsubstitute_in_file_name (val);
2830 #endif /* Old version */
2832 syms_of_fileio ()
2834 Qfile_error = intern ("file-error");
2835 staticpro (&Qfile_error);
2836 Qfile_already_exists = intern("file-already-exists");
2837 staticpro (&Qfile_already_exists);
2839 Fput (Qfile_error, Qerror_conditions,
2840 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
2841 Fput (Qfile_error, Qerror_message,
2842 build_string ("File error"));
2844 Fput (Qfile_already_exists, Qerror_conditions,
2845 Fcons (Qfile_already_exists,
2846 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
2847 Fput (Qfile_already_exists, Qerror_message,
2848 build_string ("File already exists"));
2850 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
2851 "*Non-nil means when reading a filename start with default dir in minibuffer.");
2852 insert_default_directory = 1;
2854 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
2855 "*Non-nil means write new files with record format `stmlf'.\n\
2856 nil means use format `var'. This variable is meaningful only on VMS.");
2857 vms_stmlf_recfm = 0;
2859 defsubr (&Sfile_name_directory);
2860 defsubr (&Sfile_name_nondirectory);
2861 defsubr (&Sfile_name_as_directory);
2862 defsubr (&Sdirectory_file_name);
2863 defsubr (&Smake_temp_name);
2864 defsubr (&Sexpand_file_name);
2865 defsubr (&Ssubstitute_in_file_name);
2866 defsubr (&Scopy_file);
2867 defsubr (&Smake_directory);
2868 defsubr (&Sdelete_directory);
2869 defsubr (&Sdelete_file);
2870 defsubr (&Srename_file);
2871 defsubr (&Sadd_name_to_file);
2872 #ifdef S_IFLNK
2873 defsubr (&Smake_symbolic_link);
2874 #endif /* S_IFLNK */
2875 #ifdef VMS
2876 defsubr (&Sdefine_logical_name);
2877 #endif /* VMS */
2878 #ifdef HPUX_NET
2879 defsubr (&Ssysnetunam);
2880 #endif /* HPUX_NET */
2881 defsubr (&Sfile_name_absolute_p);
2882 defsubr (&Sfile_exists_p);
2883 defsubr (&Sfile_executable_p);
2884 defsubr (&Sfile_readable_p);
2885 defsubr (&Sfile_writable_p);
2886 defsubr (&Sfile_symlink_p);
2887 defsubr (&Sfile_directory_p);
2888 defsubr (&Sfile_accessible_directory_p);
2889 defsubr (&Sfile_modes);
2890 defsubr (&Sset_file_modes);
2891 defsubr (&Sset_umask);
2892 defsubr (&Sumask);
2893 defsubr (&Sfile_newer_than_file_p);
2894 defsubr (&Sinsert_file_contents);
2895 defsubr (&Swrite_region);
2896 defsubr (&Sverify_visited_file_modtime);
2897 defsubr (&Sclear_visited_file_modtime);
2898 defsubr (&Sset_visited_file_modtime);
2899 defsubr (&Sdo_auto_save);
2900 defsubr (&Sset_buffer_auto_saved);
2901 defsubr (&Srecent_auto_save_p);
2903 defsubr (&Sread_file_name_internal);
2904 defsubr (&Sread_file_name);
2906 defsubr (&Sunix_sync);