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