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