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