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