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