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