*** empty log message ***
[bpt/emacs.git] / src / fileio.c
CommitLineData
570d7624 1/* File IO for GNU Emacs.
43fb7d9a
DL
2 Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000
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;
1976 unsigned char *target;
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 */
2183}
2184\f
067ffa38 2185/* A slightly faster and more convenient way to get
298b760e 2186 (directory-file-name (expand-file-name FOO)). */
067ffa38 2187
570d7624
JB
2188Lisp_Object
2189expand_and_dir_to_file (filename, defdir)
2190 Lisp_Object filename, defdir;
2191{
199607e4 2192 register Lisp_Object absname;
570d7624 2193
199607e4 2194 absname = Fexpand_file_name (filename, defdir);
570d7624
JB
2195#ifdef VMS
2196 {
fc932ac6 2197 register int c = XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1];
570d7624 2198 if (c == ':' || c == ']' || c == '>')
199607e4 2199 absname = Fdirectory_file_name (absname);
570d7624
JB
2200 }
2201#else
199607e4 2202 /* Remove final slash, if any (unless this is the root dir).
570d7624 2203 stat behaves differently depending! */
199607e4 2204 if (XSTRING (absname)->size > 1
fc932ac6
RS
2205 && IS_DIRECTORY_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname)) - 1])
2206 && !IS_DEVICE_SEP (XSTRING (absname)->data[STRING_BYTES (XSTRING (absname))-2]))
ddc61f46 2207 /* We cannot take shortcuts; they might be wrong for magic file names. */
199607e4 2208 absname = Fdirectory_file_name (absname);
570d7624 2209#endif
199607e4 2210 return absname;
570d7624
JB
2211}
2212\f
3ed15d97
RS
2213/* Signal an error if the file ABSNAME already exists.
2214 If INTERACTIVE is nonzero, ask the user whether to proceed,
2215 and bypass the error if the user says to go ahead.
2216 QUERYSTRING is a name for the action that is being considered
2217 to alter the file.
de1d0127 2218
3ed15d97 2219 *STATPTR is used to store the stat information if the file exists.
de1d0127 2220 If the file does not exist, STATPTR->st_mode is set to 0.
b8b29dc9
RS
2221 If STATPTR is null, we don't store into it.
2222
2223 If QUICK is nonzero, we ask for y or n, not yes or no. */
3ed15d97 2224
c4df73f9 2225void
b8b29dc9 2226barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
570d7624
JB
2227 Lisp_Object absname;
2228 unsigned char *querystring;
2229 int interactive;
3ed15d97 2230 struct stat *statptr;
b8b29dc9 2231 int quick;
570d7624 2232{
643c73b9 2233 register Lisp_Object tem, encoded_filename;
4018b5ef 2234 struct stat statbuf;
570d7624
JB
2235 struct gcpro gcpro1;
2236
643c73b9
RS
2237 encoded_filename = ENCODE_FILE (absname);
2238
4018b5ef
RS
2239 /* stat is a good way to tell whether the file exists,
2240 regardless of what access permissions it has. */
643c73b9 2241 if (stat (XSTRING (encoded_filename)->data, &statbuf) >= 0)
570d7624
JB
2242 {
2243 if (! interactive)
2244 Fsignal (Qfile_already_exists,
2245 Fcons (build_string ("File already exists"),
2246 Fcons (absname, Qnil)));
2247 GCPRO1 (absname);
b8b29dc9
RS
2248 tem = format1 ("File %s already exists; %s anyway? ",
2249 XSTRING (absname)->data, querystring);
2250 if (quick)
2251 tem = Fy_or_n_p (tem);
2252 else
2253 tem = do_yes_or_no_p (tem);
570d7624 2254 UNGCPRO;
265a9e55 2255 if (NILP (tem))
570d7624
JB
2256 Fsignal (Qfile_already_exists,
2257 Fcons (build_string ("File already exists"),
2258 Fcons (absname, Qnil)));
3ed15d97
RS
2259 if (statptr)
2260 *statptr = statbuf;
2261 }
2262 else
2263 {
2264 if (statptr)
2265 statptr->st_mode = 0;
570d7624
JB
2266 }
2267 return;
2268}
2269
2270DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 4,
349a7710 2271 "fCopy file: \nFCopy %s to file: \np\nP",
570d7624
JB
2272 "Copy FILE to NEWNAME. Both args must be strings.\n\
2273Signals a `file-already-exists' error if file NEWNAME already exists,\n\
2274unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.\n\
2275A number as third arg means request confirmation if NEWNAME already exists.\n\
2276This is what happens in interactive use with M-x.\n\
349a7710
JB
2277Fourth arg KEEP-TIME non-nil means give the new file the same\n\
2278last-modified time as the old one. (This works on only some systems.)\n\
2279A prefix arg makes KEEP-TIME non-nil.")
3b7f6e60
EN
2280 (file, newname, ok_if_already_exists, keep_date)
2281 Lisp_Object file, newname, ok_if_already_exists, keep_date;
570d7624
JB
2282{
2283 int ifd, ofd, n;
2284 char buf[16 * 1024];
3ed15d97 2285 struct stat st, out_st;
32f4334d 2286 Lisp_Object handler;
b1d1b865 2287 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
b5148e85 2288 int count = specpdl_ptr - specpdl;
f73b0ada 2289 int input_file_statable_p;
b1d1b865 2290 Lisp_Object encoded_file, encoded_newname;
570d7624 2291
b1d1b865
RS
2292 encoded_file = encoded_newname = Qnil;
2293 GCPRO4 (file, newname, encoded_file, encoded_newname);
3b7f6e60 2294 CHECK_STRING (file, 0);
570d7624 2295 CHECK_STRING (newname, 1);
b1d1b865 2296
3b7f6e60 2297 file = Fexpand_file_name (file, Qnil);
570d7624 2298 newname = Fexpand_file_name (newname, Qnil);
32f4334d 2299
0bf2eed2 2300 /* If the input file name has special constructs in it,
32f4334d 2301 call the corresponding file handler. */
3b7f6e60 2302 handler = Ffind_file_name_handler (file, Qcopy_file);
0bf2eed2 2303 /* Likewise for output file name. */
51cf6d37 2304 if (NILP (handler))
49307295 2305 handler = Ffind_file_name_handler (newname, Qcopy_file);
32f4334d 2306 if (!NILP (handler))
3b7f6e60 2307 RETURN_UNGCPRO (call5 (handler, Qcopy_file, file, newname,
36712b0a 2308 ok_if_already_exists, keep_date));
32f4334d 2309
b1d1b865
RS
2310 encoded_file = ENCODE_FILE (file);
2311 encoded_newname = ENCODE_FILE (newname);
2312
265a9e55 2313 if (NILP (ok_if_already_exists)
93c30b5f 2314 || INTEGERP (ok_if_already_exists))
b1d1b865 2315 barf_or_query_if_file_exists (encoded_newname, "copy to it",
b8b29dc9 2316 INTEGERP (ok_if_already_exists), &out_st, 0);
b1d1b865 2317 else if (stat (XSTRING (encoded_newname)->data, &out_st) < 0)
3ed15d97 2318 out_st.st_mode = 0;
570d7624 2319
68c45bf0 2320 ifd = emacs_open (XSTRING (encoded_file)->data, O_RDONLY, 0);
570d7624 2321 if (ifd < 0)
3b7f6e60 2322 report_file_error ("Opening input file", Fcons (file, Qnil));
570d7624 2323
b5148e85
RS
2324 record_unwind_protect (close_file_unwind, make_number (ifd));
2325
f73b0ada
BF
2326 /* We can only copy regular files and symbolic links. Other files are not
2327 copyable by us. */
2328 input_file_statable_p = (fstat (ifd, &st) >= 0);
2329
f9ba66ce 2330#if !defined (DOS_NT) || __DJGPP__ > 1
3ed15d97
RS
2331 if (out_st.st_mode != 0
2332 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2333 {
2334 errno = 0;
2335 report_file_error ("Input and output files are the same",
3b7f6e60 2336 Fcons (file, Fcons (newname, Qnil)));
3ed15d97
RS
2337 }
2338#endif
2339
f73b0ada
BF
2340#if defined (S_ISREG) && defined (S_ISLNK)
2341 if (input_file_statable_p)
2342 {
2343 if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode)))
2344 {
2345#if defined (EISDIR)
2346 /* Get a better looking error message. */
2347 errno = EISDIR;
2348#endif /* EISDIR */
3b7f6e60 2349 report_file_error ("Non-regular file", Fcons (file, Qnil));
f73b0ada
BF
2350 }
2351 }
2352#endif /* S_ISREG && S_ISLNK */
2353
570d7624
JB
2354#ifdef VMS
2355 /* Create the copy file with the same record format as the input file */
b1d1b865 2356 ofd = sys_creat (XSTRING (encoded_newname)->data, 0666, ifd);
570d7624 2357#else
4c3c22f3
RS
2358#ifdef MSDOS
2359 /* System's default file type was set to binary by _fmode in emacs.c. */
b1d1b865 2360 ofd = creat (XSTRING (encoded_newname)->data, S_IREAD | S_IWRITE);
4c3c22f3 2361#else /* not MSDOS */
b1d1b865 2362 ofd = creat (XSTRING (encoded_newname)->data, 0666);
4c3c22f3 2363#endif /* not MSDOS */
570d7624
JB
2364#endif /* VMS */
2365 if (ofd < 0)
3ed15d97 2366 report_file_error ("Opening output file", Fcons (newname, Qnil));
b5148e85
RS
2367
2368 record_unwind_protect (close_file_unwind, make_number (ofd));
570d7624 2369
b5148e85
RS
2370 immediate_quit = 1;
2371 QUIT;
68c45bf0
PE
2372 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
2373 if (emacs_write (ofd, buf, n) != n)
3ed15d97 2374 report_file_error ("I/O error", Fcons (newname, Qnil));
b5148e85 2375 immediate_quit = 0;
570d7624 2376
5acac34e 2377 /* Closing the output clobbers the file times on some systems. */
68c45bf0 2378 if (emacs_close (ofd) < 0)
5acac34e
RS
2379 report_file_error ("I/O error", Fcons (newname, Qnil));
2380
f73b0ada 2381 if (input_file_statable_p)
570d7624 2382 {
265a9e55 2383 if (!NILP (keep_date))
570d7624 2384 {
de5bf5d3
JB
2385 EMACS_TIME atime, mtime;
2386 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
2387 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
b1d1b865
RS
2388 if (set_file_times (XSTRING (encoded_newname)->data,
2389 atime, mtime))
c0b7b21c 2390 Fsignal (Qfile_date_error,
d1b9ed63 2391 Fcons (build_string ("Cannot set file date"),
3dbcf3f6 2392 Fcons (newname, Qnil)));
570d7624 2393 }
2dc3be7e 2394#ifndef MSDOS
b1d1b865 2395 chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
2dc3be7e
RS
2396#else /* MSDOS */
2397#if defined (__DJGPP__) && __DJGPP__ > 1
2398 /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
2399 and if it can't, it tells so. Otherwise, under MSDOS we usually
2400 get only the READ bit, which will make the copied file read-only,
2401 so it's better not to chmod at all. */
2402 if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
b1d1b865 2403 chmod (XSTRING (encoded_newname)->data, st.st_mode & 07777);
2dc3be7e
RS
2404#endif /* DJGPP version 2 or newer */
2405#endif /* MSDOS */
570d7624
JB
2406 }
2407
68c45bf0 2408 emacs_close (ifd);
5acac34e 2409
b5148e85
RS
2410 /* Discard the unwind protects. */
2411 specpdl_ptr = specpdl + count;
2412
570d7624
JB
2413 UNGCPRO;
2414 return Qnil;
2415}
385b6cc7 2416\f
9bbe01fb 2417DEFUN ("make-directory-internal", Fmake_directory_internal,
353cfc19 2418 Smake_directory_internal, 1, 1, 0,
3b7f6e60
EN
2419 "Create a new directory named DIRECTORY.")
2420 (directory)
2421 Lisp_Object directory;
570d7624
JB
2422{
2423 unsigned char *dir;
32f4334d 2424 Lisp_Object handler;
b1d1b865 2425 Lisp_Object encoded_dir;
570d7624 2426
3b7f6e60
EN
2427 CHECK_STRING (directory, 0);
2428 directory = Fexpand_file_name (directory, Qnil);
32f4334d 2429
3b7f6e60 2430 handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
32f4334d 2431 if (!NILP (handler))
3b7f6e60 2432 return call2 (handler, Qmake_directory_internal, directory);
9bbe01fb 2433
b1d1b865
RS
2434 encoded_dir = ENCODE_FILE (directory);
2435
2436 dir = XSTRING (encoded_dir)->data;
570d7624 2437
5e570b75
RS
2438#ifdef WINDOWSNT
2439 if (mkdir (dir) != 0)
2440#else
570d7624 2441 if (mkdir (dir, 0777) != 0)
5e570b75 2442#endif
3b7f6e60 2443 report_file_error ("Creating directory", Flist (1, &directory));
570d7624 2444
32f4334d 2445 return Qnil;
570d7624
JB
2446}
2447
aa734e17 2448DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
3b7f6e60
EN
2449 "Delete the directory named DIRECTORY.")
2450 (directory)
2451 Lisp_Object directory;
570d7624
JB
2452{
2453 unsigned char *dir;
32f4334d 2454 Lisp_Object handler;
b1d1b865 2455 Lisp_Object encoded_dir;
570d7624 2456
3b7f6e60
EN
2457 CHECK_STRING (directory, 0);
2458 directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
570d7624 2459
3b7f6e60 2460 handler = Ffind_file_name_handler (directory, Qdelete_directory);
32f4334d 2461 if (!NILP (handler))
3b7f6e60 2462 return call2 (handler, Qdelete_directory, directory);
32f4334d 2463
b1d1b865
RS
2464 encoded_dir = ENCODE_FILE (directory);
2465
2466 dir = XSTRING (encoded_dir)->data;
2467
570d7624 2468 if (rmdir (dir) != 0)
3b7f6e60 2469 report_file_error ("Removing directory", Flist (1, &directory));
570d7624
JB
2470
2471 return Qnil;
2472}
2473
2474DEFUN ("delete-file", Fdelete_file, Sdelete_file, 1, 1, "fDelete file: ",
3b7f6e60 2475 "Delete file named FILENAME.\n\
570d7624
JB
2476If file has multiple names, it continues to exist with the other names.")
2477 (filename)
2478 Lisp_Object filename;
2479{
32f4334d 2480 Lisp_Object handler;
b1d1b865
RS
2481 Lisp_Object encoded_file;
2482
570d7624
JB
2483 CHECK_STRING (filename, 0);
2484 filename = Fexpand_file_name (filename, Qnil);
32f4334d 2485
49307295 2486 handler = Ffind_file_name_handler (filename, Qdelete_file);
32f4334d 2487 if (!NILP (handler))
8a9b0da9 2488 return call2 (handler, Qdelete_file, filename);
32f4334d 2489
b1d1b865
RS
2490 encoded_file = ENCODE_FILE (filename);
2491
2492 if (0 > unlink (XSTRING (encoded_file)->data))
570d7624 2493 report_file_error ("Removing old name", Flist (1, &filename));
8a9b0da9 2494 return Qnil;
570d7624
JB
2495}
2496
385b6cc7
RS
2497static Lisp_Object
2498internal_delete_file_1 (ignore)
2499 Lisp_Object ignore;
2500{
2501 return Qt;
2502}
2503
2504/* Delete file FILENAME, returning 1 if successful and 0 if failed. */
2505
2506int
2507internal_delete_file (filename)
2508 Lisp_Object filename;
2509{
2510 return NILP (internal_condition_case_1 (Fdelete_file, filename,
2511 Qt, internal_delete_file_1));
2512}
2513\f
570d7624
JB
2514DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2515 "fRename file: \nFRename %s to file: \np",
2516 "Rename FILE as NEWNAME. Both args strings.\n\
2517If file has names other than FILE, it continues to have those names.\n\
2518Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2519unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2520A number as third arg means request confirmation if NEWNAME already exists.\n\
2521This is what happens in interactive use with M-x.")
3b7f6e60
EN
2522 (file, newname, ok_if_already_exists)
2523 Lisp_Object file, newname, ok_if_already_exists;
570d7624
JB
2524{
2525#ifdef NO_ARG_ARRAY
2526 Lisp_Object args[2];
2527#endif
32f4334d 2528 Lisp_Object handler;
b1d1b865
RS
2529 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2530 Lisp_Object encoded_file, encoded_newname;
570d7624 2531
b1d1b865
RS
2532 encoded_file = encoded_newname = Qnil;
2533 GCPRO4 (file, newname, encoded_file, encoded_newname);
3b7f6e60 2534 CHECK_STRING (file, 0);
570d7624 2535 CHECK_STRING (newname, 1);
3b7f6e60 2536 file = Fexpand_file_name (file, Qnil);
570d7624 2537 newname = Fexpand_file_name (newname, Qnil);
32f4334d
RS
2538
2539 /* If the file name has special constructs in it,
2540 call the corresponding file handler. */
3b7f6e60 2541 handler = Ffind_file_name_handler (file, Qrename_file);
51cf6d37 2542 if (NILP (handler))
49307295 2543 handler = Ffind_file_name_handler (newname, Qrename_file);
32f4334d 2544 if (!NILP (handler))
36712b0a 2545 RETURN_UNGCPRO (call4 (handler, Qrename_file,
3b7f6e60 2546 file, newname, ok_if_already_exists));
32f4334d 2547
b1d1b865
RS
2548 encoded_file = ENCODE_FILE (file);
2549 encoded_newname = ENCODE_FILE (newname);
2550
bc77278f
EZ
2551#ifdef DOS_NT
2552 /* If the file names are identical but for the case, don't ask for
2553 confirmation: they simply want to change the letter-case of the
2554 file name. */
2555 if (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
2556#endif
265a9e55 2557 if (NILP (ok_if_already_exists)
93c30b5f 2558 || INTEGERP (ok_if_already_exists))
b1d1b865 2559 barf_or_query_if_file_exists (encoded_newname, "rename to it",
b8b29dc9 2560 INTEGERP (ok_if_already_exists), 0, 0);
570d7624 2561#ifndef BSD4_1
b1d1b865 2562 if (0 > rename (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
570d7624 2563#else
b1d1b865
RS
2564 if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data)
2565 || 0 > unlink (XSTRING (encoded_file)->data))
570d7624
JB
2566#endif
2567 {
2568 if (errno == EXDEV)
2569 {
3b7f6e60 2570 Fcopy_file (file, newname,
d093c3ac
RM
2571 /* We have already prompted if it was an integer,
2572 so don't have copy-file prompt again. */
2573 NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
3b7f6e60 2574 Fdelete_file (file);
570d7624
JB
2575 }
2576 else
2577#ifdef NO_ARG_ARRAY
2578 {
3b7f6e60 2579 args[0] = file;
570d7624
JB
2580 args[1] = newname;
2581 report_file_error ("Renaming", Flist (2, args));
2582 }
2583#else
3b7f6e60 2584 report_file_error ("Renaming", Flist (2, &file));
570d7624
JB
2585#endif
2586 }
2587 UNGCPRO;
2588 return Qnil;
2589}
2590
2591DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
2592 "fAdd name to file: \nFName to add to %s: \np",
2593 "Give FILE additional name NEWNAME. Both args strings.\n\
2594Signals a `file-already-exists' error if a file NEWNAME already exists\n\
2595unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
2596A number as third arg means request confirmation if NEWNAME already exists.\n\
2597This is what happens in interactive use with M-x.")
3b7f6e60
EN
2598 (file, newname, ok_if_already_exists)
2599 Lisp_Object file, newname, ok_if_already_exists;
570d7624
JB
2600{
2601#ifdef NO_ARG_ARRAY
2602 Lisp_Object args[2];
2603#endif
32f4334d 2604 Lisp_Object handler;
b1d1b865
RS
2605 Lisp_Object encoded_file, encoded_newname;
2606 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
570d7624 2607
b1d1b865
RS
2608 GCPRO4 (file, newname, encoded_file, encoded_newname);
2609 encoded_file = encoded_newname = Qnil;
3b7f6e60 2610 CHECK_STRING (file, 0);
570d7624 2611 CHECK_STRING (newname, 1);
3b7f6e60 2612 file = Fexpand_file_name (file, Qnil);
570d7624 2613 newname = Fexpand_file_name (newname, Qnil);
32f4334d
RS
2614
2615 /* If the file name has special constructs in it,
2616 call the corresponding file handler. */
3b7f6e60 2617 handler = Ffind_file_name_handler (file, Qadd_name_to_file);
32f4334d 2618 if (!NILP (handler))
3b7f6e60 2619 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
36712b0a 2620 newname, ok_if_already_exists));
32f4334d 2621
adc6741c
RS
2622 /* If the new name has special constructs in it,
2623 call the corresponding file handler. */
2624 handler = Ffind_file_name_handler (newname, Qadd_name_to_file);
2625 if (!NILP (handler))
3b7f6e60 2626 RETURN_UNGCPRO (call4 (handler, Qadd_name_to_file, file,
adc6741c
RS
2627 newname, ok_if_already_exists));
2628
b1d1b865
RS
2629 encoded_file = ENCODE_FILE (file);
2630 encoded_newname = ENCODE_FILE (newname);
2631
265a9e55 2632 if (NILP (ok_if_already_exists)
93c30b5f 2633 || INTEGERP (ok_if_already_exists))
b1d1b865 2634 barf_or_query_if_file_exists (encoded_newname, "make it a new name",
b8b29dc9 2635 INTEGERP (ok_if_already_exists), 0, 0);
5e570b75 2636
570d7624 2637 unlink (XSTRING (newname)->data);
b1d1b865 2638 if (0 > link (XSTRING (encoded_file)->data, XSTRING (encoded_newname)->data))
570d7624
JB
2639 {
2640#ifdef NO_ARG_ARRAY
3b7f6e60 2641 args[0] = file;
570d7624
JB
2642 args[1] = newname;
2643 report_file_error ("Adding new name", Flist (2, args));
2644#else
3b7f6e60 2645 report_file_error ("Adding new name", Flist (2, &file));
570d7624
JB
2646#endif
2647 }
2648
2649 UNGCPRO;
2650 return Qnil;
2651}
2652
2653#ifdef S_IFLNK
2654DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2655 "FMake symbolic link to file: \nFMake symbolic link to file %s: \np",
2656 "Make a symbolic link to FILENAME, named LINKNAME. Both args strings.\n\
11183104 2657Signals a `file-already-exists' error if a file LINKNAME already exists\n\
570d7624 2658unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.\n\
11183104 2659A number as third arg means request confirmation if LINKNAME already exists.\n\
570d7624 2660This happens for interactive use with M-x.")
e5d77022
JB
2661 (filename, linkname, ok_if_already_exists)
2662 Lisp_Object filename, linkname, ok_if_already_exists;
570d7624
JB
2663{
2664#ifdef NO_ARG_ARRAY
2665 Lisp_Object args[2];
2666#endif
32f4334d 2667 Lisp_Object handler;
b1d1b865
RS
2668 Lisp_Object encoded_filename, encoded_linkname;
2669 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
570d7624 2670
b1d1b865
RS
2671 GCPRO4 (filename, linkname, encoded_filename, encoded_linkname);
2672 encoded_filename = encoded_linkname = Qnil;
570d7624 2673 CHECK_STRING (filename, 0);
e5d77022 2674 CHECK_STRING (linkname, 1);
d9bc1c99
RS
2675 /* If the link target has a ~, we must expand it to get
2676 a truly valid file name. Otherwise, do not expand;
2677 we want to permit links to relative file names. */
2678 if (XSTRING (filename)->data[0] == '~')
2679 filename = Fexpand_file_name (filename, Qnil);
e5d77022 2680 linkname = Fexpand_file_name (linkname, Qnil);
32f4334d
RS
2681
2682 /* If the file name has special constructs in it,
2683 call the corresponding file handler. */
49307295 2684 handler = Ffind_file_name_handler (filename, Qmake_symbolic_link);
32f4334d 2685 if (!NILP (handler))
36712b0a
KH
2686 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2687 linkname, ok_if_already_exists));
32f4334d 2688
adc6741c
RS
2689 /* If the new link name has special constructs in it,
2690 call the corresponding file handler. */
2691 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
2692 if (!NILP (handler))
2693 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2694 linkname, ok_if_already_exists));
2695
b1d1b865
RS
2696 encoded_filename = ENCODE_FILE (filename);
2697 encoded_linkname = ENCODE_FILE (linkname);
2698
265a9e55 2699 if (NILP (ok_if_already_exists)
93c30b5f 2700 || INTEGERP (ok_if_already_exists))
b1d1b865 2701 barf_or_query_if_file_exists (encoded_linkname, "make it a link",
b8b29dc9 2702 INTEGERP (ok_if_already_exists), 0, 0);
b1d1b865
RS
2703 if (0 > symlink (XSTRING (encoded_filename)->data,
2704 XSTRING (encoded_linkname)->data))
570d7624
JB
2705 {
2706 /* If we didn't complain already, silently delete existing file. */
2707 if (errno == EEXIST)
2708 {
b1d1b865
RS
2709 unlink (XSTRING (encoded_linkname)->data);
2710 if (0 <= symlink (XSTRING (encoded_filename)->data,
2711 XSTRING (encoded_linkname)->data))
1a04498e
KH
2712 {
2713 UNGCPRO;
2714 return Qnil;
2715 }
570d7624
JB
2716 }
2717
2718#ifdef NO_ARG_ARRAY
2719 args[0] = filename;
e5d77022 2720 args[1] = linkname;
570d7624
JB
2721 report_file_error ("Making symbolic link", Flist (2, args));
2722#else
2723 report_file_error ("Making symbolic link", Flist (2, &filename));
2724#endif
2725 }
2726 UNGCPRO;
2727 return Qnil;
2728}
2729#endif /* S_IFLNK */
2730
2731#ifdef VMS
2732
2733DEFUN ("define-logical-name", Fdefine_logical_name, Sdefine_logical_name,
2734 2, 2, "sDefine logical name: \nsDefine logical name %s as: ",
2735 "Define the job-wide logical name NAME to have the value STRING.\n\
2736If STRING is nil or a null string, the logical name NAME is deleted.")
3b7f6e60
EN
2737 (name, string)
2738 Lisp_Object name;
570d7624
JB
2739 Lisp_Object string;
2740{
3b7f6e60 2741 CHECK_STRING (name, 0);
265a9e55 2742 if (NILP (string))
3b7f6e60 2743 delete_logical_name (XSTRING (name)->data);
570d7624
JB
2744 else
2745 {
2746 CHECK_STRING (string, 1);
2747
2748 if (XSTRING (string)->size == 0)
3b7f6e60 2749 delete_logical_name (XSTRING (name)->data);
570d7624 2750 else
3b7f6e60 2751 define_logical_name (XSTRING (name)->data, XSTRING (string)->data);
570d7624
JB
2752 }
2753
2754 return string;
2755}
2756#endif /* VMS */
2757
2758#ifdef HPUX_NET
2759
2760DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2761 "Open a network connection to PATH using LOGIN as the login string.")
2762 (path, login)
2763 Lisp_Object path, login;
2764{
2765 int netresult;
199607e4 2766
570d7624 2767 CHECK_STRING (path, 0);
199607e4
RS
2768 CHECK_STRING (login, 0);
2769
570d7624
JB
2770 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2771
2772 if (netresult == -1)
2773 return Qnil;
2774 else
2775 return Qt;
2776}
2777#endif /* HPUX_NET */
2778\f
2779DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2780 1, 1, 0,
199607e4 2781 "Return t if file FILENAME specifies an absolute file name.\n\
570d7624
JB
2782On Unix, this is a name starting with a `/' or a `~'.")
2783 (filename)
2784 Lisp_Object filename;
2785{
2786 unsigned char *ptr;
2787
2788 CHECK_STRING (filename, 0);
2789 ptr = XSTRING (filename)->data;
5e570b75 2790 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
570d7624
JB
2791#ifdef VMS
2792/* ??? This criterion is probably wrong for '<'. */
2793 || index (ptr, ':') || index (ptr, '<')
2794 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2795 && ptr[1] != '.')
2796#endif /* VMS */
5e570b75 2797#ifdef DOS_NT
199607e4 2798 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
4c3c22f3 2799#endif
570d7624
JB
2800 )
2801 return Qt;
2802 else
2803 return Qnil;
2804}
3beeedfe
RS
2805\f
2806/* Return nonzero if file FILENAME exists and can be executed. */
2807
2808static int
2809check_executable (filename)
2810 char *filename;
2811{
3be3c08e
RS
2812#ifdef DOS_NT
2813 int len = strlen (filename);
2814 char *suffix;
2815 struct stat st;
2816 if (stat (filename, &st) < 0)
2817 return 0;
34ead71a 2818#if defined (WINDOWSNT) || (defined (MSDOS) && __DJGPP__ > 1)
199607e4
RS
2819 return ((st.st_mode & S_IEXEC) != 0);
2820#else
3be3c08e
RS
2821 return (S_ISREG (st.st_mode)
2822 && len >= 5
2823 && (stricmp ((suffix = filename + len-4), ".com") == 0
2824 || stricmp (suffix, ".exe") == 0
2dc3be7e
RS
2825 || stricmp (suffix, ".bat") == 0)
2826 || (st.st_mode & S_IFMT) == S_IFDIR);
199607e4 2827#endif /* not WINDOWSNT */
3be3c08e 2828#else /* not DOS_NT */
de0be7dd
RS
2829#ifdef HAVE_EUIDACCESS
2830 return (euidaccess (filename, 1) >= 0);
3beeedfe
RS
2831#else
2832 /* Access isn't quite right because it uses the real uid
2833 and we really want to test with the effective uid.
2834 But Unix doesn't give us a right way to do it. */
2835 return (access (filename, 1) >= 0);
2836#endif
3be3c08e 2837#endif /* not DOS_NT */
3beeedfe
RS
2838}
2839
2840/* Return nonzero if file FILENAME exists and can be written. */
2841
2842static int
2843check_writable (filename)
2844 char *filename;
2845{
3be3c08e
RS
2846#ifdef MSDOS
2847 struct stat st;
2848 if (stat (filename, &st) < 0)
2849 return 0;
2850 return (st.st_mode & S_IWRITE || (st.st_mode & S_IFMT) == S_IFDIR);
2851#else /* not MSDOS */
41f3fb38
KH
2852#ifdef HAVE_EUIDACCESS
2853 return (euidaccess (filename, 2) >= 0);
3beeedfe
RS
2854#else
2855 /* Access isn't quite right because it uses the real uid
2856 and we really want to test with the effective uid.
2857 But Unix doesn't give us a right way to do it.
2858 Opening with O_WRONLY could work for an ordinary file,
2859 but would lose for directories. */
2860 return (access (filename, 2) >= 0);
2861#endif
3be3c08e 2862#endif /* not MSDOS */
3beeedfe 2863}
570d7624
JB
2864
2865DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2866 "Return t if file FILENAME exists. (This does not mean you can read it.)\n\
2867See also `file-readable-p' and `file-attributes'.")
2868 (filename)
2869 Lisp_Object filename;
2870{
199607e4 2871 Lisp_Object absname;
32f4334d 2872 Lisp_Object handler;
4018b5ef 2873 struct stat statbuf;
570d7624
JB
2874
2875 CHECK_STRING (filename, 0);
199607e4 2876 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
2877
2878 /* If the file name has special constructs in it,
2879 call the corresponding file handler. */
199607e4 2880 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
32f4334d 2881 if (!NILP (handler))
199607e4 2882 return call2 (handler, Qfile_exists_p, absname);
32f4334d 2883
b1d1b865
RS
2884 absname = ENCODE_FILE (absname);
2885
199607e4 2886 return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
570d7624
JB
2887}
2888
2889DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
2890 "Return t if FILENAME can be executed by you.\n\
8b235fde 2891For a directory, this means you can access files in that directory.")
570d7624
JB
2892 (filename)
2893 Lisp_Object filename;
2894
2895{
199607e4 2896 Lisp_Object absname;
32f4334d 2897 Lisp_Object handler;
570d7624
JB
2898
2899 CHECK_STRING (filename, 0);
199607e4 2900 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
2901
2902 /* If the file name has special constructs in it,
2903 call the corresponding file handler. */
199607e4 2904 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
32f4334d 2905 if (!NILP (handler))
199607e4 2906 return call2 (handler, Qfile_executable_p, absname);
32f4334d 2907
b1d1b865
RS
2908 absname = ENCODE_FILE (absname);
2909
199607e4 2910 return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
570d7624
JB
2911}
2912
2913DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2914 "Return t if file FILENAME exists and you can read it.\n\
2915See also `file-exists-p' and `file-attributes'.")
2916 (filename)
2917 Lisp_Object filename;
2918{
199607e4 2919 Lisp_Object absname;
32f4334d 2920 Lisp_Object handler;
4018b5ef 2921 int desc;
bb369dc6
RS
2922 int flags;
2923 struct stat statbuf;
570d7624
JB
2924
2925 CHECK_STRING (filename, 0);
199607e4 2926 absname = Fexpand_file_name (filename, Qnil);
32f4334d
RS
2927
2928 /* If the file name has special constructs in it,
2929 call the corresponding file handler. */
199607e4 2930 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
32f4334d 2931 if (!NILP (handler))
199607e4 2932 return call2 (handler, Qfile_readable_p, absname);
32f4334d 2933
b1d1b865
RS
2934 absname = ENCODE_FILE (absname);
2935
199607e4
RS
2936#ifdef DOS_NT
2937 /* Under MS-DOS and Windows, open does not work for directories. */
2938 if (access (XSTRING (absname)->data, 0) == 0)
a8a7d065
RS
2939 return Qt;
2940 return Qnil;
199607e4 2941#else /* not DOS_NT */
bb369dc6
RS
2942 flags = O_RDONLY;
2943#if defined (S_ISFIFO) && defined (O_NONBLOCK)
2944 /* Opening a fifo without O_NONBLOCK can wait.
2945 We don't want to wait. But we don't want to mess wth O_NONBLOCK
2946 except in the case of a fifo, on a system which handles it. */
2947 desc = stat (XSTRING (absname)->data, &statbuf);
2948 if (desc < 0)
2949 return Qnil;
2950 if (S_ISFIFO (statbuf.st_mode))
2951 flags |= O_NONBLOCK;
2952#endif
68c45bf0 2953 desc = emacs_open (XSTRING (absname)->data, flags, 0);
4018b5ef
RS
2954 if (desc < 0)
2955 return Qnil;
68c45bf0 2956 emacs_close (desc);
4018b5ef 2957 return Qt;
199607e4 2958#endif /* not DOS_NT */
570d7624
JB
2959}
2960
f793dc6c
RS
2961/* Having this before file-symlink-p mysteriously caused it to be forgotten
2962 on the RT/PC. */
2963DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2964 "Return t if file FILENAME can be written or created by you.")
2965 (filename)
2966 Lisp_Object filename;
2967{
b1d1b865 2968 Lisp_Object absname, dir, encoded;
f793dc6c
RS
2969 Lisp_Object handler;
2970 struct stat statbuf;
2971
2972 CHECK_STRING (filename, 0);
199607e4 2973 absname = Fexpand_file_name (filename, Qnil);
f793dc6c
RS
2974
2975 /* If the file name has special constructs in it,
2976 call the corresponding file handler. */
199607e4 2977 handler = Ffind_file_name_handler (absname, Qfile_writable_p);
f793dc6c 2978 if (!NILP (handler))
199607e4 2979 return call2 (handler, Qfile_writable_p, absname);
f793dc6c 2980
b1d1b865
RS
2981 encoded = ENCODE_FILE (absname);
2982 if (stat (XSTRING (encoded)->data, &statbuf) >= 0)
2983 return (check_writable (XSTRING (encoded)->data)
f793dc6c 2984 ? Qt : Qnil);
b1d1b865 2985
199607e4 2986 dir = Ffile_name_directory (absname);
f793dc6c
RS
2987#ifdef VMS
2988 if (!NILP (dir))
2989 dir = Fdirectory_file_name (dir);
2990#endif /* VMS */
2991#ifdef MSDOS
2992 if (!NILP (dir))
2993 dir = Fdirectory_file_name (dir);
2994#endif /* MSDOS */
b1d1b865
RS
2995
2996 dir = ENCODE_FILE (dir);
e3e8a75a
GM
2997#ifdef WINDOWSNT
2998 /* The read-only attribute of the parent directory doesn't affect
2999 whether a file or directory can be created within it. Some day we
3000 should check ACLs though, which do affect this. */
3001 if (stat (XSTRING (dir)->data, &statbuf) < 0)
3002 return Qnil;
3003 return (statbuf.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
3004#else
f793dc6c
RS
3005 return (check_writable (!NILP (dir) ? (char *) XSTRING (dir)->data : "")
3006 ? Qt : Qnil);
e3e8a75a 3007#endif
f793dc6c
RS
3008}
3009\f
1f8653eb
RS
3010DEFUN ("access-file", Faccess_file, Saccess_file, 2, 2, 0,
3011 "Access file FILENAME, and get an error if that does not work.\n\
3012The second argument STRING is used in the error message.\n\
3013If there is no error, we return nil.")
3014 (filename, string)
3015 Lisp_Object filename, string;
3016{
b1d1b865 3017 Lisp_Object handler, encoded_filename;
1f8653eb
RS
3018 int fd;
3019
3020 CHECK_STRING (filename, 0);
a79485af 3021 CHECK_STRING (string, 1);
1f8653eb
RS
3022
3023 /* If the file name has special constructs in it,
3024 call the corresponding file handler. */
3025 handler = Ffind_file_name_handler (filename, Qaccess_file);
3026 if (!NILP (handler))
3027 return call3 (handler, Qaccess_file, filename, string);
3028
b1d1b865
RS
3029 encoded_filename = ENCODE_FILE (filename);
3030
68c45bf0 3031 fd = emacs_open (XSTRING (encoded_filename)->data, O_RDONLY, 0);
1f8653eb
RS
3032 if (fd < 0)
3033 report_file_error (XSTRING (string)->data, Fcons (filename, Qnil));
68c45bf0 3034 emacs_close (fd);
1f8653eb
RS
3035
3036 return Qnil;
3037}
3038\f
570d7624 3039DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
89de89c7
RS
3040 "Return non-nil if file FILENAME is the name of a symbolic link.\n\
3041The value is the name of the file to which it is linked.\n\
3042Otherwise returns nil.")
570d7624
JB
3043 (filename)
3044 Lisp_Object filename;
3045{
3046#ifdef S_IFLNK
3047 char *buf;
3048 int bufsize;
3049 int valsize;
3050 Lisp_Object val;
32f4334d 3051 Lisp_Object handler;
570d7624
JB
3052
3053 CHECK_STRING (filename, 0);
3054 filename = Fexpand_file_name (filename, Qnil);
3055
32f4334d
RS
3056 /* If the file name has special constructs in it,
3057 call the corresponding file handler. */
49307295 3058 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
32f4334d
RS
3059 if (!NILP (handler))
3060 return call2 (handler, Qfile_symlink_p, filename);
3061
b1d1b865
RS
3062 filename = ENCODE_FILE (filename);
3063
570d7624
JB
3064 bufsize = 100;
3065 while (1)
3066 {
3067 buf = (char *) xmalloc (bufsize);
3068 bzero (buf, bufsize);
3069 valsize = readlink (XSTRING (filename)->data, buf, bufsize);
3070 if (valsize < bufsize) break;
3071 /* Buffer was not long enough */
9ac0d9e0 3072 xfree (buf);
570d7624
JB
3073 bufsize *= 2;
3074 }
3075 if (valsize == -1)
3076 {
9ac0d9e0 3077 xfree (buf);
570d7624
JB
3078 return Qnil;
3079 }
3080 val = make_string (buf, valsize);
69ac1891
GM
3081 if (buf[0] == '/' && index (buf, ':'))
3082 val = concat2 (build_string ("/:"), val);
9ac0d9e0 3083 xfree (buf);
cd913586
KH
3084 val = DECODE_FILE (val);
3085 return val;
570d7624
JB
3086#else /* not S_IFLNK */
3087 return Qnil;
3088#endif /* not S_IFLNK */
3089}
3090
570d7624 3091DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
3be6c6a0
DL
3092 "Return t if FILENAME names an existing directory.\n\
3093Symbolic links to directories count as directories.\n\
3094See `file-symlink-p' to distinguish symlinks.")
570d7624
JB
3095 (filename)
3096 Lisp_Object filename;
3097{
199607e4 3098 register Lisp_Object absname;
570d7624 3099 struct stat st;
32f4334d 3100 Lisp_Object handler;
570d7624 3101
199607e4 3102 absname = expand_and_dir_to_file (filename, current_buffer->directory);
570d7624 3103
32f4334d
RS
3104 /* If the file name has special constructs in it,
3105 call the corresponding file handler. */
199607e4 3106 handler = Ffind_file_name_handler (absname, Qfile_directory_p);
32f4334d 3107 if (!NILP (handler))
199607e4 3108 return call2 (handler, Qfile_directory_p, absname);
32f4334d 3109
b1d1b865
RS
3110 absname = ENCODE_FILE (absname);
3111
199607e4 3112 if (stat (XSTRING (absname)->data, &st) < 0)
570d7624
JB
3113 return Qnil;
3114 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
3115}
3116
b72dea2a
JB
3117DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, Sfile_accessible_directory_p, 1, 1, 0,
3118 "Return t if file FILENAME is the name of a directory as a file,\n\
3119and files in that directory can be opened by you. In order to use a\n\
3120directory as a buffer's current directory, this predicate must return true.\n\
3121A directory name spec may be given instead; then the value is t\n\
3122if the directory so specified exists and really is a readable and\n\
3123searchable directory.")
3124 (filename)
3125 Lisp_Object filename;
3126{
32f4334d 3127 Lisp_Object handler;
1a04498e 3128 int tem;
d26859eb 3129 struct gcpro gcpro1;
32f4334d
RS
3130
3131 /* If the file name has special constructs in it,
3132 call the corresponding file handler. */
49307295 3133 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
32f4334d
RS
3134 if (!NILP (handler))
3135 return call2 (handler, Qfile_accessible_directory_p, filename);
3136
d26859eb
KH
3137 /* It's an unlikely combination, but yes we really do need to gcpro:
3138 Suppose that file-accessible-directory-p has no handler, but
3139 file-directory-p does have a handler; this handler causes a GC which
3140 relocates the string in `filename'; and finally file-directory-p
3141 returns non-nil. Then we would end up passing a garbaged string
3142 to file-executable-p. */
3143 GCPRO1 (filename);
1a04498e
KH
3144 tem = (NILP (Ffile_directory_p (filename))
3145 || NILP (Ffile_executable_p (filename)));
d26859eb 3146 UNGCPRO;
1a04498e 3147 return tem ? Qnil : Qt;
b72dea2a
JB
3148}
3149
f793dc6c
RS
3150DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
3151 "Return t if file FILENAME is the name of a regular file.\n\
3152This is the sort of file that holds an ordinary stream of data bytes.")
3153 (filename)
3154 Lisp_Object filename;
3155{
199607e4 3156 register Lisp_Object absname;
f793dc6c
RS
3157 struct stat st;
3158 Lisp_Object handler;
3159
199607e4 3160 absname = expand_and_dir_to_file (filename, current_buffer->directory);
f793dc6c
RS
3161
3162 /* If the file name has special constructs in it,
3163 call the corresponding file handler. */
199607e4 3164 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
f793dc6c 3165 if (!NILP (handler))
199607e4 3166 return call2 (handler, Qfile_regular_p, absname);
f793dc6c 3167
b1d1b865
RS
3168 absname = ENCODE_FILE (absname);
3169
c1c4693e
RS
3170#ifdef WINDOWSNT
3171 {
3172 int result;
3173 Lisp_Object tem = Vw32_get_true_file_attributes;
3174
3175 /* Tell stat to use expensive method to get accurate info. */
3176 Vw32_get_true_file_attributes = Qt;
3177 result = stat (XSTRING (absname)->data, &st);
3178 Vw32_get_true_file_attributes = tem;
3179
3180 if (result < 0)
3181 return Qnil;
3182 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
3183 }
3184#else
4cd8344a 3185 if (stat (XSTRING (absname)->data, &st) < 0)
f793dc6c
RS
3186 return Qnil;
3187 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
c1c4693e 3188#endif
f793dc6c
RS
3189}
3190\f
570d7624 3191DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
3b7f6e60 3192 "Return mode bits of file named FILENAME, as an integer.")
570d7624
JB
3193 (filename)
3194 Lisp_Object filename;
3195{
199607e4 3196 Lisp_Object absname;
570d7624 3197 struct stat st;
32f4334d 3198 Lisp_Object handler;
570d7624 3199
199607e4 3200 absname = expand_and_dir_to_file (filename, current_buffer->directory);
570d7624 3201
32f4334d
RS
3202 /* If the file name has special constructs in it,
3203 call the corresponding file handler. */
199607e4 3204 handler = Ffind_file_name_handler (absname, Qfile_modes);
32f4334d 3205 if (!NILP (handler))
199607e4 3206 return call2 (handler, Qfile_modes, absname);
32f4334d 3207
b1d1b865
RS
3208 absname = ENCODE_FILE (absname);
3209
199607e4 3210 if (stat (XSTRING (absname)->data, &st) < 0)
570d7624 3211 return Qnil;
34ead71a 3212#if defined (MSDOS) && __DJGPP__ < 2
199607e4 3213 if (check_executable (XSTRING (absname)->data))
3be3c08e 3214 st.st_mode |= S_IEXEC;
34ead71a 3215#endif /* MSDOS && __DJGPP__ < 2 */
3ace87e3 3216
570d7624
JB
3217 return make_number (st.st_mode & 07777);
3218}
3219
3220DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2, 0,
3b7f6e60 3221 "Set mode bits of file named FILENAME to MODE (an integer).\n\
570d7624
JB
3222Only the 12 low bits of MODE are used.")
3223 (filename, mode)
3224 Lisp_Object filename, mode;
3225{
b1d1b865 3226 Lisp_Object absname, encoded_absname;
32f4334d 3227 Lisp_Object handler;
570d7624 3228
199607e4 3229 absname = Fexpand_file_name (filename, current_buffer->directory);
570d7624
JB
3230 CHECK_NUMBER (mode, 1);
3231
32f4334d
RS
3232 /* If the file name has special constructs in it,
3233 call the corresponding file handler. */
199607e4 3234 handler = Ffind_file_name_handler (absname, Qset_file_modes);
32f4334d 3235 if (!NILP (handler))
199607e4 3236 return call3 (handler, Qset_file_modes, absname, mode);
32f4334d 3237
b1d1b865
RS
3238 encoded_absname = ENCODE_FILE (absname);
3239
3240 if (chmod (XSTRING (encoded_absname)->data, XINT (mode)) < 0)
199607e4 3241 report_file_error ("Doing chmod", Fcons (absname, Qnil));
570d7624
JB
3242
3243 return Qnil;
3244}
3245
c24e9a53 3246DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
5f85ea58
RS
3247 "Set the file permission bits for newly created files.\n\
3248The argument MODE should be an integer; only the low 9 bits are used.\n\
36a8c287 3249This setting is inherited by subprocesses.")
5f85ea58
RS
3250 (mode)
3251 Lisp_Object mode;
36a8c287 3252{
5f85ea58 3253 CHECK_NUMBER (mode, 0);
199607e4 3254
5f85ea58 3255 umask ((~ XINT (mode)) & 0777);
36a8c287
JB
3256
3257 return Qnil;
3258}
3259
c24e9a53 3260DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
5f85ea58
RS
3261 "Return the default file protection for created files.\n\
3262The value is an integer.")
36a8c287
JB
3263 ()
3264{
5f85ea58
RS
3265 int realmask;
3266 Lisp_Object value;
36a8c287 3267
5f85ea58
RS
3268 realmask = umask (0);
3269 umask (realmask);
36a8c287 3270
46283abe 3271 XSETINT (value, (~ realmask) & 0777);
5f85ea58 3272 return value;
36a8c287 3273}
5df5e07c 3274
f793dc6c 3275\f
5df5e07c
GM
3276#ifdef __NetBSD__
3277#define unix 42
3278#endif
85ffea93 3279
5df5e07c 3280#ifdef unix
85ffea93
RS
3281DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
3282 "Tell Unix to finish all pending disk updates.")
3283 ()
3284{
3285 sync ();
3286 return Qnil;
3287}
3288
3289#endif /* unix */
3290
570d7624
JB
3291DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
3292 "Return t if file FILE1 is newer than file FILE2.\n\
3293If FILE1 does not exist, the answer is nil;\n\
3294otherwise, if FILE2 does not exist, the answer is t.")
3295 (file1, file2)
3296 Lisp_Object file1, file2;
3297{
199607e4 3298 Lisp_Object absname1, absname2;
570d7624
JB
3299 struct stat st;
3300 int mtime1;
32f4334d 3301 Lisp_Object handler;
09121adc 3302 struct gcpro gcpro1, gcpro2;
570d7624
JB
3303
3304 CHECK_STRING (file1, 0);
3305 CHECK_STRING (file2, 0);
3306
199607e4
RS
3307 absname1 = Qnil;
3308 GCPRO2 (absname1, file2);
3309 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
3310 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
09121adc 3311 UNGCPRO;
570d7624 3312
32f4334d
RS
3313 /* If the file name has special constructs in it,
3314 call the corresponding file handler. */
199607e4 3315 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
51cf6d37 3316 if (NILP (handler))
199607e4 3317 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
32f4334d 3318 if (!NILP (handler))
199607e4 3319 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
32f4334d 3320
b1d1b865
RS
3321 GCPRO2 (absname1, absname2);
3322 absname1 = ENCODE_FILE (absname1);
3323 absname2 = ENCODE_FILE (absname2);
3324 UNGCPRO;
3325
199607e4 3326 if (stat (XSTRING (absname1)->data, &st) < 0)
570d7624
JB
3327 return Qnil;
3328
3329 mtime1 = st.st_mtime;
3330
199607e4 3331 if (stat (XSTRING (absname2)->data, &st) < 0)
570d7624
JB
3332 return Qt;
3333
3334 return (mtime1 > st.st_mtime) ? Qt : Qnil;
3335}
3336\f
5e570b75 3337#ifdef DOS_NT
4c3c22f3 3338Lisp_Object Qfind_buffer_file_type;
5e570b75 3339#endif /* DOS_NT */
4c3c22f3 3340
6fdaa9a0
KH
3341#ifndef READ_BUF_SIZE
3342#define READ_BUF_SIZE (64 << 10)
3343#endif
3344
98a7d268
KH
3345extern void adjust_markers_for_delete P_ ((int, int, int, int));
3346
3347/* This function is called after Lisp functions to decide a coding
3348 system are called, or when they cause an error. Before they are
3349 called, the current buffer is set unibyte and it contains only a
3350 newly inserted text (thus the buffer was empty before the
3351 insertion).
3352
3353 The functions may set markers, overlays, text properties, or even
3354 alter the buffer contents, change the current buffer.
3355
3356 Here, we reset all those changes by:
3357 o set back the current buffer.
3358 o move all markers and overlays to BEG.
3359 o remove all text properties.
3360 o set back the buffer multibyteness. */
f736ffbf
KH
3361
3362static Lisp_Object
98a7d268
KH
3363decide_coding_unwind (unwind_data)
3364 Lisp_Object unwind_data;
f736ffbf 3365{
98a7d268 3366 Lisp_Object multibyte, undo_list, buffer;
f736ffbf 3367
98a7d268
KH
3368 multibyte = XCAR (unwind_data);
3369 unwind_data = XCDR (unwind_data);
3370 undo_list = XCAR (unwind_data);
3371 buffer = XCDR (unwind_data);
3372
3373 if (current_buffer != XBUFFER (buffer))
3374 set_buffer_internal (XBUFFER (buffer));
3375 adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
3376 adjust_overlays_for_delete (BEG, Z - BEG);
3377 BUF_INTERVALS (current_buffer) = 0;
3378 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
3379
3380 /* Now we are safe to change the buffer's multibyteness directly. */
3381 current_buffer->enable_multibyte_characters = multibyte;
3382 current_buffer->undo_list = undo_list;
f736ffbf
KH
3383
3384 return Qnil;
3385}
3386
570d7624 3387DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
3d0387c0 3388 1, 5, 0,
570d7624 3389 "Insert contents of file FILENAME after point.\n\
ec7adf26 3390Returns list of absolute file name and number of bytes inserted.\n\
570d7624
JB
3391If second argument VISIT is non-nil, the buffer's visited filename\n\
3392and last save file modtime are set, and it is marked unmodified.\n\
3393If visiting and the file does not exist, visiting is completed\n\
6fdaa9a0 3394before the error is signaled.\n\
7fded690
JB
3395The optional third and fourth arguments BEG and END\n\
3396specify what portion of the file to insert.\n\
ec7adf26 3397These arguments count bytes in the file, not characters in the buffer.\n\
3d0387c0 3398If VISIT is non-nil, BEG and END must be nil.\n\
94bec52a 3399\n\
3d0387c0
RS
3400If optional fifth argument REPLACE is non-nil,\n\
3401it means replace the current buffer contents (in the accessible portion)\n\
3402with the file contents. This is better than simply deleting and inserting\n\
3403the whole thing because (1) it preserves some marker positions\n\
94bec52a
RS
3404and (2) it puts less data in the undo list.\n\
3405When REPLACE is non-nil, the value is the number of characters actually read,\n\
6fdaa9a0 3406which is often less than the number of characters to be read.\n\
6cf71bf1 3407\n\
6fdaa9a0 3408This does code conversion according to the value of\n\
6cf71bf1
KH
3409`coding-system-for-read' or `file-coding-system-alist',\n\
3410and sets the variable `last-coding-system-used' to the coding system\n\
3411actually used.")
3d0387c0
RS
3412 (filename, visit, beg, end, replace)
3413 Lisp_Object filename, visit, beg, end, replace;
570d7624
JB
3414{
3415 struct stat st;
3416 register int fd;
ec7adf26 3417 int inserted = 0;
570d7624 3418 register int how_much;
6fdaa9a0 3419 register int unprocessed;
570d7624 3420 int count = specpdl_ptr - specpdl;
b1d1b865
RS
3421 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3422 Lisp_Object handler, val, insval, orig_filename;
d6a3cc15 3423 Lisp_Object p;
7fded690 3424 int total;
53c34c46 3425 int not_regular = 0;
feb9dc27 3426 unsigned char read_buf[READ_BUF_SIZE];
6fdaa9a0 3427 struct coding_system coding;
3dbcf3f6 3428 unsigned char buffer[1 << 14];
727a0b4a 3429 int replace_handled = 0;
ec7adf26 3430 int set_coding_system = 0;
f736ffbf 3431 int coding_system_decided = 0;
32f4334d 3432
95385625
RS
3433 if (current_buffer->base_buffer && ! NILP (visit))
3434 error ("Cannot do file visiting in an indirect buffer");
3435
3436 if (!NILP (current_buffer->read_only))
3437 Fbarf_if_buffer_read_only ();
3438
32f4334d 3439 val = Qnil;
d6a3cc15 3440 p = Qnil;
b1d1b865 3441 orig_filename = Qnil;
32f4334d 3442
b1d1b865 3443 GCPRO4 (filename, val, p, orig_filename);
570d7624
JB
3444
3445 CHECK_STRING (filename, 0);
3446 filename = Fexpand_file_name (filename, Qnil);
3447
32f4334d
RS
3448 /* If the file name has special constructs in it,
3449 call the corresponding file handler. */
49307295 3450 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
32f4334d
RS
3451 if (!NILP (handler))
3452 {
3d0387c0
RS
3453 val = call6 (handler, Qinsert_file_contents, filename,
3454 visit, beg, end, replace);
03699b14
KR
3455 if (CONSP (val) && CONSP (XCDR (val)))
3456 inserted = XINT (XCAR (XCDR (val)));
32f4334d
RS
3457 goto handled;
3458 }
3459
b1d1b865
RS
3460 orig_filename = filename;
3461 filename = ENCODE_FILE (filename);
3462
570d7624
JB
3463 fd = -1;
3464
c1c4693e
RS
3465#ifdef WINDOWSNT
3466 {
3467 Lisp_Object tem = Vw32_get_true_file_attributes;
3468
3469 /* Tell stat to use expensive method to get accurate info. */
3470 Vw32_get_true_file_attributes = Qt;
3471 total = stat (XSTRING (filename)->data, &st);
3472 Vw32_get_true_file_attributes = tem;
3473 }
3474 if (total < 0)
3475#else
570d7624 3476#ifndef APOLLO
99bc28f4 3477 if (stat (XSTRING (filename)->data, &st) < 0)
570d7624 3478#else
68c45bf0 3479 if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0
570d7624
JB
3480 || fstat (fd, &st) < 0)
3481#endif /* not APOLLO */
c1c4693e 3482#endif /* WINDOWSNT */
570d7624 3483 {
68c45bf0 3484 if (fd >= 0) emacs_close (fd);
99bc28f4 3485 badopen:
265a9e55 3486 if (NILP (visit))
b1d1b865 3487 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
570d7624
JB
3488 st.st_mtime = -1;
3489 how_much = 0;
0de6b8f4 3490 if (!NILP (Vcoding_system_for_read))
22d92d6b 3491 Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
570d7624
JB
3492 goto notfound;
3493 }
3494
99bc28f4 3495#ifdef S_IFREG
be53b411
JB
3496 /* This code will need to be changed in order to work on named
3497 pipes, and it's probably just not worth it. So we should at
3498 least signal an error. */
99bc28f4 3499 if (!S_ISREG (st.st_mode))
330bfe57 3500 {
d4b8687b
RS
3501 not_regular = 1;
3502
3503 if (! NILP (visit))
3504 goto notfound;
3505
3506 if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
330bfe57
RS
3507 Fsignal (Qfile_error,
3508 Fcons (build_string ("not a regular file"),
b1d1b865 3509 Fcons (orig_filename, Qnil)));
330bfe57 3510 }
be53b411
JB
3511#endif
3512
99bc28f4 3513 if (fd < 0)
68c45bf0 3514 if ((fd = emacs_open (XSTRING (filename)->data, O_RDONLY, 0)) < 0)
99bc28f4
KH
3515 goto badopen;
3516
3517 /* Replacement should preserve point as it preserves markers. */
3518 if (!NILP (replace))
3519 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
3520
3521 record_unwind_protect (close_file_unwind, make_number (fd));
3522
570d7624 3523 /* Supposedly happens on VMS. */
d4b8687b 3524 if (! not_regular && st.st_size < 0)
570d7624 3525 error ("File size is negative");
be53b411 3526
9c856db9
GM
3527 /* Prevent redisplay optimizations. */
3528 current_buffer->clip_changed = 1;
3529
9f57b6b4
KH
3530 if (!NILP (visit))
3531 {
3532 if (!NILP (beg) || !NILP (end))
3533 error ("Attempt to visit less than an entire file");
3534 if (BEG < Z && NILP (replace))
3535 error ("Cannot do file visiting in a non-empty buffer");
3536 }
7fded690
JB
3537
3538 if (!NILP (beg))
3539 CHECK_NUMBER (beg, 0);
3540 else
2acfd7ae 3541 XSETFASTINT (beg, 0);
7fded690
JB
3542
3543 if (!NILP (end))
3544 CHECK_NUMBER (end, 0);
3545 else
3546 {
d4b8687b
RS
3547 if (! not_regular)
3548 {
3549 XSETINT (end, st.st_size);
68c45bf0
PE
3550
3551 /* Arithmetic overflow can occur if an Emacs integer cannot
3552 represent the file size, or if the calculations below
3553 overflow. The calculations below double the file size
3554 twice, so check that it can be multiplied by 4 safely. */
3555 if (XINT (end) != st.st_size
3556 || ((int) st.st_size * 4) / 4 != st.st_size)
d4b8687b
RS
3557 error ("Maximum buffer size exceeded");
3558 }
7fded690
JB
3559 }
3560
f736ffbf
KH
3561 if (BEG < Z)
3562 {
3563 /* Decide the coding system to use for reading the file now
3564 because we can't use an optimized method for handling
3565 `coding:' tag if the current buffer is not empty. */
3566 Lisp_Object val;
3567 val = Qnil;
feb9dc27 3568
f736ffbf
KH
3569 if (!NILP (Vcoding_system_for_read))
3570 val = Vcoding_system_for_read;
3571 else if (! NILP (replace))
3572 /* In REPLACE mode, we can use the same coding system
3573 that was used to visit the file. */
3574 val = current_buffer->buffer_file_coding_system;
3575 else
3576 {
3577 /* Don't try looking inside a file for a coding system
3578 specification if it is not seekable. */
3579 if (! not_regular && ! NILP (Vset_auto_coding_function))
3580 {
3581 /* Find a coding system specified in the heading two
3582 lines or in the tailing several lines of the file.
3583 We assume that the 1K-byte and 3K-byte for heading
003a7eaa 3584 and tailing respectively are sufficient for this
f736ffbf 3585 purpose. */
07590973 3586 int nread;
f736ffbf
KH
3587
3588 if (st.st_size <= (1024 * 4))
68c45bf0 3589 nread = emacs_read (fd, read_buf, 1024 * 4);
f736ffbf
KH
3590 else
3591 {
68c45bf0 3592 nread = emacs_read (fd, read_buf, 1024);
f736ffbf
KH
3593 if (nread >= 0)
3594 {
3595 if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
3596 report_file_error ("Setting file position",
3597 Fcons (orig_filename, Qnil));
68c45bf0 3598 nread += emacs_read (fd, read_buf + nread, 1024 * 3);
f736ffbf
KH
3599 }
3600 }
feb9dc27 3601
f736ffbf
KH
3602 if (nread < 0)
3603 error ("IO error reading %s: %s",
68c45bf0 3604 XSTRING (orig_filename)->data, emacs_strerror (errno));
f736ffbf
KH
3605 else if (nread > 0)
3606 {
f736ffbf 3607 struct buffer *prev = current_buffer;
1d92afcd 3608 int count1;
f736ffbf
KH
3609
3610 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
1d92afcd
GM
3611
3612 /* The call to temp_output_buffer_setup binds
3613 standard-output. */
3614 count1 = specpdl_ptr - specpdl;
f736ffbf 3615 temp_output_buffer_setup (" *code-converting-work*");
1d92afcd 3616
f736ffbf
KH
3617 set_buffer_internal (XBUFFER (Vstandard_output));
3618 current_buffer->enable_multibyte_characters = Qnil;
3619 insert_1_both (read_buf, nread, nread, 0, 0, 0);
3620 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
1255deb9
KH
3621 val = call2 (Vset_auto_coding_function,
3622 filename, make_number (nread));
f736ffbf 3623 set_buffer_internal (prev);
1d92afcd
GM
3624
3625 /* Remove the binding for standard-output. */
3626 unbind_to (count1, Qnil);
3627
f736ffbf
KH
3628 /* Discard the unwind protect for recovering the
3629 current buffer. */
3630 specpdl_ptr--;
3631
3632 /* Rewind the file for the actual read done later. */
3633 if (lseek (fd, 0, 0) < 0)
3634 report_file_error ("Setting file position",
3635 Fcons (orig_filename, Qnil));
3636 }
3637 }
feb9dc27 3638
f736ffbf
KH
3639 if (NILP (val))
3640 {
3641 /* If we have not yet decided a coding system, check
3642 file-coding-system-alist. */
3643 Lisp_Object args[6], coding_systems;
3644
3645 args[0] = Qinsert_file_contents, args[1] = orig_filename;
3646 args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
3647 coding_systems = Ffind_operation_coding_system (6, args);
3648 if (CONSP (coding_systems))
03699b14 3649 val = XCAR (coding_systems);
f736ffbf
KH
3650 }
3651 }
c9e82392 3652
f736ffbf 3653 setup_coding_system (Fcheck_coding_system (val), &coding);
f8569325
DL
3654 /* Ensure we set Vlast_coding_system_used. */
3655 set_coding_system = 1;
c8a6d68a 3656
237a6fd2
RS
3657 if (NILP (current_buffer->enable_multibyte_characters)
3658 && ! NILP (val))
3659 /* We must suppress all character code conversion except for
3660 end-of-line conversion. */
57515cfe 3661 setup_raw_text_coding_system (&coding);
54369368 3662
8c3b9441
KH
3663 coding.src_multibyte = 0;
3664 coding.dst_multibyte
3665 = !NILP (current_buffer->enable_multibyte_characters);
f736ffbf
KH
3666 coding_system_decided = 1;
3667 }
6cf71bf1 3668
3d0387c0
RS
3669 /* If requested, replace the accessible part of the buffer
3670 with the file contents. Avoid replacing text at the
3671 beginning or end of the buffer that matches the file contents;
3dbcf3f6
RS
3672 that preserves markers pointing to the unchanged parts.
3673
3674 Here we implement this feature in an optimized way
3675 for the case where code conversion is NOT needed.
3676 The following if-statement handles the case of conversion
727a0b4a
RS
3677 in a less optimal way.
3678
3679 If the code conversion is "automatic" then we try using this
3680 method and hope for the best.
3681 But if we discover the need for conversion, we give up on this method
3682 and let the following if-statement handle the replace job. */
3dbcf3f6 3683 if (!NILP (replace)
f736ffbf 3684 && BEGV < ZV
8c3b9441 3685 && !(coding.common_flags & CODING_REQUIRE_DECODING_MASK))
3d0387c0 3686 {
ec7adf26
RS
3687 /* same_at_start and same_at_end count bytes,
3688 because file access counts bytes
3689 and BEG and END count bytes. */
3690 int same_at_start = BEGV_BYTE;
3691 int same_at_end = ZV_BYTE;
9c28748f 3692 int overlap;
6fdaa9a0
KH
3693 /* There is still a possibility we will find the need to do code
3694 conversion. If that happens, we set this variable to 1 to
727a0b4a 3695 give up on handling REPLACE in the optimized way. */
6fdaa9a0 3696 int giveup_match_end = 0;
9c28748f 3697
4d2a0879
RS
3698 if (XINT (beg) != 0)
3699 {
3700 if (lseek (fd, XINT (beg), 0) < 0)
3701 report_file_error ("Setting file position",
b1d1b865 3702 Fcons (orig_filename, Qnil));
4d2a0879
RS
3703 }
3704
3d0387c0
RS
3705 immediate_quit = 1;
3706 QUIT;
3707 /* Count how many chars at the start of the file
3708 match the text at the beginning of the buffer. */
3709 while (1)
3710 {
3711 int nread, bufpos;
3712
68c45bf0 3713 nread = emacs_read (fd, buffer, sizeof buffer);
3d0387c0
RS
3714 if (nread < 0)
3715 error ("IO error reading %s: %s",
68c45bf0 3716 XSTRING (orig_filename)->data, emacs_strerror (errno));
3d0387c0
RS
3717 else if (nread == 0)
3718 break;
6fdaa9a0 3719
0ef69138 3720 if (coding.type == coding_type_undecided)
727a0b4a 3721 detect_coding (&coding, buffer, nread);
8c3b9441 3722 if (coding.common_flags & CODING_REQUIRE_DECODING_MASK)
727a0b4a
RS
3723 /* We found that the file should be decoded somehow.
3724 Let's give up here. */
3725 {
3726 giveup_match_end = 1;
3727 break;
3728 }
3729
0ef69138 3730 if (coding.eol_type == CODING_EOL_UNDECIDED)
727a0b4a 3731 detect_eol (&coding, buffer, nread);
1b335d29 3732 if (coding.eol_type != CODING_EOL_UNDECIDED
70ec4328 3733 && coding.eol_type != CODING_EOL_LF)
727a0b4a
RS
3734 /* We found that the format of eol should be decoded.
3735 Let's give up here. */
3736 {
3737 giveup_match_end = 1;
3738 break;
3739 }
3740
3d0387c0 3741 bufpos = 0;
ec7adf26 3742 while (bufpos < nread && same_at_start < ZV_BYTE
6fdaa9a0 3743 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3d0387c0
RS
3744 same_at_start++, bufpos++;
3745 /* If we found a discrepancy, stop the scan.
8e6208c5 3746 Otherwise loop around and scan the next bufferful. */
3d0387c0
RS
3747 if (bufpos != nread)
3748 break;
3749 }
3750 immediate_quit = 0;
3751 /* If the file matches the buffer completely,
3752 there's no need to replace anything. */
ec7adf26 3753 if (same_at_start - BEGV_BYTE == XINT (end))
3d0387c0 3754 {
68c45bf0 3755 emacs_close (fd);
a1d2b64a 3756 specpdl_ptr--;
1051b3b3 3757 /* Truncate the buffer to the size of the file. */
7dae4502 3758 del_range_1 (same_at_start, same_at_end, 0, 0);
3d0387c0
RS
3759 goto handled;
3760 }
3761 immediate_quit = 1;
3762 QUIT;
3763 /* Count how many chars at the end of the file
6fdaa9a0
KH
3764 match the text at the end of the buffer. But, if we have
3765 already found that decoding is necessary, don't waste time. */
3766 while (!giveup_match_end)
3d0387c0
RS
3767 {
3768 int total_read, nread, bufpos, curpos, trial;
3769
3770 /* At what file position are we now scanning? */
ec7adf26 3771 curpos = XINT (end) - (ZV_BYTE - same_at_end);
fc81fa9e
KH
3772 /* If the entire file matches the buffer tail, stop the scan. */
3773 if (curpos == 0)
3774 break;
3d0387c0
RS
3775 /* How much can we scan in the next step? */
3776 trial = min (curpos, sizeof buffer);
3777 if (lseek (fd, curpos - trial, 0) < 0)
3778 report_file_error ("Setting file position",
b1d1b865 3779 Fcons (orig_filename, Qnil));
3d0387c0
RS
3780
3781 total_read = 0;
3782 while (total_read < trial)
3783 {
68c45bf0 3784 nread = emacs_read (fd, buffer + total_read, trial - total_read);
3d0387c0
RS
3785 if (nread <= 0)
3786 error ("IO error reading %s: %s",
68c45bf0 3787 XSTRING (orig_filename)->data, emacs_strerror (errno));
3d0387c0
RS
3788 total_read += nread;
3789 }
8e6208c5 3790 /* Scan this bufferful from the end, comparing with
3d0387c0
RS
3791 the Emacs buffer. */
3792 bufpos = total_read;
3793 /* Compare with same_at_start to avoid counting some buffer text
3794 as matching both at the file's beginning and at the end. */
3795 while (bufpos > 0 && same_at_end > same_at_start
6fdaa9a0 3796 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3d0387c0 3797 same_at_end--, bufpos--;
727a0b4a 3798
3d0387c0 3799 /* If we found a discrepancy, stop the scan.
8e6208c5 3800 Otherwise loop around and scan the preceding bufferful. */
3d0387c0 3801 if (bufpos != 0)
727a0b4a
RS
3802 {
3803 /* If this discrepancy is because of code conversion,
3804 we cannot use this method; giveup and try the other. */
3805 if (same_at_end > same_at_start
3806 && FETCH_BYTE (same_at_end - 1) >= 0200
71312b68 3807 && ! NILP (current_buffer->enable_multibyte_characters)
c8a6d68a 3808 && (CODING_MAY_REQUIRE_DECODING (&coding)))
727a0b4a
RS
3809 giveup_match_end = 1;
3810 break;
3811 }
3d0387c0
RS
3812 }
3813 immediate_quit = 0;
9c28748f 3814
727a0b4a
RS
3815 if (! giveup_match_end)
3816 {
ec7adf26
RS
3817 int temp;
3818
727a0b4a 3819 /* We win! We can handle REPLACE the optimized way. */
9c28748f 3820
20f6783d
RS
3821 /* Extend the start of non-matching text area to multibyte
3822 character boundary. */
3823 if (! NILP (current_buffer->enable_multibyte_characters))
3824 while (same_at_start > BEGV_BYTE
3825 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
3826 same_at_start--;
3827
3828 /* Extend the end of non-matching text area to multibyte
71312b68
RS
3829 character boundary. */
3830 if (! NILP (current_buffer->enable_multibyte_characters))
ec7adf26
RS
3831 while (same_at_end < ZV_BYTE
3832 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
71312b68
RS
3833 same_at_end++;
3834
727a0b4a 3835 /* Don't try to reuse the same piece of text twice. */
ec7adf26
RS
3836 overlap = (same_at_start - BEGV_BYTE
3837 - (same_at_end + st.st_size - ZV));
727a0b4a
RS
3838 if (overlap > 0)
3839 same_at_end += overlap;
9c28748f 3840
727a0b4a 3841 /* Arrange to read only the nonmatching middle part of the file. */
ec7adf26
RS
3842 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
3843 XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
3dbcf3f6 3844
ec7adf26 3845 del_range_byte (same_at_start, same_at_end, 0);
727a0b4a 3846 /* Insert from the file at the proper position. */
ec7adf26
RS
3847 temp = BYTE_TO_CHAR (same_at_start);
3848 SET_PT_BOTH (temp, same_at_start);
727a0b4a
RS
3849
3850 /* If display currently starts at beginning of line,
3851 keep it that way. */
3852 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3853 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3854
3855 replace_handled = 1;
3856 }
3dbcf3f6
RS
3857 }
3858
3859 /* If requested, replace the accessible part of the buffer
3860 with the file contents. Avoid replacing text at the
3861 beginning or end of the buffer that matches the file contents;
3862 that preserves markers pointing to the unchanged parts.
3863
3864 Here we implement this feature for the case where code conversion
3865 is needed, in a simple way that needs a lot of memory.
3866 The preceding if-statement handles the case of no conversion
3867 in a more optimized way. */
f736ffbf 3868 if (!NILP (replace) && ! replace_handled && BEGV < ZV)
3dbcf3f6 3869 {
ec7adf26
RS
3870 int same_at_start = BEGV_BYTE;
3871 int same_at_end = ZV_BYTE;
3dbcf3f6
RS
3872 int overlap;
3873 int bufpos;
3874 /* Make sure that the gap is large enough. */
3875 int bufsize = 2 * st.st_size;
b00ca0d7 3876 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
ec7adf26 3877 int temp;
3dbcf3f6
RS
3878
3879 /* First read the whole file, performing code conversion into
3880 CONVERSION_BUFFER. */
3881
727a0b4a
RS
3882 if (lseek (fd, XINT (beg), 0) < 0)
3883 {
68cfd853 3884 xfree (conversion_buffer);
727a0b4a 3885 report_file_error ("Setting file position",
b1d1b865 3886 Fcons (orig_filename, Qnil));
727a0b4a
RS
3887 }
3888
3dbcf3f6
RS
3889 total = st.st_size; /* Total bytes in the file. */
3890 how_much = 0; /* Bytes read from file so far. */
3891 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
3892 unprocessed = 0; /* Bytes not processed in previous loop. */
3893
3894 while (how_much < total)
3895 {
3896 /* try is reserved in some compilers (Microsoft C) */
3897 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
cadf50ff 3898 unsigned char *destination = read_buf + unprocessed;
3dbcf3f6
RS
3899 int this;
3900
3901 /* Allow quitting out of the actual I/O. */
3902 immediate_quit = 1;
3903 QUIT;
68c45bf0 3904 this = emacs_read (fd, destination, trytry);
3dbcf3f6
RS
3905 immediate_quit = 0;
3906
3907 if (this < 0 || this + unprocessed == 0)
3908 {
3909 how_much = this;
3910 break;
3911 }
3912
3913 how_much += this;
3914
c8a6d68a 3915 if (CODING_MAY_REQUIRE_DECODING (&coding))
3dbcf3f6 3916 {
c8a6d68a 3917 int require, result;
3dbcf3f6
RS
3918
3919 this += unprocessed;
3920
3921 /* If we are using more space than estimated,
3922 make CONVERSION_BUFFER bigger. */
3923 require = decoding_buffer_size (&coding, this);
3924 if (inserted + require + 2 * (total - how_much) > bufsize)
3925 {
3926 bufsize = inserted + require + 2 * (total - how_much);
92cf1086 3927 conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
3dbcf3f6
RS
3928 }
3929
3930 /* Convert this batch with results in CONVERSION_BUFFER. */
3931 if (how_much >= total) /* This is the last block. */
c8a6d68a
KH
3932 coding.mode |= CODING_MODE_LAST_BLOCK;
3933 result = decode_coding (&coding, read_buf,
3934 conversion_buffer + inserted,
3935 this, bufsize - inserted);
3dbcf3f6
RS
3936
3937 /* Save for next iteration whatever we didn't convert. */
c8a6d68a
KH
3938 unprocessed = this - coding.consumed;
3939 bcopy (read_buf + coding.consumed, read_buf, unprocessed);
8c3b9441
KH
3940 if (!NILP (current_buffer->enable_multibyte_characters))
3941 this = coding.produced;
3942 else
3943 this = str_as_unibyte (conversion_buffer + inserted,
3944 coding.produced);
3dbcf3f6
RS
3945 }
3946
3947 inserted += this;
3948 }
3949
c8a6d68a 3950 /* At this point, INSERTED is how many characters (i.e. bytes)
3dbcf3f6
RS
3951 are present in CONVERSION_BUFFER.
3952 HOW_MUCH should equal TOTAL,
3953 or should be <= 0 if we couldn't read the file. */
3954
3955 if (how_much < 0)
3956 {
a36837e4 3957 xfree (conversion_buffer);
3dbcf3f6
RS
3958
3959 if (how_much == -1)
3960 error ("IO error reading %s: %s",
68c45bf0 3961 XSTRING (orig_filename)->data, emacs_strerror (errno));
3dbcf3f6
RS
3962 else if (how_much == -2)
3963 error ("maximum buffer size exceeded");
3964 }
3965
3966 /* Compare the beginning of the converted file
3967 with the buffer text. */
3968
3969 bufpos = 0;
3970 while (bufpos < inserted && same_at_start < same_at_end
3971 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
3972 same_at_start++, bufpos++;
3973
3974 /* If the file matches the buffer completely,
3975 there's no need to replace anything. */
3976
3977 if (bufpos == inserted)
3978 {
a36837e4 3979 xfree (conversion_buffer);
68c45bf0 3980 emacs_close (fd);
3dbcf3f6
RS
3981 specpdl_ptr--;
3982 /* Truncate the buffer to the size of the file. */
427f5aab
KH
3983 del_range_byte (same_at_start, same_at_end, 0);
3984 inserted = 0;
3dbcf3f6
RS
3985 goto handled;
3986 }
3987
20f6783d
RS
3988 /* Extend the start of non-matching text area to multibyte
3989 character boundary. */
3990 if (! NILP (current_buffer->enable_multibyte_characters))
3991 while (same_at_start > BEGV_BYTE
3992 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_start)))
3993 same_at_start--;
3994
3dbcf3f6
RS
3995 /* Scan this bufferful from the end, comparing with
3996 the Emacs buffer. */
3997 bufpos = inserted;
3998
3999 /* Compare with same_at_start to avoid counting some buffer text
4000 as matching both at the file's beginning and at the end. */
4001 while (bufpos > 0 && same_at_end > same_at_start
4002 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
4003 same_at_end--, bufpos--;
4004
20f6783d
RS
4005 /* Extend the end of non-matching text area to multibyte
4006 character boundary. */
4007 if (! NILP (current_buffer->enable_multibyte_characters))
4008 while (same_at_end < ZV_BYTE
4009 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
4010 same_at_end++;
4011
3dbcf3f6 4012 /* Don't try to reuse the same piece of text twice. */
ec7adf26 4013 overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
3dbcf3f6
RS
4014 if (overlap > 0)
4015 same_at_end += overlap;
4016
727a0b4a
RS
4017 /* If display currently starts at beginning of line,
4018 keep it that way. */
4019 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
4020 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
4021
3dbcf3f6
RS
4022 /* Replace the chars that we need to replace,
4023 and update INSERTED to equal the number of bytes
4024 we are taking from the file. */
ec7adf26 4025 inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
427f5aab 4026
643c73b9 4027 if (same_at_end != same_at_start)
427f5aab
KH
4028 {
4029 del_range_byte (same_at_start, same_at_end, 0);
4030 temp = GPT;
4031 same_at_start = GPT_BYTE;
4032 }
643c73b9
RS
4033 else
4034 {
643c73b9 4035 temp = BYTE_TO_CHAR (same_at_start);
643c73b9 4036 }
427f5aab
KH
4037 /* Insert from the file at the proper position. */
4038 SET_PT_BOTH (temp, same_at_start);
ec7adf26
RS
4039 insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
4040 0, 0, 0);
427f5aab
KH
4041 /* Set `inserted' to the number of inserted characters. */
4042 inserted = PT - temp;
3dbcf3f6 4043
93184560 4044 xfree (conversion_buffer);
68c45bf0 4045 emacs_close (fd);
3dbcf3f6
RS
4046 specpdl_ptr--;
4047
3dbcf3f6 4048 goto handled;
3d0387c0
RS
4049 }
4050
d4b8687b
RS
4051 if (! not_regular)
4052 {
4053 register Lisp_Object temp;
7fded690 4054
d4b8687b 4055 total = XINT (end) - XINT (beg);
570d7624 4056
d4b8687b
RS
4057 /* Make sure point-max won't overflow after this insertion. */
4058 XSETINT (temp, total);
4059 if (total != XINT (temp))
4060 error ("Maximum buffer size exceeded");
4061 }
4062 else
4063 /* For a special file, all we can do is guess. */
4064 total = READ_BUF_SIZE;
570d7624 4065
57d8d468 4066 if (NILP (visit) && total > 0)
6c478ee2 4067 prepare_to_modify_buffer (PT, PT, NULL);
570d7624 4068
7fe52289 4069 move_gap (PT);
7fded690
JB
4070 if (GAP_SIZE < total)
4071 make_gap (total - GAP_SIZE);
4072
a1d2b64a 4073 if (XINT (beg) != 0 || !NILP (replace))
7fded690
JB
4074 {
4075 if (lseek (fd, XINT (beg), 0) < 0)
b1d1b865
RS
4076 report_file_error ("Setting file position",
4077 Fcons (orig_filename, Qnil));
7fded690
JB
4078 }
4079
6fdaa9a0 4080 /* In the following loop, HOW_MUCH contains the total bytes read so
c8a6d68a
KH
4081 far for a regular file, and not changed for a special file. But,
4082 before exiting the loop, it is set to a negative value if I/O
4083 error occurs. */
a1d2b64a 4084 how_much = 0;
6fdaa9a0
KH
4085 /* Total bytes inserted. */
4086 inserted = 0;
c8a6d68a
KH
4087 /* Here, we don't do code conversion in the loop. It is done by
4088 code_convert_region after all data are read into the buffer. */
6fdaa9a0 4089 while (how_much < total)
570d7624 4090 {
5e570b75 4091 /* try is reserved in some compilers (Microsoft C) */
c8a6d68a
KH
4092 int trytry = min (total - how_much, READ_BUF_SIZE);
4093 int this;
4094
4095 /* For a special file, GAP_SIZE should be checked every time. */
4096 if (not_regular && GAP_SIZE < trytry)
4097 make_gap (total - GAP_SIZE);
b5148e85
RS
4098
4099 /* Allow quitting out of the actual I/O. */
4100 immediate_quit = 1;
4101 QUIT;
68c45bf0
PE
4102 this = emacs_read (fd, BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
4103 trytry);
b5148e85 4104 immediate_quit = 0;
570d7624 4105
c8a6d68a 4106 if (this <= 0)
570d7624
JB
4107 {
4108 how_much = this;
4109 break;
4110 }
4111
c8a6d68a
KH
4112 GAP_SIZE -= this;
4113 GPT_BYTE += this;
4114 ZV_BYTE += this;
4115 Z_BYTE += this;
4116 GPT += this;
4117 ZV += this;
4118 Z += this;
4119
d4b8687b
RS
4120 /* For a regular file, where TOTAL is the real size,
4121 count HOW_MUCH to compare with it.
4122 For a special file, where TOTAL is just a buffer size,
4123 so don't bother counting in HOW_MUCH.
4124 (INSERTED is where we count the number of characters inserted.) */
4125 if (! not_regular)
4126 how_much += this;
c8a6d68a
KH
4127 inserted += this;
4128 }
6fdaa9a0 4129
c8a6d68a
KH
4130 if (GAP_SIZE > 0)
4131 /* Put an anchor to ensure multi-byte form ends at gap. */
4132 *GPT_ADDR = 0;
d4b8687b 4133
68c45bf0 4134 emacs_close (fd);
6fdaa9a0 4135
c8a6d68a
KH
4136 /* Discard the unwind protect for closing the file. */
4137 specpdl_ptr--;
6fdaa9a0 4138
c8a6d68a
KH
4139 if (how_much < 0)
4140 error ("IO error reading %s: %s",
68c45bf0 4141 XSTRING (orig_filename)->data, emacs_strerror (errno));
ec7adf26 4142
f8569325
DL
4143 notfound:
4144
2df42e09 4145 if (! coding_system_decided)
c8a6d68a 4146 {
2df42e09 4147 /* The coding system is not yet decided. Decide it by an
dfe35e7b
RS
4148 optimized method for handling `coding:' tag.
4149
4150 Note that we can get here only if the buffer was empty
4151 before the insertion. */
2df42e09
KH
4152 Lisp_Object val;
4153 val = Qnil;
f736ffbf 4154
2df42e09
KH
4155 if (!NILP (Vcoding_system_for_read))
4156 val = Vcoding_system_for_read;
4157 else
4158 {
98a7d268
KH
4159 /* Since we are sure that the current buffer was empty
4160 before the insertion, we can toggle
4161 enable-multibyte-characters directly here without taking
4162 care of marker adjustment and byte combining problem. By
4163 this way, we can run Lisp program safely before decoding
4164 the inserted text. */
4165 Lisp_Object unwind_data;
2df42e09
KH
4166 int count = specpdl_ptr - specpdl;
4167
98a7d268
KH
4168 unwind_data = Fcons (current_buffer->enable_multibyte_characters,
4169 Fcons (current_buffer->undo_list,
4170 Fcurrent_buffer ()));
2df42e09 4171 current_buffer->enable_multibyte_characters = Qnil;
98a7d268
KH
4172 current_buffer->undo_list = Qt;
4173 record_unwind_protect (decide_coding_unwind, unwind_data);
4174
4175 if (inserted > 0 && ! NILP (Vset_auto_coding_function))
4176 {
1255deb9
KH
4177 val = call2 (Vset_auto_coding_function,
4178 filename, make_number (inserted));
2df42e09 4179 }
f736ffbf 4180
2df42e09
KH
4181 if (NILP (val))
4182 {
4183 /* If the coding system is not yet decided, check
4184 file-coding-system-alist. */
4185 Lisp_Object args[6], coding_systems;
f736ffbf 4186
2df42e09
KH
4187 args[0] = Qinsert_file_contents, args[1] = orig_filename;
4188 args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
4189 coding_systems = Ffind_operation_coding_system (6, args);
4190 if (CONSP (coding_systems))
03699b14 4191 val = XCAR (coding_systems);
f736ffbf 4192 }
98a7d268
KH
4193
4194 unbind_to (count, Qnil);
4195 inserted = Z_BYTE - BEG_BYTE;
2df42e09 4196 }
f736ffbf 4197
2df42e09
KH
4198 /* The following kludgy code is to avoid some compiler bug.
4199 We can't simply do
4200 setup_coding_system (val, &coding);
4201 on some system. */
4202 {
4203 struct coding_system temp_coding;
4204 setup_coding_system (val, &temp_coding);
4205 bcopy (&temp_coding, &coding, sizeof coding);
4206 }
f8569325
DL
4207 /* Ensure we set Vlast_coding_system_used. */
4208 set_coding_system = 1;
f736ffbf 4209
237a6fd2
RS
4210 if (NILP (current_buffer->enable_multibyte_characters)
4211 && ! NILP (val))
4212 /* We must suppress all character code conversion except for
2df42e09
KH
4213 end-of-line conversion. */
4214 setup_raw_text_coding_system (&coding);
6db43875
KH
4215 coding.src_multibyte = 0;
4216 coding.dst_multibyte
4217 = !NILP (current_buffer->enable_multibyte_characters);
2df42e09 4218 }
f736ffbf 4219
8c3b9441
KH
4220 if (!NILP (visit)
4221 && (coding.type == coding_type_no_conversion
4222 || coding.type == coding_type_raw_text))
4223 {
4224 /* Visiting a file with these coding system always make the buffer
4225 unibyte. */
4226 current_buffer->enable_multibyte_characters = Qnil;
4227 coding.dst_multibyte = 0;
4228 }
4229
c91beee2 4230 if (inserted > 0 || coding.type == coding_type_ccl)
2df42e09 4231 {
c8a6d68a 4232 if (CODING_MAY_REQUIRE_DECODING (&coding))
64e0ae2a
KH
4233 {
4234 code_convert_region (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
4235 &coding, 0, 0);
8c3b9441 4236 inserted = coding.produced_char;
f8198e19 4237 }
e9cea947
AS
4238 else
4239 adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
8c3b9441 4240 inserted);
2df42e09 4241 }
570d7624 4242
04e6f79c 4243#ifdef DOS_NT
2df42e09
KH
4244 /* Use the conversion type to determine buffer-file-type
4245 (find-buffer-file-type is now used to help determine the
4246 conversion). */
4247 if ((coding.eol_type == CODING_EOL_UNDECIDED
4248 || coding.eol_type == CODING_EOL_LF)
4249 && ! CODING_REQUIRE_DECODING (&coding))
4250 current_buffer->buffer_file_type = Qt;
4251 else
4252 current_buffer->buffer_file_type = Qnil;
04e6f79c 4253#endif
570d7624 4254
32f4334d 4255 handled:
570d7624 4256
265a9e55 4257 if (!NILP (visit))
570d7624 4258 {
cfadd376
RS
4259 if (!EQ (current_buffer->undo_list, Qt))
4260 current_buffer->undo_list = Qnil;
570d7624
JB
4261#ifdef APOLLO
4262 stat (XSTRING (filename)->data, &st);
4263#endif
62bcf009 4264
a7e82472
RS
4265 if (NILP (handler))
4266 {
4267 current_buffer->modtime = st.st_mtime;
b1d1b865 4268 current_buffer->filename = orig_filename;
a7e82472 4269 }
62bcf009 4270
95385625 4271 SAVE_MODIFF = MODIFF;
570d7624 4272 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 4273 XSETFASTINT (current_buffer->save_length, Z - BEG);
570d7624 4274#ifdef CLASH_DETECTION
32f4334d
RS
4275 if (NILP (handler))
4276 {
f471f4c2
RS
4277 if (!NILP (current_buffer->file_truename))
4278 unlock_file (current_buffer->file_truename);
32f4334d
RS
4279 unlock_file (filename);
4280 }
570d7624 4281#endif /* CLASH_DETECTION */
330bfe57
RS
4282 if (not_regular)
4283 Fsignal (Qfile_error,
4284 Fcons (build_string ("not a regular file"),
b1d1b865 4285 Fcons (orig_filename, Qnil)));
570d7624
JB
4286 }
4287
0d420e88 4288 /* Decode file format */
c8a6d68a 4289 if (inserted > 0)
0d420e88 4290 {
199607e4 4291 insval = call3 (Qformat_decode,
c8a6d68a 4292 Qnil, make_number (inserted), visit);
0d420e88 4293 CHECK_NUMBER (insval, 0);
c8a6d68a 4294 inserted = XFASTINT (insval);
0d420e88
BG
4295 }
4296
ce51c54c
KH
4297 if (set_coding_system)
4298 Vlast_coding_system_used = coding.symbol;
4299
0342d8c5
RS
4300 /* Call after-change hooks for the inserted text, aside from the case
4301 of normal visiting (not with REPLACE), which is done in a new buffer
4302 "before" the buffer is changed. */
c8a6d68a 4303 if (inserted > 0 && total > 0
0342d8c5 4304 && (NILP (visit) || !NILP (replace)))
ce51c54c
KH
4305 {
4306 signal_after_change (PT, 0, inserted);
4307 update_compositions (PT, PT, CHECK_BORDER);
4308 }
b56567b5 4309
f8569325
DL
4310 p = Vafter_insert_file_functions;
4311 while (!NILP (p))
d6a3cc15 4312 {
f8569325
DL
4313 insval = call1 (Fcar (p), make_number (inserted));
4314 if (!NILP (insval))
d6a3cc15 4315 {
f8569325
DL
4316 CHECK_NUMBER (insval, 0);
4317 inserted = XFASTINT (insval);
d6a3cc15 4318 }
f8569325
DL
4319 QUIT;
4320 p = Fcdr (p);
4321 }
4322
4323 if (!NILP (visit)
4324 && current_buffer->modtime == -1)
4325 {
4326 /* If visiting nonexistent file, return nil. */
4327 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
d6a3cc15
RS
4328 }
4329
ec7adf26 4330 /* ??? Retval needs to be dealt with in all cases consistently. */
a1d2b64a 4331 if (NILP (val))
b1d1b865 4332 val = Fcons (orig_filename,
a1d2b64a
RS
4333 Fcons (make_number (inserted),
4334 Qnil));
4335
4336 RETURN_UNGCPRO (unbind_to (count, val));
570d7624 4337}
7fded690 4338\f
ec7adf26
RS
4339static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
4340 Lisp_Object));
d6a3cc15 4341
6fc6f94b 4342/* If build_annotations switched buffers, switch back to BUF.
6fdaa9a0
KH
4343 Kill the temporary buffer that was selected in the meantime.
4344
4345 Since this kill only the last temporary buffer, some buffers remain
4346 not killed if build_annotations switched buffers more than once.
4347 -- K.Handa */
6fc6f94b 4348
199607e4 4349static Lisp_Object
6fc6f94b
RS
4350build_annotations_unwind (buf)
4351 Lisp_Object buf;
4352{
4353 Lisp_Object tembuf;
4354
4355 if (XBUFFER (buf) == current_buffer)
4356 return Qnil;
4357 tembuf = Fcurrent_buffer ();
4358 Fset_buffer (buf);
4359 Fkill_buffer (tembuf);
4360 return Qnil;
4361}
4362
de1d0127
RS
4363DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 7,
4364 "r\nFWrite region to file: \ni\ni\ni\np",
570d7624
JB
4365 "Write current region into specified file.\n\
4366When called from a program, takes three arguments:\n\
4367START, END and FILENAME. START and END are buffer positions.\n\
4368Optional fourth argument APPEND if non-nil means\n\
43fb7d9a
DL
4369 append to existing file contents (if any). If it is an integer,\n\
4370 seek to that offset in the file before writing.\n\
570d7624
JB
4371Optional fifth argument VISIT if t means\n\
4372 set the last-save-file-modtime of buffer to this file's modtime\n\
4373 and mark buffer not modified.\n\
3b7792ed
RS
4374If VISIT is a string, it is a second file name;\n\
4375 the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
4376 VISIT is also the file name to lock and unlock for clash detection.\n\
1d386d28
RS
4377If VISIT is neither t nor nil nor a string,\n\
4378 that means do not print the \"Wrote file\" message.\n\
7204a979 4379The optional sixth arg LOCKNAME, if non-nil, specifies the name to\n\
8b68aae7 4380 use for locking and unlocking, overriding FILENAME and VISIT.\n\
f7b4065f
RS
4381The optional seventh arg MUSTBENEW, if non-nil, insists on a check\n\
4382 for an existing file with the same name. If MUSTBENEW is `excl',\n\
4383 that means to get an error if the file already exists; never overwrite.\n\
4384 If MUSTBENEW is neither nil nor `excl', that means ask for\n\
4385 confirmation before overwriting, but do go ahead and overwrite the file\n\
4386 if the user confirms.\n\
570d7624 4387Kludgy feature: if START is a string, then that string is written\n\
6cf71bf1
KH
4388to the file, instead of any buffer contents, and END is ignored.\n\
4389\n\
4390This does code conversion according to the value of\n\
4391`coding-system-for-write', `buffer-file-coding-system', or\n\
4392`file-coding-system-alist', and sets the variable\n\
4393`last-coding-system-used' to the coding system actually used.")
4394
f7b4065f
RS
4395 (start, end, filename, append, visit, lockname, mustbenew)
4396 Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
570d7624
JB
4397{
4398 register int desc;
4399 int failure;
4400 int save_errno;
4401 unsigned char *fn;
4402 struct stat st;
c975dd7a 4403 int tem;
570d7624 4404 int count = specpdl_ptr - specpdl;
6fc6f94b 4405 int count1;
570d7624 4406#ifdef VMS
5e570b75 4407 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
570d7624 4408#endif /* VMS */
3eac9910 4409 Lisp_Object handler;
4ad827c5 4410 Lisp_Object visit_file;
d6a3cc15 4411 Lisp_Object annotations;
b1d1b865 4412 Lisp_Object encoded_filename;
d6a3cc15 4413 int visiting, quietly;
7204a979 4414 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
6fc6f94b 4415 struct buffer *given_buffer;
5e570b75 4416#ifdef DOS_NT
fa228724 4417 int buffer_file_type = O_BINARY;
5e570b75 4418#endif /* DOS_NT */
6fdaa9a0 4419 struct coding_system coding;
570d7624 4420
95385625
RS
4421 if (current_buffer->base_buffer && ! NILP (visit))
4422 error ("Cannot do file visiting in an indirect buffer");
4423
561cb8e1 4424 if (!NILP (start) && !STRINGP (start))
570d7624
JB
4425 validate_region (&start, &end);
4426
115af127 4427 GCPRO4 (start, filename, visit, lockname);
cdfb0f1d 4428
b1d1b865 4429 /* Decide the coding-system to encode the data with. */
cdfb0f1d
KH
4430 {
4431 Lisp_Object val;
4432
cbc64b2a 4433 if (auto_saving)
cdfb0f1d 4434 val = Qnil;
cdfb0f1d
KH
4435 else if (!NILP (Vcoding_system_for_write))
4436 val = Vcoding_system_for_write;
1255deb9 4437 else
450c1a67
KH
4438 {
4439 /* If the variable `buffer-file-coding-system' is set locally,
4440 it means that the file was read with some kind of code
4441 conversion or the varialbe is explicitely set by users. We
4442 had better write it out with the same coding system even if
4443 `enable-multibyte-characters' is nil.
4444
c8a6d68a 4445 If it is not set locally, we anyway have to convert EOL
450c1a67
KH
4446 format if the default value of `buffer-file-coding-system'
4447 tells that it is not Unix-like (LF only) format. */
ef38927f
KH
4448 int using_default_coding = 0;
4449 int force_raw_text = 0;
4450
450c1a67 4451 val = current_buffer->buffer_file_coding_system;
1255deb9
KH
4452 if (NILP (val)
4453 || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
450c1a67 4454 {
450c1a67 4455 val = Qnil;
ef38927f
KH
4456 if (NILP (current_buffer->enable_multibyte_characters))
4457 force_raw_text = 1;
450c1a67 4458 }
ef38927f 4459
1255deb9
KH
4460 if (NILP (val))
4461 {
4462 /* Check file-coding-system-alist. */
4463 Lisp_Object args[7], coding_systems;
4464
4465 args[0] = Qwrite_region; args[1] = start; args[2] = end;
4466 args[3] = filename; args[4] = append; args[5] = visit;
4467 args[6] = lockname;
4468 coding_systems = Ffind_operation_coding_system (7, args);
03699b14
KR
4469 if (CONSP (coding_systems) && !NILP (XCDR (coding_systems)))
4470 val = XCDR (coding_systems);
1255deb9
KH
4471 }
4472
ef38927f
KH
4473 if (NILP (val)
4474 && !NILP (current_buffer->buffer_file_coding_system))
4475 {
4476 /* If we still have not decided a coding system, use the
4477 default value of buffer-file-coding-system. */
4478 val = current_buffer->buffer_file_coding_system;
4479 using_default_coding = 1;
4480 }
1255deb9 4481
ef38927f 4482 if (!force_raw_text
1255deb9
KH
4483 && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
4484 /* Confirm that VAL can surely encode the current region. */
c8a6d68a 4485 val = call3 (Vselect_safe_coding_system_function, start, end, val);
ef38927f
KH
4486
4487 setup_coding_system (Fcheck_coding_system (val), &coding);
4488 if (coding.eol_type == CODING_EOL_UNDECIDED
4489 && !using_default_coding)
4490 {
4491 if (! EQ (default_buffer_file_coding.symbol,
4492 buffer_defaults.buffer_file_coding_system))
4493 setup_coding_system (buffer_defaults.buffer_file_coding_system,
4494 &default_buffer_file_coding);
4495 if (default_buffer_file_coding.eol_type != CODING_EOL_UNDECIDED)
4496 {
4497 Lisp_Object subsidiaries;
4498
4499 coding.eol_type = default_buffer_file_coding.eol_type;
4500 subsidiaries = Fget (coding.symbol, Qeol_type);
4501 if (VECTORP (subsidiaries)
4502 && XVECTOR (subsidiaries)->size == 3)
4503 coding.symbol
4504 = XVECTOR (subsidiaries)->contents[coding.eol_type];
4505 }
4506 }
4507
4508 if (force_raw_text)
4509 setup_raw_text_coding_system (&coding);
4510 goto done_setup_coding;
cdfb0f1d 4511 }
ef38927f 4512
1255deb9 4513 setup_coding_system (Fcheck_coding_system (val), &coding);
450c1a67
KH
4514
4515 done_setup_coding:
cdfb0f1d 4516 if (!STRINGP (start) && !NILP (current_buffer->selective_display))
c8a6d68a 4517 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
cdfb0f1d
KH
4518 }
4519
b56567b5
KH
4520 Vlast_coding_system_used = coding.symbol;
4521
570d7624 4522 filename = Fexpand_file_name (filename, Qnil);
de1d0127 4523
7c752c80 4524 if (! NILP (mustbenew) && !EQ (mustbenew, Qexcl))
b8b29dc9 4525 barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1);
de1d0127 4526
561cb8e1 4527 if (STRINGP (visit))
e5176bae 4528 visit_file = Fexpand_file_name (visit, Qnil);
4ad827c5
RS
4529 else
4530 visit_file = filename;
1a04498e 4531 UNGCPRO;
4ad827c5 4532
561cb8e1 4533 visiting = (EQ (visit, Qt) || STRINGP (visit));
d6a3cc15
RS
4534 quietly = !NILP (visit);
4535
4536 annotations = Qnil;
4537
7204a979
RS
4538 if (NILP (lockname))
4539 lockname = visit_file;
4540
4541 GCPRO5 (start, filename, annotations, visit_file, lockname);
570d7624 4542
32f4334d
RS
4543 /* If the file name has special constructs in it,
4544 call the corresponding file handler. */
49307295 4545 handler = Ffind_file_name_handler (filename, Qwrite_region);
b56ad927 4546 /* If FILENAME has no handler, see if VISIT has one. */
93c30b5f 4547 if (NILP (handler) && STRINGP (visit))
199607e4 4548 handler = Ffind_file_name_handler (visit, Qwrite_region);
3eac9910 4549
32f4334d
RS
4550 if (!NILP (handler))
4551 {
32f4334d 4552 Lisp_Object val;
51cf6d37
RS
4553 val = call6 (handler, Qwrite_region, start, end,
4554 filename, append, visit);
32f4334d 4555
d6a3cc15 4556 if (visiting)
32f4334d 4557 {
95385625 4558 SAVE_MODIFF = MODIFF;
2acfd7ae 4559 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 4560 current_buffer->filename = visit_file;
32f4334d 4561 }
09121adc 4562 UNGCPRO;
32f4334d
RS
4563 return val;
4564 }
4565
561cb8e1
RS
4566 /* Special kludge to simplify auto-saving. */
4567 if (NILP (start))
4568 {
2acfd7ae
KH
4569 XSETFASTINT (start, BEG);
4570 XSETFASTINT (end, Z);
561cb8e1
RS
4571 }
4572
6fc6f94b
RS
4573 record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
4574 count1 = specpdl_ptr - specpdl;
4575
4576 given_buffer = current_buffer;
6fdaa9a0 4577 annotations = build_annotations (start, end, coding.pre_write_conversion);
6fc6f94b
RS
4578 if (current_buffer != given_buffer)
4579 {
3cf29f61
RS
4580 XSETFASTINT (start, BEGV);
4581 XSETFASTINT (end, ZV);
6fc6f94b 4582 }
d6a3cc15 4583
570d7624
JB
4584#ifdef CLASH_DETECTION
4585 if (!auto_saving)
84f6296a 4586 {
a9171faa 4587#if 0 /* This causes trouble for GNUS. */
84f6296a
RS
4588 /* If we've locked this file for some other buffer,
4589 query before proceeding. */
4590 if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
bffd00b0 4591 call2 (intern ("ask-user-about-lock"), filename, Vuser_login_name);
a9171faa 4592#endif
84f6296a
RS
4593
4594 lock_file (lockname);
4595 }
570d7624
JB
4596#endif /* CLASH_DETECTION */
4597
b1d1b865
RS
4598 encoded_filename = ENCODE_FILE (filename);
4599
4600 fn = XSTRING (encoded_filename)->data;
570d7624 4601 desc = -1;
265a9e55 4602 if (!NILP (append))
5e570b75 4603#ifdef DOS_NT
68c45bf0 4604 desc = emacs_open (fn, O_WRONLY | buffer_file_type, 0);
5e570b75 4605#else /* not DOS_NT */
68c45bf0 4606 desc = emacs_open (fn, O_WRONLY, 0);
5e570b75 4607#endif /* not DOS_NT */
570d7624 4608
b1d1b865 4609 if (desc < 0 && (NILP (append) || errno == ENOENT))
570d7624 4610#ifdef VMS
5e570b75 4611 if (auto_saving) /* Overwrite any previous version of autosave file */
570d7624 4612 {
5e570b75 4613 vms_truncate (fn); /* if fn exists, truncate to zero length */
68c45bf0 4614 desc = emacs_open (fn, O_RDWR, 0);
570d7624 4615 if (desc < 0)
561cb8e1 4616 desc = creat_copy_attrs (STRINGP (current_buffer->filename)
b72dea2a
JB
4617 ? XSTRING (current_buffer->filename)->data : 0,
4618 fn);
570d7624 4619 }
5e570b75 4620 else /* Write to temporary name and rename if no errors */
570d7624
JB
4621 {
4622 Lisp_Object temp_name;
4623 temp_name = Ffile_name_directory (filename);
4624
265a9e55 4625 if (!NILP (temp_name))
570d7624
JB
4626 {
4627 temp_name = Fmake_temp_name (concat2 (temp_name,
4628 build_string ("$$SAVE$$")));
4629 fname = XSTRING (filename)->data;
4630 fn = XSTRING (temp_name)->data;
4631 desc = creat_copy_attrs (fname, fn);
4632 if (desc < 0)
4633 {
4634 /* If we can't open the temporary file, try creating a new
4635 version of the original file. VMS "creat" creates a
4636 new version rather than truncating an existing file. */
4637 fn = fname;
4638 fname = 0;
4639 desc = creat (fn, 0666);
4640#if 0 /* This can clobber an existing file and fail to replace it,
4641 if the user runs out of space. */
4642 if (desc < 0)
4643 {
4644 /* We can't make a new version;
4645 try to truncate and rewrite existing version if any. */
4646 vms_truncate (fn);
68c45bf0 4647 desc = emacs_open (fn, O_RDWR, 0);
570d7624
JB
4648 }
4649#endif
4650 }
4651 }
4652 else
4653 desc = creat (fn, 0666);
4654 }
4655#else /* not VMS */
5e570b75 4656#ifdef DOS_NT
68c45bf0
PE
4657 desc = emacs_open (fn,
4658 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type
4659 | (mustbenew == Qexcl ? O_EXCL : 0),
4660 S_IREAD | S_IWRITE);
5e570b75 4661#else /* not DOS_NT */
68c45bf0 4662 desc = emacs_open (fn, O_WRONLY | O_TRUNC | O_CREAT
7c752c80 4663 | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
68c45bf0 4664 auto_saving ? auto_save_mode_bits : 0666);
5e570b75 4665#endif /* not DOS_NT */
570d7624
JB
4666#endif /* not VMS */
4667
4668 if (desc < 0)
4669 {
4670#ifdef CLASH_DETECTION
4671 save_errno = errno;
7204a979 4672 if (!auto_saving) unlock_file (lockname);
570d7624
JB
4673 errno = save_errno;
4674#endif /* CLASH_DETECTION */
43fb7d9a 4675 UNGCPRO;
570d7624
JB
4676 report_file_error ("Opening output file", Fcons (filename, Qnil));
4677 }
4678
4679 record_unwind_protect (close_file_unwind, make_number (desc));
4680
c1c4693e 4681 if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
43fb7d9a
DL
4682 {
4683 long ret;
4684
4685 if (NUMBERP (append))
4686 ret = lseek (desc, XINT (append), 1);
4687 else
4688 ret = lseek (desc, 0, 2);
4689 if (ret < 0)
4690 {
570d7624 4691#ifdef CLASH_DETECTION
43fb7d9a 4692 if (!auto_saving) unlock_file (lockname);
570d7624 4693#endif /* CLASH_DETECTION */
43fb7d9a
DL
4694 UNGCPRO;
4695 report_file_error ("Lseek error", Fcons (filename, Qnil));
4696 }
4697 }
4698
4699 UNGCPRO;
570d7624
JB
4700
4701#ifdef VMS
4702/*
4703 * Kludge Warning: The VMS C RTL likes to insert carriage returns
4704 * if we do writes that don't end with a carriage return. Furthermore
4705 * it cannot handle writes of more then 16K. The modified
4706 * version of "sys_write" in SYSDEP.C (see comment there) copes with
4707 * this EXCEPT for the last record (iff it doesn't end with a carriage
4708 * return). This implies that if your buffer doesn't end with a carriage
4709 * return, you get one free... tough. However it also means that if
4710 * we make two calls to sys_write (a la the following code) you can
4711 * get one at the gap as well. The easiest way to fix this (honest)
4712 * is to move the gap to the next newline (or the end of the buffer).
4713 * Thus this change.
4714 *
4715 * Yech!
4716 */
4717 if (GPT > BEG && GPT_ADDR[-1] != '\n')
4718 move_gap (find_next_newline (GPT, 1));
cdfb0f1d
KH
4719#else
4720 /* Whether VMS or not, we must move the gap to the next of newline
4721 when we must put designation sequences at beginning of line. */
4722 if (INTEGERP (start)
4723 && coding.type == coding_type_iso2022
4724 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
4725 && GPT > BEG && GPT_ADDR[-1] != '\n')
ec7adf26
RS
4726 {
4727 int opoint = PT, opoint_byte = PT_BYTE;
4728 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
4729 move_gap_both (PT, PT_BYTE);
4730 SET_PT_BOTH (opoint, opoint_byte);
4731 }
570d7624
JB
4732#endif
4733
4734 failure = 0;
4735 immediate_quit = 1;
4736
561cb8e1 4737 if (STRINGP (start))
570d7624 4738 {
ce51c54c
KH
4739 failure = 0 > a_write (desc, start, 0, XSTRING (start)->size,
4740 &annotations, &coding);
570d7624
JB
4741 save_errno = errno;
4742 }
4743 else if (XINT (start) != XINT (end))
4744 {
ec7adf26
RS
4745 tem = CHAR_TO_BYTE (XINT (start));
4746
570d7624
JB
4747 if (XINT (start) < GPT)
4748 {
ce51c54c
KH
4749 failure = 0 > a_write (desc, Qnil, XINT (start),
4750 min (GPT, XINT (end)) - XINT (start),
4751 &annotations, &coding);
570d7624
JB
4752 save_errno = errno;
4753 }
4754
4755 if (XINT (end) > GPT && !failure)
4756 {
ce51c54c
KH
4757 tem = max (XINT (start), GPT);
4758 failure = 0 > a_write (desc, Qnil, tem , XINT (end) - tem,
4759 &annotations, &coding);
d6a3cc15
RS
4760 save_errno = errno;
4761 }
69f6e679
RS
4762 }
4763 else
4764 {
4765 /* If file was empty, still need to write the annotations */
c8a6d68a 4766 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 4767 failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
6fdaa9a0
KH
4768 save_errno = errno;
4769 }
4770
c8a6d68a
KH
4771 if (CODING_REQUIRE_FLUSHING (&coding)
4772 && !(coding.mode & CODING_MODE_LAST_BLOCK)
1354debd 4773 && ! failure)
6fdaa9a0
KH
4774 {
4775 /* We have to flush out a data. */
c8a6d68a 4776 coding.mode |= CODING_MODE_LAST_BLOCK;
ce51c54c 4777 failure = 0 > e_write (desc, Qnil, 0, 0, &coding);
69f6e679 4778 save_errno = errno;
570d7624
JB
4779 }
4780
4781 immediate_quit = 0;
4782
6e23c83e 4783#ifdef HAVE_FSYNC
570d7624
JB
4784 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
4785 Disk full in NFS may be reported here. */
1daffa1c
RS
4786 /* mib says that closing the file will try to write as fast as NFS can do
4787 it, and that means the fsync here is not crucial for autosave files. */
4788 if (!auto_saving && fsync (desc) < 0)
cb33c142
KH
4789 {
4790 /* If fsync fails with EINTR, don't treat that as serious. */
4791 if (errno != EINTR)
4792 failure = 1, save_errno = errno;
4793 }
570d7624
JB
4794#endif
4795
199607e4 4796 /* Spurious "file has changed on disk" warnings have been
570d7624
JB
4797 observed on Suns as well.
4798 It seems that `close' can change the modtime, under nfs.
4799
4800 (This has supposedly been fixed in Sunos 4,
4801 but who knows about all the other machines with NFS?) */
4802#if 0
4803
4804 /* On VMS and APOLLO, must do the stat after the close
4805 since closing changes the modtime. */
4806#ifndef VMS
4807#ifndef APOLLO
4808 /* Recall that #if defined does not work on VMS. */
4809#define FOO
4810 fstat (desc, &st);
4811#endif
4812#endif
4813#endif
4814
4815 /* NFS can report a write failure now. */
68c45bf0 4816 if (emacs_close (desc) < 0)
570d7624
JB
4817 failure = 1, save_errno = errno;
4818
4819#ifdef VMS
4820 /* If we wrote to a temporary name and had no errors, rename to real name. */
4821 if (fname)
4822 {
4823 if (!failure)
4824 failure = (rename (fn, fname) != 0), save_errno = errno;
4825 fn = fname;
4826 }
4827#endif /* VMS */
4828
4829#ifndef FOO
4830 stat (fn, &st);
4831#endif
6fc6f94b
RS
4832 /* Discard the unwind protect for close_file_unwind. */
4833 specpdl_ptr = specpdl + count1;
4834 /* Restore the original current buffer. */
98295b48 4835 visit_file = unbind_to (count, visit_file);
570d7624
JB
4836
4837#ifdef CLASH_DETECTION
4838 if (!auto_saving)
7204a979 4839 unlock_file (lockname);
570d7624
JB
4840#endif /* CLASH_DETECTION */
4841
4842 /* Do this before reporting IO error
4843 to avoid a "file has changed on disk" warning on
4844 next attempt to save. */
d6a3cc15 4845 if (visiting)
570d7624
JB
4846 current_buffer->modtime = st.st_mtime;
4847
4848 if (failure)
b1d1b865 4849 error ("IO error writing %s: %s", XSTRING (filename)->data,
68c45bf0 4850 emacs_strerror (save_errno));
570d7624 4851
d6a3cc15 4852 if (visiting)
570d7624 4853 {
95385625 4854 SAVE_MODIFF = MODIFF;
2acfd7ae 4855 XSETFASTINT (current_buffer->save_length, Z - BEG);
3b7792ed 4856 current_buffer->filename = visit_file;
f4226e89 4857 update_mode_lines++;
570d7624 4858 }
d6a3cc15 4859 else if (quietly)
570d7624
JB
4860 return Qnil;
4861
4862 if (!auto_saving)
60d67b83 4863 message_with_string ("Wrote %s", visit_file, 1);
570d7624
JB
4864
4865 return Qnil;
4866}
ec7adf26 4867\f
d6a3cc15
RS
4868Lisp_Object merge ();
4869
4870DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
2ba0ccff 4871 "Return t if (car A) is numerically less than (car B).")
d6a3cc15
RS
4872 (a, b)
4873 Lisp_Object a, b;
4874{
4875 return Flss (Fcar (a), Fcar (b));
4876}
4877
4878/* Build the complete list of annotations appropriate for writing out
4879 the text between START and END, by calling all the functions in
6fc6f94b
RS
4880 write-region-annotate-functions and merging the lists they return.
4881 If one of these functions switches to a different buffer, we assume
4882 that buffer contains altered text. Therefore, the caller must
4883 make sure to restore the current buffer in all cases,
4884 as save-excursion would do. */
d6a3cc15
RS
4885
4886static Lisp_Object
6fdaa9a0
KH
4887build_annotations (start, end, pre_write_conversion)
4888 Lisp_Object start, end, pre_write_conversion;
d6a3cc15
RS
4889{
4890 Lisp_Object annotations;
4891 Lisp_Object p, res;
4892 struct gcpro gcpro1, gcpro2;
0a20b684 4893 Lisp_Object original_buffer;
532ed661 4894 int i;
0a20b684
RS
4895
4896 XSETBUFFER (original_buffer, current_buffer);
d6a3cc15
RS
4897
4898 annotations = Qnil;
4899 p = Vwrite_region_annotate_functions;
4900 GCPRO2 (annotations, p);
4901 while (!NILP (p))
4902 {
6fc6f94b
RS
4903 struct buffer *given_buffer = current_buffer;
4904 Vwrite_region_annotations_so_far = annotations;
d6a3cc15 4905 res = call2 (Fcar (p), start, end);
6fc6f94b
RS
4906 /* If the function makes a different buffer current,
4907 assume that means this buffer contains altered text to be output.
4908 Reset START and END from the buffer bounds
4909 and discard all previous annotations because they should have
4910 been dealt with by this function. */
4911 if (current_buffer != given_buffer)
4912 {
3cf29f61
RS
4913 XSETFASTINT (start, BEGV);
4914 XSETFASTINT (end, ZV);
6fc6f94b
RS
4915 annotations = Qnil;
4916 }
d6a3cc15
RS
4917 Flength (res); /* Check basic validity of return value */
4918 annotations = merge (annotations, res, Qcar_less_than_car);
4919 p = Fcdr (p);
4920 }
0d420e88
BG
4921
4922 /* Now do the same for annotation functions implied by the file-format */
4923 if (auto_saving && (!EQ (Vauto_save_file_format, Qt)))
4924 p = Vauto_save_file_format;
4925 else
4926 p = current_buffer->file_format;
532ed661 4927 for (i = 0; !NILP (p); p = Fcdr (p), ++i)
0d420e88
BG
4928 {
4929 struct buffer *given_buffer = current_buffer;
532ed661 4930
0d420e88 4931 Vwrite_region_annotations_so_far = annotations;
532ed661
GM
4932
4933 /* Value is either a list of annotations or nil if the function
4934 has written annotations to a temporary buffer, which is now
4935 current. */
4936 res = call5 (Qformat_annotate_function, Fcar (p), start, end,
4937 original_buffer, make_number (i));
0d420e88
BG
4938 if (current_buffer != given_buffer)
4939 {
3cf29f61
RS
4940 XSETFASTINT (start, BEGV);
4941 XSETFASTINT (end, ZV);
0d420e88
BG
4942 annotations = Qnil;
4943 }
532ed661
GM
4944
4945 if (CONSP (res))
4946 annotations = merge (annotations, res, Qcar_less_than_car);
0d420e88 4947 }
6fdaa9a0
KH
4948
4949 /* At last, do the same for the function PRE_WRITE_CONVERSION
4950 implied by the current coding-system. */
4951 if (!NILP (pre_write_conversion))
4952 {
4953 struct buffer *given_buffer = current_buffer;
4954 Vwrite_region_annotations_so_far = annotations;
4955 res = call2 (pre_write_conversion, start, end);
6fdaa9a0 4956 Flength (res);
cdfb0f1d
KH
4957 annotations = (current_buffer != given_buffer
4958 ? res
4959 : merge (annotations, res, Qcar_less_than_car));
6fdaa9a0
KH
4960 }
4961
d6a3cc15
RS
4962 UNGCPRO;
4963 return annotations;
4964}
ec7adf26 4965\f
ce51c54c
KH
4966/* Write to descriptor DESC the NCHARS chars starting at POS of STRING.
4967 If STRING is nil, POS is the character position in the current buffer.
d6a3cc15 4968 Intersperse with them the annotations from *ANNOT
ce51c54c 4969 which fall within the range of POS to POS + NCHARS,
d6a3cc15
RS
4970 each at its appropriate position.
4971
ec7adf26
RS
4972 We modify *ANNOT by discarding elements as we use them up.
4973
d6a3cc15
RS
4974 The return value is negative in case of system call failure. */
4975
ec7adf26 4976static int
ce51c54c 4977a_write (desc, string, pos, nchars, annot, coding)
d6a3cc15 4978 int desc;
ce51c54c
KH
4979 Lisp_Object string;
4980 register int nchars;
4981 int pos;
d6a3cc15 4982 Lisp_Object *annot;
6fdaa9a0 4983 struct coding_system *coding;
d6a3cc15
RS
4984{
4985 Lisp_Object tem;
4986 int nextpos;
ce51c54c 4987 int lastpos = pos + nchars;
d6a3cc15 4988
eb15aa18 4989 while (NILP (*annot) || CONSP (*annot))
d6a3cc15
RS
4990 {
4991 tem = Fcar_safe (Fcar (*annot));
ce51c54c 4992 nextpos = pos - 1;
ec7adf26 4993 if (INTEGERP (tem))
ce51c54c 4994 nextpos = XFASTINT (tem);
ec7adf26
RS
4995
4996 /* If there are no more annotations in this range,
4997 output the rest of the range all at once. */
ce51c54c
KH
4998 if (! (nextpos >= pos && nextpos <= lastpos))
4999 return e_write (desc, string, pos, lastpos, coding);
ec7adf26
RS
5000
5001 /* Output buffer text up to the next annotation's position. */
ce51c54c 5002 if (nextpos > pos)
d6a3cc15 5003 {
055a28c9 5004 if (0 > e_write (desc, string, pos, nextpos, coding))
d6a3cc15 5005 return -1;
ce51c54c 5006 pos = nextpos;
d6a3cc15 5007 }
ec7adf26 5008 /* Output the annotation. */
d6a3cc15
RS
5009 tem = Fcdr (Fcar (*annot));
5010 if (STRINGP (tem))
5011 {
055a28c9 5012 if (0 > e_write (desc, tem, 0, XSTRING (tem)->size, coding))
d6a3cc15
RS
5013 return -1;
5014 }
5015 *annot = Fcdr (*annot);
5016 }
dfcf069d 5017 return 0;
d6a3cc15
RS
5018}
5019
6fdaa9a0
KH
5020#ifndef WRITE_BUF_SIZE
5021#define WRITE_BUF_SIZE (16 * 1024)
5022#endif
5023
ce51c54c
KH
5024/* Write text in the range START and END into descriptor DESC,
5025 encoding them with coding system CODING. If STRING is nil, START
5026 and END are character positions of the current buffer, else they
5027 are indexes to the string STRING. */
ec7adf26
RS
5028
5029static int
ce51c54c 5030e_write (desc, string, start, end, coding)
570d7624 5031 int desc;
ce51c54c
KH
5032 Lisp_Object string;
5033 int start, end;
6fdaa9a0 5034 struct coding_system *coding;
570d7624 5035{
ce51c54c
KH
5036 register char *addr;
5037 register int nbytes;
6fdaa9a0 5038 char buf[WRITE_BUF_SIZE];
ce51c54c 5039 int return_val = 0;
8c3b9441 5040 int require_encoding_p;
ce51c54c
KH
5041
5042 if (start >= end)
5043 coding->composing = COMPOSITION_DISABLED;
5044 if (coding->composing != COMPOSITION_DISABLED)
5045 coding_save_composition (coding, start, end, string);
5046
5047 if (STRINGP (string))
5048 {
5049 addr = XSTRING (string)->data;
5050 nbytes = STRING_BYTES (XSTRING (string));
8c3b9441 5051 coding->src_multibyte = STRING_MULTIBYTE (string);
ce51c54c
KH
5052 }
5053 else if (start < end)
5054 {
5055 /* It is assured that the gap is not in the range START and END-1. */
5056 addr = CHAR_POS_ADDR (start);
5057 nbytes = CHAR_TO_BYTE (end) - CHAR_TO_BYTE (start);
8c3b9441
KH
5058 coding->src_multibyte
5059 = !NILP (current_buffer->enable_multibyte_characters);
ce51c54c
KH
5060 }
5061 else
5062 {
5063 addr = "";
5064 nbytes = 0;
8c3b9441 5065 coding->src_multibyte = 1;
ce51c54c 5066 }
570d7624 5067
6fdaa9a0
KH
5068 /* We used to have a code for handling selective display here. But,
5069 now it is handled within encode_coding. */
5070 while (1)
570d7624 5071 {
b4132433
KH
5072 int result;
5073
5074 result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
c8a6d68a 5075 if (coding->produced > 0)
6fdaa9a0 5076 {
68c45bf0 5077 coding->produced -= emacs_write (desc, buf, coding->produced);
ce51c54c
KH
5078 if (coding->produced)
5079 {
5080 return_val = -1;
5081 break;
5082 }
570d7624 5083 }
ca91fb26
KH
5084 nbytes -= coding->consumed;
5085 addr += coding->consumed;
5086 if (result == CODING_FINISH_INSUFFICIENT_SRC
5087 && nbytes > 0)
b4132433
KH
5088 {
5089 /* The source text ends by an incomplete multibyte form.
5090 There's no way other than write it out as is. */
68c45bf0 5091 nbytes -= emacs_write (desc, addr, nbytes);
ce51c54c
KH
5092 if (nbytes)
5093 {
5094 return_val = -1;
5095 break;
5096 }
b4132433 5097 }
ec7adf26 5098 if (nbytes <= 0)
6fdaa9a0 5099 break;
ce51c54c
KH
5100 start += coding->consumed_char;
5101 if (coding->cmp_data)
5102 coding_adjust_composition_offset (coding, start);
570d7624 5103 }
0c41a39c
KH
5104
5105 if (coding->cmp_data)
5106 coding_free_composition_data (coding);
5107
055a28c9 5108 return return_val;
570d7624 5109}
ec7adf26 5110\f
570d7624
JB
5111DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
5112 Sverify_visited_file_modtime, 1, 1, 0,
5113 "Return t if last mod time of BUF's visited file matches what BUF records.\n\
5114This means that the file has not been changed since it was visited or saved.")
5115 (buf)
5116 Lisp_Object buf;
5117{
5118 struct buffer *b;
5119 struct stat st;
32f4334d 5120 Lisp_Object handler;
b1d1b865 5121 Lisp_Object filename;
570d7624
JB
5122
5123 CHECK_BUFFER (buf, 0);
5124 b = XBUFFER (buf);
5125
93c30b5f 5126 if (!STRINGP (b->filename)) return Qt;
570d7624
JB
5127 if (b->modtime == 0) return Qt;
5128
32f4334d
RS
5129 /* If the file name has special constructs in it,
5130 call the corresponding file handler. */
49307295
KH
5131 handler = Ffind_file_name_handler (b->filename,
5132 Qverify_visited_file_modtime);
32f4334d 5133 if (!NILP (handler))
09121adc 5134 return call2 (handler, Qverify_visited_file_modtime, buf);
32f4334d 5135
b1d1b865
RS
5136 filename = ENCODE_FILE (b->filename);
5137
5138 if (stat (XSTRING (filename)->data, &st) < 0)
570d7624
JB
5139 {
5140 /* If the file doesn't exist now and didn't exist before,
5141 we say that it isn't modified, provided the error is a tame one. */
5142 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
5143 st.st_mtime = -1;
5144 else
5145 st.st_mtime = 0;
5146 }
5147 if (st.st_mtime == b->modtime
5148 /* If both are positive, accept them if they are off by one second. */
5149 || (st.st_mtime > 0 && b->modtime > 0
5150 && (st.st_mtime == b->modtime + 1
5151 || st.st_mtime == b->modtime - 1)))
5152 return Qt;
5153 return Qnil;
5154}
5155
5156DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
5157 Sclear_visited_file_modtime, 0, 0, 0,
5158 "Clear out records of last mod time of visited file.\n\
5159Next attempt to save will certainly not complain of a discrepancy.")
5160 ()
5161{
5162 current_buffer->modtime = 0;
5163 return Qnil;
5164}
5165
f5d5eccf
RS
5166DEFUN ("visited-file-modtime", Fvisited_file_modtime,
5167 Svisited_file_modtime, 0, 0, 0,
5168 "Return the current buffer's recorded visited file modification time.\n\
5169The value is a list of the form (HIGH . LOW), like the time values\n\
5170that `file-attributes' returns.")
5171 ()
5172{
b50536bb 5173 return long_to_cons ((unsigned long) current_buffer->modtime);
f5d5eccf
RS
5174}
5175
570d7624 5176DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
f5d5eccf 5177 Sset_visited_file_modtime, 0, 1, 0,
570d7624
JB
5178 "Update buffer's recorded modification time from the visited file's time.\n\
5179Useful if the buffer was not read from the file normally\n\
f5d5eccf
RS
5180or if the file itself has been changed for some known benign reason.\n\
5181An argument specifies the modification time value to use\n\
5182\(instead of that of the visited file), in the form of a list\n\
5183\(HIGH . LOW) or (HIGH LOW).")
5184 (time_list)
5185 Lisp_Object time_list;
570d7624 5186{
f5d5eccf
RS
5187 if (!NILP (time_list))
5188 current_buffer->modtime = cons_to_long (time_list);
5189 else
5190 {
5191 register Lisp_Object filename;
5192 struct stat st;
5193 Lisp_Object handler;
570d7624 5194
f5d5eccf 5195 filename = Fexpand_file_name (current_buffer->filename, Qnil);
32f4334d 5196
f5d5eccf
RS
5197 /* If the file name has special constructs in it,
5198 call the corresponding file handler. */
49307295 5199 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
f5d5eccf 5200 if (!NILP (handler))
caf3c431 5201 /* The handler can find the file name the same way we did. */
76c881b0 5202 return call2 (handler, Qset_visited_file_modtime, Qnil);
b1d1b865
RS
5203
5204 filename = ENCODE_FILE (filename);
5205
5206 if (stat (XSTRING (filename)->data, &st) >= 0)
f5d5eccf
RS
5207 current_buffer->modtime = st.st_mtime;
5208 }
570d7624
JB
5209
5210 return Qnil;
5211}
5212\f
5213Lisp_Object
5214auto_save_error ()
5215{
570d7624 5216 ring_bell ();
60d67b83 5217 message_with_string ("Autosaving...error for %s", current_buffer->name, 1);
de49a6d3 5218 Fsleep_for (make_number (1), Qnil);
60d67b83 5219 message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
de49a6d3 5220 Fsleep_for (make_number (1), Qnil);
60d67b83 5221 message_with_string ("Autosaving...error for %s", current_buffer->name, 0);
de49a6d3 5222 Fsleep_for (make_number (1), Qnil);
570d7624
JB
5223 return Qnil;
5224}
5225
5226Lisp_Object
5227auto_save_1 ()
5228{
570d7624
JB
5229 struct stat st;
5230
5231 /* Get visited file's mode to become the auto save file's mode. */
8801a864
KR
5232 if (! NILP (current_buffer->filename)
5233 && stat (XSTRING (current_buffer->filename)->data, &st) >= 0)
570d7624
JB
5234 /* But make sure we can overwrite it later! */
5235 auto_save_mode_bits = st.st_mode | 0600;
5236 else
5237 auto_save_mode_bits = 0666;
5238
5239 return
5240 Fwrite_region (Qnil, Qnil,
5241 current_buffer->auto_save_file_name,
de1d0127 5242 Qnil, Qlambda, Qnil, Qnil);
570d7624
JB
5243}
5244
e54d3b5d 5245static Lisp_Object
1b335d29
RS
5246do_auto_save_unwind (stream) /* used as unwind-protect function */
5247 Lisp_Object stream;
e54d3b5d 5248{
3be3c08e 5249 auto_saving = 0;
1b335d29 5250 if (!NILP (stream))
03699b14
KR
5251 fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
5252 | XFASTINT (XCDR (stream))));
e54d3b5d
RS
5253 return Qnil;
5254}
5255
a8c828be
RS
5256static Lisp_Object
5257do_auto_save_unwind_1 (value) /* used as unwind-protect function */
5258 Lisp_Object value;
5259{
5260 minibuffer_auto_raise = XINT (value);
5261 return Qnil;
5262}
5263
570d7624
JB
5264DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
5265 "Auto-save all buffers that need it.\n\
5266This is all buffers that have auto-saving enabled\n\
5267and are changed since last auto-saved.\n\
5268Auto-saving writes the buffer into a file\n\
5269so that your editing is not lost if the system crashes.\n\
012d4cdc
RS
5270This file is not the file you visited; that changes only when you save.\n\
5271Normally we run the normal hook `auto-save-hook' before saving.\n\n\
3b7f6e60
EN
5272A non-nil NO-MESSAGE argument means do not print any message if successful.\n\
5273A non-nil CURRENT-ONLY argument means save only current buffer.")
17857782
JB
5274 (no_message, current_only)
5275 Lisp_Object no_message, current_only;
570d7624
JB
5276{
5277 struct buffer *old = current_buffer, *b;
5278 Lisp_Object tail, buf;
5279 int auto_saved = 0;
f14b1c68 5280 int do_handled_files;
ff4c9993 5281 Lisp_Object oquit;
1b335d29
RS
5282 FILE *stream;
5283 Lisp_Object lispstream;
e54d3b5d 5284 int count = specpdl_ptr - specpdl;
a8c828be 5285 int orig_minibuffer_auto_raise = minibuffer_auto_raise;
c71106e5 5286 int message_p = push_message ();
9c856db9 5287
ff4c9993
RS
5288 /* Ordinarily don't quit within this function,
5289 but don't make it impossible to quit (in case we get hung in I/O). */
5290 oquit = Vquit_flag;
5291 Vquit_flag = Qnil;
570d7624
JB
5292
5293 /* No GCPRO needed, because (when it matters) all Lisp_Object variables
5294 point to non-strings reached from Vbuffer_alist. */
5295
570d7624 5296 if (minibuf_level)
17857782 5297 no_message = Qt;
570d7624 5298
265a9e55 5299 if (!NILP (Vrun_hooks))
570d7624
JB
5300 call1 (Vrun_hooks, intern ("auto-save-hook"));
5301
e54d3b5d
RS
5302 if (STRINGP (Vauto_save_list_file_name))
5303 {
b272d624
GM
5304 Lisp_Object listfile, dir;
5305
258fd2cb 5306 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
b272d624
GM
5307
5308 dir = Ffile_name_directory (listfile);
5309 if (NILP (Ffile_directory_p (dir)))
5310 call2 (Qmake_directory, dir, Qt);
5311
1b335d29 5312 stream = fopen (XSTRING (listfile)->data, "w");
0eff1f85
RS
5313 if (stream != NULL)
5314 {
5315 /* Arrange to close that file whether or not we get an error.
5316 Also reset auto_saving to 0. */
5317 lispstream = Fcons (Qnil, Qnil);
03699b14
KR
5318 XSETFASTINT (XCAR (lispstream), (EMACS_UINT)stream >> 16);
5319 XSETFASTINT (XCDR (lispstream), (EMACS_UINT)stream & 0xffff);
0eff1f85
RS
5320 }
5321 else
5322 lispstream = Qnil;
e54d3b5d
RS
5323 }
5324 else
1b335d29
RS
5325 {
5326 stream = NULL;
5327 lispstream = Qnil;
5328 }
199607e4 5329
1b335d29 5330 record_unwind_protect (do_auto_save_unwind, lispstream);
a8c828be
RS
5331 record_unwind_protect (do_auto_save_unwind_1,
5332 make_number (minibuffer_auto_raise));
5333 minibuffer_auto_raise = 0;
3be3c08e
RS
5334 auto_saving = 1;
5335
f14b1c68
JB
5336 /* First, save all files which don't have handlers. If Emacs is
5337 crashing, the handlers may tweak what is causing Emacs to crash
5338 in the first place, and it would be a shame if Emacs failed to
5339 autosave perfectly ordinary files because it couldn't handle some
5340 ange-ftp'd file. */
5341 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
03699b14 5342 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail))
f14b1c68 5343 {
03699b14 5344 buf = XCDR (XCAR (tail));
f14b1c68 5345 b = XBUFFER (buf);
199607e4 5346
e54d3b5d 5347 /* Record all the buffers that have auto save mode
258fd2cb
RS
5348 in the special file that lists them. For each of these buffers,
5349 Record visited name (if any) and auto save name. */
93c30b5f 5350 if (STRINGP (b->auto_save_file_name)
1b335d29 5351 && stream != NULL && do_handled_files == 0)
e54d3b5d 5352 {
258fd2cb
RS
5353 if (!NILP (b->filename))
5354 {
1b335d29 5355 fwrite (XSTRING (b->filename)->data, 1,
fc932ac6 5356 STRING_BYTES (XSTRING (b->filename)), stream);
258fd2cb 5357 }
1b335d29
RS
5358 putc ('\n', stream);
5359 fwrite (XSTRING (b->auto_save_file_name)->data, 1,
fc932ac6 5360 STRING_BYTES (XSTRING (b->auto_save_file_name)), stream);
1b335d29 5361 putc ('\n', stream);
e54d3b5d 5362 }
17857782 5363
f14b1c68
JB
5364 if (!NILP (current_only)
5365 && b != current_buffer)
5366 continue;
e54d3b5d 5367
95385625
RS
5368 /* Don't auto-save indirect buffers.
5369 The base buffer takes care of it. */
5370 if (b->base_buffer)
5371 continue;
5372
f14b1c68
JB
5373 /* Check for auto save enabled
5374 and file changed since last auto save
5375 and file changed since last real save. */
93c30b5f 5376 if (STRINGP (b->auto_save_file_name)
95385625 5377 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
f14b1c68 5378 && b->auto_save_modified < BUF_MODIFF (b)
82c2d839
RS
5379 /* -1 means we've turned off autosaving for a while--see below. */
5380 && XINT (b->save_length) >= 0
f14b1c68 5381 && (do_handled_files
49307295
KH
5382 || NILP (Ffind_file_name_handler (b->auto_save_file_name,
5383 Qwrite_region))))
f14b1c68 5384 {
b60247d9
RS
5385 EMACS_TIME before_time, after_time;
5386
5387 EMACS_GET_TIME (before_time);
5388
5389 /* If we had a failure, don't try again for 20 minutes. */
5390 if (b->auto_save_failure_time >= 0
5391 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
5392 continue;
5393
f14b1c68
JB
5394 if ((XFASTINT (b->save_length) * 10
5395 > (BUF_Z (b) - BUF_BEG (b)) * 13)
5396 /* A short file is likely to change a large fraction;
5397 spare the user annoying messages. */
5398 && XFASTINT (b->save_length) > 5000
5399 /* These messages are frequent and annoying for `*mail*'. */
5400 && !EQ (b->filename, Qnil)
5401 && NILP (no_message))
5402 {
5403 /* It has shrunk too much; turn off auto-saving here. */
a8c828be 5404 minibuffer_auto_raise = orig_minibuffer_auto_raise;
60d67b83
RS
5405 message_with_string ("Buffer %s has shrunk a lot; auto save turned off there",
5406 b->name, 1);
a8c828be 5407 minibuffer_auto_raise = 0;
82c2d839
RS
5408 /* Turn off auto-saving until there's a real save,
5409 and prevent any more warnings. */
46283abe 5410 XSETINT (b->save_length, -1);
f14b1c68
JB
5411 Fsleep_for (make_number (1), Qnil);
5412 continue;
5413 }
5414 set_buffer_internal (b);
5415 if (!auto_saved && NILP (no_message))
5416 message1 ("Auto-saving...");
5417 internal_condition_case (auto_save_1, Qt, auto_save_error);
5418 auto_saved++;
5419 b->auto_save_modified = BUF_MODIFF (b);
2acfd7ae 5420 XSETFASTINT (current_buffer->save_length, Z - BEG);
f14b1c68 5421 set_buffer_internal (old);
b60247d9
RS
5422
5423 EMACS_GET_TIME (after_time);
5424
5425 /* If auto-save took more than 60 seconds,
5426 assume it was an NFS failure that got a timeout. */
5427 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60)
5428 b->auto_save_failure_time = EMACS_SECS (after_time);
f14b1c68
JB
5429 }
5430 }
570d7624 5431
b67f2ca5
RS
5432 /* Prevent another auto save till enough input events come in. */
5433 record_auto_save ();
570d7624 5434
17857782 5435 if (auto_saved && NILP (no_message))
f05b275b 5436 {
c71106e5 5437 if (message_p)
31f3d831 5438 {
22e59fa7 5439 sit_for (1, 0, 0, 0, 0);
c71106e5 5440 restore_message ();
31f3d831 5441 }
f05b275b
KH
5442 else
5443 message1 ("Auto-saving...done");
5444 }
570d7624 5445
ff4c9993
RS
5446 Vquit_flag = oquit;
5447
c71106e5 5448 pop_message ();
e54d3b5d 5449 unbind_to (count, Qnil);
570d7624
JB
5450 return Qnil;
5451}
5452
5453DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved,
5454 Sset_buffer_auto_saved, 0, 0, 0,
5455 "Mark current buffer as auto-saved with its current text.\n\
5456No auto-save file will be written until the buffer changes again.")
5457 ()
5458{
5459 current_buffer->auto_save_modified = MODIFF;
2acfd7ae 5460 XSETFASTINT (current_buffer->save_length, Z - BEG);
b60247d9
RS
5461 current_buffer->auto_save_failure_time = -1;
5462 return Qnil;
5463}
5464
5465DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
5466 Sclear_buffer_auto_save_failure, 0, 0, 0,
5467 "Clear any record of a recent auto-save failure in the current buffer.")
5468 ()
5469{
5470 current_buffer->auto_save_failure_time = -1;
570d7624
JB
5471 return Qnil;
5472}
5473
5474DEFUN ("recent-auto-save-p", Frecent_auto_save_p, Srecent_auto_save_p,
5475 0, 0, 0,
5476 "Return t if buffer has been auto-saved since last read in or saved.")
5477 ()
5478{
95385625 5479 return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
570d7624
JB
5480}
5481\f
5482/* Reading and completing file names */
5483extern Lisp_Object Ffile_name_completion (), Ffile_name_all_completions ();
5484
6e710ae5
RS
5485/* In the string VAL, change each $ to $$ and return the result. */
5486
5487static Lisp_Object
5488double_dollars (val)
5489 Lisp_Object val;
5490{
5491 register unsigned char *old, *new;
5492 register int n;
5493 int osize, count;
5494
fc932ac6 5495 osize = STRING_BYTES (XSTRING (val));
60d67b83
RS
5496
5497 /* Count the number of $ characters. */
6e710ae5
RS
5498 for (n = osize, count = 0, old = XSTRING (val)->data; n > 0; n--)
5499 if (*old++ == '$') count++;
5500 if (count > 0)
5501 {
5502 old = XSTRING (val)->data;
60d67b83
RS
5503 val = make_uninit_multibyte_string (XSTRING (val)->size + count,
5504 osize + count);
6e710ae5
RS
5505 new = XSTRING (val)->data;
5506 for (n = osize; n > 0; n--)
5507 if (*old != '$')
5508 *new++ = *old++;
5509 else
5510 {
5511 *new++ = '$';
5512 *new++ = '$';
5513 old++;
5514 }
5515 }
5516 return val;
5517}
5518
570d7624
JB
5519DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
5520 3, 3, 0,
5521 "Internal subroutine for read-file-name. Do not call this.")
5522 (string, dir, action)
5523 Lisp_Object string, dir, action;
5524 /* action is nil for complete, t for return list of completions,
5525 lambda for verify final value */
5526{
5527 Lisp_Object name, specdir, realdir, val, orig_string;
09121adc 5528 int changed;
8ce069f5 5529 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
09121adc 5530
58cc3710
RS
5531 CHECK_STRING (string, 0);
5532
09121adc
RS
5533 realdir = dir;
5534 name = string;
5535 orig_string = Qnil;
5536 specdir = Qnil;
5537 changed = 0;
5538 /* No need to protect ACTION--we only compare it with t and nil. */
8ce069f5 5539 GCPRO5 (string, realdir, name, specdir, orig_string);
570d7624
JB
5540
5541 if (XSTRING (string)->size == 0)
5542 {
570d7624 5543 if (EQ (action, Qlambda))
09121adc
RS
5544 {
5545 UNGCPRO;
5546 return Qnil;
5547 }
570d7624
JB
5548 }
5549 else
5550 {
5551 orig_string = string;
5552 string = Fsubstitute_in_file_name (string);
09121adc 5553 changed = NILP (Fstring_equal (string, orig_string));
570d7624 5554 name = Ffile_name_nondirectory (string);
09121adc
RS
5555 val = Ffile_name_directory (string);
5556 if (! NILP (val))
5557 realdir = Fexpand_file_name (val, realdir);
570d7624
JB
5558 }
5559
265a9e55 5560 if (NILP (action))
570d7624
JB
5561 {
5562 specdir = Ffile_name_directory (string);
5563 val = Ffile_name_completion (name, realdir);
09121adc 5564 UNGCPRO;
93c30b5f 5565 if (!STRINGP (val))
570d7624 5566 {
09121adc 5567 if (changed)
dbd04e01 5568 return double_dollars (string);
09121adc 5569 return val;
570d7624
JB
5570 }
5571
265a9e55 5572 if (!NILP (specdir))
570d7624
JB
5573 val = concat2 (specdir, val);
5574#ifndef VMS
6e710ae5
RS
5575 return double_dollars (val);
5576#else /* not VMS */
09121adc 5577 return val;
6e710ae5 5578#endif /* not VMS */
570d7624 5579 }
09121adc 5580 UNGCPRO;
570d7624
JB
5581
5582 if (EQ (action, Qt))
5583 return Ffile_name_all_completions (name, realdir);
5584 /* Only other case actually used is ACTION = lambda */
5585#ifdef VMS
5586 /* Supposedly this helps commands such as `cd' that read directory names,
5587 but can someone explain how it helps them? -- RMS */
5588 if (XSTRING (name)->size == 0)
5589 return Qt;
5590#endif /* VMS */
5591 return Ffile_exists_p (string);
5592}
5593
5594DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 5, 0,
5595 "Read file name, prompting with PROMPT and completing in directory DIR.\n\
5596Value is not expanded---you must call `expand-file-name' yourself.\n\
3b7f6e60
EN
5597Default name to DEFAULT-FILENAME if user enters a null string.\n\
5598 (If DEFAULT-FILENAME is omitted, the visited file name is used,\n\
3beeedfe 5599 except that if INITIAL is specified, that combined with DIR is used.)\n\
570d7624
JB
5600Fourth arg MUSTMATCH non-nil means require existing file's name.\n\
5601 Non-nil and non-t means also require confirmation after completion.\n\
5602Fifth arg INITIAL specifies text to start with.\n\
5603DIR defaults to current buffer's directory default.")
3b7f6e60
EN
5604 (prompt, dir, default_filename, mustmatch, initial)
5605 Lisp_Object prompt, dir, default_filename, mustmatch, initial;
570d7624 5606{
8d6d9fef 5607 Lisp_Object val, insdef, tem;
570d7624
JB
5608 struct gcpro gcpro1, gcpro2;
5609 register char *homedir;
62f555a5
RS
5610 int replace_in_history = 0;
5611 int add_to_history = 0;
570d7624
JB
5612 int count;
5613
265a9e55 5614 if (NILP (dir))
570d7624 5615 dir = current_buffer->directory;
3b7f6e60 5616 if (NILP (default_filename))
3beeedfe
RS
5617 {
5618 if (! NILP (initial))
3b7f6e60 5619 default_filename = Fexpand_file_name (initial, dir);
3beeedfe 5620 else
3b7f6e60 5621 default_filename = current_buffer->filename;
3beeedfe 5622 }
570d7624
JB
5623
5624 /* If dir starts with user's homedir, change that to ~. */
5625 homedir = (char *) egetenv ("HOME");
199607e4
RS
5626#ifdef DOS_NT
5627 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
5628 CORRECT_DIR_SEPS (homedir);
5629#endif
570d7624 5630 if (homedir != 0
93c30b5f 5631 && STRINGP (dir)
570d7624 5632 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
5e570b75 5633 && IS_DIRECTORY_SEP (XSTRING (dir)->data[strlen (homedir)]))
570d7624
JB
5634 {
5635 dir = make_string (XSTRING (dir)->data + strlen (homedir) - 1,
fc932ac6 5636 STRING_BYTES (XSTRING (dir)) - strlen (homedir) + 1);
570d7624
JB
5637 XSTRING (dir)->data[0] = '~';
5638 }
8d6d9fef
AS
5639 /* Likewise for default_filename. */
5640 if (homedir != 0
5641 && STRINGP (default_filename)
5642 && !strncmp (homedir, XSTRING (default_filename)->data, strlen (homedir))
5643 && IS_DIRECTORY_SEP (XSTRING (default_filename)->data[strlen (homedir)]))
5644 {
5645 default_filename
5646 = make_string (XSTRING (default_filename)->data + strlen (homedir) - 1,
5647 STRING_BYTES (XSTRING (default_filename)) - strlen (homedir) + 1);
5648 XSTRING (default_filename)->data[0] = '~';
5649 }
5650 if (!NILP (default_filename))
b537a6c7
RS
5651 {
5652 CHECK_STRING (default_filename, 3);
5653 default_filename = double_dollars (default_filename);
5654 }
570d7624 5655
58cc3710 5656 if (insert_default_directory && STRINGP (dir))
570d7624
JB
5657 {
5658 insdef = dir;
265a9e55 5659 if (!NILP (initial))
570d7624 5660 {
15c65264 5661 Lisp_Object args[2], pos;
570d7624
JB
5662
5663 args[0] = insdef;
5664 args[1] = initial;
5665 insdef = Fconcat (2, args);
351bd676 5666 pos = make_number (XSTRING (double_dollars (dir))->size);
8d6d9fef 5667 insdef = Fcons (double_dollars (insdef), pos);
570d7624 5668 }
6e710ae5 5669 else
8d6d9fef 5670 insdef = double_dollars (insdef);
570d7624 5671 }
58cc3710 5672 else if (STRINGP (initial))
8d6d9fef 5673 insdef = Fcons (double_dollars (initial), make_number (0));
570d7624 5674 else
8d6d9fef 5675 insdef = Qnil;
570d7624 5676
570d7624 5677 count = specpdl_ptr - specpdl;
a79485af 5678#ifdef VMS
570d7624
JB
5679 specbind (intern ("completion-ignore-case"), Qt);
5680#endif
5681
a79485af
RS
5682 specbind (intern ("minibuffer-completing-file-name"), Qt);
5683
3b7f6e60 5684 GCPRO2 (insdef, default_filename);
9c856db9 5685
f73f57bd 5686#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
9c856db9
GM
5687 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
5688 && use_dialog_box
5689 && have_menus_p ())
5690 {
9172b88d
GM
5691 /* If DIR contains a file name, split it. */
5692 Lisp_Object file;
5693 file = Ffile_name_nondirectory (dir);
5694 if (XSTRING (file)->size && NILP (default_filename))
5695 {
5696 default_filename = file;
5697 dir = Ffile_name_directory (dir);
5698 }
f73f57bd
JR
5699 if (!NILP(default_filename))
5700 default_filename = Fexpand_file_name (default_filename, dir);
9c856db9
GM
5701 val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
5702 add_to_history = 1;
5703 }
5704 else
5705#endif
5706 val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
5707 dir, mustmatch, insdef,
5708 Qfile_name_history, default_filename, Qnil);
62f555a5
RS
5709
5710 tem = Fsymbol_value (Qfile_name_history);
03699b14 5711 if (CONSP (tem) && EQ (XCAR (tem), val))
62f555a5
RS
5712 replace_in_history = 1;
5713
5714 /* If Fcompleting_read returned the inserted default string itself
a8c828be
RS
5715 (rather than a new string with the same contents),
5716 it has to mean that the user typed RET with the minibuffer empty.
5717 In that case, we really want to return ""
5718 so that commands such as set-visited-file-name can distinguish. */
5719 if (EQ (val, default_filename))
62f555a5
RS
5720 {
5721 /* In this case, Fcompleting_read has not added an element
5722 to the history. Maybe we should. */
5723 if (! replace_in_history)
5724 add_to_history = 1;
5725
5726 val = build_string ("");
5727 }
570d7624 5728
570d7624 5729 unbind_to (count, Qnil);
570d7624 5730 UNGCPRO;
265a9e55 5731 if (NILP (val))
570d7624 5732 error ("No file name specified");
62f555a5 5733
8d6d9fef 5734 tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
62f555a5 5735
3b7f6e60 5736 if (!NILP (tem) && !NILP (default_filename))
62f555a5
RS
5737 val = default_filename;
5738 else if (XSTRING (val)->size == 0 && NILP (insdef))
d9bc1c99 5739 {
3b7f6e60 5740 if (!NILP (default_filename))
62f555a5 5741 val = default_filename;
d9bc1c99
RS
5742 else
5743 error ("No default file name");
5744 }
62f555a5 5745 val = Fsubstitute_in_file_name (val);
570d7624 5746
62f555a5
RS
5747 if (replace_in_history)
5748 /* Replace what Fcompleting_read added to the history
5749 with what we will actually return. */
03699b14 5750 XCAR (Fsymbol_value (Qfile_name_history)) = double_dollars (val);
62f555a5 5751 else if (add_to_history)
570d7624 5752 {
62f555a5
RS
5753 /* Add the value to the history--but not if it matches
5754 the last value already there. */
8d6d9fef 5755 Lisp_Object val1 = double_dollars (val);
62f555a5 5756 tem = Fsymbol_value (Qfile_name_history);
03699b14 5757 if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
62f555a5 5758 Fset (Qfile_name_history,
8d6d9fef 5759 Fcons (val1, tem));
570d7624 5760 }
9c856db9 5761
62f555a5 5762 return val;
570d7624 5763}
9c856db9 5764
570d7624 5765\f
dbda5089
GV
5766void
5767init_fileio_once ()
5768{
5769 /* Must be set before any path manipulation is performed. */
5770 XSETFASTINT (Vdirectory_sep_char, '/');
5771}
5772
9c856db9 5773\f
dfcf069d 5774void
570d7624
JB
5775syms_of_fileio ()
5776{
0bf2eed2 5777 Qexpand_file_name = intern ("expand-file-name");
273e0829 5778 Qsubstitute_in_file_name = intern ("substitute-in-file-name");
0bf2eed2
RS
5779 Qdirectory_file_name = intern ("directory-file-name");
5780 Qfile_name_directory = intern ("file-name-directory");
5781 Qfile_name_nondirectory = intern ("file-name-nondirectory");
642ef245 5782 Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
0bf2eed2 5783 Qfile_name_as_directory = intern ("file-name-as-directory");
32f4334d 5784 Qcopy_file = intern ("copy-file");
a6e6e718 5785 Qmake_directory_internal = intern ("make-directory-internal");
b272d624 5786 Qmake_directory = intern ("make-directory");
32f4334d
RS
5787 Qdelete_directory = intern ("delete-directory");
5788 Qdelete_file = intern ("delete-file");
5789 Qrename_file = intern ("rename-file");
5790 Qadd_name_to_file = intern ("add-name-to-file");
5791 Qmake_symbolic_link = intern ("make-symbolic-link");
5792 Qfile_exists_p = intern ("file-exists-p");
5793 Qfile_executable_p = intern ("file-executable-p");
5794 Qfile_readable_p = intern ("file-readable-p");
32f4334d 5795 Qfile_writable_p = intern ("file-writable-p");
1f8653eb
RS
5796 Qfile_symlink_p = intern ("file-symlink-p");
5797 Qaccess_file = intern ("access-file");
32f4334d 5798 Qfile_directory_p = intern ("file-directory-p");
adedc71d 5799 Qfile_regular_p = intern ("file-regular-p");
32f4334d
RS
5800 Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
5801 Qfile_modes = intern ("file-modes");
5802 Qset_file_modes = intern ("set-file-modes");
5803 Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
5804 Qinsert_file_contents = intern ("insert-file-contents");
5805 Qwrite_region = intern ("write-region");
5806 Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
3ec46acd 5807 Qset_visited_file_modtime = intern ("set-visited-file-modtime");
32f4334d 5808
642ef245 5809 staticpro (&Qexpand_file_name);
273e0829 5810 staticpro (&Qsubstitute_in_file_name);
642ef245
JB
5811 staticpro (&Qdirectory_file_name);
5812 staticpro (&Qfile_name_directory);
5813 staticpro (&Qfile_name_nondirectory);
5814 staticpro (&Qunhandled_file_name_directory);
5815 staticpro (&Qfile_name_as_directory);
15c65264 5816 staticpro (&Qcopy_file);
c34b559d 5817 staticpro (&Qmake_directory_internal);
b272d624 5818 staticpro (&Qmake_directory);
15c65264
RS
5819 staticpro (&Qdelete_directory);
5820 staticpro (&Qdelete_file);
5821 staticpro (&Qrename_file);
5822 staticpro (&Qadd_name_to_file);
5823 staticpro (&Qmake_symbolic_link);
5824 staticpro (&Qfile_exists_p);
5825 staticpro (&Qfile_executable_p);
5826 staticpro (&Qfile_readable_p);
15c65264 5827 staticpro (&Qfile_writable_p);
1f8653eb
RS
5828 staticpro (&Qaccess_file);
5829 staticpro (&Qfile_symlink_p);
15c65264 5830 staticpro (&Qfile_directory_p);
adedc71d 5831 staticpro (&Qfile_regular_p);
15c65264
RS
5832 staticpro (&Qfile_accessible_directory_p);
5833 staticpro (&Qfile_modes);
5834 staticpro (&Qset_file_modes);
5835 staticpro (&Qfile_newer_than_file_p);
5836 staticpro (&Qinsert_file_contents);
5837 staticpro (&Qwrite_region);
5838 staticpro (&Qverify_visited_file_modtime);
0a61794b 5839 staticpro (&Qset_visited_file_modtime);
642ef245
JB
5840
5841 Qfile_name_history = intern ("file-name-history");
5842 Fset (Qfile_name_history, Qnil);
15c65264
RS
5843 staticpro (&Qfile_name_history);
5844
570d7624
JB
5845 Qfile_error = intern ("file-error");
5846 staticpro (&Qfile_error);
199607e4 5847 Qfile_already_exists = intern ("file-already-exists");
570d7624 5848 staticpro (&Qfile_already_exists);
c0b7b21c
RS
5849 Qfile_date_error = intern ("file-date-error");
5850 staticpro (&Qfile_date_error);
505ab9bc
RS
5851 Qexcl = intern ("excl");
5852 staticpro (&Qexcl);
570d7624 5853
5e570b75 5854#ifdef DOS_NT
4c3c22f3
RS
5855 Qfind_buffer_file_type = intern ("find-buffer-file-type");
5856 staticpro (&Qfind_buffer_file_type);
5e570b75 5857#endif /* DOS_NT */
4c3c22f3 5858
b1d1b865 5859 DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system,
cd913586
KH
5860 "*Coding system for encoding file names.\n\
5861If it is nil, default-file-name-coding-system (which see) is used.");
b1d1b865
RS
5862 Vfile_name_coding_system = Qnil;
5863
cd913586
KH
5864 DEFVAR_LISP ("default-file-name-coding-system",
5865 &Vdefault_file_name_coding_system,
5866 "Default coding system for encoding file names.\n\
5867This variable is used only when file-name-coding-system is nil.\n\
5868\n\
5869This variable is set/changed by the command set-language-environment.\n\
5870User should not set this variable manually,\n\
5871instead use file-name-coding-system to get a constant encoding\n\
5872of file names regardless of the current language environment.");
5873 Vdefault_file_name_coding_system = Qnil;
5874
0d420e88 5875 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format,
824a483f 5876 "*Format in which to write auto-save files.\n\
0d420e88
BG
5877Should be a list of symbols naming formats that are defined in `format-alist'.\n\
5878If it is t, which is the default, auto-save files are written in the\n\
5879same format as a regular save would use.");
5880 Vauto_save_file_format = Qt;
5881
5882 Qformat_decode = intern ("format-decode");
5883 staticpro (&Qformat_decode);
5884 Qformat_annotate_function = intern ("format-annotate-function");
5885 staticpro (&Qformat_annotate_function);
5886
d6a3cc15
RS
5887 Qcar_less_than_car = intern ("car-less-than-car");
5888 staticpro (&Qcar_less_than_car);
5889
570d7624
JB
5890 Fput (Qfile_error, Qerror_conditions,
5891 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
5892 Fput (Qfile_error, Qerror_message,
5893 build_string ("File error"));
5894
5895 Fput (Qfile_already_exists, Qerror_conditions,
5896 Fcons (Qfile_already_exists,
5897 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5898 Fput (Qfile_already_exists, Qerror_message,
5899 build_string ("File already exists"));
5900
c0b7b21c
RS
5901 Fput (Qfile_date_error, Qerror_conditions,
5902 Fcons (Qfile_date_error,
5903 Fcons (Qfile_error, Fcons (Qerror, Qnil))));
5904 Fput (Qfile_date_error, Qerror_message,
5905 build_string ("Cannot set file date"));
5906
570d7624
JB
5907 DEFVAR_BOOL ("insert-default-directory", &insert_default_directory,
5908 "*Non-nil means when reading a filename start with default dir in minibuffer.");
5909 insert_default_directory = 1;
5910
5911 DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm,
5912 "*Non-nil means write new files with record format `stmlf'.\n\
5913nil means use format `var'. This variable is meaningful only on VMS.");
5914 vms_stmlf_recfm = 0;
5915
199607e4
RS
5916 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
5917 "Directory separator character for built-in functions that return file names.\n\
5918The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
5919This variable affects the built-in functions only on Windows,\n\
5920on other platforms, it is initialized so that Lisp code can find out\n\
5921what the normal separator is.");
199607e4 5922
1d1826db
RS
5923 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
5924 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
5925If a file name matches REGEXP, then all I/O on that file is done by calling\n\
5926HANDLER.\n\
5927\n\
5928The first argument given to HANDLER is the name of the I/O primitive\n\
5929to be handled; the remaining arguments are the arguments that were\n\
5930passed to that primitive. For example, if you do\n\
5931 (file-exists-p FILENAME)\n\
5932and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
642ef245
JB
5933 (funcall HANDLER 'file-exists-p FILENAME)\n\
5934The function `find-file-name-handler' checks this list for a handler\n\
5935for its argument.");
09121adc
RS
5936 Vfile_name_handler_alist = Qnil;
5937
0414b394
KH
5938 DEFVAR_LISP ("set-auto-coding-function",
5939 &Vset_auto_coding_function,
7fc4808e 5940 "If non-nil, a function to call to decide a coding system of file.\n\
1255deb9
KH
5941Two arguments are passed to this function: the file name\n\
5942and the length of a file contents following the point.\n\
5943This function should return a coding system to decode the file contents.\n\
5944It should check the file name against `auto-coding-alist'.\n\
5945If no coding system is decided, it should check a coding system\n\
7fc4808e 5946specified in the heading lines with the format:\n\
0414b394
KH
5947 -*- ... coding: CODING-SYSTEM; ... -*-\n\
5948or local variable spec of the tailing lines with `coding:' tag.");
5949 Vset_auto_coding_function = Qnil;
c9e82392 5950
d6a3cc15 5951 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
246cfea5
RS
5952 "A list of functions to be called at the end of `insert-file-contents'.\n\
5953Each is passed one argument, the number of bytes inserted. It should return\n\
5954the new byte count, and leave point the same. If `insert-file-contents' is\n\
5955intercepted by a handler from `file-name-handler-alist', that handler is\n\
d6a3cc15
RS
5956responsible for calling the after-insert-file-functions if appropriate.");
5957 Vafter_insert_file_functions = Qnil;
5958
5959 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
246cfea5 5960 "A list of functions to be called at the start of `write-region'.\n\
568aa585
RS
5961Each is passed two arguments, START and END as for `write-region'.\n\
5962These are usually two numbers but not always; see the documentation\n\
5963for `write-region'. The function should return a list of pairs\n\
5964of the form (POSITION . STRING), consisting of strings to be effectively\n\
246cfea5
RS
5965inserted at the specified positions of the file being written (1 means to\n\
5966insert before the first byte written). The POSITIONs must be sorted into\n\
5967increasing order. If there are several functions in the list, the several\n\
d6a3cc15
RS
5968lists are merged destructively.");
5969 Vwrite_region_annotate_functions = Qnil;
5970
6fc6f94b
RS
5971 DEFVAR_LISP ("write-region-annotations-so-far",
5972 &Vwrite_region_annotations_so_far,
5973 "When an annotation function is called, this holds the previous annotations.\n\
5974These are the annotations made by other annotation functions\n\
5975that were already called. See also `write-region-annotate-functions'.");
5976 Vwrite_region_annotations_so_far = Qnil;
5977
82c2d839 5978 DEFVAR_LISP ("inhibit-file-name-handlers", &Vinhibit_file_name_handlers,
268466ed 5979 "A list of file name handlers that temporarily should not be used.\n\
e3e86241 5980This applies only to the operation `inhibit-file-name-operation'.");
82c2d839
RS
5981 Vinhibit_file_name_handlers = Qnil;
5982
a65970a0
RS
5983 DEFVAR_LISP ("inhibit-file-name-operation", &Vinhibit_file_name_operation,
5984 "The operation for which `inhibit-file-name-handlers' is applicable.");
5985 Vinhibit_file_name_operation = Qnil;
5986
e54d3b5d 5987 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name,
51931aca
KH
5988 "File name in which we write a list of all auto save file names.\n\
5989This variable is initialized automatically from `auto-save-list-file-prefix'\n\
5990shortly after Emacs reads your `.emacs' file, if you have not yet given it\n\
5991a non-nil value.");
e54d3b5d
RS
5992 Vauto_save_list_file_name = Qnil;
5993
642ef245 5994 defsubr (&Sfind_file_name_handler);
570d7624
JB
5995 defsubr (&Sfile_name_directory);
5996 defsubr (&Sfile_name_nondirectory);
642ef245 5997 defsubr (&Sunhandled_file_name_directory);
570d7624
JB
5998 defsubr (&Sfile_name_as_directory);
5999 defsubr (&Sdirectory_file_name);
6000 defsubr (&Smake_temp_name);
6001 defsubr (&Sexpand_file_name);
6002 defsubr (&Ssubstitute_in_file_name);
6003 defsubr (&Scopy_file);
9bbe01fb 6004 defsubr (&Smake_directory_internal);
aa734e17 6005 defsubr (&Sdelete_directory);
570d7624
JB
6006 defsubr (&Sdelete_file);
6007 defsubr (&Srename_file);
6008 defsubr (&Sadd_name_to_file);
6009#ifdef S_IFLNK
6010 defsubr (&Smake_symbolic_link);
6011#endif /* S_IFLNK */
6012#ifdef VMS
6013 defsubr (&Sdefine_logical_name);
6014#endif /* VMS */
6015#ifdef HPUX_NET
6016 defsubr (&Ssysnetunam);
6017#endif /* HPUX_NET */
6018 defsubr (&Sfile_name_absolute_p);
6019 defsubr (&Sfile_exists_p);
6020 defsubr (&Sfile_executable_p);
6021 defsubr (&Sfile_readable_p);
6022 defsubr (&Sfile_writable_p);
1f8653eb 6023 defsubr (&Saccess_file);
570d7624
JB
6024 defsubr (&Sfile_symlink_p);
6025 defsubr (&Sfile_directory_p);
b72dea2a 6026 defsubr (&Sfile_accessible_directory_p);
f793dc6c 6027 defsubr (&Sfile_regular_p);
570d7624
JB
6028 defsubr (&Sfile_modes);
6029 defsubr (&Sset_file_modes);
c24e9a53
RS
6030 defsubr (&Sset_default_file_modes);
6031 defsubr (&Sdefault_file_modes);
570d7624
JB
6032 defsubr (&Sfile_newer_than_file_p);
6033 defsubr (&Sinsert_file_contents);
6034 defsubr (&Swrite_region);
d6a3cc15 6035 defsubr (&Scar_less_than_car);
570d7624
JB
6036 defsubr (&Sverify_visited_file_modtime);
6037 defsubr (&Sclear_visited_file_modtime);
f5d5eccf 6038 defsubr (&Svisited_file_modtime);
570d7624
JB
6039 defsubr (&Sset_visited_file_modtime);
6040 defsubr (&Sdo_auto_save);
6041 defsubr (&Sset_buffer_auto_saved);
b60247d9 6042 defsubr (&Sclear_buffer_auto_save_failure);
570d7624
JB
6043 defsubr (&Srecent_auto_save_p);
6044
6045 defsubr (&Sread_file_name_internal);
6046 defsubr (&Sread_file_name);
85ffea93 6047
483a2e10 6048#ifdef unix
85ffea93 6049 defsubr (&Sunix_sync);
483a2e10 6050#endif
570d7624 6051}
71e1147d 6052