(font_idx_temp): Extern it.
[bpt/emacs.git] / src / fileio.c
1 /* File IO for GNU Emacs.
2 Copyright (C) 1985,86,87,88,93,94,95,96 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <config.h>
22
23 #if defined (USG5) || defined (BSD_SYSTEM) || defined (LINUX)
24 #include <fcntl.h>
25 #endif
26
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #if !defined (S_ISLNK) && defined (S_IFLNK)
36 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
37 #endif
38
39 #if !defined (S_ISFIFO) && defined (S_IFIFO)
40 # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
41 #endif
42
43 #if !defined (S_ISREG) && defined (S_IFREG)
44 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
45 #endif
46
47 #ifdef VMS
48 #include "vms-pwd.h"
49 #else
50 #include <pwd.h>
51 #endif
52
53 #ifdef MSDOS
54 #include "msdos.h"
55 #include <sys/param.h>
56 #if __DJGPP__ >= 2
57 #include <fcntl.h>
58 #include <string.h>
59 #endif
60 #endif
61
62 #include <ctype.h>
63
64 #ifdef VMS
65 #include "vmsdir.h"
66 #include <perror.h>
67 #include <stddef.h>
68 #include <string.h>
69 #endif
70
71 #include <errno.h>
72
73 #ifndef vax11c
74 extern int errno;
75 #endif
76
77 extern char *strerror ();
78
79 #ifdef APOLLO
80 #include <sys/time.h>
81 #endif
82
83 #ifndef USG
84 #ifndef VMS
85 #ifndef BSD4_1
86 #ifndef WINDOWSNT
87 #define HAVE_FSYNC
88 #endif
89 #endif
90 #endif
91 #endif
92
93 #include "lisp.h"
94 #include "intervals.h"
95 #include "buffer.h"
96 #include "charset.h"
97 #include "coding.h"
98 #include "window.h"
99
100 #ifdef WINDOWSNT
101 #define NOMINMAX 1
102 #include <windows.h>
103 #include <stdlib.h>
104 #include <fcntl.h>
105 #endif /* not WINDOWSNT */
106
107 #ifdef DOS_NT
108 #define CORRECT_DIR_SEPS(s) \
109 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
110 else unixtodos_filename (s); \
111 } while (0)
112 /* On Windows, drive letters must be alphabetic - on DOS, the Netware
113 redirector allows the six letters between 'Z' and 'a' as well. */
114 #ifdef MSDOS
115 #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
116 #endif
117 #ifdef WINDOWSNT
118 #define IS_DRIVE(x) isalpha (x)
119 #endif
120 /* Need to lower-case the drive letter, or else expanded
121 filenames will sometimes compare inequal, because
122 `expand-file-name' doesn't always down-case the drive letter. */
123 #define DRIVE_LETTER(x) (tolower (x))
124 #endif
125
126 #ifdef VMS
127 #include <file.h>
128 #include <rmsdef.h>
129 #include <fab.h>
130 #include <nam.h>
131 #endif
132
133 #include "systime.h"
134
135 #ifdef HPUX
136 #include <netio.h>
137 #ifndef HPUX8
138 #ifndef HPUX9
139 #include <errnet.h>
140 #endif
141 #endif
142 #endif
143
144 #ifndef O_WRONLY
145 #define O_WRONLY 1
146 #endif
147
148 #ifndef O_RDONLY
149 #define O_RDONLY 0
150 #endif
151
152 #define min(a, b) ((a) < (b) ? (a) : (b))
153 #define max(a, b) ((a) > (b) ? (a) : (b))
154
155 /* Nonzero during writing of auto-save files */
156 int auto_saving;
157
158 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
159 a new file with the same mode as the original */
160 int auto_save_mode_bits;
161
162 /* Alist of elements (REGEXP . HANDLER) for file names
163 whose I/O is done with a special handler. */
164 Lisp_Object Vfile_name_handler_alist;
165
166 /* Format for auto-save files */
167 Lisp_Object Vauto_save_file_format;
168
169 /* Lisp functions for translating file formats */
170 Lisp_Object Qformat_decode, Qformat_annotate_function;
171
172 /* Functions to be called to process text properties in inserted file. */
173 Lisp_Object Vafter_insert_file_functions;
174
175 /* Functions to be called to create text property annotations for file. */
176 Lisp_Object Vwrite_region_annotate_functions;
177
178 /* During build_annotations, each time an annotation function is called,
179 this holds the annotations made by the previous functions. */
180 Lisp_Object Vwrite_region_annotations_so_far;
181
182 /* File name in which we write a list of all our auto save files. */
183 Lisp_Object Vauto_save_list_file_name;
184
185 /* Nonzero means, when reading a filename in the minibuffer,
186 start out by inserting the default directory into the minibuffer. */
187 int insert_default_directory;
188
189 /* On VMS, nonzero means write new files with record format stmlf.
190 Zero means use var format. */
191 int vms_stmlf_recfm;
192
193 /* On NT, specifies the directory separator character, used (eg.) when
194 expanding file names. This can be bound to / or \. */
195 Lisp_Object Vdirectory_sep_char;
196
197 extern Lisp_Object Vuser_login_name;
198
199 extern int minibuf_level;
200
201 /* These variables describe handlers that have "already" had a chance
202 to handle the current operation.
203
204 Vinhibit_file_name_handlers is a list of file name handlers.
205 Vinhibit_file_name_operation is the operation being handled.
206 If we try to handle that operation, we ignore those handlers. */
207
208 static Lisp_Object Vinhibit_file_name_handlers;
209 static Lisp_Object Vinhibit_file_name_operation;
210
211 Lisp_Object Qfile_error, Qfile_already_exists, Qfile_date_error;
212
213 Lisp_Object Qfile_name_history;
214
215 Lisp_Object Qcar_less_than_car;
216
217 report_file_error (string, data)
218 char *string;
219 Lisp_Object data;
220 {
221 Lisp_Object errstring;
222
223 errstring = build_string (strerror (errno));
224
225 /* System error messages are capitalized. Downcase the initial
226 unless it is followed by a slash. */
227 if (XSTRING (errstring)->data[1] != '/')
228 XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
229
230 while (1)
231 Fsignal (Qfile_error,
232 Fcons (build_string (string), Fcons (errstring, data)));
233 }
234
235 close_file_unwind (fd)
236 Lisp_Object fd;
237 {
238 close (XFASTINT (fd));
239 }
240
241 /* Restore point, having saved it as a marker. */
242
243 restore_point_unwind (location)
244 Lisp_Object location;
245 {
246 SET_PT (marker_position (location));
247 Fset_marker (location, Qnil, Qnil);
248 }
249 \f
250 Lisp_Object Qexpand_file_name;
251 Lisp_Object Qsubstitute_in_file_name;
252 Lisp_Object Qdirectory_file_name;
253 Lisp_Object Qfile_name_directory;
254 Lisp_Object Qfile_name_nondirectory;
255 Lisp_Object Qunhandled_file_name_directory;
256 Lisp_Object Qfile_name_as_directory;
257 Lisp_Object Qcopy_file;
258 Lisp_Object Qmake_directory_internal;
259 Lisp_Object Qdelete_directory;
260 Lisp_Object Qdelete_file;
261 Lisp_Object Qrename_file;
262 Lisp_Object Qadd_name_to_file;
263 Lisp_Object Qmake_symbolic_link;
264 Lisp_Object Qfile_exists_p;
265 Lisp_Object Qfile_executable_p;
266 Lisp_Object Qfile_readable_p;
267 Lisp_Object Qfile_writable_p;
268 Lisp_Object Qfile_symlink_p;
269 Lisp_Object Qaccess_file;
270 Lisp_Object Qfile_directory_p;
271 Lisp_Object Qfile_regular_p;
272 Lisp_Object Qfile_accessible_directory_p;
273 Lisp_Object Qfile_modes;
274 Lisp_Object Qset_file_modes;
275 Lisp_Object Qfile_newer_than_file_p;
276 Lisp_Object Qinsert_file_contents;
277 Lisp_Object Qwrite_region;
278 Lisp_Object Qverify_visited_file_modtime;
279 Lisp_Object Qset_visited_file_modtime;
280
281 DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 2, 2, 0,
282 "Return FILENAME's handler function for OPERATION, if it has one.\n\
283 Otherwise, return nil.\n\
284 A file name is handled if one of the regular expressions in\n\
285 `file-name-handler-alist' matches it.\n\n\
286 If OPERATION equals `inhibit-file-name-operation', then we ignore\n\
287 any handlers that are members of `inhibit-file-name-handlers',\n\
288 but we still do run any other handlers. This lets handlers\n\
289 use the standard functions without calling themselves recursively.")
290 (filename, operation)
291 Lisp_Object filename, operation;
292 {
293 /* This function must not munge the match data. */
294 Lisp_Object chain, inhibited_handlers;
295
296 CHECK_STRING (filename, 0);
297
298 if (EQ (operation, Vinhibit_file_name_operation))
299 inhibited_handlers = Vinhibit_file_name_handlers;
300 else
301 inhibited_handlers = Qnil;
302
303 for (chain = Vfile_name_handler_alist; CONSP (chain);
304 chain = XCONS (chain)->cdr)
305 {
306 Lisp_Object elt;
307 elt = XCONS (chain)->car;
308 if (CONSP (elt))
309 {
310 Lisp_Object string;
311 string = XCONS (elt)->car;
312 if (STRINGP (string) && fast_string_match (string, filename) >= 0)
313 {
314 Lisp_Object handler, tem;
315
316 handler = XCONS (elt)->cdr;
317 tem = Fmemq (handler, inhibited_handlers);
318 if (NILP (tem))
319 return handler;
320 }
321 }
322
323 QUIT;
324 }
325 return Qnil;
326 }
327 \f
328 DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
329 1, 1, 0,
330 "Return the directory component in file name FILENAME.\n\
331 Return nil if FILENAME does not include a directory.\n\
332 Otherwise return a directory spec.\n\
333 Given a Unix syntax file name, returns a string ending in slash;\n\
334 on VMS, perhaps instead a string ending in `:', `]' or `>'.")
335 (filename)
336 Lisp_Object filename;
337 {
338 register unsigned char *beg;
339 register unsigned char *p;
340 Lisp_Object handler;
341
342 CHECK_STRING (filename, 0);
343
344 /* If the file name has special constructs in it,
345 call the corresponding file handler. */
346 handler = Ffind_file_name_handler (filename, Qfile_name_directory);
347 if (!NILP (handler))
348 return call2 (handler, Qfile_name_directory, filename);
349
350 #ifdef FILE_SYSTEM_CASE
351 filename = FILE_SYSTEM_CASE (filename);
352 #endif
353 beg = XSTRING (filename)->data;
354 #ifdef DOS_NT
355 beg = strcpy (alloca (strlen (beg) + 1), beg);
356 #endif
357 p = beg + XSTRING (filename)->size;
358
359 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
360 #ifdef VMS
361 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
362 #endif /* VMS */
363 #ifdef DOS_NT
364 /* only recognise drive specifier at beginning */
365 && !(p[-1] == ':' && p == beg + 2)
366 #endif
367 ) p--;
368
369 if (p == beg)
370 return Qnil;
371 #ifdef DOS_NT
372 /* Expansion of "c:" to drive and default directory. */
373 if (p == beg + 2 && beg[1] == ':')
374 {
375 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
376 unsigned char *res = alloca (MAXPATHLEN + 1);
377 if (getdefdir (toupper (*beg) - 'A' + 1, res))
378 {
379 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
380 strcat (res, "/");
381 beg = res;
382 p = beg + strlen (beg);
383 }
384 }
385 CORRECT_DIR_SEPS (beg);
386 #endif /* DOS_NT */
387 return make_string (beg, p - beg);
388 }
389
390 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
391 1, 1, 0,
392 "Return file name FILENAME sans its directory.\n\
393 For example, in a Unix-syntax file name,\n\
394 this is everything after the last slash,\n\
395 or the entire name if it contains no slash.")
396 (filename)
397 Lisp_Object filename;
398 {
399 register unsigned char *beg, *p, *end;
400 Lisp_Object handler;
401
402 CHECK_STRING (filename, 0);
403
404 /* If the file name has special constructs in it,
405 call the corresponding file handler. */
406 handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory);
407 if (!NILP (handler))
408 return call2 (handler, Qfile_name_nondirectory, filename);
409
410 beg = XSTRING (filename)->data;
411 end = p = beg + XSTRING (filename)->size;
412
413 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
414 #ifdef VMS
415 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
416 #endif /* VMS */
417 #ifdef DOS_NT
418 /* only recognise drive specifier at beginning */
419 && !(p[-1] == ':' && p == beg + 2)
420 #endif
421 ) p--;
422
423 return make_string (p, end - p);
424 }
425
426 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
427 "Return a directly usable directory name somehow associated with FILENAME.\n\
428 A `directly usable' directory name is one that may be used without the\n\
429 intervention of any file handler.\n\
430 If FILENAME is a directly usable file itself, return\n\
431 (file-name-directory FILENAME).\n\
432 The `call-process' and `start-process' functions use this function to\n\
433 get a current directory to run processes in.")
434 (filename)
435 Lisp_Object filename;
436 {
437 Lisp_Object handler;
438
439 /* If the file name has special constructs in it,
440 call the corresponding file handler. */
441 handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory);
442 if (!NILP (handler))
443 return call2 (handler, Qunhandled_file_name_directory, filename);
444
445 return Ffile_name_directory (filename);
446 }
447
448 \f
449 char *
450 file_name_as_directory (out, in)
451 char *out, *in;
452 {
453 int size = strlen (in) - 1;
454
455 strcpy (out, in);
456
457 #ifdef VMS
458 /* Is it already a directory string? */
459 if (in[size] == ':' || in[size] == ']' || in[size] == '>')
460 return out;
461 /* Is it a VMS directory file name? If so, hack VMS syntax. */
462 else if (! index (in, '/')
463 && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
464 || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
465 || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
466 || ! strncmp (&in[size - 5], ".dir", 4))
467 && (in[size - 1] == '.' || in[size - 1] == ';')
468 && in[size] == '1')))
469 {
470 register char *p, *dot;
471 char brack;
472
473 /* x.dir -> [.x]
474 dir:x.dir --> dir:[x]
475 dir:[x]y.dir --> dir:[x.y] */
476 p = in + size;
477 while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
478 if (p != in)
479 {
480 strncpy (out, in, p - in);
481 out[p - in] = '\0';
482 if (*p == ':')
483 {
484 brack = ']';
485 strcat (out, ":[");
486 }
487 else
488 {
489 brack = *p;
490 strcat (out, ".");
491 }
492 p++;
493 }
494 else
495 {
496 brack = ']';
497 strcpy (out, "[.");
498 }
499 dot = index (p, '.');
500 if (dot)
501 {
502 /* blindly remove any extension */
503 size = strlen (out) + (dot - p);
504 strncat (out, p, dot - p);
505 }
506 else
507 {
508 strcat (out, p);
509 size = strlen (out);
510 }
511 out[size++] = brack;
512 out[size] = '\0';
513 }
514 #else /* not VMS */
515 /* For Unix syntax, Append a slash if necessary */
516 if (!IS_DIRECTORY_SEP (out[size]))
517 {
518 out[size + 1] = DIRECTORY_SEP;
519 out[size + 2] = '\0';
520 }
521 #ifdef DOS_NT
522 CORRECT_DIR_SEPS (out);
523 #endif
524 #endif /* not VMS */
525 return out;
526 }
527
528 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
529 Sfile_name_as_directory, 1, 1, 0,
530 "Return a string representing file FILENAME interpreted as a directory.\n\
531 This operation exists because a directory is also a file, but its name as\n\
532 a directory is different from its name as a file.\n\
533 The result can be used as the value of `default-directory'\n\
534 or passed as second argument to `expand-file-name'.\n\
535 For a Unix-syntax file name, just appends a slash.\n\
536 On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
537 (file)
538 Lisp_Object file;
539 {
540 char *buf;
541 Lisp_Object handler;
542
543 CHECK_STRING (file, 0);
544 if (NILP (file))
545 return Qnil;
546
547 /* If the file name has special constructs in it,
548 call the corresponding file handler. */
549 handler = Ffind_file_name_handler (file, Qfile_name_as_directory);
550 if (!NILP (handler))
551 return call2 (handler, Qfile_name_as_directory, file);
552
553 buf = (char *) alloca (XSTRING (file)->size + 10);
554 return build_string (file_name_as_directory (buf, XSTRING (file)->data));
555 }
556 \f
557 /*
558 * Convert from directory name to filename.
559 * On VMS:
560 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
561 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
562 * On UNIX, it's simple: just make sure there isn't a terminating /
563
564 * Value is nonzero if the string output is different from the input.
565 */
566
567 directory_file_name (src, dst)
568 char *src, *dst;
569 {
570 long slen;
571 #ifdef VMS
572 long rlen;
573 char * ptr, * rptr;
574 char bracket;
575 struct FAB fab = cc$rms_fab;
576 struct NAM nam = cc$rms_nam;
577 char esa[NAM$C_MAXRSS];
578 #endif /* VMS */
579
580 slen = strlen (src);
581 #ifdef VMS
582 if (! index (src, '/')
583 && (src[slen - 1] == ']'
584 || src[slen - 1] == ':'
585 || src[slen - 1] == '>'))
586 {
587 /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
588 fab.fab$l_fna = src;
589 fab.fab$b_fns = slen;
590 fab.fab$l_nam = &nam;
591 fab.fab$l_fop = FAB$M_NAM;
592
593 nam.nam$l_esa = esa;
594 nam.nam$b_ess = sizeof esa;
595 nam.nam$b_nop |= NAM$M_SYNCHK;
596
597 /* We call SYS$PARSE to handle such things as [--] for us. */
598 if (SYS$PARSE (&fab, 0, 0) == RMS$_NORMAL)
599 {
600 slen = nam.nam$b_esl;
601 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
602 slen -= 2;
603 esa[slen] = '\0';
604 src = esa;
605 }
606 if (src[slen - 1] != ']' && src[slen - 1] != '>')
607 {
608 /* what about when we have logical_name:???? */
609 if (src[slen - 1] == ':')
610 { /* Xlate logical name and see what we get */
611 ptr = strcpy (dst, src); /* upper case for getenv */
612 while (*ptr)
613 {
614 if ('a' <= *ptr && *ptr <= 'z')
615 *ptr -= 040;
616 ptr++;
617 }
618 dst[slen - 1] = 0; /* remove colon */
619 if (!(src = egetenv (dst)))
620 return 0;
621 /* should we jump to the beginning of this procedure?
622 Good points: allows us to use logical names that xlate
623 to Unix names,
624 Bad points: can be a problem if we just translated to a device
625 name...
626 For now, I'll punt and always expect VMS names, and hope for
627 the best! */
628 slen = strlen (src);
629 if (src[slen - 1] != ']' && src[slen - 1] != '>')
630 { /* no recursion here! */
631 strcpy (dst, src);
632 return 0;
633 }
634 }
635 else
636 { /* not a directory spec */
637 strcpy (dst, src);
638 return 0;
639 }
640 }
641 bracket = src[slen - 1];
642
643 /* If bracket is ']' or '>', bracket - 2 is the corresponding
644 opening bracket. */
645 ptr = index (src, bracket - 2);
646 if (ptr == 0)
647 { /* no opening bracket */
648 strcpy (dst, src);
649 return 0;
650 }
651 if (!(rptr = rindex (src, '.')))
652 rptr = ptr;
653 slen = rptr - src;
654 strncpy (dst, src, slen);
655 dst[slen] = '\0';
656 if (*rptr == '.')
657 {
658 dst[slen++] = bracket;
659 dst[slen] = '\0';
660 }
661 else
662 {
663 /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
664 then translate the device and recurse. */
665 if (dst[slen - 1] == ':'
666 && dst[slen - 2] != ':' /* skip decnet nodes */
667 && strcmp (src + slen, "[000000]") == 0)
668 {
669 dst[slen - 1] = '\0';
670 if ((ptr = egetenv (dst))
671 && (rlen = strlen (ptr) - 1) > 0
672 && (ptr[rlen] == ']' || ptr[rlen] == '>')
673 && ptr[rlen - 1] == '.')
674 {
675 char * buf = (char *) alloca (strlen (ptr) + 1);
676 strcpy (buf, ptr);
677 buf[rlen - 1] = ']';
678 buf[rlen] = '\0';
679 return directory_file_name (buf, dst);
680 }
681 else
682 dst[slen - 1] = ':';
683 }
684 strcat (dst, "[000000]");
685 slen += 8;
686 }
687 rptr++;
688 rlen = strlen (rptr) - 1;
689 strncat (dst, rptr, rlen);
690 dst[slen + rlen] = '\0';
691 strcat (dst, ".DIR.1");
692 return 1;
693 }
694 #endif /* VMS */
695 /* Process as Unix format: just remove any final slash.
696 But leave "/" unchanged; do not change it to "". */
697 strcpy (dst, src);
698 #ifdef APOLLO
699 /* Handle // as root for apollo's. */
700 if ((slen > 2 && dst[slen - 1] == '/')
701 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/'))
702 dst[slen - 1] = 0;
703 #else
704 if (slen > 1
705 && IS_DIRECTORY_SEP (dst[slen - 1])
706 #ifdef DOS_NT
707 && !IS_ANY_SEP (dst[slen - 2])
708 #endif
709 )
710 dst[slen - 1] = 0;
711 #endif
712 #ifdef DOS_NT
713 CORRECT_DIR_SEPS (dst);
714 #endif
715 return 1;
716 }
717
718 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
719 1, 1, 0,
720 "Returns the file name of the directory named DIRECTORY.\n\
721 This is the name of the file that holds the data for the directory DIRECTORY.\n\
722 This operation exists because a directory is also a file, but its name as\n\
723 a directory is different from its name as a file.\n\
724 In Unix-syntax, this function just removes the final slash.\n\
725 On VMS, given a VMS-syntax directory name such as \"[X.Y]\",\n\
726 it returns a file name such as \"[X]Y.DIR.1\".")
727 (directory)
728 Lisp_Object directory;
729 {
730 char *buf;
731 Lisp_Object handler;
732
733 CHECK_STRING (directory, 0);
734
735 if (NILP (directory))
736 return Qnil;
737
738 /* If the file name has special constructs in it,
739 call the corresponding file handler. */
740 handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
741 if (!NILP (handler))
742 return call2 (handler, Qdirectory_file_name, directory);
743
744 #ifdef VMS
745 /* 20 extra chars is insufficient for VMS, since we might perform a
746 logical name translation. an equivalence string can be up to 255
747 chars long, so grab that much extra space... - sss */
748 buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
749 #else
750 buf = (char *) alloca (XSTRING (directory)->size + 20);
751 #endif
752 directory_file_name (XSTRING (directory)->data, buf);
753 return build_string (buf);
754 }
755
756 DEFUN ("make-temp-name", Fmake_temp_name, Smake_temp_name, 1, 1, 0,
757 "Generate temporary file name (string) starting with PREFIX (a string).\n\
758 The Emacs process number forms part of the result,\n\
759 so there is no danger of generating a name being used by another process.")
760 (prefix)
761 Lisp_Object prefix;
762 {
763 Lisp_Object val;
764 #ifdef MSDOS
765 /* Don't use too many characters of the restricted 8+3 DOS
766 filename space. */
767 val = concat2 (prefix, build_string ("a.XXX"));
768 #else
769 val = concat2 (prefix, build_string ("XXXXXX"));
770 #endif
771 mktemp (XSTRING (val)->data);
772 #ifdef DOS_NT
773 CORRECT_DIR_SEPS (XSTRING (val)->data);
774 #endif
775 return val;
776 }
777 \f
778 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
779 "Convert filename NAME to absolute, and canonicalize it.\n\
780 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\
781 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\
782 the current buffer's value of default-directory is used.\n\
783 File name components that are `.' are removed, and \n\
784 so are file name components followed by `..', along with the `..' itself;\n\
785 note that these simplifications are done without checking the resulting\n\
786 file names in the file system.\n\
787 An initial `~/' expands to your home directory.\n\
788 An initial `~USER/' expands to USER's home directory.\n\
789 See also the function `substitute-in-file-name'.")
790 (name, default_directory)
791 Lisp_Object name, default_directory;
792 {
793 unsigned char *nm;
794
795 register unsigned char *newdir, *p, *o;
796 int tlen;
797 unsigned char *target;
798 struct passwd *pw;
799 #ifdef VMS
800 unsigned char * colon = 0;
801 unsigned char * close = 0;
802 unsigned char * slash = 0;
803 unsigned char * brack = 0;
804 int lbrack = 0, rbrack = 0;
805 int dots = 0;
806 #endif /* VMS */
807 #ifdef DOS_NT
808 int drive = 0;
809 int collapse_newdir = 1;
810 #endif /* DOS_NT */
811 int length;
812 Lisp_Object handler;
813
814 CHECK_STRING (name, 0);
815
816 /* If the file name has special constructs in it,
817 call the corresponding file handler. */
818 handler = Ffind_file_name_handler (name, Qexpand_file_name);
819 if (!NILP (handler))
820 return call3 (handler, Qexpand_file_name, name, default_directory);
821
822 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
823 if (NILP (default_directory))
824 default_directory = current_buffer->directory;
825 CHECK_STRING (default_directory, 1);
826
827 if (!NILP (default_directory))
828 {
829 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
830 if (!NILP (handler))
831 return call3 (handler, Qexpand_file_name, name, default_directory);
832 }
833
834 o = XSTRING (default_directory)->data;
835
836 /* Make sure DEFAULT_DIRECTORY is properly expanded.
837 It would be better to do this down below where we actually use
838 default_directory. Unfortunately, calling Fexpand_file_name recursively
839 could invoke GC, and the strings might be relocated. This would
840 be annoying because we have pointers into strings lying around
841 that would need adjusting, and people would add new pointers to
842 the code and forget to adjust them, resulting in intermittent bugs.
843 Putting this call here avoids all that crud.
844
845 The EQ test avoids infinite recursion. */
846 if (! NILP (default_directory) && !EQ (default_directory, name)
847 /* Save time in some common cases - as long as default_directory
848 is not relative, it can be canonicalized with name below (if it
849 is needed at all) without requiring it to be expanded now. */
850 #ifdef DOS_NT
851 /* Detect MSDOS file names with drive specifiers. */
852 && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
853 #ifdef WINDOWSNT
854 /* Detect Windows file names in UNC format. */
855 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
856 #endif
857 #else /* not DOS_NT */
858 /* Detect Unix absolute file names (/... alone is not absolute on
859 DOS or Windows). */
860 && ! (IS_DIRECTORY_SEP (o[0]))
861 #endif /* not DOS_NT */
862 )
863 {
864 struct gcpro gcpro1;
865
866 GCPRO1 (name);
867 default_directory = Fexpand_file_name (default_directory, Qnil);
868 UNGCPRO;
869 }
870
871 #ifdef VMS
872 /* Filenames on VMS are always upper case. */
873 name = Fupcase (name);
874 #endif
875 #ifdef FILE_SYSTEM_CASE
876 name = FILE_SYSTEM_CASE (name);
877 #endif
878
879 nm = XSTRING (name)->data;
880
881 #ifdef DOS_NT
882 /* We will force directory separators to be either all \ or /, so make
883 a local copy to modify, even if there ends up being no change. */
884 nm = strcpy (alloca (strlen (nm) + 1), nm);
885
886 /* Find and remove drive specifier if present; this makes nm absolute
887 even if the rest of the name appears to be relative. */
888 {
889 unsigned char *colon = rindex (nm, ':');
890
891 if (colon)
892 /* Only recognize colon as part of drive specifier if there is a
893 single alphabetic character preceeding the colon (and if the
894 character before the drive letter, if present, is a directory
895 separator); this is to support the remote system syntax used by
896 ange-ftp, and the "po:username" syntax for POP mailboxes. */
897 look_again:
898 if (nm == colon)
899 nm++;
900 else if (IS_DRIVE (colon[-1])
901 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
902 {
903 drive = colon[-1];
904 nm = colon + 1;
905 }
906 else
907 {
908 while (--colon >= nm)
909 if (colon[0] == ':')
910 goto look_again;
911 }
912 }
913 #endif /* DOS_NT */
914
915 #ifdef WINDOWSNT
916 /* Discard any previous drive specifier if nm is now in UNC format. */
917 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
918 {
919 drive = 0;
920 }
921 #endif
922
923 /* If nm is absolute, look for /./ or /../ sequences; if none are
924 found, we can probably return right away. We will avoid allocating
925 a new string if name is already fully expanded. */
926 if (
927 IS_DIRECTORY_SEP (nm[0])
928 #ifdef MSDOS
929 && drive
930 #endif
931 #ifdef WINDOWSNT
932 && (drive || IS_DIRECTORY_SEP (nm[1]))
933 #endif
934 #ifdef VMS
935 || index (nm, ':')
936 #endif /* VMS */
937 )
938 {
939 /* If it turns out that the filename we want to return is just a
940 suffix of FILENAME, we don't need to go through and edit
941 things; we just need to construct a new string using data
942 starting at the middle of FILENAME. If we set lose to a
943 non-zero value, that means we've discovered that we can't do
944 that cool trick. */
945 int lose = 0;
946
947 p = nm;
948 while (*p)
949 {
950 /* Since we know the name is absolute, we can assume that each
951 element starts with a "/". */
952
953 /* "." and ".." are hairy. */
954 if (IS_DIRECTORY_SEP (p[0])
955 && p[1] == '.'
956 && (IS_DIRECTORY_SEP (p[2])
957 || p[2] == 0
958 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
959 || p[3] == 0))))
960 lose = 1;
961 #ifdef VMS
962 if (p[0] == '\\')
963 lose = 1;
964 if (p[0] == '/') {
965 /* if dev:[dir]/, move nm to / */
966 if (!slash && p > nm && (brack || colon)) {
967 nm = (brack ? brack + 1 : colon + 1);
968 lbrack = rbrack = 0;
969 brack = 0;
970 colon = 0;
971 }
972 slash = p;
973 }
974 if (p[0] == '-')
975 #ifndef VMS4_4
976 /* VMS pre V4.4,convert '-'s in filenames. */
977 if (lbrack == rbrack)
978 {
979 if (dots < 2) /* this is to allow negative version numbers */
980 p[0] = '_';
981 }
982 else
983 #endif /* VMS4_4 */
984 if (lbrack > rbrack &&
985 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
986 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
987 lose = 1;
988 #ifndef VMS4_4
989 else
990 p[0] = '_';
991 #endif /* VMS4_4 */
992 /* count open brackets, reset close bracket pointer */
993 if (p[0] == '[' || p[0] == '<')
994 lbrack++, brack = 0;
995 /* count close brackets, set close bracket pointer */
996 if (p[0] == ']' || p[0] == '>')
997 rbrack++, brack = p;
998 /* detect ][ or >< */
999 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1000 lose = 1;
1001 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1002 nm = p + 1, lose = 1;
1003 if (p[0] == ':' && (colon || slash))
1004 /* if dev1:[dir]dev2:, move nm to dev2: */
1005 if (brack)
1006 {
1007 nm = brack + 1;
1008 brack = 0;
1009 }
1010 /* if /name/dev:, move nm to dev: */
1011 else if (slash)
1012 nm = slash + 1;
1013 /* if node::dev:, move colon following dev */
1014 else if (colon && colon[-1] == ':')
1015 colon = p;
1016 /* if dev1:dev2:, move nm to dev2: */
1017 else if (colon && colon[-1] != ':')
1018 {
1019 nm = colon + 1;
1020 colon = 0;
1021 }
1022 if (p[0] == ':' && !colon)
1023 {
1024 if (p[1] == ':')
1025 p++;
1026 colon = p;
1027 }
1028 if (lbrack == rbrack)
1029 if (p[0] == ';')
1030 dots = 2;
1031 else if (p[0] == '.')
1032 dots++;
1033 #endif /* VMS */
1034 p++;
1035 }
1036 if (!lose)
1037 {
1038 #ifdef VMS
1039 if (index (nm, '/'))
1040 return build_string (sys_translate_unix (nm));
1041 #endif /* VMS */
1042 #ifdef DOS_NT
1043 /* Make sure directories are all separated with / or \ as
1044 desired, but avoid allocation of a new string when not
1045 required. */
1046 CORRECT_DIR_SEPS (nm);
1047 #ifdef WINDOWSNT
1048 if (IS_DIRECTORY_SEP (nm[1]))
1049 {
1050 if (strcmp (nm, XSTRING (name)->data) != 0)
1051 name = build_string (nm);
1052 }
1053 else
1054 #endif
1055 /* drive must be set, so this is okay */
1056 if (strcmp (nm - 2, XSTRING (name)->data) != 0)
1057 {
1058 name = make_string (nm - 2, p - nm + 2);
1059 XSTRING (name)->data[0] = DRIVE_LETTER (drive);
1060 XSTRING (name)->data[1] = ':';
1061 }
1062 return name;
1063 #else /* not DOS_NT */
1064 if (nm == XSTRING (name)->data)
1065 return name;
1066 return build_string (nm);
1067 #endif /* not DOS_NT */
1068 }
1069 }
1070
1071 /* At this point, nm might or might not be an absolute file name. We
1072 need to expand ~ or ~user if present, otherwise prefix nm with
1073 default_directory if nm is not absolute, and finally collapse /./
1074 and /foo/../ sequences.
1075
1076 We set newdir to be the appropriate prefix if one is needed:
1077 - the relevant user directory if nm starts with ~ or ~user
1078 - the specified drive's working dir (DOS/NT only) if nm does not
1079 start with /
1080 - the value of default_directory.
1081
1082 Note that these prefixes are not guaranteed to be absolute (except
1083 for the working dir of a drive). Therefore, to ensure we always
1084 return an absolute name, if the final prefix is not absolute we
1085 append it to the current working directory. */
1086
1087 newdir = 0;
1088
1089 if (nm[0] == '~') /* prefix ~ */
1090 {
1091 if (IS_DIRECTORY_SEP (nm[1])
1092 #ifdef VMS
1093 || nm[1] == ':'
1094 #endif /* VMS */
1095 || nm[1] == 0) /* ~ by itself */
1096 {
1097 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1098 newdir = (unsigned char *) "";
1099 nm++;
1100 #ifdef DOS_NT
1101 collapse_newdir = 0;
1102 #endif
1103 #ifdef VMS
1104 nm++; /* Don't leave the slash in nm. */
1105 #endif /* VMS */
1106 }
1107 else /* ~user/filename */
1108 {
1109 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)
1110 #ifdef VMS
1111 && *p != ':'
1112 #endif /* VMS */
1113 ); p++);
1114 o = (unsigned char *) alloca (p - nm + 1);
1115 bcopy ((char *) nm, o, p - nm);
1116 o [p - nm] = 0;
1117
1118 pw = (struct passwd *) getpwnam (o + 1);
1119 if (pw)
1120 {
1121 newdir = (unsigned char *) pw -> pw_dir;
1122 #ifdef VMS
1123 nm = p + 1; /* skip the terminator */
1124 #else
1125 nm = p;
1126 #ifdef DOS_NT
1127 collapse_newdir = 0;
1128 #endif
1129 #endif /* VMS */
1130 }
1131
1132 /* If we don't find a user of that name, leave the name
1133 unchanged; don't move nm forward to p. */
1134 }
1135 }
1136
1137 #ifdef DOS_NT
1138 /* On DOS and Windows, nm is absolute if a drive name was specified;
1139 use the drive's current directory as the prefix if needed. */
1140 if (!newdir && drive)
1141 {
1142 /* Get default directory if needed to make nm absolute. */
1143 if (!IS_DIRECTORY_SEP (nm[0]))
1144 {
1145 newdir = alloca (MAXPATHLEN + 1);
1146 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1147 newdir = NULL;
1148 }
1149 if (!newdir)
1150 {
1151 /* Either nm starts with /, or drive isn't mounted. */
1152 newdir = alloca (4);
1153 newdir[0] = DRIVE_LETTER (drive);
1154 newdir[1] = ':';
1155 newdir[2] = '/';
1156 newdir[3] = 0;
1157 }
1158 }
1159 #endif /* DOS_NT */
1160
1161 /* Finally, if no prefix has been specified and nm is not absolute,
1162 then it must be expanded relative to default_directory. */
1163
1164 if (1
1165 #ifndef DOS_NT
1166 /* /... alone is not absolute on DOS and Windows. */
1167 && !IS_DIRECTORY_SEP (nm[0])
1168 #endif
1169 #ifdef WINDOWSNT
1170 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1171 #endif
1172 #ifdef VMS
1173 && !index (nm, ':')
1174 #endif
1175 && !newdir)
1176 {
1177 newdir = XSTRING (default_directory)->data;
1178 }
1179
1180 #ifdef DOS_NT
1181 if (newdir)
1182 {
1183 /* First ensure newdir is an absolute name. */
1184 if (
1185 /* Detect MSDOS file names with drive specifiers. */
1186 ! (IS_DRIVE (newdir[0])
1187 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
1188 #ifdef WINDOWSNT
1189 /* Detect Windows file names in UNC format. */
1190 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1191 #endif
1192 )
1193 {
1194 /* Effectively, let newdir be (expand-file-name newdir cwd).
1195 Because of the admonition against calling expand-file-name
1196 when we have pointers into lisp strings, we accomplish this
1197 indirectly by prepending newdir to nm if necessary, and using
1198 cwd (or the wd of newdir's drive) as the new newdir. */
1199
1200 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1201 {
1202 drive = newdir[0];
1203 newdir += 2;
1204 }
1205 if (!IS_DIRECTORY_SEP (nm[0]))
1206 {
1207 char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
1208 file_name_as_directory (tmp, newdir);
1209 strcat (tmp, nm);
1210 nm = tmp;
1211 }
1212 newdir = alloca (MAXPATHLEN + 1);
1213 if (drive)
1214 {
1215 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1216 newdir = "/";
1217 }
1218 else
1219 getwd (newdir);
1220 }
1221
1222 /* Strip off drive name from prefix, if present. */
1223 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1224 {
1225 drive = newdir[0];
1226 newdir += 2;
1227 }
1228
1229 /* Keep only a prefix from newdir if nm starts with slash
1230 (//server/share for UNC, nothing otherwise). */
1231 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir)
1232 {
1233 #ifdef WINDOWSNT
1234 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1235 {
1236 newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
1237 p = newdir + 2;
1238 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1239 p++;
1240 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1241 *p = 0;
1242 }
1243 else
1244 #endif
1245 newdir = "";
1246 }
1247 }
1248 #endif /* DOS_NT */
1249
1250 if (newdir)
1251 {
1252 /* Get rid of any slash at the end of newdir, unless newdir is
1253 just // (an incomplete UNC name). */
1254 length = strlen (newdir);
1255 if (length > 0 && IS_DIRECTORY_SEP (newdir[length - 1])
1256 #ifdef WINDOWSNT
1257 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1258 #endif
1259 )
1260 {
1261 unsigned char *temp = (unsigned char *) alloca (length);
1262 bcopy (newdir, temp, length - 1);
1263 temp[length - 1] = 0;
1264 newdir = temp;
1265 }
1266 tlen = length + 1;
1267 }
1268 else
1269 tlen = 0;
1270
1271 /* Now concatenate the directory and name to new space in the stack frame */
1272 tlen += strlen (nm) + 1;
1273 #ifdef DOS_NT
1274 /* Add reserved space for drive name. (The Microsoft x86 compiler
1275 produces incorrect code if the following two lines are combined.) */
1276 target = (unsigned char *) alloca (tlen + 2);
1277 target += 2;
1278 #else /* not DOS_NT */
1279 target = (unsigned char *) alloca (tlen);
1280 #endif /* not DOS_NT */
1281 *target = 0;
1282
1283 if (newdir)
1284 {
1285 #ifndef VMS
1286 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
1287 strcpy (target, newdir);
1288 else
1289 #endif
1290 file_name_as_directory (target, newdir);
1291 }
1292
1293 strcat (target, nm);
1294 #ifdef VMS
1295 if (index (target, '/'))
1296 strcpy (target, sys_translate_unix (target));
1297 #endif /* VMS */
1298
1299 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
1300
1301 /* Now canonicalize by removing /. and /foo/.. if they appear. */
1302
1303 p = target;
1304 o = target;
1305
1306 while (*p)
1307 {
1308 #ifdef VMS
1309 if (*p != ']' && *p != '>' && *p != '-')
1310 {
1311 if (*p == '\\')
1312 p++;
1313 *o++ = *p++;
1314 }
1315 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1316 /* brackets are offset from each other by 2 */
1317 {
1318 p += 2;
1319 if (*p != '.' && *p != '-' && o[-1] != '.')
1320 /* convert [foo][bar] to [bar] */
1321 while (o[-1] != '[' && o[-1] != '<')
1322 o--;
1323 else if (*p == '-' && *o != '.')
1324 *--p = '.';
1325 }
1326 else if (p[0] == '-' && o[-1] == '.' &&
1327 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1328 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1329 {
1330 do
1331 o--;
1332 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1333 if (p[1] == '.') /* foo.-.bar ==> bar. */
1334 p += 2;
1335 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1336 p++, o--;
1337 /* else [foo.-] ==> [-] */
1338 }
1339 else
1340 {
1341 #ifndef VMS4_4
1342 if (*p == '-' &&
1343 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1344 p[1] != ']' && p[1] != '>' && p[1] != '.')
1345 *p = '_';
1346 #endif /* VMS4_4 */
1347 *o++ = *p++;
1348 }
1349 #else /* not VMS */
1350 if (!IS_DIRECTORY_SEP (*p))
1351 {
1352 *o++ = *p++;
1353 }
1354 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
1355 #if defined (APOLLO) || defined (WINDOWSNT)
1356 /* // at start of filename is meaningful in Apollo
1357 and WindowsNT systems */
1358 && o != target
1359 #endif /* APOLLO || WINDOWSNT */
1360 )
1361 {
1362 o = target;
1363 p++;
1364 }
1365 else if (IS_DIRECTORY_SEP (p[0])
1366 && p[1] == '.'
1367 && (IS_DIRECTORY_SEP (p[2])
1368 || p[2] == 0))
1369 {
1370 /* If "/." is the entire filename, keep the "/". Otherwise,
1371 just delete the whole "/.". */
1372 if (o == target && p[2] == '\0')
1373 *o++ = *p;
1374 p += 2;
1375 }
1376 else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.'
1377 /* `/../' is the "superroot" on certain file systems. */
1378 && o != target
1379 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
1380 {
1381 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
1382 ;
1383 /* Keep initial / only if this is the whole name. */
1384 if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
1385 ++o;
1386 p += 3;
1387 }
1388 else
1389 {
1390 *o++ = *p++;
1391 }
1392 #endif /* not VMS */
1393 }
1394
1395 #ifdef DOS_NT
1396 /* At last, set drive name. */
1397 #ifdef WINDOWSNT
1398 /* Except for network file name. */
1399 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
1400 #endif /* WINDOWSNT */
1401 {
1402 if (!drive) abort ();
1403 target -= 2;
1404 target[0] = DRIVE_LETTER (drive);
1405 target[1] = ':';
1406 }
1407 CORRECT_DIR_SEPS (target);
1408 #endif /* DOS_NT */
1409
1410 return make_string (target, o - target);
1411 }
1412
1413 #if 0
1414 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
1415 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1416 "Convert FILENAME to absolute, and canonicalize it.\n\
1417 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
1418 (does not start with slash); if DEFAULT is nil or missing,\n\
1419 the current buffer's value of default-directory is used.\n\
1420 Filenames containing `.' or `..' as components are simplified;\n\
1421 initial `~/' expands to your home directory.\n\
1422 See also the function `substitute-in-file-name'.")
1423 (name, defalt)
1424 Lisp_Object name, defalt;
1425 {
1426 unsigned char *nm;
1427
1428 register unsigned char *newdir, *p, *o;
1429 int tlen;
1430 unsigned char *target;
1431 struct passwd *pw;
1432 int lose;
1433 #ifdef VMS
1434 unsigned char * colon = 0;
1435 unsigned char * close = 0;
1436 unsigned char * slash = 0;
1437 unsigned char * brack = 0;
1438 int lbrack = 0, rbrack = 0;
1439 int dots = 0;
1440 #endif /* VMS */
1441
1442 CHECK_STRING (name, 0);
1443
1444 #ifdef VMS
1445 /* Filenames on VMS are always upper case. */
1446 name = Fupcase (name);
1447 #endif
1448
1449 nm = XSTRING (name)->data;
1450
1451 /* If nm is absolute, flush ...// and detect /./ and /../.
1452 If no /./ or /../ we can return right away. */
1453 if (
1454 nm[0] == '/'
1455 #ifdef VMS
1456 || index (nm, ':')
1457 #endif /* VMS */
1458 )
1459 {
1460 p = nm;
1461 lose = 0;
1462 while (*p)
1463 {
1464 if (p[0] == '/' && p[1] == '/'
1465 #ifdef APOLLO
1466 /* // at start of filename is meaningful on Apollo system */
1467 && nm != p
1468 #endif /* APOLLO */
1469 )
1470 nm = p + 1;
1471 if (p[0] == '/' && p[1] == '~')
1472 nm = p + 1, lose = 1;
1473 if (p[0] == '/' && p[1] == '.'
1474 && (p[2] == '/' || p[2] == 0
1475 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
1476 lose = 1;
1477 #ifdef VMS
1478 if (p[0] == '\\')
1479 lose = 1;
1480 if (p[0] == '/') {
1481 /* if dev:[dir]/, move nm to / */
1482 if (!slash && p > nm && (brack || colon)) {
1483 nm = (brack ? brack + 1 : colon + 1);
1484 lbrack = rbrack = 0;
1485 brack = 0;
1486 colon = 0;
1487 }
1488 slash = p;
1489 }
1490 if (p[0] == '-')
1491 #ifndef VMS4_4
1492 /* VMS pre V4.4,convert '-'s in filenames. */
1493 if (lbrack == rbrack)
1494 {
1495 if (dots < 2) /* this is to allow negative version numbers */
1496 p[0] = '_';
1497 }
1498 else
1499 #endif /* VMS4_4 */
1500 if (lbrack > rbrack &&
1501 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
1502 (p[1] == '.' || p[1] == ']' || p[1] == '>')))
1503 lose = 1;
1504 #ifndef VMS4_4
1505 else
1506 p[0] = '_';
1507 #endif /* VMS4_4 */
1508 /* count open brackets, reset close bracket pointer */
1509 if (p[0] == '[' || p[0] == '<')
1510 lbrack++, brack = 0;
1511 /* count close brackets, set close bracket pointer */
1512 if (p[0] == ']' || p[0] == '>')
1513 rbrack++, brack = p;
1514 /* detect ][ or >< */
1515 if ((p[0] == ']' || p[0] == '>') && (p[1] == '[' || p[1] == '<'))
1516 lose = 1;
1517 if ((p[0] == ':' || p[0] == ']' || p[0] == '>') && p[1] == '~')
1518 nm = p + 1, lose = 1;
1519 if (p[0] == ':' && (colon || slash))
1520 /* if dev1:[dir]dev2:, move nm to dev2: */
1521 if (brack)
1522 {
1523 nm = brack + 1;
1524 brack = 0;
1525 }
1526 /* If /name/dev:, move nm to dev: */
1527 else if (slash)
1528 nm = slash + 1;
1529 /* If node::dev:, move colon following dev */
1530 else if (colon && colon[-1] == ':')
1531 colon = p;
1532 /* If dev1:dev2:, move nm to dev2: */
1533 else if (colon && colon[-1] != ':')
1534 {
1535 nm = colon + 1;
1536 colon = 0;
1537 }
1538 if (p[0] == ':' && !colon)
1539 {
1540 if (p[1] == ':')
1541 p++;
1542 colon = p;
1543 }
1544 if (lbrack == rbrack)
1545 if (p[0] == ';')
1546 dots = 2;
1547 else if (p[0] == '.')
1548 dots++;
1549 #endif /* VMS */
1550 p++;
1551 }
1552 if (!lose)
1553 {
1554 #ifdef VMS
1555 if (index (nm, '/'))
1556 return build_string (sys_translate_unix (nm));
1557 #endif /* VMS */
1558 if (nm == XSTRING (name)->data)
1559 return name;
1560 return build_string (nm);
1561 }
1562 }
1563
1564 /* Now determine directory to start with and put it in NEWDIR */
1565
1566 newdir = 0;
1567
1568 if (nm[0] == '~') /* prefix ~ */
1569 if (nm[1] == '/'
1570 #ifdef VMS
1571 || nm[1] == ':'
1572 #endif /* VMS */
1573 || nm[1] == 0)/* ~/filename */
1574 {
1575 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1576 newdir = (unsigned char *) "";
1577 nm++;
1578 #ifdef VMS
1579 nm++; /* Don't leave the slash in nm. */
1580 #endif /* VMS */
1581 }
1582 else /* ~user/filename */
1583 {
1584 /* Get past ~ to user */
1585 unsigned char *user = nm + 1;
1586 /* Find end of name. */
1587 unsigned char *ptr = (unsigned char *) index (user, '/');
1588 int len = ptr ? ptr - user : strlen (user);
1589 #ifdef VMS
1590 unsigned char *ptr1 = index (user, ':');
1591 if (ptr1 != 0 && ptr1 - user < len)
1592 len = ptr1 - user;
1593 #endif /* VMS */
1594 /* Copy the user name into temp storage. */
1595 o = (unsigned char *) alloca (len + 1);
1596 bcopy ((char *) user, o, len);
1597 o[len] = 0;
1598
1599 /* Look up the user name. */
1600 pw = (struct passwd *) getpwnam (o + 1);
1601 if (!pw)
1602 error ("\"%s\" isn't a registered user", o + 1);
1603
1604 newdir = (unsigned char *) pw->pw_dir;
1605
1606 /* Discard the user name from NM. */
1607 nm += len;
1608 }
1609
1610 if (nm[0] != '/'
1611 #ifdef VMS
1612 && !index (nm, ':')
1613 #endif /* not VMS */
1614 && !newdir)
1615 {
1616 if (NILP (defalt))
1617 defalt = current_buffer->directory;
1618 CHECK_STRING (defalt, 1);
1619 newdir = XSTRING (defalt)->data;
1620 }
1621
1622 /* Now concatenate the directory and name to new space in the stack frame */
1623
1624 tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
1625 target = (unsigned char *) alloca (tlen);
1626 *target = 0;
1627
1628 if (newdir)
1629 {
1630 #ifndef VMS
1631 if (nm[0] == 0 || nm[0] == '/')
1632 strcpy (target, newdir);
1633 else
1634 #endif
1635 file_name_as_directory (target, newdir);
1636 }
1637
1638 strcat (target, nm);
1639 #ifdef VMS
1640 if (index (target, '/'))
1641 strcpy (target, sys_translate_unix (target));
1642 #endif /* VMS */
1643
1644 /* Now canonicalize by removing /. and /foo/.. if they appear */
1645
1646 p = target;
1647 o = target;
1648
1649 while (*p)
1650 {
1651 #ifdef VMS
1652 if (*p != ']' && *p != '>' && *p != '-')
1653 {
1654 if (*p == '\\')
1655 p++;
1656 *o++ = *p++;
1657 }
1658 else if ((p[0] == ']' || p[0] == '>') && p[0] == p[1] + 2)
1659 /* brackets are offset from each other by 2 */
1660 {
1661 p += 2;
1662 if (*p != '.' && *p != '-' && o[-1] != '.')
1663 /* convert [foo][bar] to [bar] */
1664 while (o[-1] != '[' && o[-1] != '<')
1665 o--;
1666 else if (*p == '-' && *o != '.')
1667 *--p = '.';
1668 }
1669 else if (p[0] == '-' && o[-1] == '.' &&
1670 (p[1] == '.' || p[1] == ']' || p[1] == '>'))
1671 /* flush .foo.- ; leave - if stopped by '[' or '<' */
1672 {
1673 do
1674 o--;
1675 while (o[-1] != '.' && o[-1] != '[' && o[-1] != '<');
1676 if (p[1] == '.') /* foo.-.bar ==> bar. */
1677 p += 2;
1678 else if (o[-1] == '.') /* '.foo.-]' ==> ']' */
1679 p++, o--;
1680 /* else [foo.-] ==> [-] */
1681 }
1682 else
1683 {
1684 #ifndef VMS4_4
1685 if (*p == '-' &&
1686 o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
1687 p[1] != ']' && p[1] != '>' && p[1] != '.')
1688 *p = '_';
1689 #endif /* VMS4_4 */
1690 *o++ = *p++;
1691 }
1692 #else /* not VMS */
1693 if (*p != '/')
1694 {
1695 *o++ = *p++;
1696 }
1697 else if (!strncmp (p, "//", 2)
1698 #ifdef APOLLO
1699 /* // at start of filename is meaningful in Apollo system */
1700 && o != target
1701 #endif /* APOLLO */
1702 )
1703 {
1704 o = target;
1705 p++;
1706 }
1707 else if (p[0] == '/' && p[1] == '.' &&
1708 (p[2] == '/' || p[2] == 0))
1709 p += 2;
1710 else if (!strncmp (p, "/..", 3)
1711 /* `/../' is the "superroot" on certain file systems. */
1712 && o != target
1713 && (p[3] == '/' || p[3] == 0))
1714 {
1715 while (o != target && *--o != '/')
1716 ;
1717 #ifdef APOLLO
1718 if (o == target + 1 && o[-1] == '/' && o[0] == '/')
1719 ++o;
1720 else
1721 #endif /* APOLLO */
1722 if (o == target && *o == '/')
1723 ++o;
1724 p += 3;
1725 }
1726 else
1727 {
1728 *o++ = *p++;
1729 }
1730 #endif /* not VMS */
1731 }
1732
1733 return make_string (target, o - target);
1734 }
1735 #endif
1736 \f
1737 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
1738 Ssubstitute_in_file_name, 1, 1, 0,
1739 "Substitute environment variables referred to in FILENAME.\n\
1740 `$FOO' where FOO is an environment variable name means to substitute\n\
1741 the value of that variable. The variable name should be terminated\n\
1742 with a character not a letter, digit or underscore; otherwise, enclose\n\
1743 the entire variable name in braces.\n\
1744 If `/~' appears, all of FILENAME through that `/' is discarded.\n\n\
1745 On VMS, `$' substitution is not done; this function does little and only\n\
1746 duplicates what `expand-file-name' does.")
1747 (filename)
1748 Lisp_Object filename;
1749 {
1750 unsigned char *nm;
1751
1752 register unsigned char *s, *p, *o, *x, *endp;
1753 unsigned char *target;
1754 int total = 0;
1755 int substituted = 0;
1756 unsigned char *xnm;
1757 Lisp_Object handler;
1758
1759 CHECK_STRING (filename, 0);
1760
1761 /* If the file name has special constructs in it,
1762 call the corresponding file handler. */
1763 handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
1764 if (!NILP (handler))
1765 return call2 (handler, Qsubstitute_in_file_name, filename);
1766
1767 nm = XSTRING (filename)->data;
1768 #ifdef DOS_NT
1769 nm = strcpy (alloca (strlen (nm) + 1), nm);
1770 CORRECT_DIR_SEPS (nm);
1771 substituted = (strcmp (nm, XSTRING (filename)->data) != 0);
1772 #endif
1773 endp = nm + XSTRING (filename)->size;
1774
1775 /* If /~ or // appears, discard everything through first slash. */
1776
1777 for (p = nm; p != endp; p++)
1778 {
1779 if ((p[0] == '~'
1780 #if defined (APOLLO) || defined (WINDOWSNT)
1781 /* // at start of file name is meaningful in Apollo and
1782 WindowsNT systems */
1783 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
1784 #else /* not (APOLLO || WINDOWSNT) */
1785 || IS_DIRECTORY_SEP (p[0])
1786 #endif /* not (APOLLO || WINDOWSNT) */
1787 )
1788 && p != nm
1789 && (0
1790 #ifdef VMS
1791 || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
1792 #endif /* VMS */
1793 || IS_DIRECTORY_SEP (p[-1])))
1794 {
1795 nm = p;
1796 substituted = 1;
1797 }
1798 #ifdef DOS_NT
1799 /* see comment in expand-file-name about drive specifiers */
1800 else if (IS_DRIVE (p[0]) && p[1] == ':'
1801 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1802 {
1803 nm = p;
1804 substituted = 1;
1805 }
1806 #endif /* DOS_NT */
1807 }
1808
1809 #ifdef VMS
1810 return build_string (nm);
1811 #else
1812
1813 /* See if any variables are substituted into the string
1814 and find the total length of their values in `total' */
1815
1816 for (p = nm; p != endp;)
1817 if (*p != '$')
1818 p++;
1819 else
1820 {
1821 p++;
1822 if (p == endp)
1823 goto badsubst;
1824 else if (*p == '$')
1825 {
1826 /* "$$" means a single "$" */
1827 p++;
1828 total -= 1;
1829 substituted = 1;
1830 continue;
1831 }
1832 else if (*p == '{')
1833 {
1834 o = ++p;
1835 while (p != endp && *p != '}') p++;
1836 if (*p != '}') goto missingclose;
1837 s = p;
1838 }
1839 else
1840 {
1841 o = p;
1842 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1843 s = p;
1844 }
1845
1846 /* Copy out the variable name */
1847 target = (unsigned char *) alloca (s - o + 1);
1848 strncpy (target, o, s - o);
1849 target[s - o] = 0;
1850 #ifdef DOS_NT
1851 strupr (target); /* $home == $HOME etc. */
1852 #endif /* DOS_NT */
1853
1854 /* Get variable value */
1855 o = (unsigned char *) egetenv (target);
1856 if (!o) goto badvar;
1857 total += strlen (o);
1858 substituted = 1;
1859 }
1860
1861 if (!substituted)
1862 return filename;
1863
1864 /* If substitution required, recopy the string and do it */
1865 /* Make space in stack frame for the new copy */
1866 xnm = (unsigned char *) alloca (XSTRING (filename)->size + total + 1);
1867 x = xnm;
1868
1869 /* Copy the rest of the name through, replacing $ constructs with values */
1870 for (p = nm; *p;)
1871 if (*p != '$')
1872 *x++ = *p++;
1873 else
1874 {
1875 p++;
1876 if (p == endp)
1877 goto badsubst;
1878 else if (*p == '$')
1879 {
1880 *x++ = *p++;
1881 continue;
1882 }
1883 else if (*p == '{')
1884 {
1885 o = ++p;
1886 while (p != endp && *p != '}') p++;
1887 if (*p != '}') goto missingclose;
1888 s = p++;
1889 }
1890 else
1891 {
1892 o = p;
1893 while (p != endp && (isalnum (*p) || *p == '_')) p++;
1894 s = p;
1895 }
1896
1897 /* Copy out the variable name */
1898 target = (unsigned char *) alloca (s - o + 1);
1899 strncpy (target, o, s - o);
1900 target[s - o] = 0;
1901 #ifdef DOS_NT
1902 strupr (target); /* $home == $HOME etc. */
1903 #endif /* DOS_NT */
1904
1905 /* Get variable value */
1906 o = (unsigned char *) egetenv (target);
1907 if (!o)
1908 goto badvar;
1909
1910 strcpy (x, o);
1911 x += strlen (o);
1912 }
1913
1914 *x = 0;
1915
1916 /* If /~ or // appears, discard everything through first slash. */
1917
1918 for (p = xnm; p != x; p++)
1919 if ((p[0] == '~'
1920 #if defined (APOLLO) || defined (WINDOWSNT)
1921 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
1922 #else /* not (APOLLO || WINDOWSNT) */
1923 || IS_DIRECTORY_SEP (p[0])
1924 #endif /* not (APOLLO || WINDOWSNT) */
1925 )
1926 && p != xnm && IS_DIRECTORY_SEP (p[-1]))
1927 xnm = p;
1928 #ifdef DOS_NT
1929 else if (IS_DRIVE (p[0]) && p[1] == ':'
1930 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1931 xnm = p;
1932 #endif
1933
1934 return make_string (xnm, x - xnm);
1935
1936 badsubst:
1937 error ("Bad format environment-variable substitution");
1938 missingclose:
1939 error ("Missing \"}\" in environment-variable substitution");
1940 badvar:
1941 error ("Substituting nonexistent environment variable \"%s\"", target);
1942
1943 /* NOTREACHED */
1944 #endif /* not VMS */
1945 }
1946 \f
1947 /* A slightly faster and more convenient way to get
1948 (directory-file-name (expand-file-name FOO)). */
1949
1950 Lisp_Object
1951 expand_and_dir_to_file (filename, defdir)
1952 Lisp_Object filename, defdir;
1953 {
1954 register Lisp_Object absname;
1955
1956 absname = Fexpand_file_name (filename, defdir);
1957 #ifdef VMS
1958 {
1959 register int c = XSTRING (absname)->data[XSTRING (absname)->size - 1];
1960 if (c == ':' || c == ']' || c == '>')
1961 absname = Fdirectory_file_name (absname);
1962 }
1963 #else
1964 /* Remove final slash, if any (unless this is the root dir).
1965 stat behaves differently depending! */
1966 if (XSTRING (absname)->size > 1
1967 && IS_DIRECTORY_SEP (XSTRING (absname)->data[XSTRING (absname)->size - 1])
1968 && !IS_DEVICE_SEP (XSTRING (absname)->data[XSTRING (absname)->size-2]))
1969 /* We cannot take shortcuts; they might be wrong for magic file names. */
1970 absname = Fdirectory_file_name (absname);
1971 #endif
1972 return absname;
1973 }
1974 \f
1975 /* Signal an error if the file ABSNAME already exists.
1976 If INTERACTIVE is nonzero, ask the user whether to proceed,
1977 and bypass the error if the user says to go ahead.
1978 QUERYSTRING is a name for the action that is being considered
1979 to alter the file.
1980 *STATPTR is used to store the stat information if the file exists.
1981 If the file does not exist, STATPTR->st_mode is set to 0. */
1982
1983 void
1984 barf_or_query_if_file_exists (absname, querystring, interactive, statptr)
1985 Lisp_Object absname;
1986 unsigned char *querystring;
1987 int interactive;
1988 struct stat *statptr;
1989 {
1990 register Lisp_Object tem;
1991 struct stat statbuf;
1992 struct gcpro gcpro1;
1993
1994 /* stat is a good way to tell whether the file exists,
1995 regardless of what access permissions it has. */
1996 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
1997 {
1998 if (! interactive)
1999 Fsignal (Qfile_already_exists,
2000 Fcons (build_string ("File already exists"),
2001 Fcons (absname, Qnil)));
2002 GCPRO1 (absname);
2003 tem = do_yes_or_no_p (format1 ("File %s already exists; %s anyway? ",
2004 XSTRING (absname)->data, querystring));
2005 UNGCPRO;
2006 if (NILP (tem))
2007 Fsignal (Qfile_already_exists,
2008 Fcons (build_string ("File already exists"),
2009 Fcons (absname, Qnil)));
2010 if (statptr)
2011 *statptr = statbuf;
2012 }
2013 else
2014 {
2015 if (statptr)
2016 statptr->st_mode = 0;
2017 }
2018 return;
2019 }
2020
2021 DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
2022 "fCopy file: \nFCopy %s to file: \np\nP",
2023 "Copy FILE to NEWNAME. Both args must be strings.\n\
2024 Signals a `file-already-exists' error if file NEWNAME already exists,\n\
2025 unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
2026 A number as third arg means request confirmation if NEWNAME already exists.\n\
2027 This is what happens in interactive use with M-x.\n\
2028 Fourth arg KEEP-TIME non-nil means give the new file the same\n\
2029 last-modified time as the old one. (This works on only some systems.)\n\
2030 A prefix arg makes KEEP-TIME non-nil.")
2031 (file, newname, ok_if_already_exists, keep_date)
2032 Lisp_Object file, newname, ok_if_already_exists, keep_date;
2033 {
2034 int ifd, ofd, n;
2035 char buf[16 * 1024];
2036 struct stat st, out_st;
2037 Lisp_Object handler;
2038 struct gcpro gcpro1, gcpro2;
2039 int count = specpdl_ptr - specpdl;
2040 int input_file_statable_p;
2041
2042 GCPRO2 (file, newname);
2043 CHECK_STRING (file, 0);
2044 CHECK_STRING (newname, 1);
2045 file = Fexpand_file_name (file, Qnil);
2046 newname = Fexpand_file_name (newname, Qnil);
2047
2048 /* If the input file name has special constructs in it,
2049 call the corresponding file handler. */
2050 handler = Ffind_file_name_handler (file, Qcopy_file);
2051 /* Likewise for output file name. */
2052 if (NILP (handler))
2053 handler = Ffind_file_name_handler (newname, Qcopy_file);
2054 if (!NILP (handler))
2055 RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
2056 ok_if_already_exists, keep_date));
2057
2058 if (NILP (ok_if_already_exists)
2059 || INTEGERP (ok_if_already_exists))
2060 barf_or_query_if_file_exists (newname, "copy to it",
2061 INTEGERP (ok_if_already_exists), &out_st);
2062 else if (stat (XSTRING (newname)->data, &out_st) < 0)
2063 out_st.st_mode = 0;
2064
2065 ifd = open (XSTRING (file)->data, O_RDONLY);
2066 if (ifd < 0)
2067 report_file_error ("Opening input file", Fcons (file, Qnil));
2068
2069 record_unwind_protect (close_file_unwind, make_number (ifd));
2070
2071 /* We can only copy regular files and symbolic links. Other files are not
2072 copyable by us. */
2073 input_file_statable_p = (fstat (ifd, &st) >= 0);
2074
2075 #if !defined (MSDOS) || __DJGPP__ > 1
2076 if (out_st.st_mode != 0
2077 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2078 {
2079 errno = 0;
2080 report_file_error ("Input and output files are the same",
2081 Fcons (file, Fcons (newname, Qnil)));
2082 }
2083 #endif
2084
2085 #if defined (S_ISREG) && defined (S_ISLNK)
2086 if (input_file_statable_p)
2087 {
2088 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
2089 {
2090 #if defined (EISDIR)
2091 /* Get a better looking error message. */
2092 errno = EISDIR;
2093 #endif /* EISDIR */
2094 report_file_error ("Non-regular file", Fcons (file, Qnil));
2095 }
2096 }
2097 #endif /* S_ISREG && S_ISLNK */
2098
2099 #ifdef VMS
2100 /* Create the copy file with the same record format as the input file */
2101 ofd = sys_creat (XSTRING (newname)->data, 0666, ifd);
2102 #else
2103 #ifdef MSDOS
2104 /* System's default file type was set to binary by _fmode in emacs.c. */
2105 ofd = creat (XSTRING (newname)->data, S_IREAD | S_IWRITE);
2106 #else /* not MSDOS */
2107 ofd = creat (XSTRING (newname)->data, 0666);
2108 #endif /* not MSDOS */
2109 #endif /* VMS */
2110 if (ofd < 0)
2111 report_file_error ("Opening output file", Fcons (newname, Qnil));
2112
2113 record_unwind_protect (close_file_unwind, make_number (ofd));
2114
2115 immediate_quit = 1;
2116 QUIT;
2117 while ((n = read (ifd, buf, sizeof buf)) > 0)
2118 if (write (ofd, buf, n) != n)
2119 report_file_error ("I/O error", Fcons (newname, Qnil));
2120 immediate_quit = 0;
2121
2122 /* Closing the output clobbers the file times on some systems. */
2123 if (close (ofd) < 0)
2124 report_file_error ("I/O error", Fcons (newname, Qnil));
2125
2126 if (input_file_statable_p)
2127 {
2128 if (!NILP (keep_date))
2129 {
2130 EMACS_TIME atime, mtime;
2131 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
2132 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
2133 if (set_file_times (XSTRING (newname)->data, atime, mtime))
2134 Fsignal (Qfile_date_error,
2135 Fcons (build_string ("Cannot set file date"),
2136 Fcons (newname, Qnil)));
2137 }
2138 #ifndef MSDOS
2139 chmod (XSTRING (newname)->data, st.st_mode & 07777);
2140 #else /* MSDOS */
2141 #if defined (__DJGPP__) && __DJGPP__ > 1
2142 /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
2143 and if it can't, it tells so. Otherwise, under MSDOS we usually
2144 get only the READ bit, which will make the copied file read-only,
2145 so it's better not to chmod at all. */
2146 if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
2147 chmod (XSTRING (newname)->data, st.st_mode & 07777);
2148 #endif /* DJGPP version 2 or newer */
2149 #endif /* MSDOS */
2150 }
2151
2152 close (ifd);
2153
2154 /* Discard the unwind protects. */
2155 specpdl_ptr = specpdl + count;
2156
2157 UNGCPRO;
2158 return Qnil;
2159 }
2160 \f
2161 DEFUN ("make-directory-internal", Fmake_directory_internal,
2162 Smake_directory_internal, 1, 1, 0,
2163 "Create a new directory named DIRECTORY.")
2164 (directory)
2165 Lisp_Object directory;
2166 {
2167 unsigned char *dir;
2168 Lisp_Object handler;
2169
2170 CHECK_STRING (directory, 0);
2171 directory = Fexpand_file_name (directory, Qnil);
2172
2173 handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
2174 if (!NILP (handler))
2175 return call2 (handler, Qmake_directory_internal, directory);
2176
2177 dir = XSTRING (directory)->data;
2178
2179 #ifdef WINDOWSNT
2180 if (mkdir (dir) != 0)
2181 #else
2182 if (mkdir (dir, 0777) != 0)
2183 #endif
2184 report_file_error ("Creating directory", Flist (1, &directory));
2185
2186 return Qnil;
2187 }
2188
2189 DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
2190 "Delete the directory named DIRECTORY.")
2191 (directory)
2192 Lisp_Object directory;
2193 {
2194 unsigned char *dir;
2195 Lisp_Object handler;
2196
2197 CHECK_STRING (directory, 0);
2198 directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
2199 dir = XSTRING (directory)->data;
2200
2201 handler = Ffind_file_name_handler (directory, Qdelete_directory);
2202 if (!NILP (handler))
2203 return call2 (handler, Qdelete_directory, directory);
2204
2205 if (rmdir (dir) != 0)
2206 report_file_error ("Removing directory", Flist (1, &directory));
2207
2208 return Qnil;
2209 }
2210
2211 DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
2212 "Delete file named FILENAME.\n\
2213 If file has multiple names, it continues to exist with the other names.")
2214 (filename)
2215 Lisp_Object filename;
2216 {
2217 Lisp_Object handler;
2218 CHECK_STRING (filename, 0);
2219 filename = Fexpand_file_name (filename, Qnil);
2220
2221 handler = Ffind_file_name_handler (filename, Qdelete_file);
2222 if (!NILP (handler))
2223 return call2 (handler, Qdelete_file, filename);
2224
2225 if (0 > unlink (XSTRING (filename)->data))
2226 report_file_error ("Removing old name", Flist (1, &filename));
2227 return Qnil;
2228 }
2229
2230 static Lisp_Object
2231 internal_delete_file_1 (ignore)
2232 Lisp_Object ignore;
2233 {
2234 return Qt;
2235 }
2236
2237 /* Delete file FILENAME, returning 1 if successful and 0 if failed. */
2238
2239 int
2240 internal_delete_file (filename)
2241 Lisp_Object filename;
2242 {
2243 return NILP (internal_condition_case_1 (Fdelete_file, filename,
2244 Qt, internal_delete_file_1));
2245 }
2246 \f
2247 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2248 "fRename file: \nFRename %s to file: \np",
2249 "Rename FILE as NEWNAME. Both args strings.\n\
2250 If file has names other than FILE, it continues to have those names.\n\
2251 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2252 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2253 A number as third arg means request confirmation if NEWNAME already exists.\n\
2254 This is what happens in interactive use with M-x.")
2255 (file, newname, ok_if_already_exists)
2256 Lisp_Object file, newname, ok_if_already_exists;
2257 {
2258 #ifdef NO_ARG_ARRAY
2259 Lisp_Object args[2];
2260 #endif
2261 Lisp_Object handler;
2262 struct gcpro gcpro1, gcpro2;
2263
2264 GCPRO2 (file, newname);
2265 CHECK_STRING (file, 0);
2266 CHECK_STRING (newname, 1);
2267 file = Fexpand_file_name (file, Qnil);
2268 newname = Fexpand_file_name (newname, Qnil);
2269
2270 /* If the file name has special constructs in it,
2271 call the corresponding file handler. */
2272 handler = Ffind_file_name_handler (file, Qrename_file);
2273 if (NILP (handler))
2274 handler = Ffind_file_name_handler (newname, Qrename_file);
2275 if (!NILP (handler))
2276 RETURN_UNGCPRO (call4 (handler, Qrename_file,
2277 file, newname, ok_if_already_exists));
2278
2279 if (NILP (ok_if_already_exists)
2280 || INTEGERP (ok_if_already_exists))
2281 barf_or_query_if_file_exists (newname, "rename to it",
2282 INTEGERP (ok_if_already_exists), 0);
2283 #ifndef BSD4_1
2284 if (0 > rename (XSTRING (file)->data, XSTRING (newname)->data))
2285 #else
2286 if (0 > link (XSTRING (file)->data, XSTRING (newname)->data)
2287 || 0 > unlink (XSTRING (file)->data))
2288 #endif
2289 {
2290 if (errno == EXDEV)
2291 {
2292 Fcopy_file (file, newname,
2293 /* We have already prompted if it was an integer,
2294 so don't have copy-file prompt again. */
2295 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
2296 Fdelete_file (file);
2297 }
2298 else
2299 #ifdef NO_ARG_ARRAY
2300 {
2301 args[0] = file;
2302 args[1] = newname;
2303 report_file_error ("Renaming", Flist (2, args));
2304 }
2305 #else
2306 report_file_error ("Renaming", Flist (2, &file));
2307 #endif
2308 }
2309 UNGCPRO;
2310 return Qnil;
2311 }
2312
2313 DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
2314 "fAdd name to file: \nFName to add to %s: \np",
2315 "Give FILE additional name NEWNAME. Both args strings.\n\
2316 Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2317 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2318 A number as third arg means request confirmation if NEWNAME already exists.\n\
2319 This is what happens in interactive use with M-x.")
2320 (file, newname, ok_if_already_exists)
2321 Lisp_Object file, newname, ok_if_already_exists;
2322 {
2323 #ifdef NO_ARG_ARRAY
2324 Lisp_Object args[2];
2325 #endif
2326 Lisp_Object handler;
2327 struct gcpro gcpro1, gcpro2;
2328
2329 GCPRO2 (file, newname);
2330 CHECK_STRING (file, 0);
2331 CHECK_STRING (newname, 1);
2332 file = Fexpand_file_name (file, Qnil);
2333 newname = Fexpand_file_name (newname, Qnil);
2334
2335 /* If the file name has special constructs in it,
2336 call the corresponding file handler. */
2337 handler = Ffind_file_name_handler (file, Qadd_name_to_file);
2338 if (!NILP (handler))
2339 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
2340 newname, ok_if_already_exists));
2341
2342 /* If the new name has special constructs in it,
2343 call the corresponding file handler. */
2344 handler = Ffind_file_name_handler (newname, Qadd_name_to_file);
2345 if (!NILP (handler))
2346 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
2347 newname, ok_if_already_exists));
2348
2349 if (NILP (ok_if_already_exists)
2350 || INTEGERP (ok_if_already_exists))
2351 barf_or_query_if_file_exists (newname, "make it a new name",
2352 INTEGERP (ok_if_already_exists), 0);
2353 #ifdef WINDOWSNT
2354 /* Windows does not support this operation. */
2355 report_file_error ("Adding new name", Flist (2, &file));
2356 #else /* not WINDOWSNT */
2357
2358 unlink (XSTRING (newname)->data);
2359 if (0 > link (XSTRING (file)->data, XSTRING (newname)->data))
2360 {
2361 #ifdef NO_ARG_ARRAY
2362 args[0] = file;
2363 args[1] = newname;
2364 report_file_error ("Adding new name", Flist (2, args));
2365 #else
2366 report_file_error ("Adding new name", Flist (2, &file));
2367 #endif
2368 }
2369 #endif /* not WINDOWSNT */
2370
2371 UNGCPRO;
2372 return Qnil;
2373 }
2374
2375 #ifdef S_IFLNK
2376 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2377 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2378 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
2379 Signals a `file-already-exists' error if a file LINKNAME already exists\n\
2380 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2381 A number as third arg means request confirmation if LINKNAME already exists.\n\
2382 This happens for interactive use with M-x.")
2383 (filename, linkname, ok_if_already_exists)
2384 Lisp_Object filename, linkname, ok_if_already_exists;
2385 {
2386 #ifdef NO_ARG_ARRAY
2387 Lisp_Object args[2];
2388 #endif
2389 Lisp_Object handler;
2390 struct gcpro gcpro1, gcpro2;
2391
2392 GCPRO2 (filename, linkname);
2393 CHECK_STRING (filename, 0);
2394 CHECK_STRING (linkname, 1);
2395 /* If the link target has a ~, we must expand it to get
2396 a truly valid file name. Otherwise, do not expand;
2397 we want to permit links to relative file names. */
2398 if (XSTRING (filename)->data[0] == '~')
2399 filename = Fexpand_file_name (filename, Qnil);
2400 linkname = Fexpand_file_name (linkname, Qnil);
2401
2402 /* If the file name has special constructs in it,
2403 call the corresponding file handler. */
2404 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
2405 if (!NILP (handler))
2406 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2407 linkname, ok_if_already_exists));
2408
2409 /* If the new link name has special constructs in it,
2410 call the corresponding file handler. */
2411 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
2412 if (!NILP (handler))
2413 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2414 linkname, ok_if_already_exists));
2415
2416 if (NILP (ok_if_already_exists)
2417 || INTEGERP (ok_if_already_exists))
2418 barf_or_query_if_file_exists (linkname, "make it a link",
2419 INTEGERP (ok_if_already_exists), 0);
2420 if (0 > symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2421 {
2422 /* If we didn't complain already, silently delete existing file. */
2423 if (errno == EEXIST)
2424 {
2425 unlink (XSTRING (linkname)->data);
2426 if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
2427 {
2428 UNGCPRO;
2429 return Qnil;
2430 }
2431 }
2432
2433 #ifdef NO_ARG_ARRAY
2434 args[0] = filename;
2435 args[1] = linkname;
2436 report_file_error ("Making symbolic link", Flist (2, args));
2437 #else
2438 report_file_error ("Making symbolic link", Flist (2, &filename));
2439 #endif
2440 }
2441 UNGCPRO;
2442 return Qnil;
2443 }
2444 #endif /* S_IFLNK */
2445
2446 #ifdef VMS
2447
2448 DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2449 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
2450 "Define the job-wide logical name NAME to have the value STRING.\n\
2451 If STRING is nil or a null string, the logical name NAME is deleted.")
2452 (name, string)
2453 Lisp_Object name;
2454 Lisp_Object string;
2455 {
2456 CHECK_STRING (name, 0);
2457 if (NILP (string))
2458 delete_logical_name (XSTRING (name)->data);
2459 else
2460 {
2461 CHECK_STRING (string, 1);
2462
2463 if (XSTRING (string)->size == 0)
2464 delete_logical_name (XSTRING (name)->data);
2465 else
2466 define_logical_name (XSTRING (name)->data, XSTRING (string)->data);
2467 }
2468
2469 return string;
2470 }
2471 #endif /* VMS */
2472
2473 #ifdef HPUX_NET
2474
2475 DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2476 "Open a network connection to PATH using LOGIN as the login string.")
2477 (path, login)
2478 Lisp_Object path, login;
2479 {
2480 int netresult;
2481
2482 CHECK_STRING (path, 0);
2483 CHECK_STRING (login, 0);
2484
2485 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2486
2487 if (netresult == -1)
2488 return Qnil;
2489 else
2490 return Qt;
2491 }
2492 #endif /* HPUX_NET */
2493 \f
2494 DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2495 1, 1, 0,
2496 "Return t if file FILENAME specifies an absolute file name.\n\
2497 On Unix, this is a name starting with a `/' or a `~'.")
2498 (filename)
2499 Lisp_Object filename;
2500 {
2501 unsigned char *ptr;
2502
2503 CHECK_STRING (filename, 0);
2504 ptr = XSTRING (filename)->data;
2505 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
2506 #ifdef VMS
2507 /* ??? This criterion is probably wrong for '<'. */
2508 || index (ptr, ':') || index (ptr, '<')
2509 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2510 && ptr[1] != '.')
2511 #endif /* VMS */
2512 #ifdef DOS_NT
2513 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
2514 #endif
2515 )
2516 return Qt;
2517 else
2518 return Qnil;
2519 }
2520 \f
2521 /* Return nonzero if file FILENAME exists and can be executed. */
2522
2523 static int
2524 check_executable (filename)
2525 char *filename;
2526 {
2527 #ifdef DOS_NT
2528 int len = strlen (filename);
2529 char *suffix;
2530 struct stat st;
2531 if (stat (filename, &st) < 0)
2532 return 0;
2533 #if defined (WINDOWSNT) || (defined (MSDOS) && __DJGPP__ > 1)
2534 return ((st.st_mode & S_IEXEC) != 0);
2535 #else
2536 return (S_ISREG (st.st_mode)
2537 && len >= 5
2538 && (stricmp ((suffix = filename + len-4), ".com") == 0
2539 || stricmp (suffix, ".exe") == 0
2540 || stricmp (suffix, ".bat") == 0)
2541 || (st.st_mode & S_IFMT) == S_IFDIR);
2542 #endif /* not WINDOWSNT */
2543 #else /* not DOS_NT */
2544 #ifdef HAVE_EUIDACCESS
2545 return (euidaccess (filename, 1) >= 0);
2546 #else
2547 /* Access isn't quite right because it uses the real uid
2548 and we really want to test with the effective uid.
2549 But Unix doesn't give us a right way to do it. */
2550 return (access (filename, 1) >= 0);
2551 #endif
2552 #endif /* not DOS_NT */
2553 }
2554
2555 /* Return nonzero if file FILENAME exists and can be written. */
2556
2557 static int
2558 check_writable (filename)
2559 char *filename;
2560 {
2561 #ifdef MSDOS
2562 struct stat st;
2563 if (stat (filename, &st) < 0)
2564 return 0;
2565 return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR);
2566 #else /* not MSDOS */
2567 #ifdef HAVE_EUIDACCESS
2568 return (euidaccess (filename, 2) >= 0);
2569 #else
2570 /* Access isn't quite right because it uses the real uid
2571 and we really want to test with the effective uid.
2572 But Unix doesn't give us a right way to do it.
2573 Opening with O_WRONLY could work for an ordinary file,
2574 but would lose for directories. */
2575 return (access (filename, 2) >= 0);
2576 #endif
2577 #endif /* not MSDOS */
2578 }
2579
2580 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2581 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
2582 See also `file-readable-p' and `file-attributes'.")
2583 (filename)
2584 Lisp_Object filename;
2585 {
2586 Lisp_Object absname;
2587 Lisp_Object handler;
2588 struct stat statbuf;
2589
2590 CHECK_STRING (filename, 0);
2591 absname = Fexpand_file_name (filename, Qnil);
2592
2593 /* If the file name has special constructs in it,
2594 call the corresponding file handler. */
2595 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2596 if (!NILP (handler))
2597 return call2 (handler, Qfile_exists_p, absname);
2598
2599 return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
2600 }
2601
2602 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
2603 "Return t if FILENAME can be executed by you.\n\
2604 For a directory, this means you can access files in that directory.")
2605 (filename)
2606 Lisp_Object filename;
2607
2608 {
2609 Lisp_Object absname;
2610 Lisp_Object handler;
2611
2612 CHECK_STRING (filename, 0);
2613 absname = Fexpand_file_name (filename, Qnil);
2614
2615 /* If the file name has special constructs in it,
2616 call the corresponding file handler. */
2617 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
2618 if (!NILP (handler))
2619 return call2 (handler, Qfile_executable_p, absname);
2620
2621 return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
2622 }
2623
2624 DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2625 "Return t if file FILENAME exists and you can read it.\n\
2626 See also `file-exists-p' and `file-attributes'.")
2627 (filename)
2628 Lisp_Object filename;
2629 {
2630 Lisp_Object absname;
2631 Lisp_Object handler;
2632 int desc;
2633 int flags;
2634 struct stat statbuf;
2635
2636 CHECK_STRING (filename, 0);
2637 absname = Fexpand_file_name (filename, Qnil);
2638
2639 /* If the file name has special constructs in it,
2640 call the corresponding file handler. */
2641 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
2642 if (!NILP (handler))
2643 return call2 (handler, Qfile_readable_p, absname);
2644
2645 #ifdef DOS_NT
2646 /* Under MS-DOS and Windows, open does not work for directories. */
2647 if (access (XSTRING (absname)->data, 0) == 0)
2648 return Qt;
2649 return Qnil;
2650 #else /* not DOS_NT */
2651 flags = O_RDONLY;
2652 #if defined (S_ISFIFO) && defined (O_NONBLOCK)
2653 /* Opening a fifo without O_NONBLOCK can wait.
2654 We don't want to wait. But we don't want to mess wth O_NONBLOCK
2655 except in the case of a fifo, on a system which handles it. */
2656 desc = stat (XSTRING (absname)->data, &statbuf);
2657 if (desc < 0)
2658 return Qnil;
2659 if (S_ISFIFO (statbuf.st_mode))
2660 flags |= O_NONBLOCK;
2661 #endif
2662 desc = open (XSTRING (absname)->data, flags);
2663 if (desc < 0)
2664 return Qnil;
2665 close (desc);
2666 return Qt;
2667 #endif /* not DOS_NT */
2668 }
2669
2670 /* Having this before file-symlink-p mysteriously caused it to be forgotten
2671 on the RT/PC. */
2672 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2673 "Return t if file FILENAME can be written or created by you.")
2674 (filename)
2675 Lisp_Object filename;
2676 {
2677 Lisp_Object absname, dir;
2678 Lisp_Object handler;
2679 struct stat statbuf;
2680
2681 CHECK_STRING (filename, 0);
2682 absname = Fexpand_file_name (filename, Qnil);
2683
2684 /* If the file name has special constructs in it,
2685 call the corresponding file handler. */
2686 handler = Ffind_file_name_handler (absname, Qfile_writable_p);
2687 if (!NILP (handler))
2688 return call2 (handler, Qfile_writable_p, absname);
2689
2690 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
2691 return (check_writable (XSTRING (absname)->data)
2692 ? Qt : Qnil);
2693 dir = Ffile_name_directory (absname);
2694 #ifdef VMS
2695 if (!NILP (dir))
2696 dir = Fdirectory_file_name (dir);
2697 #endif /* VMS */
2698 #ifdef MSDOS
2699 if (!NILP (dir))
2700 dir = Fdirectory_file_name (dir);
2701 #endif /* MSDOS */
2702 return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
2703 ? Qt : Qnil);
2704 }
2705 \f
2706 DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
2707 "Access file FILENAME, and get an error if that does not work.\n\
2708 The second argument STRING is used in the error message.\n\
2709 If there is no error, we return nil.")
2710 (filename, string)
2711 Lisp_Object filename, string;
2712 {
2713 Lisp_Object handler;
2714 int fd;
2715
2716 CHECK_STRING (filename, 0);
2717
2718 /* If the file name has special constructs in it,
2719 call the corresponding file handler. */
2720 handler = Ffind_file_name_handler (filename, Qaccess_file);
2721 if (!NILP (handler))
2722 return call3 (handler, Qaccess_file, filename, string);
2723
2724 fd = open (XSTRING (filename)->data, O_RDONLY);
2725 if (fd < 0)
2726 report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
2727 close (fd);
2728
2729 return Qnil;
2730 }
2731 \f
2732 DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2733 "Return non-nil if file FILENAME is the name of a symbolic link.\n\
2734 The value is the name of the file to which it is linked.\n\
2735 Otherwise returns nil.")
2736 (filename)
2737 Lisp_Object filename;
2738 {
2739 #ifdef S_IFLNK
2740 char *buf;
2741 int bufsize;
2742 int valsize;
2743 Lisp_Object val;
2744 Lisp_Object handler;
2745
2746 CHECK_STRING (filename, 0);
2747 filename = Fexpand_file_name (filename, Qnil);
2748
2749 /* If the file name has special constructs in it,
2750 call the corresponding file handler. */
2751 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
2752 if (!NILP (handler))
2753 return call2 (handler, Qfile_symlink_p, filename);
2754
2755 bufsize = 100;
2756 while (1)
2757 {
2758 buf = (char *) xmalloc (bufsize);
2759 bzero (buf, bufsize);
2760 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
2761 if (valsize < bufsize) break;
2762 /* Buffer was not long enough */
2763 xfree (buf);
2764 bufsize *= 2;
2765 }
2766 if (valsize == -1)
2767 {
2768 xfree (buf);
2769 return Qnil;
2770 }
2771 val = make_string (buf, valsize);
2772 xfree (buf);
2773 return val;
2774 #else /* not S_IFLNK */
2775 return Qnil;
2776 #endif /* not S_IFLNK */
2777 }
2778
2779 DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2780 "Return t if file FILENAME is the name of a directory as a file.\n\
2781 A directory name spec may be given instead; then the value is t\n\
2782 if the directory so specified exists and really is a directory.")
2783 (filename)
2784 Lisp_Object filename;
2785 {
2786 register Lisp_Object absname;
2787 struct stat st;
2788 Lisp_Object handler;
2789
2790 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2791
2792 /* If the file name has special constructs in it,
2793 call the corresponding file handler. */
2794 handler = Ffind_file_name_handler (absname, Qfile_directory_p);
2795 if (!NILP (handler))
2796 return call2 (handler, Qfile_directory_p, absname);
2797
2798 if (stat (XSTRING (absname)->data, &st) < 0)
2799 return Qnil;
2800 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2801 }
2802
2803 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
2804 "Return t if file FILENAME is the name of a directory as a file,\n\
2805 and files in that directory can be opened by you. In order to use a\n\
2806 directory as a buffer's current directory, this predicate must return true.\n\
2807 A directory name spec may be given instead; then the value is t\n\
2808 if the directory so specified exists and really is a readable and\n\
2809 searchable directory.")
2810 (filename)
2811 Lisp_Object filename;
2812 {
2813 Lisp_Object handler;
2814 int tem;
2815 struct gcpro gcpro1;
2816
2817 /* If the file name has special constructs in it,
2818 call the corresponding file handler. */
2819 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2820 if (!NILP (handler))
2821 return call2 (handler, Qfile_accessible_directory_p, filename);
2822
2823 /* It's an unlikely combination, but yes we really do need to gcpro:
2824 Suppose that file-accessible-directory-p has no handler, but
2825 file-directory-p does have a handler; this handler causes a GC which
2826 relocates the string in `filename'; and finally file-directory-p
2827 returns non-nil. Then we would end up passing a garbaged string
2828 to file-executable-p. */
2829 GCPRO1 (filename);
2830 tem = (NILP (Ffile_directory_p (filename))
2831 || NILP (Ffile_executable_p (filename)));
2832 UNGCPRO;
2833 return tem ? Qnil : Qt;
2834 }
2835
2836 DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
2837 "Return t if file FILENAME is the name of a regular file.\n\
2838 This is the sort of file that holds an ordinary stream of data bytes.")
2839 (filename)
2840 Lisp_Object filename;
2841 {
2842 register Lisp_Object absname;
2843 struct stat st;
2844 Lisp_Object handler;
2845
2846 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2847
2848 /* If the file name has special constructs in it,
2849 call the corresponding file handler. */
2850 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
2851 if (!NILP (handler))
2852 return call2 (handler, Qfile_regular_p, absname);
2853
2854 if (stat (XSTRING (absname)->data, &st) < 0)
2855 return Qnil;
2856 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
2857 }
2858 \f
2859 DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2860 "Return mode bits of file named FILENAME, as an integer.")
2861 (filename)
2862 Lisp_Object filename;
2863 {
2864 Lisp_Object absname;
2865 struct stat st;
2866 Lisp_Object handler;
2867
2868 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2869
2870 /* If the file name has special constructs in it,
2871 call the corresponding file handler. */
2872 handler = Ffind_file_name_handler (absname, Qfile_modes);
2873 if (!NILP (handler))
2874 return call2 (handler, Qfile_modes, absname);
2875
2876 if (stat (XSTRING (absname)->data, &st) < 0)
2877 return Qnil;
2878 #if defined (MSDOS) && __DJGPP__ < 2
2879 if (check_executable (XSTRING (absname)->data))
2880 st.st_mode |= S_IEXEC;
2881 #endif /* MSDOS && __DJGPP__ < 2 */
2882
2883 return make_number (st.st_mode & 07777);
2884 }
2885
2886 DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
2887 "Set mode bits of file named FILENAME to MODE (an integer).\n\
2888 Only the 12 low bits of MODE are used.")
2889 (filename, mode)
2890 Lisp_Object filename, mode;
2891 {
2892 Lisp_Object absname;
2893 Lisp_Object handler;
2894
2895 absname = Fexpand_file_name (filename, current_buffer->directory);
2896 CHECK_NUMBER (mode, 1);
2897
2898 /* If the file name has special constructs in it,
2899 call the corresponding file handler. */
2900 handler = Ffind_file_name_handler (absname, Qset_file_modes);
2901 if (!NILP (handler))
2902 return call3 (handler, Qset_file_modes, absname, mode);
2903
2904 if (chmod (XSTRING (absname)->data, XINT (mode)) < 0)
2905 report_file_error ("Doing chmod", Fcons (absname, Qnil));
2906
2907 return Qnil;
2908 }
2909
2910 DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
2911 "Set the file permission bits for newly created files.\n\
2912 The argument MODE should be an integer; only the low 9 bits are used.\n\
2913 This setting is inherited by subprocesses.")
2914 (mode)
2915 Lisp_Object mode;
2916 {
2917 CHECK_NUMBER (mode, 0);
2918
2919 umask ((~ XINT (mode)) & 0777);
2920
2921 return Qnil;
2922 }
2923
2924 DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
2925 "Return the default file protection for created files.\n\
2926 The value is an integer.")
2927 ()
2928 {
2929 int realmask;
2930 Lisp_Object value;
2931
2932 realmask = umask (0);
2933 umask (realmask);
2934
2935 XSETINT (value, (~ realmask) & 0777);
2936 return value;
2937 }
2938 \f
2939 #ifdef unix
2940
2941 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
2942 "Tell Unix to finish all pending disk updates.")
2943 ()
2944 {
2945 sync ();
2946 return Qnil;
2947 }
2948
2949 #endif /* unix */
2950
2951 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
2952 "Return t if file FILE1 is newer than file FILE2.\n\
2953 If FILE1 does not exist, the answer is nil;\n\
2954 otherwise, if FILE2 does not exist, the answer is t.")
2955 (file1, file2)
2956 Lisp_Object file1, file2;
2957 {
2958 Lisp_Object absname1, absname2;
2959 struct stat st;
2960 int mtime1;
2961 Lisp_Object handler;
2962 struct gcpro gcpro1, gcpro2;
2963
2964 CHECK_STRING (file1, 0);
2965 CHECK_STRING (file2, 0);
2966
2967 absname1 = Qnil;
2968 GCPRO2 (absname1, file2);
2969 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
2970 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
2971 UNGCPRO;
2972
2973 /* If the file name has special constructs in it,
2974 call the corresponding file handler. */
2975 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
2976 if (NILP (handler))
2977 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
2978 if (!NILP (handler))
2979 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
2980
2981 if (stat (XSTRING (absname1)->data, &st) < 0)
2982 return Qnil;
2983
2984 mtime1 = st.st_mtime;
2985
2986 if (stat (XSTRING (absname2)->data, &st) < 0)
2987 return Qt;
2988
2989 return (mtime1 > st.st_mtime) ? Qt : Qnil;
2990 }
2991 \f
2992 #ifdef DOS_NT
2993 Lisp_Object Qfind_buffer_file_type;
2994 #endif /* DOS_NT */
2995
2996 #ifndef READ_BUF_SIZE
2997 #define READ_BUF_SIZE (64 << 10)
2998 #endif
2999
3000 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
3001 1, 5, 0,
3002 "Insert contents of file FILENAME after point.\n\
3003 Returns list of absolute file name and length of data inserted.\n\
3004 If second argument VISIT is non-nil, the buffer's visited filename\n\
3005 and last save file modtime are set, and it is marked unmodified.\n\
3006 If visiting and the file does not exist, visiting is completed\n\
3007 before the error is signaled.\n\
3008 The optional third and fourth arguments BEG and END\n\
3009 specify what portion of the file to insert.\n\
3010 If VISIT is non-nil, BEG and END must be nil.\n\
3011 \n\
3012 If optional fifth argument REPLACE is non-nil,\n\
3013 it means replace the current buffer contents (in the accessible portion)\n\
3014 with the file contents. This is better than simply deleting and inserting\n\
3015 the whole thing because (1) it preserves some marker positions\n\
3016 and (2) it puts less data in the undo list.\n\
3017 When REPLACE is non-nil, the value is the number of characters actually read,\n\
3018 which is often less than the number of characters to be read.\n\
3019 This does code conversion according to the value of\n\
3020 `coding-system-for-read' or `coding-system-alist', and sets the variable\n\
3021 `last-coding-system-used' to the coding system actually used.")
3022 (filename, visit, beg, end, replace)
3023 Lisp_Object filename, visit, beg, end, replace;
3024 {
3025 struct stat st;
3026 register int fd;
3027 register int inserted = 0;
3028 register int how_much;
3029 register int unprocessed;
3030 int count = specpdl_ptr - specpdl;
3031 struct gcpro gcpro1, gcpro2, gcpro3;
3032 Lisp_Object handler, val, insval;
3033 Lisp_Object p;
3034 int total;
3035 int not_regular = 0;
3036 char read_buf[READ_BUF_SIZE];
3037 struct coding_system coding;
3038 unsigned char buffer[1 << 14];
3039 int replace_handled = 0;
3040
3041 if (current_buffer->base_buffer && ! NILP (visit))
3042 error ("Cannot do file visiting in an indirect buffer");
3043
3044 if (!NILP (current_buffer->read_only))
3045 Fbarf_if_buffer_read_only ();
3046
3047 val = Qnil;
3048 p = Qnil;
3049
3050 GCPRO3 (filename, val, p);
3051
3052 CHECK_STRING (filename, 0);
3053 filename = Fexpand_file_name (filename, Qnil);
3054
3055 /* If the file name has special constructs in it,
3056 call the corresponding file handler. */
3057 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
3058 if (!NILP (handler))
3059 {
3060 val = call6 (handler, Qinsert_file_contents, filename,
3061 visit, beg, end, replace);
3062 goto handled;
3063 }
3064
3065 /* Decide the coding-system of the file. */
3066 {
3067 Lisp_Object val = Vcoding_system_for_read;
3068 if (NILP (current_buffer->enable_multibyte_characters))
3069 val = Qnil;
3070 else if (NILP (val))
3071 {
3072 Lisp_Object args[6], coding_systems;
3073
3074 args[0] = Qinsert_file_contents, args[1] = filename, args[2] = visit,
3075 args[3] = beg, args[4] = end, args[5] = replace;
3076 coding_systems = Ffind_coding_system (6, args);
3077 val = CONSP (coding_systems) ? XCONS (coding_systems)->car : Qnil;
3078 }
3079 setup_coding_system (Fcheck_coding_system (val), &coding);
3080 }
3081
3082 fd = -1;
3083
3084 #ifndef APOLLO
3085 if (stat (XSTRING (filename)->data, &st) < 0)
3086 #else
3087 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0
3088 || fstat (fd, &st) < 0)
3089 #endif /* not APOLLO */
3090 {
3091 if (fd >= 0) close (fd);
3092 badopen:
3093 if (NILP (visit))
3094 report_file_error ("Opening input file", Fcons (filename, Qnil));
3095 st.st_mtime = -1;
3096 how_much = 0;
3097 goto notfound;
3098 }
3099
3100 #ifdef S_IFREG
3101 /* This code will need to be changed in order to work on named
3102 pipes, and it's probably just not worth it. So we should at
3103 least signal an error. */
3104 if (!S_ISREG (st.st_mode))
3105 {
3106 not_regular = 1;
3107
3108 if (! NILP (visit))
3109 goto notfound;
3110
3111 if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
3112 Fsignal (Qfile_error,
3113 Fcons (build_string ("not a regular file"),
3114 Fcons (filename, Qnil)));
3115 }
3116 #endif
3117
3118 if (fd < 0)
3119 if ((fd = open (XSTRING (filename)->data, O_RDONLY)) < 0)
3120 goto badopen;
3121
3122 /* Replacement should preserve point as it preserves markers. */
3123 if (!NILP (replace))
3124 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3125
3126 record_unwind_protect (close_file_unwind, make_number (fd));
3127
3128 /* Supposedly happens on VMS. */
3129 if (! not_regular && st.st_size < 0)
3130 error ("File size is negative");
3131
3132 if (!NILP (beg) || !NILP (end))
3133 if (!NILP (visit))
3134 error ("Attempt to visit less than an entire file");
3135
3136 if (!NILP (beg))
3137 CHECK_NUMBER (beg, 0);
3138 else
3139 XSETFASTINT (beg, 0);
3140
3141 if (!NILP (end))
3142 CHECK_NUMBER (end, 0);
3143 else
3144 {
3145 if (! not_regular)
3146 {
3147 XSETINT (end, st.st_size);
3148 if (XINT (end) != st.st_size)
3149 error ("Maximum buffer size exceeded");
3150 }
3151 }
3152
3153 /* If requested, replace the accessible part of the buffer
3154 with the file contents. Avoid replacing text at the
3155 beginning or end of the buffer that matches the file contents;
3156 that preserves markers pointing to the unchanged parts.
3157
3158 Here we implement this feature in an optimized way
3159 for the case where code conversion is NOT needed.
3160 The following if-statement handles the case of conversion
3161 in a less optimal way.
3162
3163 If the code conversion is "automatic" then we try using this
3164 method and hope for the best.
3165 But if we discover the need for conversion, we give up on this method
3166 and let the following if-statement handle the replace job. */
3167 if (!NILP (replace)
3168 && (! CODING_REQUIRE_CONVERSION (&coding)
3169 || (coding.type == coding_type_undecided
3170 && ! CODING_REQUIRE_EOL_CONVERSION (&coding))
3171 || (coding.eol_type == CODING_EOL_UNDECIDED
3172 && ! CODING_REQUIRE_TEXT_CONVERSION (&coding))))
3173 {
3174 int same_at_start = BEGV;
3175 int same_at_end = ZV;
3176 int overlap;
3177 /* There is still a possibility we will find the need to do code
3178 conversion. If that happens, we set this variable to 1 to
3179 give up on handling REPLACE in the optimized way. */
3180 int giveup_match_end = 0;
3181
3182 if (XINT (beg) != 0)
3183 {
3184 if (lseek (fd, XINT (beg), 0) < 0)
3185 report_file_error ("Setting file position",
3186 Fcons (filename, Qnil));
3187 }
3188
3189 immediate_quit = 1;
3190 QUIT;
3191 /* Count how many chars at the start of the file
3192 match the text at the beginning of the buffer. */
3193 while (1)
3194 {
3195 int nread, bufpos;
3196
3197 nread = read (fd, buffer, sizeof buffer);
3198 if (nread < 0)
3199 error ("IO error reading %s: %s",
3200 XSTRING (filename)->data, strerror (errno));
3201 else if (nread == 0)
3202 break;
3203
3204 if (coding.type == coding_type_undecided)
3205 detect_coding (&coding, buffer, nread);
3206 if (coding.type != coding_type_undecided
3207 && CODING_REQUIRE_TEXT_CONVERSION (&coding))
3208 /* We found that the file should be decoded somehow.
3209 Let's give up here. */
3210 {
3211 giveup_match_end = 1;
3212 break;
3213 }
3214
3215 if (coding.eol_type == CODING_EOL_UNDECIDED)
3216 detect_eol (&coding, buffer, nread);
3217 if (coding.eol_type != CODING_EOL_UNDECIDED
3218 && CODING_REQUIRE_EOL_CONVERSION (&coding))
3219 /* We found that the format of eol should be decoded.
3220 Let's give up here. */
3221 {
3222 giveup_match_end = 1;
3223 break;
3224 }
3225
3226 bufpos = 0;
3227 while (bufpos < nread && same_at_start < ZV
3228 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3229 same_at_start++, bufpos++;
3230 /* If we found a discrepancy, stop the scan.
3231 Otherwise loop around and scan the next bufferful. */
3232 if (bufpos != nread)
3233 break;
3234 }
3235 immediate_quit = 0;
3236 /* If the file matches the buffer completely,
3237 there's no need to replace anything. */
3238 if (same_at_start - BEGV == XINT (end))
3239 {
3240 close (fd);
3241 specpdl_ptr--;
3242 /* Truncate the buffer to the size of the file. */
3243 del_range_1 (same_at_start, same_at_end, 0);
3244 goto handled;
3245 }
3246 immediate_quit = 1;
3247 QUIT;
3248 /* Count how many chars at the end of the file
3249 match the text at the end of the buffer. But, if we have
3250 already found that decoding is necessary, don't waste time. */
3251 while (!giveup_match_end)
3252 {
3253 int total_read, nread, bufpos, curpos, trial;
3254
3255 /* At what file position are we now scanning? */
3256 curpos = XINT (end) - (ZV - same_at_end);
3257 /* If the entire file matches the buffer tail, stop the scan. */
3258 if (curpos == 0)
3259 break;
3260 /* How much can we scan in the next step? */
3261 trial = min (curpos, sizeof buffer);
3262 if (lseek (fd, curpos - trial, 0) < 0)
3263 report_file_error ("Setting file position",
3264 Fcons (filename, Qnil));
3265
3266 total_read = 0;
3267 while (total_read < trial)
3268 {
3269 nread = read (fd, buffer + total_read, trial - total_read);
3270 if (nread <= 0)
3271 error ("IO error reading %s: %s",
3272 XSTRING (filename)->data, strerror (errno));
3273 total_read += nread;
3274 }
3275 /* Scan this bufferful from the end, comparing with
3276 the Emacs buffer. */
3277 bufpos = total_read;
3278 /* Compare with same_at_start to avoid counting some buffer text
3279 as matching both at the file's beginning and at the end. */
3280 while (bufpos > 0 && same_at_end > same_at_start
3281 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3282 same_at_end--, bufpos--;
3283
3284 /* If we found a discrepancy, stop the scan.
3285 Otherwise loop around and scan the preceding bufferful. */
3286 if (bufpos != 0)
3287 {
3288 /* If this discrepancy is because of code conversion,
3289 we cannot use this method; giveup and try the other. */
3290 if (same_at_end > same_at_start
3291 && FETCH_BYTE (same_at_end - 1) >= 0200
3292 && ! NILP (current_buffer->enable_multibyte_characters))
3293 giveup_match_end = 1;
3294 break;
3295 }
3296 }
3297 immediate_quit = 0;
3298
3299 if (! giveup_match_end)
3300 {
3301 /* We win! We can handle REPLACE the optimized way. */
3302
3303 /* Don't try to reuse the same piece of text twice. */
3304 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV);
3305 if (overlap > 0)
3306 same_at_end += overlap;
3307
3308 /* Arrange to read only the nonmatching middle part of the file. */
3309 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV));
3310 XSETFASTINT (end, XINT (end) - (ZV - same_at_end));
3311
3312 del_range_1 (same_at_start, same_at_end, 0);
3313 /* Insert from the file at the proper position. */
3314 SET_PT (same_at_start);
3315
3316 /* If display currently starts at beginning of line,
3317 keep it that way. */
3318 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3319 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3320
3321 replace_handled = 1;
3322 }
3323 }
3324
3325 /* If requested, replace the accessible part of the buffer
3326 with the file contents. Avoid replacing text at the
3327 beginning or end of the buffer that matches the file contents;
3328 that preserves markers pointing to the unchanged parts.
3329
3330 Here we implement this feature for the case where code conversion
3331 is needed, in a simple way that needs a lot of memory.
3332 The preceding if-statement handles the case of no conversion
3333 in a more optimized way. */
3334 if (!NILP (replace) && ! replace_handled)
3335 {
3336 int same_at_start = BEGV;
3337 int same_at_end = ZV;
3338 int overlap;
3339 int bufpos;
3340 /* Make sure that the gap is large enough. */
3341 int bufsize = 2 * st.st_size;
3342 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
3343
3344 /* First read the whole file, performing code conversion into
3345 CONVERSION_BUFFER. */
3346
3347 if (lseek (fd, XINT (beg), 0) < 0)
3348 {
3349 free (conversion_buffer);
3350 report_file_error ("Setting file position",
3351 Fcons (filename, Qnil));
3352 }
3353
3354 total = st.st_size; /* Total bytes in the file. */
3355 how_much = 0; /* Bytes read from file so far. */
3356 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
3357 unprocessed = 0; /* Bytes not processed in previous loop. */
3358
3359 while (how_much < total)
3360 {
3361 /* try is reserved in some compilers (Microsoft C) */
3362 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
3363 char *destination = read_buf + unprocessed;
3364 int this;
3365
3366 /* Allow quitting out of the actual I/O. */
3367 immediate_quit = 1;
3368 QUIT;
3369 this = read (fd, destination, trytry);
3370 immediate_quit = 0;
3371
3372 if (this < 0 || this + unprocessed == 0)
3373 {
3374 how_much = this;
3375 break;
3376 }
3377
3378 how_much += this;
3379
3380 if (CODING_REQUIRE_CONVERSION (&coding))
3381 {
3382 int require, produced, consumed;
3383
3384 this += unprocessed;
3385
3386 /* If we are using more space than estimated,
3387 make CONVERSION_BUFFER bigger. */
3388 require = decoding_buffer_size (&coding, this);
3389 if (inserted + require + 2 * (total - how_much) > bufsize)
3390 {
3391 bufsize = inserted + require + 2 * (total - how_much);
3392 conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
3393 }
3394
3395 /* Convert this batch with results in CONVERSION_BUFFER. */
3396 if (how_much >= total) /* This is the last block. */
3397 coding.last_block = 1;
3398 produced = decode_coding (&coding, read_buf,
3399 conversion_buffer + inserted,
3400 this, bufsize - inserted,
3401 &consumed);
3402
3403 /* Save for next iteration whatever we didn't convert. */
3404 unprocessed = this - consumed;
3405 bcopy (read_buf + consumed, read_buf, unprocessed);
3406 this = produced;
3407 }
3408
3409 inserted += this;
3410 }
3411
3412 /* At this point, INSERTED is how many characters
3413 are present in CONVERSION_BUFFER.
3414 HOW_MUCH should equal TOTAL,
3415 or should be <= 0 if we couldn't read the file. */
3416
3417 if (how_much < 0)
3418 {
3419 free (conversion_buffer);
3420
3421 if (how_much == -1)
3422 error ("IO error reading %s: %s",
3423 XSTRING (filename)->data, strerror (errno));
3424 else if (how_much == -2)
3425 error ("maximum buffer size exceeded");
3426 }
3427
3428 /* Compare the beginning of the converted file
3429 with the buffer text. */
3430
3431 bufpos = 0;
3432 while (bufpos < inserted && same_at_start < same_at_end
3433 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
3434 same_at_start++, bufpos++;
3435
3436 /* If the file matches the buffer completely,
3437 there's no need to replace anything. */
3438
3439 if (bufpos == inserted)
3440 {
3441 free (conversion_buffer);
3442 close (fd);
3443 specpdl_ptr--;
3444 /* Truncate the buffer to the size of the file. */
3445 del_range_1 (same_at_start, same_at_end, 0);
3446 goto handled;
3447 }
3448
3449 /* Scan this bufferful from the end, comparing with
3450 the Emacs buffer. */
3451 bufpos = inserted;
3452
3453 /* Compare with same_at_start to avoid counting some buffer text
3454 as matching both at the file's beginning and at the end. */
3455 while (bufpos > 0 && same_at_end > same_at_start
3456 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
3457 same_at_end--, bufpos--;
3458
3459 /* Don't try to reuse the same piece of text twice. */
3460 overlap = same_at_start - BEGV - (same_at_end + inserted - ZV);
3461 if (overlap > 0)
3462 same_at_end += overlap;
3463
3464 /* If display currently starts at beginning of line,
3465 keep it that way. */
3466 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3467 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3468
3469 /* Replace the chars that we need to replace,
3470 and update INSERTED to equal the number of bytes
3471 we are taking from the file. */
3472 inserted -= (Z - same_at_end) + (same_at_start - BEG);
3473 move_gap (same_at_start);
3474 del_range_1 (same_at_start, same_at_end, 0);
3475 SET_PT (same_at_start);
3476 insert_1 (conversion_buffer + same_at_start - BEG, inserted, 0, 0);
3477
3478 free (conversion_buffer);
3479 close (fd);
3480 specpdl_ptr--;
3481
3482 goto handled;
3483 }
3484
3485 if (! not_regular)
3486 {
3487 register Lisp_Object temp;
3488
3489 total = XINT (end) - XINT (beg);
3490
3491 /* Make sure point-max won't overflow after this insertion. */
3492 XSETINT (temp, total);
3493 if (total != XINT (temp))
3494 error ("Maximum buffer size exceeded");
3495 }
3496 else
3497 /* For a special file, all we can do is guess. */
3498 total = READ_BUF_SIZE;
3499
3500 if (NILP (visit) && total > 0)
3501 prepare_to_modify_buffer (PT, PT);
3502
3503 move_gap (PT);
3504 if (GAP_SIZE < total)
3505 make_gap (total - GAP_SIZE);
3506
3507 if (XINT (beg) != 0 || !NILP (replace))
3508 {
3509 if (lseek (fd, XINT (beg), 0) < 0)
3510 report_file_error ("Setting file position", Fcons (filename, Qnil));
3511 }
3512
3513 /* In the following loop, HOW_MUCH contains the total bytes read so
3514 far. Before exiting the loop, it is set to -1 if I/O error
3515 occurs, set to -2 if the maximum buffer size is exceeded. */
3516 how_much = 0;
3517 /* Total bytes inserted. */
3518 inserted = 0;
3519 /* Bytes not processed in the previous loop because short gap size. */
3520 unprocessed = 0;
3521 while (how_much < total)
3522 {
3523 /* try is reserved in some compilers (Microsoft C) */
3524 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
3525 char *destination = (CODING_REQUIRE_CONVERSION (&coding)
3526 ? read_buf + unprocessed
3527 : (char *) (POS_ADDR (PT + inserted - 1) + 1));
3528 int this;
3529
3530 /* Allow quitting out of the actual I/O. */
3531 immediate_quit = 1;
3532 QUIT;
3533 this = read (fd, destination, trytry);
3534 immediate_quit = 0;
3535
3536 if (this < 0 || this + unprocessed == 0)
3537 {
3538 how_much = this;
3539 break;
3540 }
3541
3542 /* For a regular file, where TOTAL is the real size,
3543 count HOW_MUCH to compare with it.
3544 For a special file, where TOTAL is just a buffer size,
3545 so don't bother counting in HOW_MUCH.
3546 (INSERTED is where we count the number of characters inserted.) */
3547 if (! not_regular)
3548 how_much += this;
3549
3550 if (CODING_REQUIRE_CONVERSION (&coding))
3551 {
3552 int require, produced, consumed;
3553
3554 this += unprocessed;
3555 /* Make sure that the gap is large enough. */
3556 require = decoding_buffer_size (&coding, this);
3557 if (GAP_SIZE < require)
3558 make_gap (require - GAP_SIZE);
3559
3560 if (! not_regular)
3561 {
3562 if (how_much >= total) /* This is the last block. */
3563 coding.last_block = 1;
3564 }
3565 else
3566 {
3567 /* If we encounter EOF, say it is the last block. (The
3568 data this will apply to is the UNPROCESSED characters
3569 carried over from the last batch.) */
3570 if (this == 0)
3571 coding.last_block = 1;
3572 }
3573
3574 produced = decode_coding (&coding, read_buf,
3575 POS_ADDR (PT + inserted - 1) + 1,
3576 this, GAP_SIZE, &consumed);
3577 if (produced > 0)
3578 {
3579 Lisp_Object temp;
3580
3581 XSET (temp, Lisp_Int, Z + produced);
3582 if (Z + produced != XINT (temp))
3583 {
3584 how_much = -2;
3585 break;
3586 }
3587 }
3588 unprocessed = this - consumed;
3589 bcopy (read_buf + consumed, read_buf, unprocessed);
3590 this = produced;
3591 }
3592
3593 GPT += this;
3594 GAP_SIZE -= this;
3595 ZV += this;
3596 Z += this;
3597 if (GAP_SIZE > 0)
3598 /* Put an anchor to ensure multi-byte form ends at gap. */
3599 *GPT_ADDR = 0;
3600 inserted += this;
3601 }
3602
3603 /* We don't have to consider file type of MSDOS because all files
3604 are read as binary and end-of-line format has already been
3605 decoded appropriately. */
3606 #if 0
3607 #ifdef DOS_NT
3608 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
3609 /* Determine file type from name and remove LFs from CR-LFs if the file
3610 is deemed to be a text file. */
3611 {
3612 current_buffer->buffer_file_type
3613 = call1 (Qfind_buffer_file_type, filename);
3614 if (NILP (current_buffer->buffer_file_type))
3615 {
3616 int reduced_size
3617 = inserted - crlf_to_lf (inserted, POS_ADDR (PT - 1) + 1);
3618 ZV -= reduced_size;
3619 Z -= reduced_size;
3620 GPT -= reduced_size;
3621 GAP_SIZE += reduced_size;
3622 inserted -= reduced_size;
3623 }
3624 }
3625 #endif /* DOS_NT */
3626 #endif /* 0 */
3627
3628 if (inserted > 0)
3629 {
3630 record_insert (PT, inserted);
3631
3632 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3633 offset_intervals (current_buffer, PT, inserted);
3634 MODIFF++;
3635 }
3636
3637 close (fd);
3638
3639 /* Discard the unwind protect for closing the file. */
3640 specpdl_ptr--;
3641
3642 if (how_much == -1)
3643 error ("IO error reading %s: %s",
3644 XSTRING (filename)->data, strerror (errno));
3645 else if (how_much == -2)
3646 error ("maximum buffer size exceeded");
3647
3648 notfound:
3649 handled:
3650
3651 if (!NILP (visit))
3652 {
3653 if (!EQ (current_buffer->undo_list, Qt))
3654 current_buffer->undo_list = Qnil;
3655 #ifdef APOLLO
3656 stat (XSTRING (filename)->data, &st);
3657 #endif
3658
3659 if (NILP (handler))
3660 {
3661 current_buffer->modtime = st.st_mtime;
3662 current_buffer->filename = filename;
3663 }
3664
3665 SAVE_MODIFF = MODIFF;
3666 current_buffer->auto_save_modified = MODIFF;
3667 XSETFASTINT (current_buffer->save_length, Z - BEG);
3668 #ifdef CLASH_DETECTION
3669 if (NILP (handler))
3670 {
3671 if (!NILP (current_buffer->file_truename))
3672 unlock_file (current_buffer->file_truename);
3673 unlock_file (filename);
3674 }
3675 #endif /* CLASH_DETECTION */
3676 if (not_regular)
3677 Fsignal (Qfile_error,
3678 Fcons (build_string ("not a regular file"),
3679 Fcons (filename, Qnil)));
3680
3681 /* If visiting nonexistent file, return nil. */
3682 if (current_buffer->modtime == -1)
3683 report_file_error ("Opening input file", Fcons (filename, Qnil));
3684 }
3685
3686 /* Decode file format */
3687 if (inserted > 0)
3688 {
3689 insval = call3 (Qformat_decode,
3690 Qnil, make_number (inserted), visit);
3691 CHECK_NUMBER (insval, 0);
3692 inserted = XFASTINT (insval);
3693 }
3694
3695 /* Call after-change hooks for the inserted text, aside from the case
3696 of normal visiting (not with REPLACE), which is done in a new buffer
3697 "before" the buffer is changed. */
3698 if (inserted > 0 && total > 0
3699 && (NILP (visit) || !NILP (replace)))
3700 signal_after_change (PT, 0, inserted);
3701
3702 if (inserted > 0)
3703 {
3704 p = Vafter_insert_file_functions;
3705 if (!NILP (coding.post_read_conversion))
3706 p = Fcons (coding.post_read_conversion, p);
3707
3708 while (!NILP (p))
3709 {
3710 insval = call1 (Fcar (p), make_number (inserted));
3711 if (!NILP (insval))
3712 {
3713 CHECK_NUMBER (insval, 0);
3714 inserted = XFASTINT (insval);
3715 }
3716 QUIT;
3717 p = Fcdr (p);
3718 }
3719 }
3720
3721 if (NILP (val))
3722 val = Fcons (filename,
3723 Fcons (make_number (inserted),
3724 Qnil));
3725
3726 RETURN_UNGCPRO (unbind_to (count, val));
3727 }
3728 \f
3729 static Lisp_Object build_annotations ();
3730
3731 /* If build_annotations switched buffers, switch back to BUF.
3732 Kill the temporary buffer that was selected in the meantime.
3733
3734 Since this kill only the last temporary buffer, some buffers remain
3735 not killed if build_annotations switched buffers more than once.
3736 -- K.Handa */
3737
3738 static Lisp_Object
3739 build_annotations_unwind (buf)
3740 Lisp_Object buf;
3741 {
3742 Lisp_Object tembuf;
3743
3744 if (XBUFFER (buf) == current_buffer)
3745 return Qnil;
3746 tembuf = Fcurrent_buffer ();
3747 Fset_buffer (buf);
3748 Fkill_buffer (tembuf);
3749 return Qnil;
3750 }
3751
3752 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 6,
3753 "r\nFWrite region to file: ",
3754 "Write current region into specified file.\n\
3755 When called from a program, takes three arguments:\n\
3756 START, END and FILENAME. START and END are buffer positions.\n\
3757 Optional fourth argument APPEND if non-nil means\n\
3758 append to existing file contents (if any).\n\
3759 Optional fifth argument VISIT if t means\n\
3760 set the last-save-file-modtime of buffer to this file's modtime\n\
3761 and mark buffer not modified.\n\
3762 If VISIT is a string, it is a second file name;\n\
3763 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
3764 VISIT is also the file name to lock and unlock for clash detection.\n\
3765 If VISIT is neither t nor nil nor a string,\n\
3766 that means do not print the \"Wrote file\" message.\n\
3767 The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
3768 use for locking and unlocking, overriding FILENAME and VISIT.\n\
3769 Kludgy feature: if START is a string, then that string is written\n\
3770 to the file, instead of any buffer contents, and END is ignored.")
3771 (start, end, filename, append, visit, lockname)
3772 Lisp_Object start, end, filename, append, visit, lockname;
3773 {
3774 register int desc;
3775 int failure;
3776 int save_errno;
3777 unsigned char *fn;
3778 struct stat st;
3779 int tem;
3780 int count = specpdl_ptr - specpdl;
3781 int count1;
3782 #ifdef VMS
3783 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
3784 #endif /* VMS */
3785 Lisp_Object handler;
3786 Lisp_Object visit_file;
3787 Lisp_Object annotations;
3788 int visiting, quietly;
3789 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
3790 struct buffer *given_buffer;
3791 #ifdef DOS_NT
3792 int buffer_file_type
3793 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY;
3794 #endif /* DOS_NT */
3795 struct coding_system coding;
3796
3797 if (current_buffer->base_buffer && ! NILP (visit))
3798 error ("Cannot do file visiting in an indirect buffer");
3799
3800 if (!NILP (start) && !STRINGP (start))
3801 validate_region (&start, &end);
3802
3803 GCPRO4 (start, filename, visit, lockname);
3804
3805 /* Decide the coding-system to be encoded to. */
3806 {
3807 Lisp_Object val;
3808
3809 if (auto_saving || NILP (current_buffer->enable_multibyte_characters))
3810 val = Qnil;
3811 else if (!NILP (Vcoding_system_for_write))
3812 val = Vcoding_system_for_write;
3813 else if (!NILP (Flocal_variable_if_set_p (Qbuffer_file_coding_system,
3814 Qnil)))
3815 val = Fsymbol_value (Qbuffer_file_coding_system);
3816 else
3817 {
3818 Lisp_Object args[7], coding_systems;
3819
3820 args[0] = Qwrite_region, args[1] = start, args[2] = end,
3821 args[3] = filename, args[4] = append, args[5] = visit,
3822 args[6] = lockname;
3823 coding_systems = Ffind_coding_system (7, args);
3824 val = (CONSP (coding_systems)
3825 ? XCONS (coding_systems)->cdr
3826 : current_buffer->buffer_file_coding_system);
3827 }
3828 setup_coding_system (Fcheck_coding_system (val), &coding);
3829 if (!STRINGP (start) && !NILP (current_buffer->selective_display))
3830 coding.selective = 1;
3831 #ifdef DOS_NT
3832 if (!NILP (current_buffer->buffer_file_type))
3833 coding.eol_type = CODING_EOL_LF;
3834 #endif /* DOS_NT */
3835 }
3836
3837 filename = Fexpand_file_name (filename, Qnil);
3838 if (STRINGP (visit))
3839 visit_file = Fexpand_file_name (visit, Qnil);
3840 else
3841 visit_file = filename;
3842 UNGCPRO;
3843
3844 visiting = (EQ (visit, Qt) || STRINGP (visit));
3845 quietly = !NILP (visit);
3846
3847 annotations = Qnil;
3848
3849 if (NILP (lockname))
3850 lockname = visit_file;
3851
3852 GCPRO5 (start, filename, annotations, visit_file, lockname);
3853
3854 /* If the file name has special constructs in it,
3855 call the corresponding file handler. */
3856 handler = Ffind_file_name_handler (filename, Qwrite_region);
3857 /* If FILENAME has no handler, see if VISIT has one. */
3858 if (NILP (handler) && STRINGP (visit))
3859 handler = Ffind_file_name_handler (visit, Qwrite_region);
3860
3861 if (!NILP (handler))
3862 {
3863 Lisp_Object val;
3864 val = call6 (handler, Qwrite_region, start, end,
3865 filename, append, visit);
3866
3867 if (visiting)
3868 {
3869 SAVE_MODIFF = MODIFF;
3870 XSETFASTINT (current_buffer->save_length, Z - BEG);
3871 current_buffer->filename = visit_file;
3872 }
3873 UNGCPRO;
3874 return val;
3875 }
3876
3877 /* Special kludge to simplify auto-saving. */
3878 if (NILP (start))
3879 {
3880 XSETFASTINT (start, BEG);
3881 XSETFASTINT (end, Z);
3882 }
3883
3884 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
3885 count1 = specpdl_ptr - specpdl;
3886
3887 given_buffer = current_buffer;
3888 annotations = build_annotations (start, end, coding.pre_write_conversion);
3889 if (current_buffer != given_buffer)
3890 {
3891 XSETFASTINT (start, BEGV);
3892 XSETFASTINT (end, ZV);
3893 }
3894
3895 #ifdef CLASH_DETECTION
3896 if (!auto_saving)
3897 {
3898 /* If we've locked this file for some other buffer,
3899 query before proceeding. */
3900 if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
3901 call2 (intern ("ask-user-about-lock"), fn, Vuser_login_name);
3902
3903 lock_file (lockname);
3904 }
3905 #endif /* CLASH_DETECTION */
3906
3907 fn = XSTRING (filename)->data;
3908 desc = -1;
3909 if (!NILP (append))
3910 #ifdef DOS_NT
3911 desc = open (fn, O_WRONLY | buffer_file_type);
3912 #else /* not DOS_NT */
3913 desc = open (fn, O_WRONLY);
3914 #endif /* not DOS_NT */
3915
3916 if (desc < 0 && (NILP (append) || errno == ENOENT) )
3917 #ifdef VMS
3918 if (auto_saving) /* Overwrite any previous version of autosave file */
3919 {
3920 vms_truncate (fn); /* if fn exists, truncate to zero length */
3921 desc = open (fn, O_RDWR);
3922 if (desc < 0)
3923 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
3924 ? XSTRING (current_buffer->filename)->data : 0,
3925 fn);
3926 }
3927 else /* Write to temporary name and rename if no errors */
3928 {
3929 Lisp_Object temp_name;
3930 temp_name = Ffile_name_directory (filename);
3931
3932 if (!NILP (temp_name))
3933 {
3934 temp_name = Fmake_temp_name (concat2 (temp_name,
3935 build_string ("$$SAVE$$")));
3936 fname = XSTRING (filename)->data;
3937 fn = XSTRING (temp_name)->data;
3938 desc = creat_copy_attrs (fname, fn);
3939 if (desc < 0)
3940 {
3941 /* If we can't open the temporary file, try creating a new
3942 version of the original file. VMS "creat" creates a
3943 new version rather than truncating an existing file. */
3944 fn = fname;
3945 fname = 0;
3946 desc = creat (fn, 0666);
3947 #if 0 /* This can clobber an existing file and fail to replace it,
3948 if the user runs out of space. */
3949 if (desc < 0)
3950 {
3951 /* We can't make a new version;
3952 try to truncate and rewrite existing version if any. */
3953 vms_truncate (fn);
3954 desc = open (fn, O_RDWR);
3955 }
3956 #endif
3957 }
3958 }
3959 else
3960 desc = creat (fn, 0666);
3961 }
3962 #else /* not VMS */
3963 #ifdef DOS_NT
3964 desc = open (fn,
3965 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
3966 S_IREAD | S_IWRITE);
3967 #else /* not DOS_NT */
3968 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
3969 #endif /* not DOS_NT */
3970 #endif /* not VMS */
3971
3972 UNGCPRO;
3973
3974 if (desc < 0)
3975 {
3976 #ifdef CLASH_DETECTION
3977 save_errno = errno;
3978 if (!auto_saving) unlock_file (lockname);
3979 errno = save_errno;
3980 #endif /* CLASH_DETECTION */
3981 report_file_error ("Opening output file", Fcons (filename, Qnil));
3982 }
3983
3984 record_unwind_protect (close_file_unwind, make_number (desc));
3985
3986 if (!NILP (append))
3987 if (lseek (desc, 0, 2) < 0)
3988 {
3989 #ifdef CLASH_DETECTION
3990 if (!auto_saving) unlock_file (lockname);
3991 #endif /* CLASH_DETECTION */
3992 report_file_error ("Lseek error", Fcons (filename, Qnil));
3993 }
3994
3995 #ifdef VMS
3996 /*
3997 * Kludge Warning: The VMS C RTL likes to insert carriage returns
3998 * if we do writes that don't end with a carriage return. Furthermore
3999 * it cannot handle writes of more then 16K. The modified
4000 * version of "sys_write" in SYSDEP.C (see comment there) copes with
4001 * this EXCEPT for the last record (iff it doesn't end with a carriage
4002 * return). This implies that if your buffer doesn't end with a carriage
4003 * return, you get one free... tough. However it also means that if
4004 * we make two calls to sys_write (a la the following code) you can
4005 * get one at the gap as well. The easiest way to fix this (honest)
4006 * is to move the gap to the next newline (or the end of the buffer).
4007 * Thus this change.
4008 *
4009 * Yech!
4010 */
4011 if (GPT > BEG && GPT_ADDR[-1] != '\n')
4012 move_gap (find_next_newline (GPT, 1));
4013 #else
4014 /* Whether VMS or not, we must move the gap to the next of newline
4015 when we must put designation sequences at beginning of line. */
4016 if (INTEGERP (start)
4017 && coding.type == coding_type_iso2022
4018 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
4019 && GPT > BEG && GPT_ADDR[-1] != '\n')
4020 move_gap (find_next_newline (GPT, 1));
4021 #endif
4022
4023 failure = 0;
4024 immediate_quit = 1;
4025
4026 if (STRINGP (start))
4027 {
4028 failure = 0 > a_write (desc, XSTRING (start)->data,
4029 XSTRING (start)->size, 0, &annotations, &coding);
4030 save_errno = errno;
4031 }
4032 else if (XINT (start) != XINT (end))
4033 {
4034 int nwritten = 0;
4035 if (XINT (start) < GPT)
4036 {
4037 register int end1 = XINT (end);
4038 tem = XINT (start);
4039 failure = 0 > a_write (desc, POS_ADDR (tem),
4040 min (GPT, end1) - tem, tem, &annotations,
4041 &coding);
4042 nwritten += min (GPT, end1) - tem;
4043 save_errno = errno;
4044 }
4045
4046 if (XINT (end) > GPT && !failure)
4047 {
4048 tem = XINT (start);
4049 tem = max (tem, GPT);
4050 failure = 0 > a_write (desc, POS_ADDR (tem), XINT (end) - tem,
4051 tem, &annotations, &coding);
4052 nwritten += XINT (end) - tem;
4053 save_errno = errno;
4054 }
4055 }
4056 else
4057 {
4058 /* If file was empty, still need to write the annotations */
4059 coding.last_block = 1;
4060 failure = 0 > a_write (desc, "", 0, XINT (start), &annotations, &coding);
4061 save_errno = errno;
4062 }
4063
4064 if (coding.require_flushing)
4065 {
4066 /* We have to flush out a data. */
4067 coding.last_block = 1;
4068 failure = 0 > e_write (desc, "", 0, &coding);
4069 save_errno = errno;
4070 }
4071
4072 immediate_quit = 0;
4073
4074 #ifdef HAVE_FSYNC
4075 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
4076 Disk full in NFS may be reported here. */
4077 /* mib says that closing the file will try to write as fast as NFS can do
4078 it, and that means the fsync here is not crucial for autosave files. */
4079 if (!auto_saving && fsync (desc) < 0)
4080 {
4081 /* If fsync fails with EINTR, don't treat that as serious. */
4082 if (errno != EINTR)
4083 failure = 1, save_errno = errno;
4084 }
4085 #endif
4086
4087 /* Spurious "file has changed on disk" warnings have been
4088 observed on Suns as well.
4089 It seems that `close' can change the modtime, under nfs.
4090
4091 (This has supposedly been fixed in Sunos 4,
4092 but who knows about all the other machines with NFS?) */
4093 #if 0
4094
4095 /* On VMS and APOLLO, must do the stat after the close
4096 since closing changes the modtime. */
4097 #ifndef VMS
4098 #ifndef APOLLO
4099 /* Recall that #if defined does not work on VMS. */
4100 #define FOO
4101 fstat (desc, &st);
4102 #endif
4103 #endif
4104 #endif
4105
4106 /* NFS can report a write failure now. */
4107 if (close (desc) < 0)
4108 failure = 1, save_errno = errno;
4109
4110 #ifdef VMS
4111 /* If we wrote to a temporary name and had no errors, rename to real name. */
4112 if (fname)
4113 {
4114 if (!failure)
4115 failure = (rename (fn, fname) != 0), save_errno = errno;
4116 fn = fname;
4117 }
4118 #endif /* VMS */
4119
4120 #ifndef FOO
4121 stat (fn, &st);
4122 #endif
4123 /* Discard the unwind protect for close_file_unwind. */
4124 specpdl_ptr = specpdl + count1;
4125 /* Restore the original current buffer. */
4126 visit_file = unbind_to (count, visit_file);
4127
4128 #ifdef CLASH_DETECTION
4129 if (!auto_saving)
4130 unlock_file (lockname);
4131 #endif /* CLASH_DETECTION */
4132
4133 /* Do this before reporting IO error
4134 to avoid a "file has changed on disk" warning on
4135 next attempt to save. */
4136 if (visiting)
4137 current_buffer->modtime = st.st_mtime;
4138
4139 if (failure)
4140 error ("IO error writing %s: %s", fn, strerror (save_errno));
4141
4142 if (visiting)
4143 {
4144 SAVE_MODIFF = MODIFF;
4145 XSETFASTINT (current_buffer->save_length, Z - BEG);
4146 current_buffer->filename = visit_file;
4147 update_mode_lines++;
4148 }
4149 else if (quietly)
4150 return Qnil;
4151
4152 if (!auto_saving)
4153 message ("Wrote %s", XSTRING (visit_file)->data);
4154
4155 return Qnil;
4156 }
4157
4158 Lisp_Object merge ();
4159
4160 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
4161 "Return t if (car A) is numerically less than (car B).")
4162 (a, b)
4163 Lisp_Object a, b;
4164 {
4165 return Flss (Fcar (a), Fcar (b));
4166 }
4167
4168 /* Build the complete list of annotations appropriate for writing out
4169 the text between START and END, by calling all the functions in
4170 write-region-annotate-functions and merging the lists they return.
4171 If one of these functions switches to a different buffer, we assume
4172 that buffer contains altered text. Therefore, the caller must
4173 make sure to restore the current buffer in all cases,
4174 as save-excursion would do. */
4175
4176 static Lisp_Object
4177 build_annotations (start, end, pre_write_conversion)
4178 Lisp_Object start, end, pre_write_conversion;
4179 {
4180 Lisp_Object annotations;
4181 Lisp_Object p, res;
4182 struct gcpro gcpro1, gcpro2;
4183 Lisp_Object original_buffer;
4184
4185 XSETBUFFER (original_buffer, current_buffer);
4186
4187 annotations = Qnil;
4188 p = Vwrite_region_annotate_functions;
4189 GCPRO2 (annotations, p);
4190 while (!NILP (p))
4191 {
4192 struct buffer *given_buffer = current_buffer;
4193 Vwrite_region_annotations_so_far = annotations;
4194 res = call2 (Fcar (p), start, end);
4195 /* If the function makes a different buffer current,
4196 assume that means this buffer contains altered text to be output.
4197 Reset START and END from the buffer bounds
4198 and discard all previous annotations because they should have
4199 been dealt with by this function. */
4200 if (current_buffer != given_buffer)
4201 {
4202 XSETFASTINT (start, BEGV);
4203 XSETFASTINT (end, ZV);
4204 annotations = Qnil;
4205 }
4206 Flength (res); /* Check basic validity of return value */
4207 annotations = merge (annotations, res, Qcar_less_than_car);
4208 p = Fcdr (p);
4209 }
4210
4211 /* Now do the same for annotation functions implied by the file-format */
4212 if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
4213 p = Vauto_save_file_format;
4214 else
4215 p = current_buffer->file_format;
4216 while (!NILP (p))
4217 {
4218 struct buffer *given_buffer = current_buffer;
4219 Vwrite_region_annotations_so_far = annotations;
4220 res = call4 (Qformat_annotate_function, Fcar (p), start, end,
4221 original_buffer);
4222 if (current_buffer != given_buffer)
4223 {
4224 XSETFASTINT (start, BEGV);
4225 XSETFASTINT (end, ZV);
4226 annotations = Qnil;
4227 }
4228 Flength (res);
4229 annotations = merge (annotations, res, Qcar_less_than_car);
4230 p = Fcdr (p);
4231 }
4232
4233 /* At last, do the same for the function PRE_WRITE_CONVERSION
4234 implied by the current coding-system. */
4235 if (!NILP (pre_write_conversion))
4236 {
4237 struct buffer *given_buffer = current_buffer;
4238 Vwrite_region_annotations_so_far = annotations;
4239 res = call2 (pre_write_conversion, start, end);
4240 Flength (res);
4241 annotations = (current_buffer != given_buffer
4242 ? res
4243 : merge (annotations, res, Qcar_less_than_car));
4244 }
4245
4246 UNGCPRO;
4247 return annotations;
4248 }
4249
4250 /* Write to descriptor DESC the LEN characters starting at ADDR,
4251 assuming they start at position POS in the buffer.
4252 Intersperse with them the annotations from *ANNOT
4253 (those which fall within the range of positions POS to POS + LEN),
4254 each at its appropriate position.
4255
4256 Modify *ANNOT by discarding elements as we output them.
4257 The return value is negative in case of system call failure. */
4258
4259 int
4260 a_write (desc, addr, len, pos, annot, coding)
4261 int desc;
4262 register char *addr;
4263 register int len;
4264 int pos;
4265 Lisp_Object *annot;
4266 struct coding_system *coding;
4267 {
4268 Lisp_Object tem;
4269 int nextpos;
4270 int lastpos = pos + len;
4271
4272 while (NILP (*annot) || CONSP (*annot))
4273 {
4274 tem = Fcar_safe (Fcar (*annot));
4275 if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos)
4276 nextpos = XFASTINT (tem);
4277 else
4278 return e_write (desc, addr, lastpos - pos, coding);
4279 if (nextpos > pos)
4280 {
4281 if (0 > e_write (desc, addr, nextpos - pos, coding))
4282 return -1;
4283 addr += nextpos - pos;
4284 pos = nextpos;
4285 }
4286 tem = Fcdr (Fcar (*annot));
4287 if (STRINGP (tem))
4288 {
4289 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size,
4290 coding))
4291 return -1;
4292 }
4293 *annot = Fcdr (*annot);
4294 }
4295 }
4296
4297 #ifndef WRITE_BUF_SIZE
4298 #define WRITE_BUF_SIZE (16 * 1024)
4299 #endif
4300
4301 int
4302 e_write (desc, addr, len, coding)
4303 int desc;
4304 register char *addr;
4305 register int len;
4306 struct coding_system *coding;
4307 {
4308 char buf[WRITE_BUF_SIZE];
4309 int produced, consumed;
4310
4311 /* We used to have a code for handling selective display here. But,
4312 now it is handled within encode_coding. */
4313 while (1)
4314 {
4315 produced = encode_coding (coding, addr, buf, len, WRITE_BUF_SIZE,
4316 &consumed);
4317 len -= consumed, addr += consumed;
4318 if (produced > 0)
4319 {
4320 produced -= write (desc, buf, produced);
4321 if (produced) return -1;
4322 }
4323 if (len <= 0)
4324 break;
4325 }
4326 return 0;
4327 }
4328
4329 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
4330 Sverify_visited_file_modtime, 1, 1, 0,
4331 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
4332 This means that the file has not been changed since it was visited or saved.")
4333 (buf)
4334 Lisp_Object buf;
4335 {
4336 struct buffer *b;
4337 struct stat st;
4338 Lisp_Object handler;
4339
4340 CHECK_BUFFER (buf, 0);
4341 b = XBUFFER (buf);
4342
4343 if (!STRINGP (b->filename)) return Qt;
4344 if (b->modtime == 0) return Qt;
4345
4346 /* If the file name has special constructs in it,
4347 call the corresponding file handler. */
4348 handler = Ffind_file_name_handler (b->filename,
4349 Qverify_visited_file_modtime);
4350 if (!NILP (handler))
4351 return call2 (handler, Qverify_visited_file_modtime, buf);
4352
4353 if (stat (XSTRING (b->filename)->data, &st) < 0)
4354 {
4355 /* If the file doesn't exist now and didn't exist before,
4356 we say that it isn't modified, provided the error is a tame one. */
4357 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
4358 st.st_mtime = -1;
4359 else
4360 st.st_mtime = 0;
4361 }
4362 if (st.st_mtime == b->modtime
4363 /* If both are positive, accept them if they are off by one second. */
4364 || (st.st_mtime > 0 && b->modtime > 0
4365 && (st.st_mtime == b->modtime + 1
4366 || st.st_mtime == b->modtime - 1)))
4367 return Qt;
4368 return Qnil;
4369 }
4370
4371 DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
4372 Sclear_visited_file_modtime, 0, 0, 0,
4373 "Clear out records of last mod time of visited file.\n\
4374 Next attempt to save will certainly not complain of a discrepancy.")
4375 ()
4376 {
4377 current_buffer->modtime = 0;
4378 return Qnil;
4379 }
4380
4381 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
4382 Svisited_file_modtime, 0, 0, 0,
4383 "Return the current buffer's recorded visited file modification time.\n\
4384 The value is a list of the form (HIGH . LOW), like the time values\n\
4385 that `file-attributes' returns.")
4386 ()
4387 {
4388 return long_to_cons ((unsigned long) current_buffer->modtime);
4389 }
4390
4391 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
4392 Sset_visited_file_modtime, 0, 1, 0,
4393 "Update buffer's recorded modification time from the visited file's time.\n\
4394 Useful if the buffer was not read from the file normally\n\
4395 or if the file itself has been changed for some known benign reason.\n\
4396 An argument specifies the modification time value to use\n\
4397 \(instead of that of the visited file), in the form of a list\n\
4398 \(HIGH . LOW) or (HIGH LOW).")
4399 (time_list)
4400 Lisp_Object time_list;
4401 {
4402 if (!NILP (time_list))
4403 current_buffer->modtime = cons_to_long (time_list);
4404 else
4405 {
4406 register Lisp_Object filename;
4407 struct stat st;
4408 Lisp_Object handler;
4409
4410 filename = Fexpand_file_name (current_buffer->filename, Qnil);
4411
4412 /* If the file name has special constructs in it,
4413 call the corresponding file handler. */
4414 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
4415 if (!NILP (handler))
4416 /* The handler can find the file name the same way we did. */
4417 return call2 (handler, Qset_visited_file_modtime, Qnil);
4418 else if (stat (XSTRING (filename)->data, &st) >= 0)
4419 current_buffer->modtime = st.st_mtime;
4420 }
4421
4422 return Qnil;
4423 }
4424 \f
4425 Lisp_Object
4426 auto_save_error ()
4427 {
4428 ring_bell ();
4429 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
4430 Fsleep_for (make_number (1), Qnil);
4431 message ("Autosaving...error!for %s", XSTRING (current_buffer->name)->data);
4432 Fsleep_for (make_number (1), Qnil);
4433 message ("Autosaving...error for %s", XSTRING (current_buffer->name)->data);
4434 Fsleep_for (make_number (1), Qnil);
4435 return Qnil;
4436 }
4437
4438 Lisp_Object
4439 auto_save_1 ()
4440 {
4441 unsigned char *fn;
4442 struct stat st;
4443
4444 /* Get visited file's mode to become the auto save file's mode. */
4445 if (stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
4446 /* But make sure we can overwrite it later! */
4447 auto_save_mode_bits = st.st_mode | 0600;
4448 else
4449 auto_save_mode_bits = 0666;
4450
4451 return
4452 Fwrite_region (Qnil, Qnil,
4453 current_buffer->auto_save_file_name,
4454 Qnil, Qlambda, Qnil);
4455 }
4456
4457 static Lisp_Object
4458 do_auto_save_unwind (stream) /* used as unwind-protect function */
4459 Lisp_Object stream;
4460 {
4461 auto_saving = 0;
4462 if (!NILP (stream))
4463 fclose ((FILE *) (XFASTINT (XCONS (stream)->car) << 16
4464 | XFASTINT (XCONS (stream)->cdr)));
4465 return Qnil;
4466 }
4467
4468 DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
4469 "Auto-save all buffers that need it.\n\
4470 This is all buffers that have auto-saving enabled\n\
4471 and are changed since last auto-saved.\n\
4472 Auto-saving writes the buffer into a file\n\
4473 so that your editing is not lost if the system crashes.\n\
4474 This file is not the file you visited; that changes only when you save.\n\
4475 Normally we run the normal hook `auto-save-hook' before saving.\n\n\
4476 A non-nil NO-MESSAGE argument means do not print any message if successful.\n\
4477 A non-nil CURRENT-ONLY argument means save only current buffer.")
4478 (no_message, current_only)
4479 Lisp_Object no_message, current_only;
4480 {
4481 struct buffer *old = current_buffer, *b;
4482 Lisp_Object tail, buf;
4483 int auto_saved = 0;
4484 char *omessage = echo_area_glyphs;
4485 int omessage_length = echo_area_glyphs_length;
4486 int do_handled_files;
4487 Lisp_Object oquit;
4488 FILE *stream;
4489 Lisp_Object lispstream;
4490 int count = specpdl_ptr - specpdl;
4491 int *ptr;
4492
4493 /* Ordinarily don't quit within this function,
4494 but don't make it impossible to quit (in case we get hung in I/O). */
4495 oquit = Vquit_flag;
4496 Vquit_flag = Qnil;
4497
4498 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
4499 point to non-strings reached from Vbuffer_alist. */
4500
4501 if (minibuf_level)
4502 no_message = Qt;
4503
4504 if (!NILP (Vrun_hooks))
4505 call1 (Vrun_hooks, intern ("auto-save-hook"));
4506
4507 if (STRINGP (Vauto_save_list_file_name))
4508 {
4509 Lisp_Object listfile;
4510 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
4511 stream = fopen (XSTRING (listfile)->data, "w");
4512
4513 /* Arrange to close that file whether or not we get an error.
4514 Also reset auto_saving to 0. */
4515 lispstream = Fcons (Qnil, Qnil);
4516 XSETFASTINT (XCONS (lispstream)->car, (EMACS_UINT)stream >> 16);
4517 XSETFASTINT (XCONS (lispstream)->cdr, (EMACS_UINT)stream & 0xffff);
4518 }
4519 else
4520 {
4521 stream = NULL;
4522 lispstream = Qnil;
4523 }
4524
4525 record_unwind_protect (do_auto_save_unwind, lispstream);
4526
4527 auto_saving = 1;
4528
4529 /* First, save all files which don't have handlers. If Emacs is
4530 crashing, the handlers may tweak what is causing Emacs to crash
4531 in the first place, and it would be a shame if Emacs failed to
4532 autosave perfectly ordinary files because it couldn't handle some
4533 ange-ftp'd file. */
4534 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
4535 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
4536 {
4537 buf = XCONS (XCONS (tail)->car)->cdr;
4538 b = XBUFFER (buf);
4539
4540 /* Record all the buffers that have auto save mode
4541 in the special file that lists them. For each of these buffers,
4542 Record visited name (if any) and auto save name. */
4543 if (STRINGP (b->auto_save_file_name)
4544 && stream != NULL && do_handled_files == 0)
4545 {
4546 if (!NILP (b->filename))
4547 {
4548 fwrite (XSTRING (b->filename)->data, 1,
4549 XSTRING (b->filename)->size, stream);
4550 }
4551 putc ('\n', stream);
4552 fwrite (XSTRING (b->auto_save_file_name)->data, 1,
4553 XSTRING (b->auto_save_file_name)->size, stream);
4554 putc ('\n', stream);
4555 }
4556
4557 if (!NILP (current_only)
4558 && b != current_buffer)
4559 continue;
4560
4561 /* Don't auto-save indirect buffers.
4562 The base buffer takes care of it. */
4563 if (b->base_buffer)
4564 continue;
4565
4566 /* Check for auto save enabled
4567 and file changed since last auto save
4568 and file changed since last real save. */
4569 if (STRINGP (b->auto_save_file_name)
4570 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
4571 && b->auto_save_modified < BUF_MODIFF (b)
4572 /* -1 means we've turned off autosaving for a while--see below. */
4573 && XINT (b->save_length) >= 0
4574 && (do_handled_files
4575 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
4576 Qwrite_region))))
4577 {
4578 EMACS_TIME before_time, after_time;
4579
4580 EMACS_GET_TIME (before_time);
4581
4582 /* If we had a failure, don't try again for 20 minutes. */
4583 if (b->auto_save_failure_time >= 0
4584 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
4585 continue;
4586
4587 if ((XFASTINT (b->save_length) * 10
4588 > (BUF_Z (b) - BUF_BEG (b)) * 13)
4589 /* A short file is likely to change a large fraction;
4590 spare the user annoying messages. */
4591 && XFASTINT (b->save_length) > 5000
4592 /* These messages are frequent and annoying for `*mail*'. */
4593 && !EQ (b->filename, Qnil)
4594 && NILP (no_message))
4595 {
4596 /* It has shrunk too much; turn off auto-saving here. */
4597 message ("Buffer %s has shrunk a lot; auto save turned off there",
4598 XSTRING (b->name)->data);
4599 /* Turn off auto-saving until there's a real save,
4600 and prevent any more warnings. */
4601 XSETINT (b->save_length, -1);
4602 Fsleep_for (make_number (1), Qnil);
4603 continue;
4604 }
4605 set_buffer_internal (b);
4606 if (!auto_saved && NILP (no_message))
4607 message1 ("Auto-saving...");
4608 internal_condition_case (auto_save_1, Qt, auto_save_error);
4609 auto_saved++;
4610 b->auto_save_modified = BUF_MODIFF (b);
4611 XSETFASTINT (current_buffer->save_length, Z - BEG);
4612 set_buffer_internal (old);
4613
4614 EMACS_GET_TIME (after_time);
4615
4616 /* If auto-save took more than 60 seconds,
4617 assume it was an NFS failure that got a timeout. */
4618 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
4619 b->auto_save_failure_time = EMACS_SECS (after_time);
4620 }
4621 }
4622
4623 /* Prevent another auto save till enough input events come in. */
4624 record_auto_save ();
4625
4626 if (auto_saved && NILP (no_message))
4627 {
4628 if (omessage)
4629 {
4630 sit_for (1, 0, 0, 0, 0);
4631 message2 (omessage, omessage_length);
4632 }
4633 else
4634 message1 ("Auto-saving...done");
4635 }
4636
4637 Vquit_flag = oquit;
4638
4639 unbind_to (count, Qnil);
4640 return Qnil;
4641 }
4642
4643 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
4644 Sset_buffer_auto_saved, 0, 0, 0,
4645 "Mark current buffer as auto-saved with its current text.\n\
4646 No auto-save file will be written until the buffer changes again.")
4647 ()
4648 {
4649 current_buffer->auto_save_modified = MODIFF;
4650 XSETFASTINT (current_buffer->save_length, Z - BEG);
4651 current_buffer->auto_save_failure_time = -1;
4652 return Qnil;
4653 }
4654
4655 DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
4656 Sclear_buffer_auto_save_failure, 0, 0, 0,
4657 "Clear any record of a recent auto-save failure in the current buffer.")
4658 ()
4659 {
4660 current_buffer->auto_save_failure_time = -1;
4661 return Qnil;
4662 }
4663
4664 DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
4665 0, 0, 0,
4666 "Return t if buffer has been auto-saved since last read in or saved.")
4667 ()
4668 {
4669 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
4670 }
4671 \f
4672 /* Reading and completing file names */
4673 extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
4674
4675 /* In the string VAL, change each $ to $$ and return the result. */
4676
4677 static Lisp_Object
4678 double_dollars (val)
4679 Lisp_Object val;
4680 {
4681 register unsigned char *old, *new;
4682 register int n;
4683 int osize, count;
4684
4685 osize = XSTRING (val)->size;
4686 /* Quote "$" as "$$" to get it past substitute-in-file-name */
4687 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
4688 if (*old++ == '$') count++;
4689 if (count > 0)
4690 {
4691 old = XSTRING (val)->data;
4692 val = Fmake_string (make_number (osize + count), make_number (0));
4693 new = XSTRING (val)->data;
4694 for (n = osize; n > 0; n--)
4695 if (*old != '$')
4696 *new++ = *old++;
4697 else
4698 {
4699 *new++ = '$';
4700 *new++ = '$';
4701 old++;
4702 }
4703 }
4704 return val;
4705 }
4706
4707 DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
4708 3, 3, 0,
4709 "Internal subroutine for read-file-name. Do not call this.")
4710 (string, dir, action)
4711 Lisp_Object string, dir, action;
4712 /* action is nil for complete, t for return list of completions,
4713 lambda for verify final value */
4714 {
4715 Lisp_Object name, specdir, realdir, val, orig_string;
4716 int changed;
4717 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4718
4719 CHECK_STRING (string, 0);
4720
4721 realdir = dir;
4722 name = string;
4723 orig_string = Qnil;
4724 specdir = Qnil;
4725 changed = 0;
4726 /* No need to protect ACTION--we only compare it with t and nil. */
4727 GCPRO5 (string, realdir, name, specdir, orig_string);
4728
4729 if (XSTRING (string)->size == 0)
4730 {
4731 if (EQ (action, Qlambda))
4732 {
4733 UNGCPRO;
4734 return Qnil;
4735 }
4736 }
4737 else
4738 {
4739 orig_string = string;
4740 string = Fsubstitute_in_file_name (string);
4741 changed = NILP (Fstring_equal (string, orig_string));
4742 name = Ffile_name_nondirectory (string);
4743 val = Ffile_name_directory (string);
4744 if (! NILP (val))
4745 realdir = Fexpand_file_name (val, realdir);
4746 }
4747
4748 if (NILP (action))
4749 {
4750 specdir = Ffile_name_directory (string);
4751 val = Ffile_name_completion (name, realdir);
4752 UNGCPRO;
4753 if (!STRINGP (val))
4754 {
4755 if (changed)
4756 return double_dollars (string);
4757 return val;
4758 }
4759
4760 if (!NILP (specdir))
4761 val = concat2 (specdir, val);
4762 #ifndef VMS
4763 return double_dollars (val);
4764 #else /* not VMS */
4765 return val;
4766 #endif /* not VMS */
4767 }
4768 UNGCPRO;
4769
4770 if (EQ (action, Qt))
4771 return Ffile_name_all_completions (name, realdir);
4772 /* Only other case actually used is ACTION = lambda */
4773 #ifdef VMS
4774 /* Supposedly this helps commands such as `cd' that read directory names,
4775 but can someone explain how it helps them? -- RMS */
4776 if (XSTRING (name)->size == 0)
4777 return Qt;
4778 #endif /* VMS */
4779 return Ffile_exists_p (string);
4780 }
4781
4782 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
4783 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
4784 Value is not expanded---you must call `expand-file-name' yourself.\n\
4785 Default name to DEFAULT-FILENAME if user enters a null string.\n\
4786 (If DEFAULT-FILENAME is omitted, the visited file name is used,\n\
4787 except that if INITIAL is specified, that combined with DIR is used.)\n\
4788 Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
4789 Non-nil and non-t means also require confirmation after completion.\n\
4790 Fifth arg INITIAL specifies text to start with.\n\
4791 DIR defaults to current buffer's directory default.")
4792 (prompt, dir, default_filename, mustmatch, initial)
4793 Lisp_Object prompt, dir, default_filename, mustmatch, initial;
4794 {
4795 Lisp_Object val, insdef, insdef1, tem;
4796 struct gcpro gcpro1, gcpro2;
4797 register char *homedir;
4798 int count;
4799
4800 if (NILP (dir))
4801 dir = current_buffer->directory;
4802 if (NILP (default_filename))
4803 {
4804 if (! NILP (initial))
4805 default_filename = Fexpand_file_name (initial, dir);
4806 else
4807 default_filename = current_buffer->filename;
4808 }
4809
4810 /* If dir starts with user's homedir, change that to ~. */
4811 homedir = (char *) egetenv ("HOME");
4812 #ifdef DOS_NT
4813 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
4814 CORRECT_DIR_SEPS (homedir);
4815 #endif
4816 if (homedir != 0
4817 && STRINGP (dir)
4818 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
4819 && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
4820 {
4821 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
4822 XSTRING (dir)->size - strlen (homedir) + 1);
4823 XSTRING (dir)->data[0] = '~';
4824 }
4825
4826 if (insert_default_directory && STRINGP (dir))
4827 {
4828 insdef = dir;
4829 if (!NILP (initial))
4830 {
4831 Lisp_Object args[2], pos;
4832
4833 args[0] = insdef;
4834 args[1] = initial;
4835 insdef = Fconcat (2, args);
4836 pos = make_number (XSTRING (double_dollars (dir))->size);
4837 insdef1 = Fcons (double_dollars (insdef), pos);
4838 }
4839 else
4840 insdef1 = double_dollars (insdef);
4841 }
4842 else if (STRINGP (initial))
4843 {
4844 insdef = initial;
4845 insdef1 = Fcons (double_dollars (insdef), 0);
4846 }
4847 else
4848 insdef = Qnil, insdef1 = Qnil;
4849
4850 #ifdef VMS
4851 count = specpdl_ptr - specpdl;
4852 specbind (intern ("completion-ignore-case"), Qt);
4853 #endif
4854
4855 GCPRO2 (insdef, default_filename);
4856 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4857 dir, mustmatch, insdef1,
4858 Qfile_name_history, default_filename);
4859
4860 #ifdef VMS
4861 unbind_to (count, Qnil);
4862 #endif
4863
4864 UNGCPRO;
4865 if (NILP (val))
4866 error ("No file name specified");
4867 tem = Fstring_equal (val, insdef);
4868 if (!NILP (tem) && !NILP (default_filename))
4869 return default_filename;
4870 if (XSTRING (val)->size == 0 && NILP (insdef))
4871 {
4872 if (!NILP (default_filename))
4873 return default_filename;
4874 else
4875 error ("No default file name");
4876 }
4877 return Fsubstitute_in_file_name (val);
4878 }
4879
4880 #if 0 /* Old version */
4881 DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
4882 /* Don't confuse make-docfile by having two doc strings for this function.
4883 make-docfile does not pay attention to #if, for good reason! */
4884 0)
4885 (prompt, dir, defalt, mustmatch, initial)
4886 Lisp_Object prompt, dir, defalt, mustmatch, initial;
4887 {
4888 Lisp_Object val, insdef, tem;
4889 struct gcpro gcpro1, gcpro2;
4890 register char *homedir;
4891 int count;
4892
4893 if (NILP (dir))
4894 dir = current_buffer->directory;
4895 if (NILP (defalt))
4896 defalt = current_buffer->filename;
4897
4898 /* If dir starts with user's homedir, change that to ~. */
4899 homedir = (char *) egetenv ("HOME");
4900 if (homedir != 0
4901 && STRINGP (dir)
4902 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
4903 && XSTRING (dir)->data[strlen (homedir)] == '/')
4904 {
4905 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
4906 XSTRING (dir)->size - strlen (homedir) + 1);
4907 XSTRING (dir)->data[0] = '~';
4908 }
4909
4910 if (!NILP (initial))
4911 insdef = initial;
4912 else if (insert_default_directory)
4913 insdef = dir;
4914 else
4915 insdef = build_string ("");
4916
4917 #ifdef VMS
4918 count = specpdl_ptr - specpdl;
4919 specbind (intern ("completion-ignore-case"), Qt);
4920 #endif
4921
4922 GCPRO2 (insdef, defalt);
4923 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4924 dir, mustmatch,
4925 insert_default_directory ? insdef : Qnil,
4926 Qfile_name_history, Qnil);
4927
4928 #ifdef VMS
4929 unbind_to (count, Qnil);
4930 #endif
4931
4932 UNGCPRO;
4933 if (NILP (val))
4934 error ("No file name specified");
4935 tem = Fstring_equal (val, insdef);
4936 if (!NILP (tem) && !NILP (defalt))
4937 return defalt;
4938 return Fsubstitute_in_file_name (val);
4939 }
4940 #endif /* Old version */
4941 \f
4942 syms_of_fileio ()
4943 {
4944 Qexpand_file_name = intern ("expand-file-name");
4945 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
4946 Qdirectory_file_name = intern ("directory-file-name");
4947 Qfile_name_directory = intern ("file-name-directory");
4948 Qfile_name_nondirectory = intern ("file-name-nondirectory");
4949 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
4950 Qfile_name_as_directory = intern ("file-name-as-directory");
4951 Qcopy_file = intern ("copy-file");
4952 Qmake_directory_internal = intern ("make-directory-internal");
4953 Qdelete_directory = intern ("delete-directory");
4954 Qdelete_file = intern ("delete-file");
4955 Qrename_file = intern ("rename-file");
4956 Qadd_name_to_file = intern ("add-name-to-file");
4957 Qmake_symbolic_link = intern ("make-symbolic-link");
4958 Qfile_exists_p = intern ("file-exists-p");
4959 Qfile_executable_p = intern ("file-executable-p");
4960 Qfile_readable_p = intern ("file-readable-p");
4961 Qfile_writable_p = intern ("file-writable-p");
4962 Qfile_symlink_p = intern ("file-symlink-p");
4963 Qaccess_file = intern ("access-file");
4964 Qfile_directory_p = intern ("file-directory-p");
4965 Qfile_regular_p = intern ("file-regular-p");
4966 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
4967 Qfile_modes = intern ("file-modes");
4968 Qset_file_modes = intern ("set-file-modes");
4969 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
4970 Qinsert_file_contents = intern ("insert-file-contents");
4971 Qwrite_region = intern ("write-region");
4972 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
4973 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
4974
4975 staticpro (&Qexpand_file_name);
4976 staticpro (&Qsubstitute_in_file_name);
4977 staticpro (&Qdirectory_file_name);
4978 staticpro (&Qfile_name_directory);
4979 staticpro (&Qfile_name_nondirectory);
4980 staticpro (&Qunhandled_file_name_directory);
4981 staticpro (&Qfile_name_as_directory);
4982 staticpro (&Qcopy_file);
4983 staticpro (&Qmake_directory_internal);
4984 staticpro (&Qdelete_directory);
4985 staticpro (&Qdelete_file);
4986 staticpro (&Qrename_file);
4987 staticpro (&Qadd_name_to_file);
4988 staticpro (&Qmake_symbolic_link);
4989 staticpro (&Qfile_exists_p);
4990 staticpro (&Qfile_executable_p);
4991 staticpro (&Qfile_readable_p);
4992 staticpro (&Qfile_writable_p);
4993 staticpro (&Qaccess_file);
4994 staticpro (&Qfile_symlink_p);
4995 staticpro (&Qfile_directory_p);
4996 staticpro (&Qfile_regular_p);
4997 staticpro (&Qfile_accessible_directory_p);
4998 staticpro (&Qfile_modes);
4999 staticpro (&Qset_file_modes);
5000 staticpro (&Qfile_newer_than_file_p);
5001 staticpro (&Qinsert_file_contents);
5002 staticpro (&Qwrite_region);
5003 staticpro (&Qverify_visited_file_modtime);
5004 staticpro (&Qset_visited_file_modtime);
5005
5006 Qfile_name_history = intern ("file-name-history");
5007 Fset (Qfile_name_history, Qnil);
5008 staticpro (&Qfile_name_history);
5009
5010 Qfile_error = intern ("file-error");
5011 staticpro (&Qfile_error);
5012 Qfile_already_exists = intern ("file-already-exists");
5013 staticpro (&Qfile_already_exists);
5014 Qfile_date_error = intern ("file-date-error");
5015 staticpro (&Qfile_date_error);
5016
5017 #ifdef DOS_NT
5018 Qfind_buffer_file_type = intern ("find-buffer-file-type");
5019 staticpro (&Qfind_buffer_file_type);
5020 #endif /* DOS_NT */
5021
5022 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
5023 "*Format in which to write auto-save files.\n\
5024 Should be a list of symbols naming formats that are defined in `format-alist'.\n\
5025 If it is t, which is the default, auto-save files are written in the\n\
5026 same format as a regular save would use.");
5027 Vauto_save_file_format = Qt;
5028
5029 Qformat_decode = intern ("format-decode");
5030 staticpro (&Qformat_decode);
5031 Qformat_annotate_function = intern ("format-annotate-function");
5032 staticpro (&Qformat_annotate_function);
5033
5034 Qcar_less_than_car = intern ("car-less-than-car");
5035 staticpro (&Qcar_less_than_car);
5036
5037 Fput (Qfile_error, Qerror_conditions,
5038 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
5039 Fput (Qfile_error, Qerror_message,
5040 build_string ("File error"));
5041
5042 Fput (Qfile_already_exists, Qerror_conditions,
5043 Fcons (Qfile_already_exists,
5044 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5045 Fput (Qfile_already_exists, Qerror_message,
5046 build_string ("File already exists"));
5047
5048 Fput (Qfile_date_error, Qerror_conditions,
5049 Fcons (Qfile_date_error,
5050 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5051 Fput (Qfile_date_error, Qerror_message,
5052 build_string ("Cannot set file date"));
5053
5054 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
5055 "*Non-nil means when reading a filename start with default dir in minibuffer.");
5056 insert_default_directory = 1;
5057
5058 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
5059 "*Non-nil means write new files with record format `stmlf'.\n\
5060 nil means use format `var'. This variable is meaningful only on VMS.");
5061 vms_stmlf_recfm = 0;
5062
5063 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
5064 "Directory separator character for built-in functions that return file names.\n\
5065 The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
5066 This variable affects the built-in functions only on Windows,\n\
5067 on other platforms, it is initialized so that Lisp code can find out\n\
5068 what the normal separator is.");
5069 Vdirectory_sep_char = '/';
5070
5071 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
5072 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
5073 If a file name matches REGEXP, then all I/O on that file is done by calling\n\
5074 HANDLER.\n\
5075 \n\
5076 The first argument given to HANDLER is the name of the I/O primitive\n\
5077 to be handled; the remaining arguments are the arguments that were\n\
5078 passed to that primitive. For example, if you do\n\
5079 (file-exists-p FILENAME)\n\
5080 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
5081 (funcall HANDLER 'file-exists-p FILENAME)\n\
5082 The function `find-file-name-handler' checks this list for a handler\n\
5083 for its argument.");
5084 Vfile_name_handler_alist = Qnil;
5085
5086 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
5087 "A list of functions to be called at the end of `insert-file-contents'.\n\
5088 Each is passed one argument, the number of bytes inserted. It should return\n\
5089 the new byte count, and leave point the same. If `insert-file-contents' is\n\
5090 intercepted by a handler from `file-name-handler-alist', that handler is\n\
5091 responsible for calling the after-insert-file-functions if appropriate.");
5092 Vafter_insert_file_functions = Qnil;
5093
5094 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
5095 "A list of functions to be called at the start of `write-region'.\n\
5096 Each is passed two arguments, START and END as for `write-region'.\n\
5097 These are usually two numbers but not always; see the documentation\n\
5098 for `write-region'. The function should return a list of pairs\n\
5099 of the form (POSITION . STRING), consisting of strings to be effectively\n\
5100 inserted at the specified positions of the file being written (1 means to\n\
5101 insert before the first byte written). The POSITIONs must be sorted into\n\
5102 increasing order. If there are several functions in the list, the several\n\
5103 lists are merged destructively.");
5104 Vwrite_region_annotate_functions = Qnil;
5105
5106 DEFVAR_LISP ("write-region-annotations-so-far",
5107 &Vwrite_region_annotations_so_far,
5108 "When an annotation function is called, this holds the previous annotations.\n\
5109 These are the annotations made by other annotation functions\n\
5110 that were already called. See also `write-region-annotate-functions'.");
5111 Vwrite_region_annotations_so_far = Qnil;
5112
5113 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
5114 "A list of file name handlers that temporarily should not be used.\n\
5115 This applies only to the operation `inhibit-file-name-operation'.");
5116 Vinhibit_file_name_handlers = Qnil;
5117
5118 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
5119 "The operation for which `inhibit-file-name-handlers' is applicable.");
5120 Vinhibit_file_name_operation = Qnil;
5121
5122 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
5123 "File name in which we write a list of all auto save file names.\n\
5124 This variable is initialized automatically from `auto-save-list-file-prefix'\n\
5125 shortly after Emacs reads your `.emacs' file, if you have not yet given it\n\
5126 a non-nil value.");
5127 Vauto_save_list_file_name = Qnil;
5128
5129 defsubr (&Sfind_file_name_handler);
5130 defsubr (&Sfile_name_directory);
5131 defsubr (&Sfile_name_nondirectory);
5132 defsubr (&Sunhandled_file_name_directory);
5133 defsubr (&Sfile_name_as_directory);
5134 defsubr (&Sdirectory_file_name);
5135 defsubr (&Smake_temp_name);
5136 defsubr (&Sexpand_file_name);
5137 defsubr (&Ssubstitute_in_file_name);
5138 defsubr (&Scopy_file);
5139 defsubr (&Smake_directory_internal);
5140 defsubr (&Sdelete_directory);
5141 defsubr (&Sdelete_file);
5142 defsubr (&Srename_file);
5143 defsubr (&Sadd_name_to_file);
5144 #ifdef S_IFLNK
5145 defsubr (&Smake_symbolic_link);
5146 #endif /* S_IFLNK */
5147 #ifdef VMS
5148 defsubr (&Sdefine_logical_name);
5149 #endif /* VMS */
5150 #ifdef HPUX_NET
5151 defsubr (&Ssysnetunam);
5152 #endif /* HPUX_NET */
5153 defsubr (&Sfile_name_absolute_p);
5154 defsubr (&Sfile_exists_p);
5155 defsubr (&Sfile_executable_p);
5156 defsubr (&Sfile_readable_p);
5157 defsubr (&Sfile_writable_p);
5158 defsubr (&Saccess_file);
5159 defsubr (&Sfile_symlink_p);
5160 defsubr (&Sfile_directory_p);
5161 defsubr (&Sfile_accessible_directory_p);
5162 defsubr (&Sfile_regular_p);
5163 defsubr (&Sfile_modes);
5164 defsubr (&Sset_file_modes);
5165 defsubr (&Sset_default_file_modes);
5166 defsubr (&Sdefault_file_modes);
5167 defsubr (&Sfile_newer_than_file_p);
5168 defsubr (&Sinsert_file_contents);
5169 defsubr (&Swrite_region);
5170 defsubr (&Scar_less_than_car);
5171 defsubr (&Sverify_visited_file_modtime);
5172 defsubr (&Sclear_visited_file_modtime);
5173 defsubr (&Svisited_file_modtime);
5174 defsubr (&Sset_visited_file_modtime);
5175 defsubr (&Sdo_auto_save);
5176 defsubr (&Sset_buffer_auto_saved);
5177 defsubr (&Sclear_buffer_auto_save_failure);
5178 defsubr (&Srecent_auto_save_p);
5179
5180 defsubr (&Sread_file_name_internal);
5181 defsubr (&Sread_file_name);
5182
5183 #ifdef unix
5184 defsubr (&Sunix_sync);
5185 #endif
5186 }