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