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