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