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