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