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