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