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