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