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