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