comparison src/fileio.c @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents 3c5d0bca9200
children e38acbeb1cae
comparison
equal deleted inserted replaced
770:336a418893b5 771:943eaba38521
1 /* File IO for XEmacs. 1 /* File IO for XEmacs.
2 Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc. 2 Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1996, 2001 Ben Wing. 3 Copyright (C) 1996, 2001, 2002 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
18 along with XEmacs; see the file COPYING. If not, write to 18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
21 21
22 /* Synched up with: Mule 2.0, FSF 19.30. */ 22 /* Synched up with: Mule 2.0, FSF 19.30. */
23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ 23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org>
24 (Note: Sync messages from Marc Paquette may indicate
25 incomplete synching, so beware.) */
26 /* Mule-ized completely except for the #if 0-code including decrypt-string
27 and encrypt-string. --ben 7-2-00 */
28
24 29
25 #include <config.h> 30 #include <config.h>
26 #include "lisp.h" 31 #include "lisp.h"
27 32
28 #include "buffer.h" 33 #include "buffer.h"
31 #include "insdel.h" 36 #include "insdel.h"
32 #include "lstream.h" 37 #include "lstream.h"
33 #include "redisplay.h" 38 #include "redisplay.h"
34 #include "sysdep.h" 39 #include "sysdep.h"
35 #include "window.h" /* minibuf_level */ 40 #include "window.h" /* minibuf_level */
36 #ifdef FILE_CODING
37 #include "file-coding.h" 41 #include "file-coding.h"
38 #endif 42
39
40 #ifdef HAVE_LIBGEN_H /* Must come before sysfile.h */
41 #include <libgen.h>
42 #endif
43 #include "sysfile.h" 43 #include "sysfile.h"
44 #include "sysproc.h" 44 #include "sysproc.h"
45 #include "syspwd.h" 45 #include "syspwd.h"
46 #include "systime.h" 46 #include "systime.h"
47 #include "sysdir.h" 47 #include "sysdir.h"
51 #ifdef HPUX_PRE_8_0 51 #ifdef HPUX_PRE_8_0
52 #include <errnet.h> 52 #include <errnet.h>
53 #endif /* HPUX_PRE_8_0 */ 53 #endif /* HPUX_PRE_8_0 */
54 #endif /* HPUX */ 54 #endif /* HPUX */
55 55
56 #if defined(WIN32_NATIVE) || defined(CYGWIN) 56 #if defined (WIN32_NATIVE) || defined (CYGWIN)
57 #define WIN32_FILENAMES 57 #define WIN32_FILENAMES
58 #ifdef WIN32_NATIVE 58 #include "syswindows.h"
59 #include "nt.h"
60 #endif /* WIN32_NATIVE */
61 #define IS_DRIVE(x) isalpha (x) 59 #define IS_DRIVE(x) isalpha (x)
62 /* Need to lower-case the drive letter, or else expanded 60 /* Need to lower-case the drive letter, or else expanded
63 filenames will sometimes compare inequal, because 61 filenames will sometimes compare inequal, because
64 `expand-file-name' doesn't always down-case the drive letter. */ 62 `expand-file-name' doesn't always down-case the drive letter. */
65 #define DRIVE_LETTER(x) tolower (x) 63 #define DRIVE_LETTER(x) tolower (x)
66 #ifndef CORRECT_DIR_SEPS
67 #define CORRECT_DIR_SEPS(s) \
68 normalize_filename(s, DIRECTORY_SEP)
69 /* Default implementation that coerces a file to use path_sep. */
70 static void
71 normalize_filename (Intbyte *fp, Intbyte path_sep)
72 {
73 /* Always lower-case drive letters a-z, even if the filesystem
74 preserves case in filenames.
75 This is so filenames can be compared by string comparison
76 functions that are case-sensitive. Even case-preserving filesystems
77 do not distinguish case in drive letters. */
78 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
79 {
80 *fp += 'a' - 'A';
81 fp += 2;
82 }
83
84 while (*fp)
85 {
86 if (*fp == '/' || *fp == '\\')
87 *fp = path_sep;
88 fp++;
89 }
90 }
91 #endif /* CORRECT_DIR_SEPS */
92 #endif /* WIN32_NATIVE || CYGWIN */ 64 #endif /* WIN32_NATIVE || CYGWIN */
93 65
94 int lisp_to_time (Lisp_Object, time_t *); 66 int lisp_to_time (Lisp_Object, time_t *);
95 Lisp_Object time_to_lisp (time_t); 67 Lisp_Object time_to_lisp (time_t);
96 68
165 { 137 {
166 struct gcpro gcpro1; 138 struct gcpro gcpro1;
167 Lisp_Object errdata = build_error_data (NULL, data); 139 Lisp_Object errdata = build_error_data (NULL, data);
168 140
169 GCPRO1 (errdata); 141 GCPRO1 (errdata);
170 errdata = Fcons (build_translated_string (string), 142 errdata = Fcons (build_msg_string (string),
171 Fcons (oserrmess, errdata)); 143 Fcons (oserrmess, errdata));
172 signal_error_1 (errtype, errdata); 144 signal_error_1 (errtype, errdata);
173 UNGCPRO; /* not reached */ 145 UNGCPRO; /* not reached */
174 } 146 }
175 147
189 } 161 }
190 162
191 163
192 /* Just like strerror(3), except return a lisp string instead of char *. 164 /* Just like strerror(3), except return a lisp string instead of char *.
193 The string needs to be converted since it may be localized. 165 The string needs to be converted since it may be localized.
194 Perhaps this should use strerror-coding-system instead? */ 166 */
195 Lisp_Object 167 Lisp_Object
196 lisp_strerror (int errnum) 168 lisp_strerror (int errnum)
197 { 169 {
198 return build_ext_string (strerror (errnum), Qnative); 170 Extbyte *ret = strerror (errnum);
171 if (!ret)
172 {
173 Intbyte ffff[99];
174 qxesprintf (ffff, "Unknown error %d", errnum);
175 return build_intstring (ffff);
176 }
177 return build_ext_string (ret, Qstrerror_encoding);
199 } 178 }
200 179
201 static Lisp_Object 180 static Lisp_Object
202 close_file_unwind (Lisp_Object fd) 181 close_file_unwind (Lisp_Object fd)
203 { 182 {
204 if (CONSP (fd)) 183 if (CONSP (fd))
205 { 184 {
206 if (INTP (XCAR (fd))) 185 if (INTP (XCAR (fd)))
207 close (XINT (XCAR (fd))); 186 retry_close (XINT (XCAR (fd)));
208 187
209 free_cons (XCONS (fd)); 188 free_cons (XCONS (fd));
210 } 189 }
211 else 190 else
212 close (XINT (fd)); 191 retry_close (XINT (fd));
213 192
214 return Qnil; 193 return Qnil;
215 } 194 }
216 195
217 static Lisp_Object 196 static Lisp_Object
226 static Lisp_Object 205 static Lisp_Object
227 restore_point_unwind (Lisp_Object point_marker) 206 restore_point_unwind (Lisp_Object point_marker)
228 { 207 {
229 BUF_SET_PT (current_buffer, marker_position (point_marker)); 208 BUF_SET_PT (current_buffer, marker_position (point_marker));
230 return Fset_marker (point_marker, Qnil, Qnil); 209 return Fset_marker (point_marker, Qnil, Qnil);
231 }
232
233 /* Versions of read() and write() that allow quitting out of the actual
234 I/O. We don't use immediate_quit (i.e. direct longjmp() out of the
235 signal handler) because that's way too losing.
236
237 (#### Actually, longjmp()ing out of the signal handler may not be
238 as losing as I thought. See qxe_reliable_signal() in sysdep.c.) */
239
240 Bytecount
241 read_allowing_quit (int fildes, void *buf, Bytecount size)
242 {
243 QUIT;
244 return sys_read_1 (fildes, buf, size, 1);
245 }
246
247 Bytecount
248 write_allowing_quit (int fildes, const void *buf, Bytecount size)
249 {
250 QUIT;
251 return sys_write_1 (fildes, buf, size, 1);
252 } 210 }
253 211
254 212
255 Lisp_Object Qexpand_file_name; 213 Lisp_Object Qexpand_file_name;
256 Lisp_Object Qfile_truename; 214 Lisp_Object Qfile_truename;
369 Given a Unix syntax file name, returns a string ending in slash. 327 Given a Unix syntax file name, returns a string ending in slash.
370 */ 328 */
371 (filename)) 329 (filename))
372 { 330 {
373 /* This function can GC. GC checked 2000-07-28 ben */ 331 /* This function can GC. GC checked 2000-07-28 ben */
332 /* This function synched with Emacs 21.0.103. */
374 Intbyte *beg; 333 Intbyte *beg;
375 Intbyte *p; 334 Intbyte *p;
376 Lisp_Object handler; 335 Lisp_Object handler;
377 336
378 CHECK_STRING (filename); 337 CHECK_STRING (filename);
385 344
386 #ifdef FILE_SYSTEM_CASE 345 #ifdef FILE_SYSTEM_CASE
387 filename = FILE_SYSTEM_CASE (filename); 346 filename = FILE_SYSTEM_CASE (filename);
388 #endif 347 #endif
389 beg = XSTRING_DATA (filename); 348 beg = XSTRING_DATA (filename);
349 /* XEmacs: no need to alloca-copy here */
390 p = beg + XSTRING_LENGTH (filename); 350 p = beg + XSTRING_LENGTH (filename);
391 351
392 while (p != beg && !IS_ANY_SEP (p[-1]) 352 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
393 #ifdef WIN32_FILENAMES 353 #ifdef WIN32_FILENAMES
394 /* only recognize drive specifier at beginning */ 354 /* only recognise drive specifier at the beginning */
395 && !(p[-1] == ':' && p == beg + 2) 355 && !(p[-1] == ':'
356 /* handle the "/:d:foo" and "/:foo" cases correctly */
357 && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
358 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
396 #endif 359 #endif
397 ) p--; 360 ) p--;
398 361
399 if (p == beg) 362 if (p == beg)
400 return Qnil; 363 return Qnil;
401 #ifdef WIN32_NATIVE 364 #ifdef WIN32_NATIVE
402 /* Expansion of "c:" to drive and default directory. */ 365 /* Expansion of "c:" to drive and default directory. */
403 /* (NT does the right thing.) */ 366 if (p[-1] == ':')
404 if (p == beg + 2 && beg[1] == ':') 367 {
405 { 368 Intbyte *res;
406 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ 369 Intbyte *wd = mswindows_getdcwd (toupper (*beg) - 'A' + 1);
407 Intbyte *res = (Intbyte*) alloca (MAXPATHLEN + 1); 370
408 if (_getdcwd (toupper (*beg) - 'A' + 1, (char *)res, MAXPATHLEN)) 371 res = alloca_array (Intbyte,
372 (wd ? qxestrlen (wd) : 0) + 10); /* go overboard */
373 if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
409 { 374 {
410 char *c=((char *) res) + strlen ((char *) res); 375 qxestrncpy (res, beg, 2);
411 if (!IS_DIRECTORY_SEP (*c)) 376 beg += 2;
412 { 377 }
413 *c++ = DIRECTORY_SEP; 378
414 *c = '\0'; 379 if (wd)
415 } 380 {
381 qxestrcat (res, wd);
382 if (!IS_DIRECTORY_SEP (res[qxestrlen (res) - 1]))
383 qxestrcat (res, (Intbyte *) "/");
416 beg = res; 384 beg = res;
417 p = beg + strlen ((char *) beg); 385 p = beg + qxestrlen (beg);
418 } 386 }
419 } 387 if (wd)
420 #endif /* WIN32_NATIVE */ 388 xfree (wd);
389 }
390
391 #if 0 /* No! This screws up efs, which calls file-name-directory on URL's
392 and expects the slashes to be left alone. This is here because of
393 an analogous call in FSF 21. */
394 {
395 Bytecount len = p - beg;
396 Intbyte *newbeg = alloca_intbytes (len + 1);
397 Lisp_Object return_me;
398
399 qxestrncpy (newbeg, beg, len);
400 newbeg[len] = '\0';
401 newbeg = mswindows_canonicalize_filename (newbeg);
402 return_me = build_intstring (newbeg);
403 xfree (newbeg);
404 return return_me;
405 }
406 #endif
407 #endif /* not WIN32_NATIVE */
421 return make_string (beg, p - beg); 408 return make_string (beg, p - beg);
422 } 409 }
423 410
424 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* 411 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /*
425 Return file name FILENAME sans its directory. 412 Return file name FILENAME sans its directory.
428 or the entire name if it contains no slash. 415 or the entire name if it contains no slash.
429 */ 416 */
430 (filename)) 417 (filename))
431 { 418 {
432 /* This function can GC. GC checked 2000-07-28 ben */ 419 /* This function can GC. GC checked 2000-07-28 ben */
420 /* This function synched with Emacs 21.0.103. */
433 Intbyte *beg, *p, *end; 421 Intbyte *beg, *p, *end;
434 Lisp_Object handler; 422 Lisp_Object handler;
435 423
436 CHECK_STRING (filename); 424 CHECK_STRING (filename);
437 425
442 return call2_check_string (handler, Qfile_name_nondirectory, filename); 430 return call2_check_string (handler, Qfile_name_nondirectory, filename);
443 431
444 beg = XSTRING_DATA (filename); 432 beg = XSTRING_DATA (filename);
445 end = p = beg + XSTRING_LENGTH (filename); 433 end = p = beg + XSTRING_LENGTH (filename);
446 434
447 while (p != beg && !IS_ANY_SEP (p[-1]) 435 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
448 #ifdef WIN32_FILENAMES 436 #ifdef WIN32_FILENAMES
449 /* only recognize drive specifier at beginning */ 437 /* only recognise drive specifier at beginning */
450 && !(p[-1] == ':' && p == beg + 2) 438 && !(p[-1] == ':'
439 /* handle the "/:d:foo" case correctly */
440 && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
451 #endif 441 #endif
452 ) p--; 442 )
443 p--;
453 444
454 return make_string (p, end - p); 445 return make_string (p, end - p);
455 } 446 }
456 447
457 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /* 448 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /*
477 468
478 return Ffile_name_directory (filename); 469 return Ffile_name_directory (filename);
479 } 470 }
480 471
481 472
482 static char * 473 static Intbyte *
483 file_name_as_directory (char *out, char *in) 474 file_name_as_directory (Intbyte *out, Intbyte *in)
484 { 475 {
485 /* This function cannot GC */ 476 /* This function cannot GC */
486 int size = strlen (in); 477 int size = qxestrlen (in);
487 478
488 if (size == 0) 479 if (size == 0)
489 { 480 {
490 out[0] = '.'; 481 out[0] = '.';
491 out[1] = DIRECTORY_SEP; 482 out[1] = DIRECTORY_SEP;
492 out[2] = '\0'; 483 out[2] = '\0';
493 } 484 }
494 else 485 else
495 { 486 {
496 strcpy (out, in); 487 qxestrcpy (out, in);
497 /* Append a slash if necessary */ 488 /* Append a slash if necessary */
498 if (!IS_ANY_SEP (out[size-1])) 489 if (!IS_ANY_SEP (out[size-1]))
499 { 490 {
500 out[size] = DIRECTORY_SEP; 491 out[size] = DIRECTORY_SEP;
501 out[size + 1] = '\0'; 492 out[size + 1] = '\0';
514 except for (file-name-as-directory \"\") => \"./\". 505 except for (file-name-as-directory \"\") => \"./\".
515 */ 506 */
516 (filename)) 507 (filename))
517 { 508 {
518 /* This function can GC. GC checked 2000-07-28 ben */ 509 /* This function can GC. GC checked 2000-07-28 ben */
519 char *buf; 510 Intbyte *buf;
520 Lisp_Object handler; 511 Lisp_Object handler;
521 512
522 CHECK_STRING (filename); 513 CHECK_STRING (filename);
523 514
524 /* If the file name has special constructs in it, 515 /* If the file name has special constructs in it,
525 call the corresponding file handler. */ 516 call the corresponding file handler. */
526 handler = Ffind_file_name_handler (filename, Qfile_name_as_directory); 517 handler = Ffind_file_name_handler (filename, Qfile_name_as_directory);
527 if (!NILP (handler)) 518 if (!NILP (handler))
528 return call2_check_string (handler, Qfile_name_as_directory, filename); 519 return call2_check_string (handler, Qfile_name_as_directory, filename);
529 520
530 buf = (char *) alloca (XSTRING_LENGTH (filename) + 10); 521 buf = alloca_intbytes (XSTRING_LENGTH (filename) + 10);
531 return build_string (file_name_as_directory 522 return build_intstring (file_name_as_directory (buf, XSTRING_DATA (filename)));
532 (buf, (char *) XSTRING_DATA (filename)));
533 } 523 }
534 524
535 /* 525 /*
536 * Convert from directory name to filename. 526 * Convert from directory name to filename.
537 * On UNIX, it's simple: just make sure there isn't a terminating / 527 * On UNIX, it's simple: just make sure there isn't a terminating /
538 * 528 *
539 * Value is nonzero if the string output is different from the input. 529 * Value is nonzero if the string output is different from the input.
540 */ 530 */
541 531
542 static int 532 static int
543 directory_file_name (const char *src, char *dst) 533 directory_file_name (const Intbyte *src, Intbyte *dst)
544 { 534 {
545 /* This function cannot GC */ 535 /* This function cannot GC */
546 long slen = strlen (src); 536 long slen = qxestrlen (src);
547 /* Process as Unix format: just remove any final slash. 537 /* Process as Unix format: just remove any final slash.
548 But leave "/" unchanged; do not change it to "". */ 538 But leave "/" unchanged; do not change it to "". */
549 strcpy (dst, src); 539 qxestrcpy (dst, src);
550 if (slen > 1 540 if (slen > 1
551 && IS_DIRECTORY_SEP (dst[slen - 1]) 541 && IS_DIRECTORY_SEP (dst[slen - 1])
552 #ifdef WIN32_FILENAMES 542 #ifdef WIN32_FILENAMES
553 && !IS_ANY_SEP (dst[slen - 2]) 543 && !IS_ANY_SEP (dst[slen - 2])
554 #endif /* WIN32_FILENAMES */ 544 #endif /* WIN32_FILENAMES */
565 In Unix-syntax, this function just removes the final slash. 555 In Unix-syntax, this function just removes the final slash.
566 */ 556 */
567 (directory)) 557 (directory))
568 { 558 {
569 /* This function can GC. GC checked 2000-07-28 ben */ 559 /* This function can GC. GC checked 2000-07-28 ben */
570 char *buf; 560 Intbyte *buf;
571 Lisp_Object handler; 561 Lisp_Object handler;
572 562
573 CHECK_STRING (directory); 563 CHECK_STRING (directory);
574 564
575 #if 0 /* #### WTF? */ 565 #if 0 /* #### WTF? */
580 /* If the file name has special constructs in it, 570 /* If the file name has special constructs in it,
581 call the corresponding file handler. */ 571 call the corresponding file handler. */
582 handler = Ffind_file_name_handler (directory, Qdirectory_file_name); 572 handler = Ffind_file_name_handler (directory, Qdirectory_file_name);
583 if (!NILP (handler)) 573 if (!NILP (handler))
584 return call2_check_string (handler, Qdirectory_file_name, directory); 574 return call2_check_string (handler, Qdirectory_file_name, directory);
585 buf = (char *) alloca (XSTRING_LENGTH (directory) + 20); 575 buf = (Intbyte *) alloca (XSTRING_LENGTH (directory) + 20);
586 directory_file_name ((char *) XSTRING_DATA (directory), buf); 576 directory_file_name (XSTRING_DATA (directory), buf);
587 return build_string (buf); 577 return build_intstring (buf);
588 } 578 }
589 579
590 /* Fmake_temp_name used to be a simple wrapper around mktemp(), but it 580 /* Fmake_temp_name used to be a simple wrapper around mktemp(), but it
591 proved too broken for our purposes (it supported only 26 or 62 581 proved too broken for our purposes (it supported only 26 or 62
592 unique names under some implementations). For example, this 582 unique names under some implementations). For example, this
618 'o','p','q','r','s','t','u','v', 608 'o','p','q','r','s','t','u','v',
619 'w','x','y','z','0','1','2','3', 609 'w','x','y','z','0','1','2','3',
620 '4','5','6','7','8','9','-','_' 610 '4','5','6','7','8','9','-','_'
621 }; 611 };
622 612
623 Lisp_Object val;
624 Bytecount len; 613 Bytecount len;
625 Intbyte *p, *data; 614 Intbyte *p, *data;
626 615
627 CHECK_STRING (prefix); 616 CHECK_STRING (prefix);
628 617
639 628
640 3) It might yield unexpected (to stat(2)) results in the presence 629 3) It might yield unexpected (to stat(2)) results in the presence
641 of EFS and file name handlers. */ 630 of EFS and file name handlers. */
642 631
643 len = XSTRING_LENGTH (prefix); 632 len = XSTRING_LENGTH (prefix);
644 val = make_uninit_string (len + 6); 633 data = alloca_intbytes (len + 7);
645 data = XSTRING_DATA (val);
646 memcpy (data, XSTRING_DATA (prefix), len); 634 memcpy (data, XSTRING_DATA (prefix), len);
647 p = data + len; 635 p = data + len;
636 p[6] = '\0';
648 637
649 /* VAL is created by adding 6 characters to PREFIX. The first three 638 /* VAL is created by adding 6 characters to PREFIX. The first three
650 are the PID of this process, in base 64, and the second three are 639 are the PID of this process, in base 64, and the second three are
651 a pseudo-random number seeded from process startup time. This 640 a pseudo-random number seeded from process startup time. This
652 ensures 262144 unique file names per PID per PREFIX per machine. */ 641 ensures 262144 unique file names per PID per PREFIX per machine. */
653 642
654 { 643 {
655 unsigned int pid = (unsigned int) getpid (); 644 unsigned int pid = (unsigned int) qxe_getpid ();
656 *p++ = tbl[(pid >> 0) & 63]; 645 *p++ = tbl[(pid >> 0) & 63];
657 *p++ = tbl[(pid >> 6) & 63]; 646 *p++ = tbl[(pid >> 6) & 63];
658 *p++ = tbl[(pid >> 12) & 63]; 647 *p++ = tbl[(pid >> 12) & 63];
659 } 648 }
660 649
676 temp_name_rand += 25229; 665 temp_name_rand += 25229;
677 temp_name_rand %= 225307; 666 temp_name_rand %= 225307;
678 667
679 QUIT; 668 QUIT;
680 669
681 if (xemacs_stat ((const char *) data, &ignored) < 0) 670 if (qxe_stat (data, &ignored) < 0)
682 { 671 {
683 /* We want to return only if errno is ENOENT. */ 672 /* We want to return only if errno is ENOENT. */
684 if (errno == ENOENT) 673 if (errno == ENOENT)
685 return val; 674 return make_string (data, len + 6);
686 675
687 /* The error here is dubious, but there is little else we 676 /* The error here is dubious, but there is little else we
688 can do. The alternatives are to return nil, which is 677 can do. The alternatives are to return nil, which is
689 as bad as (and in many cases worse than) throwing the 678 as bad as (and in many cases worse than) throwing the
690 error, or to ignore the error, which will likely result 679 error, or to ignore the error, which will likely result
695 } 684 }
696 } 685 }
697 } 686 }
698 687
699 688
689
700 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* 690 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /*
701 Convert filename NAME to absolute, and canonicalize it. 691 Convert filename NAME to absolute, and canonicalize it.
702 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative 692 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
703 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing, 693 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
704 the current buffer's value of `default-directory' is used. 694 the current buffer's value of `default-directory' is used.
710 An initial `~USER/' expands to USER's home directory. 700 An initial `~USER/' expands to USER's home directory.
711 See also the function `substitute-in-file-name'. 701 See also the function `substitute-in-file-name'.
712 */ 702 */
713 (name, default_directory)) 703 (name, default_directory))
714 { 704 {
715 /* This function can GC. GC-checked 2000-11-18 */ 705 /* This function can GC. GC-checked 2000-11-18.
706 This function synched with Emacs 21.0.103. */
716 Intbyte *nm; 707 Intbyte *nm;
717 708
718 Intbyte *newdir, *p, *o; 709 Intbyte *newdir, *p, *o;
719 int tlen; 710 int tlen;
720 Intbyte *target; 711 Intbyte *target;
721 #ifdef WIN32_FILENAMES 712 #ifdef WIN32_FILENAMES
722 int drive = 0; 713 int drive = 0;
723 int collapse_newdir = 1; 714 int collapse_newdir = 1;
715 /* XEmacs note: This concerns the special '/:' syntax for preventing
716 wildcards and such. We don't support this currently but I'm
717 keeping the code here in case we do. */
718 int is_escaped = 0;
724 #endif 719 #endif
725 #ifndef WIN32_NATIVE 720 #ifndef WIN32_NATIVE
726 struct passwd *pw; 721 struct passwd *pw;
727 #endif /* WIN32_FILENAMES */ 722 #endif
728 int length; 723 int length;
729 Lisp_Object handler = Qnil; 724 Lisp_Object handler = Qnil;
730 #ifdef CYGWIN
731 char *user;
732 #endif
733 struct gcpro gcpro1, gcpro2, gcpro3; 725 struct gcpro gcpro1, gcpro2, gcpro3;
734 726
735 /* both of these get set below */ 727 /* both of these get set below */
736 GCPRO3 (name, default_directory, handler); 728 GCPRO3 (name, default_directory, handler);
737 729
746 738
747 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ 739 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
748 if (NILP (default_directory)) 740 if (NILP (default_directory))
749 default_directory = current_buffer->directory; 741 default_directory = current_buffer->directory;
750 if (! STRINGP (default_directory)) 742 if (! STRINGP (default_directory))
743 #ifdef WIN32_NATIVE
744 default_directory = build_string ("C:\\");
745 #else
751 default_directory = build_string ("/"); 746 default_directory = build_string ("/");
747 #endif
752 748
753 if (!NILP (default_directory)) 749 if (!NILP (default_directory))
754 { 750 {
755 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); 751 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
756 if (!NILP (handler)) 752 if (!NILP (handler))
798 nm = XSTRING_DATA (name); 794 nm = XSTRING_DATA (name);
799 795
800 #ifdef WIN32_FILENAMES 796 #ifdef WIN32_FILENAMES
801 /* We will force directory separators to be either all \ or /, so make 797 /* We will force directory separators to be either all \ or /, so make
802 a local copy to modify, even if there ends up being no change. */ 798 a local copy to modify, even if there ends up being no change. */
803 nm = (Intbyte *) strcpy ((char *) alloca (strlen ((char *) nm) + 1), 799 nm = qxestrcpy (alloca_intbytes (qxestrlen (nm) + 1), nm);
804 (char *) nm); 800
801 /* Note if special escape prefix is present, but remove for now. */
802 if (nm[0] == '/' && nm[1] == ':')
803 {
804 is_escaped = 1;
805 nm += 2;
806 }
805 807
806 /* Find and remove drive specifier if present; this makes nm absolute 808 /* Find and remove drive specifier if present; this makes nm absolute
807 even if the rest of the name appears to be relative. */ 809 even if the rest of the name appears to be relative. */
808 { 810 {
809 Intbyte *colon = (Intbyte *) strrchr ((char *)nm, ':'); 811 Intbyte *colon = qxestrrchr (nm, ':');
810 812
811 if (colon) 813 if (colon)
812 { 814 {
813 /* Only recognize colon as part of drive specifier if there is a 815 /* Only recognize colon as part of drive specifier if there is a
814 single alphabetic character preceding the colon (and if the 816 single alphabetic character preceding the colon (and if the
838 "//somedir". */ 840 "//somedir". */
839 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) 841 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
840 nm++; 842 nm++;
841 #endif /* WIN32_FILENAMES */ 843 #endif /* WIN32_FILENAMES */
842 844
845 #ifdef WIN32_FILENAMES
846 /* Discard any previous drive specifier if nm is now in UNC format. */
847 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
848 {
849 drive = 0;
850 }
851 #endif
852
843 /* If nm is absolute, look for /./ or /../ sequences; if none are 853 /* If nm is absolute, look for /./ or /../ sequences; if none are
844 found, we can probably return right away. We will avoid allocating 854 found, we can probably return right away. We will avoid allocating
845 a new string if name is already fully expanded. */ 855 a new string if name is already fully expanded. */
846 if ( 856 if (
847 IS_DIRECTORY_SEP (nm[0]) 857 IS_DIRECTORY_SEP (nm[0])
848 #ifdef WIN32_NATIVE 858 #ifdef WIN32_NATIVE
849 && (drive || IS_DIRECTORY_SEP (nm[1])) 859 && (drive || IS_DIRECTORY_SEP (nm[1])) && !is_escaped
850 #endif 860 #endif
851 ) 861 )
852 { 862 {
853 /* If it turns out that the filename we want to return is just a 863 /* If it turns out that the filename we want to return is just a
854 suffix of FILENAME, we don't need to go through and edit 864 suffix of FILENAME, we don't need to go through and edit
870 && (IS_DIRECTORY_SEP (p[2]) 880 && (IS_DIRECTORY_SEP (p[2])
871 || p[2] == 0 881 || p[2] == 0
872 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) 882 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
873 || p[3] == 0)))) 883 || p[3] == 0))))
874 lose = 1; 884 lose = 1;
885 /* We want to replace multiple `/' in a row with a single
886 slash. */
887 else if (p > nm
888 && IS_DIRECTORY_SEP (p[0])
889 && IS_DIRECTORY_SEP (p[1]))
890 lose = 1;
875 p++; 891 p++;
876 } 892 }
877 if (!lose) 893 if (!lose)
878 { 894 {
879 #ifdef WIN32_FILENAMES 895 #ifdef WIN32_FILENAMES
880 if (drive || IS_DIRECTORY_SEP (nm[1])) 896 if (drive || IS_DIRECTORY_SEP (nm[1]))
881 { 897 {
882 /* Make sure directories are all separated with / or \ as 898 Intbyte *newnm;
883 desired, but avoid allocation of a new string when not 899
884 required. */
885 CORRECT_DIR_SEPS (nm);
886 if (IS_DIRECTORY_SEP (nm[1])) 900 if (IS_DIRECTORY_SEP (nm[1]))
887 { 901 {
888 if (strcmp ((char *) nm, (char *) XSTRING_DATA (name)) != 0) 902 newnm = mswindows_canonicalize_filename (nm);
889 name = build_string ((CIntbyte *) nm); 903 if (qxestrcmp (newnm, XSTRING_DATA (name)) != 0)
904 name = build_intstring (newnm);
890 } 905 }
891 /* drive must be set, so this is okay */ 906 else
892 else if (strcmp ((char *) nm - 2,
893 (char *) XSTRING_DATA (name)) != 0)
894 { 907 {
895 name = make_string (nm - 2, p - nm + 2); 908 /* drive must be set, so this is okay */
896 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); 909 newnm = mswindows_canonicalize_filename (nm - 2);
897 XSTRING_DATA (name)[1] = ':'; 910 if (qxestrcmp (newnm, XSTRING_DATA (name)) != 0)
911 {
912 name = build_intstring (newnm);
913 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive);
914 XSTRING_DATA (name)[1] = ':';
915 }
898 } 916 }
917 xfree (newnm);
899 RETURN_UNGCPRO (name); 918 RETURN_UNGCPRO (name);
900 } 919 }
901 #endif /* not WIN32_FILENAMES */ 920 #endif /* WIN32_FILENAMES */
902 #ifndef WIN32_NATIVE 921 #ifndef WIN32_NATIVE
903 if (nm == XSTRING_DATA (name)) 922 if (nm == XSTRING_DATA (name))
904 RETURN_UNGCPRO (name); 923 RETURN_UNGCPRO (name);
905 RETURN_UNGCPRO (build_string ((char *) nm)); 924 RETURN_UNGCPRO (build_intstring (nm));
906 #endif /* not WIN32_NATIVE */ 925 #endif /* not WIN32_NATIVE */
907 } 926 }
908 } 927 }
909 928
910 /* At this point, nm might or might not be an absolute file name. We 929 /* At this point, nm might or might not be an absolute file name. We
928 if (nm[0] == '~') /* prefix ~ */ 947 if (nm[0] == '~') /* prefix ~ */
929 { 948 {
930 if (IS_DIRECTORY_SEP (nm[1]) 949 if (IS_DIRECTORY_SEP (nm[1])
931 || nm[1] == 0) /* ~ by itself */ 950 || nm[1] == 0) /* ~ by itself */
932 { 951 {
933 Extbyte *newdir_external = get_home_directory (); 952 Intbyte *homedir = get_home_directory ();
934 953
935 if (newdir_external == NULL) 954 if (!homedir)
936 newdir = (Intbyte *) ""; 955 newdir = (Intbyte *) "";
937 else 956 else
938 TO_INTERNAL_FORMAT (C_STRING, newdir_external, 957 newdir = homedir;
939 C_STRING_ALLOCA, (* ((char **) &newdir)),
940 Qfile_name);
941 958
942 nm++; 959 nm++;
943 #ifdef WIN32_FILENAMES 960 #ifdef WIN32_FILENAMES
944 collapse_newdir = 0; 961 collapse_newdir = 0;
945 #endif 962 #endif
947 else /* ~user/filename */ 964 else /* ~user/filename */
948 { 965 {
949 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++) 966 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++)
950 DO_NOTHING; 967 DO_NOTHING;
951 o = (Intbyte *) alloca (p - nm + 1); 968 o = (Intbyte *) alloca (p - nm + 1);
952 memcpy (o, (char *) nm, p - nm); 969 memcpy (o, nm, p - nm);
953 o [p - nm] = 0; 970 o [p - nm] = 0;
954 971
955 /* #### While NT is single-user (for the moment) you still 972 /* #### While NT is single-user (for the moment) you still
956 can have multiple user profiles users defined, each with 973 can have multiple user profiles users defined, each with
957 its HOME. So maybe possibly we should think about handling 974 its HOME. So maybe possibly we should think about handling
958 ~user. --ben */ 975 ~user. --ben */
959 #ifndef WIN32_NATIVE 976 #ifndef WIN32_NATIVE
960 #ifdef CYGWIN 977 #ifdef CYGWIN
961 if ((user = user_login_name (NULL)) != NULL) 978 {
962 { 979 Intbyte *user;
963 /* Does the user login name match the ~name? */ 980
964 if (strcmp (user, (char *) o + 1) == 0) 981 if ((user = user_login_name (NULL)) != NULL)
965 { 982 {
966 newdir = (Intbyte *) get_home_directory(); 983 /* Does the user login name match the ~name? */
967 nm = p; 984 if (qxestrcmp (user, o + 1) == 0)
968 } 985 {
969 } 986 newdir = get_home_directory ();
970 if (! newdir) 987 nm = p;
988 }
989 }
990 }
991 if (!newdir)
971 { 992 {
972 #endif /* CYGWIN */ 993 #endif /* CYGWIN */
973 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM 994 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM
974 occurring in it. (It can call select()). */ 995 occurring in it. (It can call select()). */
975 slow_down_interrupts (); 996 slow_down_interrupts ();
976 pw = (struct passwd *) getpwnam ((char *) o + 1); 997 pw = (struct passwd *) qxe_getpwnam (o + 1);
977 speed_up_interrupts (); 998 speed_up_interrupts ();
978 if (pw) 999 if (pw)
979 { 1000 {
980 newdir = (Intbyte *) pw -> pw_dir; 1001 newdir = (Intbyte *) pw->pw_dir;
981 nm = p; 1002 nm = p;
1003 /* FSF: if WIN32_NATIVE, collapse_newdir = 0;
1004 not possible here. */
982 } 1005 }
983 #ifdef CYGWIN 1006 #ifdef CYGWIN
984 } 1007 }
985 #endif 1008 #endif
986 #endif /* not WIN32_NATIVE */ 1009 #endif /* not WIN32_NATIVE */
997 { 1020 {
998 #ifdef WIN32_NATIVE 1021 #ifdef WIN32_NATIVE
999 /* Get default directory if needed to make nm absolute. */ 1022 /* Get default directory if needed to make nm absolute. */
1000 if (!IS_DIRECTORY_SEP (nm[0])) 1023 if (!IS_DIRECTORY_SEP (nm[0]))
1001 { 1024 {
1002 newdir = (Intbyte *) alloca (MAXPATHLEN + 1); 1025 Intbyte *newcwd = mswindows_getdcwd (toupper (drive) - 'A' + 1);
1003 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN)) 1026 if (newcwd)
1027 {
1028 INTBYTE_STRING_TO_ALLOCA (newcwd, newdir);
1029 xfree (newcwd);
1030 }
1031 else
1004 newdir = NULL; 1032 newdir = NULL;
1005 } 1033 }
1006 #endif /* WIN32_NATIVE */ 1034 #endif /* WIN32_NATIVE */
1007 if (!newdir) 1035 if (!newdir)
1008 { 1036 {
1028 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) 1056 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1029 #endif 1057 #endif
1030 && !newdir) 1058 && !newdir)
1031 { 1059 {
1032 newdir = XSTRING_DATA (default_directory); 1060 newdir = XSTRING_DATA (default_directory);
1061 #ifdef WIN32_FILENAMES
1062 /* Note if special escape prefix is present, but remove for now. */
1063 if (newdir[0] == '/' && newdir[1] == ':')
1064 {
1065 is_escaped = 1;
1066 newdir += 2;
1067 }
1068 #endif
1033 } 1069 }
1034 1070
1035 #ifdef WIN32_FILENAMES 1071 #ifdef WIN32_FILENAMES
1036 if (newdir) 1072 if (newdir)
1037 { 1073 {
1040 /* Detect Windows file names with drive specifiers. */ 1076 /* Detect Windows file names with drive specifiers. */
1041 ! (IS_DRIVE (newdir[0]) 1077 ! (IS_DRIVE (newdir[0])
1042 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2])) 1078 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
1043 /* Detect Windows file names in UNC format. */ 1079 /* Detect Windows file names in UNC format. */
1044 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) 1080 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1045 /* Detect drive spec by itself */ 1081 /* XEmacs: added these two lines: Detect drive spec by itself */
1046 && ! (IS_DEVICE_SEP (newdir[1]) && newdir[2] == 0) 1082 && ! (IS_DEVICE_SEP (newdir[1]) && newdir[2] == 0)
1047 /* Detect unix format. */ 1083 /* Detect unix format. */
1048 #ifndef WIN32_NATIVE 1084 #ifndef WIN32_NATIVE
1049 && ! (IS_DIRECTORY_SEP (newdir[0])) 1085 && ! (IS_DIRECTORY_SEP (newdir[0]))
1050 #endif 1086 #endif
1061 drive = newdir[0]; 1097 drive = newdir[0];
1062 newdir += 2; 1098 newdir += 2;
1063 } 1099 }
1064 if (!IS_DIRECTORY_SEP (nm[0])) 1100 if (!IS_DIRECTORY_SEP (nm[0]))
1065 { 1101 {
1066 Intbyte *tmp = (Intbyte *) alloca (strlen ((char *) newdir) + 1102 Intbyte *tmp = (Intbyte *) alloca (qxestrlen (newdir) +
1067 strlen ((char *) nm) + 2); 1103 qxestrlen (nm) + 2);
1068 file_name_as_directory ((char *) tmp, (char *) newdir); 1104 file_name_as_directory (tmp, newdir);
1069 strcat ((char *) tmp, (char *) nm); 1105 qxestrcat (tmp, nm);
1070 nm = tmp; 1106 nm = tmp;
1071 } 1107 }
1072 newdir = (Intbyte *) alloca (MAXPATHLEN + 1);
1073 if (drive) 1108 if (drive)
1074 { 1109 {
1075 #ifdef WIN32_NATIVE 1110 #ifdef WIN32_NATIVE
1076 if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN)) 1111 Intbyte *newcwd = mswindows_getdcwd (toupper (drive) - 'A' + 1);
1112 if (newcwd)
1113 {
1114 INTBYTE_STRING_TO_ALLOCA (newcwd, newdir);
1115 xfree (newcwd);
1116 }
1117 else
1077 #endif 1118 #endif
1078 newdir = (Intbyte *) "/"; 1119 INTBYTE_STRING_TO_ALLOCA ((Intbyte *) "/", newdir);
1079 } 1120 }
1080 else 1121 else
1081 getcwd ((char *) newdir, MAXPATHLEN); 1122 INTBYTE_STRING_TO_ALLOCA (get_initial_directory (0, 0), newdir);
1082 } 1123 }
1083 1124
1084 /* Strip off drive name from prefix, if present. */ 1125 /* Strip off drive name from prefix, if present. */
1085 if (IS_DRIVE (newdir[0]) && newdir[1] == ':') 1126 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1086 { 1127 {
1087 drive = newdir[0]; 1128 drive = newdir[0];
1088 newdir += 2; 1129 newdir += 2;
1089 } 1130 }
1090 1131
1091 /* Keep only a prefix from newdir if nm starts with slash 1132 /* Keep only a prefix from newdir if nm starts with slash
1092 (/ /server/share for UNC, nothing otherwise). */ 1133 (//server/share for UNC, nothing otherwise). */
1093 if (IS_DIRECTORY_SEP (nm[0]) 1134 if (IS_DIRECTORY_SEP (nm[0])
1094 #ifndef WIN32_NATIVE 1135 #ifndef WIN32_NATIVE
1095 && IS_DIRECTORY_SEP (nm[1]) 1136 && IS_DIRECTORY_SEP (nm[1])
1096 #endif 1137 #endif
1097 && collapse_newdir) 1138 && collapse_newdir)
1098 { 1139 {
1099 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) 1140 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1100 { 1141 {
1101 newdir = 1142 newdir =
1102 (Intbyte *) 1143 (Intbyte *)
1103 strcpy ((char *) alloca (strlen ((char *) newdir) + 1), 1144 qxestrcpy ((Intbyte *) alloca (qxestrlen (newdir) + 1),
1104 (char *) newdir); 1145 newdir);
1105 p = newdir + 2; 1146 p = newdir + 2;
1106 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1147 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1107 p++; 1148 p++;
1108 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1149 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1109 *p = 0; 1150 *p = 0;
1115 #endif /* WIN32_FILENAMES */ 1156 #endif /* WIN32_FILENAMES */
1116 1157
1117 if (newdir) 1158 if (newdir)
1118 { 1159 {
1119 /* Get rid of any slash at the end of newdir, unless newdir is 1160 /* Get rid of any slash at the end of newdir, unless newdir is
1120 just // (an incomplete UNC name). */ 1161 just / or // (an incomplete UNC name). */
1121 length = strlen ((char *) newdir); 1162 length = qxestrlen (newdir);
1122 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1163 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1123 #ifdef WIN32_FILENAMES 1164 #ifdef WIN32_FILENAMES
1124 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) 1165 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1125 #endif 1166 #endif
1126 ) 1167 )
1134 } 1175 }
1135 else 1176 else
1136 tlen = 0; 1177 tlen = 0;
1137 1178
1138 /* Now concatenate the directory and name to new space in the stack frame */ 1179 /* Now concatenate the directory and name to new space in the stack frame */
1139 tlen += strlen ((char *) nm) + 1; 1180 tlen += qxestrlen (nm) + 1;
1140 #ifdef WIN32_FILENAMES 1181 #ifdef WIN32_FILENAMES
1141 /* Add reserved space for drive name. (The Microsoft x86 compiler 1182 /* Reserve space for drive specifier and escape prefix, since either
1183 or both may need to be inserted. (The Microsoft x86 compiler
1142 produces incorrect code if the following two lines are combined.) */ 1184 produces incorrect code if the following two lines are combined.) */
1143 target = (Intbyte *) alloca (tlen + 2); 1185 target = (Intbyte *) alloca (tlen + 4);
1144 target += 2; 1186 target += 4;
1145 #else /* not WIN32_FILENAMES */ 1187 #else /* not WIN32_FILENAMES */
1146 target = (Intbyte *) alloca (tlen); 1188 target = (Intbyte *) alloca (tlen);
1147 #endif /* not WIN32_FILENAMES */ 1189 #endif /* not WIN32_FILENAMES */
1148 *target = 0; 1190 *target = 0;
1149 1191
1150 if (newdir) 1192 if (newdir)
1151 { 1193 {
1152 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) 1194 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0]))
1153 strcpy ((char *) target, (char *) newdir); 1195 {
1196 #ifdef WIN32_FILENAMES
1197 /* If newdir is effectively "C:/", then the drive letter will have
1198 been stripped and newdir will be "/". Concatenating with an
1199 absolute directory in nm produces "//", which will then be
1200 incorrectly treated as a network share. Ignore newdir in
1201 this case (keeping the drive letter). */
1202 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1203 && newdir[1] == '\0'))
1204 #endif
1205 qxestrcpy (target, newdir);
1206 }
1154 else 1207 else
1155 file_name_as_directory ((char *) target, (char *) newdir); 1208 file_name_as_directory (target, newdir);
1156 } 1209 }
1157 1210
1158 strcat ((char *) target, (char *) nm); 1211 qxestrcat (target, nm);
1159 1212
1160 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */ 1213 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
1161 1214
1162 /* Now canonicalize by removing /. and /foo/.. if they appear. */ 1215 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
1216 appear. */
1163 1217
1164 p = target; 1218 p = target;
1165 o = target; 1219 o = target;
1166 1220
1167 while (*p) 1221 while (*p)
1191 /* Keep initial / only if this is the whole name. */ 1245 /* Keep initial / only if this is the whole name. */
1192 if (o == target && IS_ANY_SEP (*o) && p[3] == 0) 1246 if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
1193 ++o; 1247 ++o;
1194 p += 3; 1248 p += 3;
1195 } 1249 }
1196 #ifdef WIN32_FILENAMES 1250 else if (p > target
1197 /* if drive is set, we're not dealing with an UNC, so 1251 && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]))
1198 multiple dir-seps are redundant (and reportedly cause trouble 1252 {
1199 under win95) */ 1253 /* Collapse multiple `/' in a row. */
1200 else if (drive && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])) 1254 *o++ = *p++;
1201 ++p; 1255 while (IS_DIRECTORY_SEP (*p))
1202 #endif 1256 ++p;
1257 }
1203 else 1258 else
1204 { 1259 {
1205 *o++ = *p++; 1260 *o++ = *p++;
1206 } 1261 }
1207 } 1262 }
1218 else 1273 else
1219 { 1274 {
1220 assert (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])); 1275 assert (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]));
1221 } 1276 }
1222 #endif 1277 #endif
1223 CORRECT_DIR_SEPS (target); 1278 /* Reinsert the escape prefix if required. */
1224 #endif /* WIN32_FILENAMES */ 1279 if (is_escaped)
1225 1280 {
1281 target -= 2;
1282 target[0] = '/';
1283 target[1] = ':';
1284 }
1285
1286 *o = '\0';
1287
1288 {
1289 Intbyte *newtarget = mswindows_canonicalize_filename (target);
1290 Lisp_Object result = build_intstring (newtarget);
1291 xfree (newtarget);
1292
1293 RETURN_UNGCPRO (result);
1294 }
1295 #else /* not WIN32_FILENAMES */
1226 RETURN_UNGCPRO (make_string (target, o - target)); 1296 RETURN_UNGCPRO (make_string (target, o - target));
1297 #endif /* not WIN32_FILENAMES */
1227 } 1298 }
1228 1299
1229 DEFUN ("file-truename", Ffile_truename, 1, 2, 0, /* 1300 DEFUN ("file-truename", Ffile_truename, 1, 2, 0, /*
1230 Return the canonical name of FILENAME. 1301 Return the canonical name of FILENAME.
1231 Second arg DEFAULT is directory to start with if FILENAME is relative 1302 Second arg DEFAULT is directory to start with if FILENAME is relative
1257 RETURN_UNGCPRO 1328 RETURN_UNGCPRO
1258 (call2_check_string (handler, Qfile_truename, expanded_name)); 1329 (call2_check_string (handler, Qfile_truename, expanded_name));
1259 } 1330 }
1260 1331
1261 { 1332 {
1262 char resolved_path[MAXPATHLEN]; 1333 Intbyte resolved_path[PATH_MAX];
1263 Extbyte *path; 1334 Bytecount elen = XSTRING_LENGTH (expanded_name);
1264 Extbyte *p; 1335 Intbyte *path;
1265 Bytecount elen; 1336 Intbyte *p;
1266 1337
1267 TO_EXTERNAL_FORMAT (LISP_STRING, expanded_name, 1338 LISP_STRING_TO_ALLOCA (expanded_name, path);
1268 ALLOCA, (path, elen),
1269 Qfile_name);
1270 p = path; 1339 p = path;
1271 if (elen > MAXPATHLEN)
1272 goto toolong;
1273 1340
1274 /* Try doing it all at once. */ 1341 /* Try doing it all at once. */
1275 /* !! Does realpath() Mule-encapsulate? 1342 if (!qxe_realpath (path, resolved_path))
1276 Answer: Nope! So we do it above */
1277 if (!xrealpath ((char *) path, resolved_path))
1278 { 1343 {
1279 /* Didn't resolve it -- have to do it one component at a time. */ 1344 /* Didn't resolve it -- have to do it one component at a time. */
1280 /* "realpath" is a typically useless, stupid un*x piece of crap. 1345 /* "realpath" is a typically useless, stupid un*x piece of crap.
1281 It claims to return a useful value in the "error" case, but since 1346 It claims to return a useful value in the "error" case, but since
1282 there is no indication provided of how far along the pathname 1347 there is no indication provided of how far along the pathname
1290 pointer to the resolved name. Otherwise, realpath() 1355 pointer to the resolved name. Otherwise, realpath()
1291 returns a null pointer and sets errno to indicate the 1356 returns a null pointer and sets errno to indicate the
1292 error, and the contents of the buffer pointed to by 1357 error, and the contents of the buffer pointed to by
1293 resolved_name are undefined." 1358 resolved_name are undefined."
1294 1359
1295 Since we depend on undocumented semantics of various system realpath()s, 1360 Since we depend on undocumented semantics of various system
1296 we just use our own version in realpath.c. */ 1361 realpath()s, we just use our own version in realpath.c. */
1297 for (;;) 1362 for (;;)
1298 { 1363 {
1299 Extbyte *pos; 1364 Intbyte *pos;
1300 1365
1301 #ifdef WIN32_FILENAMES 1366 #ifdef WIN32_FILENAMES
1302 if (IS_DRIVE (p[0]) && IS_DEVICE_SEP (p[1]) 1367 if (IS_DRIVE (p[0]) && IS_DEVICE_SEP (p[1])
1303 && IS_DIRECTORY_SEP (p[2])) 1368 && IS_DIRECTORY_SEP (p[2]))
1304 /* don't test c: on windows */ 1369 /* don't test c: on windows */
1314 break; 1379 break;
1315 } 1380 }
1316 if (p != pos) 1381 if (p != pos)
1317 p = 0; 1382 p = 0;
1318 1383
1319 if (xrealpath ((char *) path, resolved_path)) 1384 if (qxe_realpath (path, resolved_path))
1320 { 1385 {
1321 if (p) 1386 if (p)
1322 *p = DIRECTORY_SEP; 1387 *p = DIRECTORY_SEP;
1323 else 1388 else
1324 break; 1389 break;
1326 } 1391 }
1327 else if (errno == ENOENT || errno == EACCES) 1392 else if (errno == ENOENT || errno == EACCES)
1328 { 1393 {
1329 /* Failed on this component. Just tack on the rest of 1394 /* Failed on this component. Just tack on the rest of
1330 the string and we are done. */ 1395 the string and we are done. */
1331 int rlen = strlen (resolved_path); 1396 int rlen = qxestrlen (resolved_path);
1332 1397
1333 /* "On failure, it returns NULL, sets errno to indicate 1398 /* "On failure, it returns NULL, sets errno to indicate
1334 the error, and places in resolved_path the absolute pathname 1399 the error, and places in resolved_path the absolute pathname
1335 of the path component which could not be resolved." */ 1400 of the path component which could not be resolved." */
1336 1401
1354 } 1419 }
1355 } 1420 }
1356 1421
1357 { 1422 {
1358 Lisp_Object resolved_name; 1423 Lisp_Object resolved_name;
1359 int rlen = strlen (resolved_path); 1424 int rlen = qxestrlen (resolved_path);
1360 if (elen > 0 && IS_DIRECTORY_SEP (XSTRING_BYTE (expanded_name, elen - 1)) 1425 if (elen > 0 && IS_DIRECTORY_SEP (XSTRING_BYTE (expanded_name, elen - 1))
1361 && !(rlen > 0 && IS_DIRECTORY_SEP (resolved_path[rlen - 1]))) 1426 && !(rlen > 0 && IS_DIRECTORY_SEP (resolved_path[rlen - 1])))
1362 { 1427 {
1363 if (rlen + 1 > countof (resolved_path)) 1428 if (rlen + 1 > countof (resolved_path))
1364 goto toolong; 1429 goto toolong;
1365 resolved_path[rlen++] = DIRECTORY_SEP; 1430 resolved_path[rlen++] = DIRECTORY_SEP;
1366 resolved_path[rlen] = '\0'; 1431 resolved_path[rlen] = '\0';
1367 } 1432 }
1368 TO_INTERNAL_FORMAT (DATA, (resolved_path, rlen), 1433 resolved_name = make_string (resolved_path, rlen);
1369 LISP_STRING, resolved_name,
1370 Qfile_name);
1371 RETURN_UNGCPRO (resolved_name); 1434 RETURN_UNGCPRO (resolved_name);
1372 } 1435 }
1373 1436
1374 toolong: 1437 toolong:
1375 errno = ENAMETOOLONG; 1438 errno = ENAMETOOLONG;
1475 s = p; 1538 s = p;
1476 } 1539 }
1477 1540
1478 /* Copy out the variable name */ 1541 /* Copy out the variable name */
1479 target = (Intbyte *) alloca (s - o + 1); 1542 target = (Intbyte *) alloca (s - o + 1);
1480 strncpy ((char *) target, (char *) o, s - o); 1543 qxestrncpy (target, o, s - o);
1481 target[s - o] = 0; 1544 target[s - o] = 0;
1482 #ifdef WIN32_NATIVE 1545 #ifdef WIN32_NATIVE
1483 strupr (target); /* $home == $HOME etc. */ 1546 strupr (target); /* $home == $HOME etc. */
1484 #endif /* WIN32_NATIVE */ 1547 #endif /* WIN32_NATIVE */
1485 1548
1486 /* Get variable value */ 1549 /* Get variable value */
1487 o = (Intbyte *) egetenv ((char *) target); 1550 o = egetenv ((CIntbyte *) target);
1488 if (!o) goto badvar; 1551 if (!o) goto badvar;
1489 total += strlen ((char *) o); 1552 total += qxestrlen (o);
1490 substituted = 1; 1553 substituted = 1;
1491 } 1554 }
1492 1555
1493 if (!substituted) 1556 if (!substituted)
1494 return filename; 1557 return filename;
1526 s = p; 1589 s = p;
1527 } 1590 }
1528 1591
1529 /* Copy out the variable name */ 1592 /* Copy out the variable name */
1530 target = (Intbyte *) alloca (s - o + 1); 1593 target = (Intbyte *) alloca (s - o + 1);
1531 strncpy ((char *) target, (char *) o, s - o); 1594 qxestrncpy (target, o, s - o);
1532 target[s - o] = 0; 1595 target[s - o] = 0;
1533 #ifdef WIN32_NATIVE 1596 #ifdef WIN32_NATIVE
1534 strupr (target); /* $home == $HOME etc. */ 1597 strupr (target); /* $home == $HOME etc. */
1535 #endif /* WIN32_NATIVE */ 1598 #endif /* WIN32_NATIVE */
1536 1599
1537 /* Get variable value */ 1600 /* Get variable value */
1538 o = (Intbyte *) egetenv ((char *) target); 1601 o = egetenv ((CIntbyte *) target);
1539 if (!o) 1602 if (!o)
1540 goto badvar; 1603 goto badvar;
1541 1604
1542 strcpy ((char *) x, (char *) o); 1605 qxestrcpy (x, o);
1543 x += strlen ((char *) o); 1606 x += qxestrlen (o);
1544 } 1607 }
1545 1608
1546 *x = 0; 1609 *x = 0;
1547 1610
1548 /* If /~ or // appears, discard everything through first slash. */ 1611 /* If /~ or // appears, discard everything through first slash. */
1571 missingclose: 1634 missingclose:
1572 syntax_error ("Missing \"}\" in environment-variable substitution", 1635 syntax_error ("Missing \"}\" in environment-variable substitution",
1573 filename); 1636 filename);
1574 badvar: 1637 badvar:
1575 syntax_error_2 ("Substituting nonexistent environment variable", 1638 syntax_error_2 ("Substituting nonexistent environment variable",
1576 filename, build_string ((char *) target)); 1639 filename, build_intstring (target));
1577 1640
1578 /* NOTREACHED */ 1641 /* NOTREACHED */
1579 return Qnil; /* suppress compiler warning */ 1642 return Qnil; /* suppress compiler warning */
1580 } 1643 }
1581 1644
1617 /* This function can call Lisp. GC checked 2000-07-28 ben */ 1680 /* This function can call Lisp. GC checked 2000-07-28 ben */
1618 struct stat statbuf; 1681 struct stat statbuf;
1619 1682
1620 /* stat is a good way to tell whether the file exists, 1683 /* stat is a good way to tell whether the file exists,
1621 regardless of what access permissions it has. */ 1684 regardless of what access permissions it has. */
1622 if (xemacs_stat ((char *) XSTRING_DATA (absname), &statbuf) >= 0) 1685 if (qxe_stat (XSTRING_DATA (absname), &statbuf) >= 0)
1623 { 1686 {
1624 Lisp_Object tem; 1687 Lisp_Object tem;
1625 1688
1626 if (interactive) 1689 if (interactive)
1627 { 1690 {
1628 Lisp_Object prompt; 1691 Lisp_Object prompt;
1629 struct gcpro gcpro1; 1692 struct gcpro gcpro1;
1630 1693
1631 prompt = emacs_doprnt_string_c 1694 prompt =
1632 ((const Intbyte *) GETTEXT ("File %s already exists; %s anyway? "), 1695 emacs_sprintf_string
1633 Qnil, -1, XSTRING_DATA (absname), 1696 (CGETTEXT ("File %s already exists; %s anyway? "),
1634 GETTEXT (querystring)); 1697 XSTRING_DATA (absname), CGETTEXT (querystring));
1635 1698
1636 GCPRO1 (prompt); 1699 GCPRO1 (prompt);
1637 tem = call1 (Qyes_or_no_p, prompt); 1700 tem = call1 (Qyes_or_no_p, prompt);
1638 UNGCPRO; 1701 UNGCPRO;
1639 } 1702 }
1640 else 1703 else
1641 tem = Qnil; 1704 tem = Qnil;
1642 1705
1643 if (NILP (tem)) 1706 if (NILP (tem))
1644 Fsignal (Qfile_already_exists, 1707 Fsignal (Qfile_already_exists,
1645 list2 (build_translated_string ("File already exists"), 1708 list2 (build_msg_string ("File already exists"),
1646 absname)); 1709 absname));
1647 if (statptr) 1710 if (statptr)
1648 *statptr = statbuf; 1711 *statptr = statbuf;
1649 } 1712 }
1650 else 1713 else
1721 1784
1722 if (NILP (ok_if_already_exists) 1785 if (NILP (ok_if_already_exists)
1723 || INTP (ok_if_already_exists)) 1786 || INTP (ok_if_already_exists))
1724 barf_or_query_if_file_exists (newname, "copy to it", 1787 barf_or_query_if_file_exists (newname, "copy to it",
1725 INTP (ok_if_already_exists), &out_st); 1788 INTP (ok_if_already_exists), &out_st);
1726 else if (xemacs_stat ((const char *) XSTRING_DATA (newname), &out_st) < 0) 1789 else if (qxe_stat (XSTRING_DATA (newname), &out_st) < 0)
1727 out_st.st_mode = 0; 1790 out_st.st_mode = 0;
1728 1791
1729 ifd = interruptible_open ((char *) XSTRING_DATA (filename), O_RDONLY | OPEN_BINARY, 0); 1792 ifd = qxe_interruptible_open (XSTRING_DATA (filename),
1793 O_RDONLY | OPEN_BINARY, 0);
1730 if (ifd < 0) 1794 if (ifd < 0)
1731 report_file_error ("Opening input file", filename); 1795 report_file_error ("Opening input file", filename);
1732 1796
1733 record_unwind_protect (close_file_unwind, make_int (ifd)); 1797 record_unwind_protect (close_file_unwind, make_int (ifd));
1734 1798
1735 /* We can only copy regular files and symbolic links. Other files are not 1799 /* We can only copy regular files and symbolic links. Other files are not
1736 copyable by us. */ 1800 copyable by us. */
1737 input_file_statable_p = (fstat (ifd, &st) >= 0); 1801 input_file_statable_p = (qxe_fstat (ifd, &st) >= 0);
1738 1802
1739 #ifndef WIN32_NATIVE 1803 #ifndef WIN32_NATIVE
1740 if (out_st.st_mode != 0 1804 if (out_st.st_mode != 0
1741 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 1805 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
1742 { 1806 {
1763 report_file_error ("Non-regular file", filename); 1827 report_file_error ("Non-regular file", filename);
1764 } 1828 }
1765 } 1829 }
1766 #endif /* S_ISREG && S_ISLNK */ 1830 #endif /* S_ISREG && S_ISLNK */
1767 1831
1768 ofd = open( (char *) XSTRING_DATA (newname), 1832 ofd = qxe_open (XSTRING_DATA (newname),
1769 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, CREAT_MODE); 1833 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, CREAT_MODE);
1770 if (ofd < 0) 1834 if (ofd < 0)
1771 report_file_error ("Opening output file", newname); 1835 report_file_error ("Opening output file", newname);
1772 1836
1773 { 1837 {
1774 Lisp_Object ofd_locative = noseeum_cons (make_int (ofd), Qnil); 1838 Lisp_Object ofd_locative = noseeum_cons (make_int (ofd), Qnil);
1780 if (write_allowing_quit (ofd, buf, n) != n) 1844 if (write_allowing_quit (ofd, buf, n) != n)
1781 report_file_error ("I/O error", newname); 1845 report_file_error ("I/O error", newname);
1782 } 1846 }
1783 1847
1784 /* Closing the output clobbers the file times on some systems. */ 1848 /* Closing the output clobbers the file times on some systems. */
1785 if (close (ofd) < 0) 1849 if (retry_close (ofd) < 0)
1786 report_file_error ("I/O error", newname); 1850 report_file_error ("I/O error", newname);
1787 1851
1788 if (input_file_statable_p) 1852 if (input_file_statable_p)
1789 { 1853 {
1790 if (!NILP (keep_time)) 1854 if (!NILP (keep_time))
1793 EMACS_SET_SECS_USECS (atime, st.st_atime, 0); 1857 EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
1794 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0); 1858 EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
1795 if (set_file_times (newname, atime, mtime)) 1859 if (set_file_times (newname, atime, mtime))
1796 report_file_error ("I/O error", list1 (newname)); 1860 report_file_error ("I/O error", list1 (newname));
1797 } 1861 }
1798 chmod ((const char *) XSTRING_DATA (newname), 1862 qxe_chmod (XSTRING_DATA (newname), st.st_mode & 07777);
1799 st.st_mode & 07777);
1800 } 1863 }
1801 1864
1802 /* We'll close it by hand */ 1865 /* We'll close it by hand */
1803 XCAR (ofd_locative) = Qnil; 1866 XCAR (ofd_locative) = Qnil;
1804 1867
1805 /* Close ifd */ 1868 /* Close ifd */
1806 unbind_to (speccount, Qnil); 1869 unbind_to (speccount);
1807 } 1870 }
1808 1871
1809 UNGCPRO; 1872 UNGCPRO;
1810 return Qnil; 1873 return Qnil;
1811 } 1874 }
1814 Create a directory. One argument, a file name string. 1877 Create a directory. One argument, a file name string.
1815 */ 1878 */
1816 (dirname_)) 1879 (dirname_))
1817 { 1880 {
1818 /* This function can GC. GC checked 1997.04.06. */ 1881 /* This function can GC. GC checked 1997.04.06. */
1819 char dir [MAXPATHLEN];
1820 Lisp_Object handler; 1882 Lisp_Object handler;
1821 struct gcpro gcpro1; 1883 struct gcpro gcpro1;
1884 DECLARE_EISTRING (dir);
1822 1885
1823 CHECK_STRING (dirname_); 1886 CHECK_STRING (dirname_);
1824 dirname_ = Fexpand_file_name (dirname_, Qnil); 1887 dirname_ = Fexpand_file_name (dirname_, Qnil);
1825 1888
1826 GCPRO1 (dirname_); 1889 GCPRO1 (dirname_);
1827 handler = Ffind_file_name_handler (dirname_, Qmake_directory_internal); 1890 handler = Ffind_file_name_handler (dirname_, Qmake_directory_internal);
1828 UNGCPRO; 1891 UNGCPRO;
1829 if (!NILP (handler)) 1892 if (!NILP (handler))
1830 return (call2 (handler, Qmake_directory_internal, dirname_)); 1893 return (call2 (handler, Qmake_directory_internal, dirname_));
1831 1894
1832 if (XSTRING_LENGTH (dirname_) > (Bytecount) (sizeof (dir) - 1)) 1895 eicpy_lstr (dir, dirname_);
1833 { 1896 if (eigetch_char (dir, eicharlen (dir) - 1) == '/')
1834 return Fsignal (Qfile_error, 1897 eidel (dir, eilen (dir) - 1, -1, 1, -1);
1835 list3 (build_translated_string ("Creating directory"), 1898
1836 build_translated_string ("pathname too long"), 1899 if (qxe_mkdir (eidata (dir), 0777) != 0)
1837 dirname_));
1838 }
1839 strncpy (dir, (char *) XSTRING_DATA (dirname_),
1840 XSTRING_LENGTH (dirname_) + 1);
1841
1842 if (dir [XSTRING_LENGTH (dirname_) - 1] == '/')
1843 dir [XSTRING_LENGTH (dirname_) - 1] = 0;
1844
1845 if (mkdir (dir, 0777) != 0)
1846 report_file_error ("Creating directory", dirname_); 1900 report_file_error ("Creating directory", dirname_);
1847 1901
1848 return Qnil; 1902 return Qnil;
1849 } 1903 }
1850 1904
1866 handler = Ffind_file_name_handler (dirname_, Qdelete_directory); 1920 handler = Ffind_file_name_handler (dirname_, Qdelete_directory);
1867 UNGCPRO; 1921 UNGCPRO;
1868 if (!NILP (handler)) 1922 if (!NILP (handler))
1869 return (call2 (handler, Qdelete_directory, dirname_)); 1923 return (call2 (handler, Qdelete_directory, dirname_));
1870 1924
1871 if (rmdir ((char *) XSTRING_DATA (dirname_)) != 0) 1925 if (qxe_rmdir (XSTRING_DATA (dirname_)) != 0)
1872 report_file_error ("Removing directory", dirname_); 1926 report_file_error ("Removing directory", dirname_);
1873 1927
1874 return Qnil; 1928 return Qnil;
1875 } 1929 }
1876 1930
1891 handler = Ffind_file_name_handler (filename, Qdelete_file); 1945 handler = Ffind_file_name_handler (filename, Qdelete_file);
1892 UNGCPRO; 1946 UNGCPRO;
1893 if (!NILP (handler)) 1947 if (!NILP (handler))
1894 return call2 (handler, Qdelete_file, filename); 1948 return call2 (handler, Qdelete_file, filename);
1895 1949
1896 if (0 > unlink ((char *) XSTRING_DATA (filename))) 1950 if (0 > qxe_unlink (XSTRING_DATA (filename)))
1897 report_file_error ("Removing old name", filename); 1951 report_file_error ("Removing old name", filename);
1898 return Qnil; 1952 return Qnil;
1899 } 1953 }
1900 1954
1901 static Lisp_Object 1955 static Lisp_Object
1970 if (NILP (ok_if_already_exists) 2024 if (NILP (ok_if_already_exists)
1971 || INTP (ok_if_already_exists)) 2025 || INTP (ok_if_already_exists))
1972 barf_or_query_if_file_exists (newname, "rename to it", 2026 barf_or_query_if_file_exists (newname, "rename to it",
1973 INTP (ok_if_already_exists), 0); 2027 INTP (ok_if_already_exists), 0);
1974 2028
1975 /* Syncing with FSF 19.34.6 note: FSF does not have conditional code for
1976 WIN32_NATIVE here; I've removed it. --marcpa */
1977
1978 /* We have configure check for rename() and emulate using 2029 /* We have configure check for rename() and emulate using
1979 link()/unlink() if necessary. */ 2030 link()/unlink() if necessary. */
1980 if (0 > rename ((char *) XSTRING_DATA (filename), 2031 if (0 > qxe_rename (XSTRING_DATA (filename), XSTRING_DATA (newname)))
1981 (char *) XSTRING_DATA (newname)))
1982 { 2032 {
1983 if (errno == EXDEV) 2033 if (errno == EXDEV)
1984 { 2034 {
1985 Fcopy_file (filename, newname, 2035 Fcopy_file (filename, newname,
1986 /* We have already prompted if it was an integer, 2036 /* We have already prompted if it was an integer,
2034 2084
2035 if (NILP (ok_if_already_exists) 2085 if (NILP (ok_if_already_exists)
2036 || INTP (ok_if_already_exists)) 2086 || INTP (ok_if_already_exists))
2037 barf_or_query_if_file_exists (newname, "make it a new name", 2087 barf_or_query_if_file_exists (newname, "make it a new name",
2038 INTP (ok_if_already_exists), 0); 2088 INTP (ok_if_already_exists), 0);
2039 /* Syncing with FSF 19.34.6 note: FSF does not report a file error 2089 /* #### Emacs 20.6 contains an implementation of link() in w32.c.
2040 on NT here. --marcpa */ 2090 Need to port. */
2041 /* But FSF #defines link as sys_link which is supplied in nt.c. We can't do 2091 #ifndef HAVE_LINK
2042 that because sysfile.h defines sys_link depending on ENCAPSULATE_LINK.
2043 Reverted to previous behavior pending a working fix. (jhar) */
2044 #if defined(WIN32_NATIVE)
2045 /* Windows does not support this operation. */
2046 signal_error_2 (Qunimplemented, "Adding new name", filename, newname); 2092 signal_error_2 (Qunimplemented, "Adding new name", filename, newname);
2047 #else /* not defined(WIN32_NATIVE) */ 2093 #else /* HAVE_LINK */
2048 2094 qxe_unlink (XSTRING_DATA (newname));
2049 unlink ((char *) XSTRING_DATA (newname)); 2095 if (0 > qxe_link (XSTRING_DATA (filename), XSTRING_DATA (newname)))
2050 if (0 > link ((char *) XSTRING_DATA (filename),
2051 (char *) XSTRING_DATA (newname)))
2052 { 2096 {
2053 report_file_error ("Adding new name", 2097 report_file_error ("Adding new name",
2054 list3 (Qunbound, filename, newname)); 2098 list3 (Qunbound, filename, newname));
2055 } 2099 }
2056 #endif /* defined(WIN32_NATIVE) */ 2100 #endif /* HAVE_LINK */
2057 2101
2058 UNGCPRO; 2102 UNGCPRO;
2059 return Qnil; 2103 return Qnil;
2060 } 2104 }
2061 2105
2096 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link); 2140 handler = Ffind_file_name_handler (linkname, Qmake_symbolic_link);
2097 if (!NILP (handler)) 2141 if (!NILP (handler))
2098 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename, 2142 RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
2099 linkname, ok_if_already_exists)); 2143 linkname, ok_if_already_exists));
2100 2144
2101 #ifdef S_IFLNK 2145 #ifdef HAVE_SYMLINK
2102 if (NILP (ok_if_already_exists) 2146 if (NILP (ok_if_already_exists)
2103 || INTP (ok_if_already_exists)) 2147 || INTP (ok_if_already_exists))
2104 barf_or_query_if_file_exists (linkname, "make it a link", 2148 barf_or_query_if_file_exists (linkname, "make it a link",
2105 INTP (ok_if_already_exists), 0); 2149 INTP (ok_if_already_exists), 0);
2106 2150
2107 unlink ((char *) XSTRING_DATA (linkname)); 2151 qxe_unlink (XSTRING_DATA (linkname));
2108 if (0 > symlink ((char *) XSTRING_DATA (filename), 2152 if (0 > qxe_symlink (XSTRING_DATA (filename),
2109 (char *) XSTRING_DATA (linkname))) 2153 XSTRING_DATA (linkname)))
2110 { 2154 {
2111 report_file_error ("Making symbolic link", 2155 report_file_error ("Making symbolic link",
2112 list3 (Qunbound, filename, linkname)); 2156 list3 (Qunbound, filename, linkname));
2113 } 2157 }
2114 #endif /* S_IFLNK */ 2158 #endif
2115 2159
2116 UNGCPRO; 2160 UNGCPRO;
2117 return Qnil; 2161 return Qnil;
2118 } 2162 }
2119 2163
2162 } 2206 }
2163 2207
2164 /* Return nonzero if file FILENAME exists and can be executed. */ 2208 /* Return nonzero if file FILENAME exists and can be executed. */
2165 2209
2166 static int 2210 static int
2167 check_executable (char *filename) 2211 check_executable (Lisp_Object filename)
2168 { 2212 {
2169 #ifdef WIN32_NATIVE 2213 #ifdef WIN32_NATIVE
2170 struct stat st; 2214 struct stat st;
2171 if (xemacs_stat (filename, &st) < 0) 2215 if (qxe_stat (XSTRING_DATA (filename), &st) < 0)
2172 return 0; 2216 return 0;
2173 return ((st.st_mode & S_IEXEC) != 0); 2217 return ((st.st_mode & S_IEXEC) != 0);
2174 #else /* not WIN32_NATIVE */ 2218 #else /* not WIN32_NATIVE */
2175 #ifdef HAVE_EACCESS 2219 #ifdef HAVE_EACCESS
2176 return eaccess (filename, X_OK) >= 0; 2220 return qxe_eaccess (XSTRING_DATA (filename), X_OK) >= 0;
2177 #else 2221 #else
2178 /* Access isn't quite right because it uses the real uid 2222 /* Access isn't quite right because it uses the real uid
2179 and we really want to test with the effective uid. 2223 and we really want to test with the effective uid.
2180 But Unix doesn't give us a right way to do it. */ 2224 But Unix doesn't give us a right way to do it. */
2181 return access (filename, X_OK) >= 0; 2225 return qxe_access (XSTRING_DATA (filename), X_OK) >= 0;
2182 #endif /* HAVE_EACCESS */ 2226 #endif /* HAVE_EACCESS */
2183 #endif /* not WIN32_NATIVE */ 2227 #endif /* not WIN32_NATIVE */
2184 } 2228 }
2185 2229
2186 /* Return nonzero if file FILENAME exists and can be written. */ 2230 /* Return nonzero if file FILENAME exists and can be written. */
2187 2231
2188 static int 2232 static int
2189 check_writable (const char *filename) 2233 check_writable (const Intbyte *filename)
2190 { 2234 {
2191 #ifdef HAVE_EACCESS 2235 #ifdef HAVE_EACCESS
2192 return (eaccess (filename, W_OK) >= 0); 2236 return (qxe_eaccess (filename, W_OK) >= 0);
2193 #else 2237 #else
2194 /* Access isn't quite right because it uses the real uid 2238 /* Access isn't quite right because it uses the real uid
2195 and we really want to test with the effective uid. 2239 and we really want to test with the effective uid.
2196 But Unix doesn't give us a right way to do it. 2240 But Unix doesn't give us a right way to do it.
2197 Opening with O_WRONLY could work for an ordinary file, 2241 Opening with O_WRONLY could work for an ordinary file,
2198 but would lose for directories. */ 2242 but would lose for directories. */
2199 return (access (filename, W_OK) >= 0); 2243 return (qxe_access (filename, W_OK) >= 0);
2200 #endif 2244 #endif
2201 } 2245 }
2202 2246
2203 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* 2247 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*
2204 Return t if file FILENAME exists. (This does not mean you can read it.) 2248 Return t if file FILENAME exists. (This does not mean you can read it.)
2221 handler = Ffind_file_name_handler (abspath, Qfile_exists_p); 2265 handler = Ffind_file_name_handler (abspath, Qfile_exists_p);
2222 UNGCPRO; 2266 UNGCPRO;
2223 if (!NILP (handler)) 2267 if (!NILP (handler))
2224 return call2 (handler, Qfile_exists_p, abspath); 2268 return call2 (handler, Qfile_exists_p, abspath);
2225 2269
2226 return xemacs_stat ((char *) XSTRING_DATA (abspath), &statbuf) >= 0 ? Qt : Qnil; 2270 return qxe_stat (XSTRING_DATA (abspath), &statbuf) >= 0 ? Qt : Qnil;
2227 } 2271 }
2228 2272
2229 DEFUN ("file-executable-p", Ffile_executable_p, 1, 1, 0, /* 2273 DEFUN ("file-executable-p", Ffile_executable_p, 1, 1, 0, /*
2230 Return t if FILENAME can be executed by you. 2274 Return t if FILENAME can be executed by you.
2231 For a directory, this means you can access files in that directory. 2275 For a directory, this means you can access files in that directory.
2247 handler = Ffind_file_name_handler (abspath, Qfile_executable_p); 2291 handler = Ffind_file_name_handler (abspath, Qfile_executable_p);
2248 UNGCPRO; 2292 UNGCPRO;
2249 if (!NILP (handler)) 2293 if (!NILP (handler))
2250 return call2 (handler, Qfile_executable_p, abspath); 2294 return call2 (handler, Qfile_executable_p, abspath);
2251 2295
2252 return check_executable ((char *) XSTRING_DATA (abspath)) ? Qt : Qnil; 2296 return check_executable (abspath) ? Qt : Qnil;
2253 } 2297 }
2254 2298
2255 DEFUN ("file-readable-p", Ffile_readable_p, 1, 1, 0, /* 2299 DEFUN ("file-readable-p", Ffile_readable_p, 1, 1, 0, /*
2256 Return t if file FILENAME exists and you can read it. 2300 Return t if file FILENAME exists and you can read it.
2257 See also `file-exists-p' and `file-attributes'. 2301 See also `file-exists-p' and `file-attributes'.
2274 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath)); 2318 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath));
2275 2319
2276 #if defined(WIN32_FILENAMES) 2320 #if defined(WIN32_FILENAMES)
2277 /* Under MS-DOS and Windows, open does not work for directories. */ 2321 /* Under MS-DOS and Windows, open does not work for directories. */
2278 UNGCPRO; 2322 UNGCPRO;
2279 if (access ((char *) XSTRING_DATA (abspath), 0) == 0) 2323 if (qxe_access (XSTRING_DATA (abspath), 0) == 0)
2280 return Qt; 2324 return Qt;
2281 else 2325 else
2282 return Qnil; 2326 return Qnil;
2283 #else /* not WIN32_FILENAMES */ 2327 #else /* not WIN32_FILENAMES */
2284 { 2328 {
2285 int desc = interruptible_open ((char *) XSTRING_DATA (abspath), O_RDONLY | OPEN_BINARY, 0); 2329 int desc = qxe_interruptible_open (XSTRING_DATA (abspath),
2330 O_RDONLY | OPEN_BINARY, 0);
2286 UNGCPRO; 2331 UNGCPRO;
2287 if (desc < 0) 2332 if (desc < 0)
2288 return Qnil; 2333 return Qnil;
2289 close (desc); 2334 retry_close (desc);
2290 return Qt; 2335 return Qt;
2291 } 2336 }
2292 #endif /* not WIN32_FILENAMES */ 2337 #endif /* not WIN32_FILENAMES */
2293 } 2338 }
2294 2339
2314 handler = Ffind_file_name_handler (abspath, Qfile_writable_p); 2359 handler = Ffind_file_name_handler (abspath, Qfile_writable_p);
2315 UNGCPRO; 2360 UNGCPRO;
2316 if (!NILP (handler)) 2361 if (!NILP (handler))
2317 return call2 (handler, Qfile_writable_p, abspath); 2362 return call2 (handler, Qfile_writable_p, abspath);
2318 2363
2319 if (xemacs_stat ((char *) XSTRING_DATA (abspath), &statbuf) >= 0) 2364 if (qxe_stat (XSTRING_DATA (abspath), &statbuf) >= 0)
2320 return (check_writable ((char *) XSTRING_DATA (abspath)) 2365 return (check_writable (XSTRING_DATA (abspath))
2321 ? Qt : Qnil); 2366 ? Qt : Qnil);
2322 2367
2323 2368
2324 GCPRO1 (abspath); 2369 GCPRO1 (abspath);
2325 dir = Ffile_name_directory (abspath); 2370 dir = Ffile_name_directory (abspath);
2326 UNGCPRO; 2371 UNGCPRO;
2327 return (check_writable (!NILP (dir) ? (char *) XSTRING_DATA (dir) 2372 return (check_writable (!NILP (dir) ? XSTRING_DATA (dir) : (Intbyte *) "")
2328 : "")
2329 ? Qt : Qnil); 2373 ? Qt : Qnil);
2330 } 2374 }
2331 2375
2332 DEFUN ("file-symlink-p", Ffile_symlink_p, 1, 1, 0, /* 2376 DEFUN ("file-symlink-p", Ffile_symlink_p, 1, 1, 0, /*
2333 Return non-nil if file FILENAME is the name of a symbolic link. 2377 Return non-nil if file FILENAME is the name of a symbolic link.
2336 */ 2380 */
2337 (filename)) 2381 (filename))
2338 { 2382 {
2339 /* This function can GC. GC checked 1997.04.10. */ 2383 /* This function can GC. GC checked 1997.04.10. */
2340 /* XEmacs change: run handlers even if local machine doesn't have symlinks */ 2384 /* XEmacs change: run handlers even if local machine doesn't have symlinks */
2341 #ifdef S_IFLNK 2385 #ifdef HAVE_READLINK
2342 char *buf; 2386 Intbyte *buf;
2343 int bufsize; 2387 int bufsize;
2344 int valsize; 2388 int valsize;
2345 Lisp_Object val; 2389 Lisp_Object val;
2346 #endif 2390 #endif
2347 Lisp_Object handler; 2391 Lisp_Object handler;
2356 handler = Ffind_file_name_handler (filename, Qfile_symlink_p); 2400 handler = Ffind_file_name_handler (filename, Qfile_symlink_p);
2357 UNGCPRO; 2401 UNGCPRO;
2358 if (!NILP (handler)) 2402 if (!NILP (handler))
2359 return call2 (handler, Qfile_symlink_p, filename); 2403 return call2 (handler, Qfile_symlink_p, filename);
2360 2404
2361 #ifdef S_IFLNK 2405 #ifdef HAVE_READLINK
2362 bufsize = 100; 2406 bufsize = 100;
2363 while (1) 2407 while (1)
2364 { 2408 {
2365 buf = xnew_array_and_zero (char, bufsize); 2409 buf = xnew_array_and_zero (Intbyte, bufsize);
2366 valsize = readlink ((char *) XSTRING_DATA (filename), 2410 valsize = qxe_readlink (XSTRING_DATA (filename),
2367 buf, bufsize); 2411 buf, bufsize);
2368 if (valsize < bufsize) break; 2412 if (valsize < bufsize) break;
2369 /* Buffer was not long enough */ 2413 /* Buffer was not long enough */
2370 xfree (buf); 2414 xfree (buf);
2371 bufsize *= 2; 2415 bufsize *= 2;
2372 } 2416 }
2373 if (valsize == -1) 2417 if (valsize == -1)
2374 { 2418 {
2375 xfree (buf); 2419 xfree (buf);
2376 return Qnil; 2420 return Qnil;
2377 } 2421 }
2378 val = make_string ((Intbyte *) buf, valsize); 2422 val = make_string (buf, valsize);
2379 xfree (buf); 2423 xfree (buf);
2380 return val; 2424 return val;
2381 #else /* not S_IFLNK */ 2425 #else /* not HAVE_READLINK */
2382 return Qnil; 2426 return Qnil;
2383 #endif /* not S_IFLNK */ 2427 #endif /* not HAVE_READLINK */
2384 } 2428 }
2385 2429
2386 DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /* 2430 DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /*
2387 Return t if file FILENAME is the name of a directory as a file. 2431 Return t if file FILENAME is the name of a directory as a file.
2388 A directory name spec may be given instead; then the value is t 2432 A directory name spec may be given instead; then the value is t
2407 handler = Ffind_file_name_handler (abspath, Qfile_directory_p); 2451 handler = Ffind_file_name_handler (abspath, Qfile_directory_p);
2408 UNGCPRO; 2452 UNGCPRO;
2409 if (!NILP (handler)) 2453 if (!NILP (handler))
2410 return call2 (handler, Qfile_directory_p, abspath); 2454 return call2 (handler, Qfile_directory_p, abspath);
2411 2455
2412 if (xemacs_stat ((char *) XSTRING_DATA (abspath), &st) < 0) 2456 if (qxe_stat (XSTRING_DATA (abspath), &st) < 0)
2413 return Qnil; 2457 return Qnil;
2414 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil; 2458 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2415 } 2459 }
2416 2460
2417 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, 1, 1, 0, /* 2461 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, 1, 1, 0, /*
2480 handler = Ffind_file_name_handler (abspath, Qfile_regular_p); 2524 handler = Ffind_file_name_handler (abspath, Qfile_regular_p);
2481 UNGCPRO; 2525 UNGCPRO;
2482 if (!NILP (handler)) 2526 if (!NILP (handler))
2483 return call2 (handler, Qfile_regular_p, abspath); 2527 return call2 (handler, Qfile_regular_p, abspath);
2484 2528
2485 if (xemacs_stat ((char *) XSTRING_DATA (abspath), &st) < 0) 2529 if (qxe_stat (XSTRING_DATA (abspath), &st) < 0)
2486 return Qnil; 2530 return Qnil;
2487 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil; 2531 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
2488 } 2532 }
2489 2533
2490 DEFUN ("file-modes", Ffile_modes, 1, 1, 0, /* 2534 DEFUN ("file-modes", Ffile_modes, 1, 1, 0, /*
2509 handler = Ffind_file_name_handler (abspath, Qfile_modes); 2553 handler = Ffind_file_name_handler (abspath, Qfile_modes);
2510 UNGCPRO; 2554 UNGCPRO;
2511 if (!NILP (handler)) 2555 if (!NILP (handler))
2512 return call2 (handler, Qfile_modes, abspath); 2556 return call2 (handler, Qfile_modes, abspath);
2513 2557
2514 if (xemacs_stat ((char *) XSTRING_DATA (abspath), &st) < 0) 2558 if (qxe_stat (XSTRING_DATA (abspath), &st) < 0)
2515 return Qnil; 2559 return Qnil;
2516 /* Syncing with FSF 19.34.6 note: not in FSF, #if 0'ed out here. */ 2560 /* Syncing with FSF 19.34.6 note: not in FSF, #if 0'ed out here. */
2517 #if 0 2561 #if 0
2518 #ifdef WIN32_NATIVE 2562 #ifdef WIN32_NATIVE
2519 if (check_executable (XSTRING_DATA (abspath))) 2563 if (check_executable (abspath))
2520 st.st_mode |= S_IEXEC; 2564 st.st_mode |= S_IEXEC;
2521 #endif /* WIN32_NATIVE */ 2565 #endif /* WIN32_NATIVE */
2522 #endif /* 0 */ 2566 #endif /* 0 */
2523 2567
2524 return make_int (st.st_mode & 07777); 2568 return make_int (st.st_mode & 07777);
2547 handler = Ffind_file_name_handler (abspath, Qset_file_modes); 2591 handler = Ffind_file_name_handler (abspath, Qset_file_modes);
2548 UNGCPRO; 2592 UNGCPRO;
2549 if (!NILP (handler)) 2593 if (!NILP (handler))
2550 return call3 (handler, Qset_file_modes, abspath, mode); 2594 return call3 (handler, Qset_file_modes, abspath, mode);
2551 2595
2552 if (chmod ((char *) XSTRING_DATA (abspath), XINT (mode)) < 0) 2596 if (qxe_chmod (XSTRING_DATA (abspath), XINT (mode)) < 0)
2553 report_file_error ("Doing chmod", abspath); 2597 report_file_error ("Doing chmod", abspath);
2554 2598
2555 return Qnil; 2599 return Qnil;
2556 } 2600 }
2557 2601
2631 UNGCPRO; 2675 UNGCPRO;
2632 if (!NILP (handler)) 2676 if (!NILP (handler))
2633 return call3 (handler, Qfile_newer_than_file_p, abspath1, 2677 return call3 (handler, Qfile_newer_than_file_p, abspath1,
2634 abspath2); 2678 abspath2);
2635 2679
2636 if (xemacs_stat ((char *) XSTRING_DATA (abspath1), &st) < 0) 2680 if (qxe_stat (XSTRING_DATA (abspath1), &st) < 0)
2637 return Qnil; 2681 return Qnil;
2638 2682
2639 mtime1 = st.st_mtime; 2683 mtime1 = st.st_mtime;
2640 2684
2641 if (xemacs_stat ((char *) XSTRING_DATA (abspath2), &st) < 0) 2685 if (qxe_stat (XSTRING_DATA (abspath2), &st) < 0)
2642 return Qt; 2686 return Qt;
2643 2687
2644 return (mtime1 > st.st_mtime) ? Qt : Qnil; 2688 return (mtime1 > st.st_mtime) ? Qt : Qnil;
2645 } 2689 }
2646 2690
2651 2695
2652 DEFUN ("insert-file-contents-internal", Finsert_file_contents_internal, 2696 DEFUN ("insert-file-contents-internal", Finsert_file_contents_internal,
2653 1, 7, 0, /* 2697 1, 7, 0, /*
2654 Insert contents of file FILENAME after point; no coding-system frobbing. 2698 Insert contents of file FILENAME after point; no coding-system frobbing.
2655 This function is identical to `insert-file-contents' except for the 2699 This function is identical to `insert-file-contents' except for the
2656 handling of the CODESYS and USED-CODESYS arguments under 2700 handling of the CODESYS and USED-CODESYS arguments.
2657 XEmacs/Mule. (When Mule support is not present, both functions are 2701
2658 identical and ignore the CODESYS and USED-CODESYS arguments.) 2702 The file is decoded according to CODESYS; if omitted, no conversion
2659 2703 happens. If USED-CODESYS is non-nil, it should be a symbol, and the actual
2660 If support for Mule exists in this Emacs, the file is decoded according 2704 coding system that was used for the decoding is stored into it. It will in
2661 to CODESYS; if omitted, no conversion happens. If USED-CODESYS is non-nil, 2705 general be different from CODESYS if CODESYS specifies automatic encoding
2662 it should be a symbol, and the actual coding system that was used for the 2706 detection or end-of-line detection.
2663 decoding is stored into it. It will in general be different from CODESYS
2664 if CODESYS specifies automatic encoding detection or end-of-line detection.
2665 2707
2666 Currently START and END refer to byte positions (as opposed to character 2708 Currently START and END refer to byte positions (as opposed to character
2667 positions), even in Mule. (Fixing this is very difficult.) 2709 positions), even in Mule and under MS Windows. (Fixing this, particularly
2710 under Mule, is very difficult.)
2668 */ 2711 */
2669 (filename, visit, start, end, replace, codesys, used_codesys)) 2712 (filename, visit, start, end, replace, codesys, used_codesys))
2670 { 2713 {
2671 /* This function can call lisp */ 2714 /* This function can call lisp */
2672 struct stat st; 2715 struct stat st;
2680 Intbyte read_buf[READ_BUF_SIZE]; 2723 Intbyte read_buf[READ_BUF_SIZE];
2681 int mc_count; 2724 int mc_count;
2682 struct buffer *buf = current_buffer; 2725 struct buffer *buf = current_buffer;
2683 Lisp_Object curbuf; 2726 Lisp_Object curbuf;
2684 int not_regular = 0; 2727 int not_regular = 0;
2728 int do_speedy_insert =
2729 coding_system_is_binary (Fget_coding_system (codesys));
2685 2730
2686 if (buf->base_buffer && ! NILP (visit)) 2731 if (buf->base_buffer && ! NILP (visit))
2687 invalid_operation ("Cannot do file visiting in an indirect buffer", Qunbound); 2732 invalid_operation ("Cannot do file visiting in an indirect buffer", Qunbound);
2688 2733
2689 /* No need to call Fbarf_if_buffer_read_only() here. 2734 /* No need to call Fbarf_if_buffer_read_only() here.
2715 val = call6 (handler, Qinsert_file_contents, filename, 2760 val = call6 (handler, Qinsert_file_contents, filename,
2716 visit, start, end, replace); 2761 visit, start, end, replace);
2717 goto handled; 2762 goto handled;
2718 } 2763 }
2719 2764
2720 #ifdef FILE_CODING
2721 if (!NILP (used_codesys)) 2765 if (!NILP (used_codesys))
2722 CHECK_SYMBOL (used_codesys); 2766 CHECK_SYMBOL (used_codesys);
2723 #endif
2724 2767
2725 if ( (!NILP (start) || !NILP (end)) && !NILP (visit) ) 2768 if ( (!NILP (start) || !NILP (end)) && !NILP (visit) )
2726 invalid_operation ("Attempt to visit less than an entire file", Qunbound); 2769 invalid_operation ("Attempt to visit less than an entire file", Qunbound);
2727 2770
2728 fd = -1; 2771 fd = -1;
2729 2772
2730 if (xemacs_stat ((char *) XSTRING_DATA (filename), &st) < 0) 2773 if (qxe_stat (XSTRING_DATA (filename), &st) < 0)
2731 { 2774 {
2732 if (fd >= 0) close (fd); 2775 if (fd >= 0) retry_close (fd);
2733 badopen: 2776 badopen:
2734 if (NILP (visit)) 2777 if (NILP (visit))
2735 report_file_error ("Opening input file", filename); 2778 report_file_error ("Opening input file", filename);
2736 st.st_mtime = -1; 2779 st.st_mtime = -1;
2737 goto notfound; 2780 goto notfound;
2751 { 2794 {
2752 end_multiple_change (buf, mc_count); 2795 end_multiple_change (buf, mc_count);
2753 2796
2754 RETURN_UNGCPRO 2797 RETURN_UNGCPRO
2755 (Fsignal (Qfile_error, 2798 (Fsignal (Qfile_error,
2756 list2 (build_translated_string("not a regular file"), 2799 list2 (build_msg_string("not a regular file"),
2757 filename))); 2800 filename)));
2758 } 2801 }
2759 } 2802 }
2760 #endif /* S_IFREG */ 2803 #endif /* S_IFREG */
2761 2804
2767 if (!NILP (end)) 2810 if (!NILP (end))
2768 CHECK_INT (end); 2811 CHECK_INT (end);
2769 2812
2770 if (fd < 0) 2813 if (fd < 0)
2771 { 2814 {
2772 if ((fd = interruptible_open ((char *) XSTRING_DATA (filename), 2815 if ((fd = qxe_interruptible_open (XSTRING_DATA (filename),
2773 O_RDONLY | OPEN_BINARY, 0)) < 0) 2816 O_RDONLY | OPEN_BINARY, 0)) < 0)
2774 goto badopen; 2817 goto badopen;
2775 } 2818 }
2776 2819
2777 /* Replacement should preserve point as it preserves markers. */ 2820 /* Replacement should preserve point as it preserves markers. */
2778 if (!NILP (replace)) 2821 if (!NILP (replace))
2795 } 2838 }
2796 2839
2797 /* If requested, replace the accessible part of the buffer 2840 /* If requested, replace the accessible part of the buffer
2798 with the file contents. Avoid replacing text at the 2841 with the file contents. Avoid replacing text at the
2799 beginning or end of the buffer that matches the file contents; 2842 beginning or end of the buffer that matches the file contents;
2800 that preserves markers pointing to the unchanged parts. */ 2843 that preserves markers pointing to the unchanged parts. */
2801 #if !defined (FILE_CODING) 2844 /* The replace-mode code is currently implemented by comparing the
2802 /* The replace-mode code currently only works when the assumption 2845 file on disk with the contents in the buffer, character by character.
2803 'one byte == one char' holds true. This fails Mule because 2846 That works only if the characters on disk are exactly what will go into
2804 files may contain multibyte characters. It holds under Windows NT 2847 the buffer -- i.e. `binary' conversion.
2805 provided we convert CRLF into LF. */ 2848
2806 # define FSFMACS_SPEEDY_INSERT 2849 FSF tries to implement this in all situations, even the non-binary
2807 #endif /* !defined (FILE_CODING) */ 2850 conversion, by (in that case) loading the whole converted file into a
2808 2851 separate memory area, then doing the comparison. I really don't see
2809 #ifndef FSFMACS_SPEEDY_INSERT 2852 the point of this, and it will fail spectacularly if the file is many
2853 megabytes in size. To try to get around this, we could certainly read
2854 from the beginning and decode as necessary before comparing, but doing
2855 the same at the end gets very difficult because of the possibility of
2856 modal coding systems -- trying to decode data from any point forward
2857 without decoding previous data might always give you different results
2858 from starting at the beginning. We could try further tricks like
2859 keeping track of which coding systems are non-modal and providing some
2860 extra method for such coding systems to be given a chunk of data that
2861 came from a specified location in a specified file and ask the coding
2862 systems to return a "sync point" from which the data can be read
2863 forward and have results guaranteed to be the same as reading from the
2864 beginning to that point, but I really don't think it's worth it. If
2865 we implemented the FSF "brute-force" method, we would have to put a
2866 reasonable maximum file size on the files. Is any of this worth it?
2867 --ben
2868
2869 */
2870
2810 if (!NILP (replace)) 2871 if (!NILP (replace))
2811 { 2872 {
2812 buffer_delete_range (buf, BUF_BEG (buf), BUF_Z (buf), 2873 if (!do_speedy_insert)
2813 !NILP (visit) ? INSDEL_NO_LOCKING : 0); 2874 buffer_delete_range (buf, BUF_BEG (buf), BUF_Z (buf),
2814 } 2875 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2815 #else /* FSFMACS_SPEEDY_INSERT */ 2876 else
2816 if (!NILP (replace))
2817 {
2818 char buffer[1 << 14];
2819 Charbpos same_at_start = BUF_BEGV (buf);
2820 Charbpos same_at_end = BUF_ZV (buf);
2821 int overlap;
2822
2823 /* Count how many chars at the start of the file
2824 match the text at the beginning of the buffer. */
2825 while (1)
2826 { 2877 {
2827 int nread; 2878 char buffer[1 << 14];
2828 Charbpos charbpos; 2879 Charbpos same_at_start = BUF_BEGV (buf);
2829 nread = read_allowing_quit (fd, buffer, sizeof (buffer)); 2880 Charbpos same_at_end = BUF_ZV (buf);
2830 if (nread < 0) 2881 int overlap;
2831 report_file_error ("Reading", filename); 2882
2832 else if (nread == 0) 2883 /* Count how many chars at the start of the file
2833 break; 2884 match the text at the beginning of the buffer. */
2834 charbpos = 0; 2885 while (1)
2835 while (charbpos < nread && same_at_start < BUF_ZV (buf) 2886 {
2836 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[charbpos]) 2887 int nread;
2837 same_at_start++, charbpos++; 2888 Charbpos charbpos;
2838 /* If we found a discrepancy, stop the scan. 2889 nread = read_allowing_quit (fd, buffer, sizeof (buffer));
2839 Otherwise loop around and scan the next bufferful. */ 2890 if (nread < 0)
2840 if (charbpos != nread) 2891 report_file_error ("Reading", filename);
2841 break; 2892 else if (nread == 0)
2842 } 2893 break;
2843 /* If the file matches the buffer completely, 2894 charbpos = 0;
2844 there's no need to replace anything. */ 2895 while (charbpos < nread && same_at_start < BUF_ZV (buf)
2845 if (same_at_start - BUF_BEGV (buf) == st.st_size) 2896 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[charbpos])
2846 { 2897 same_at_start++, charbpos++;
2847 close (fd); 2898 /* If we found a discrepancy, stop the scan.
2848 unbind_to (speccount, Qnil); 2899 Otherwise loop around and scan the next bufferful. */
2849 /* Truncate the buffer to the size of the file. */ 2900 if (charbpos != nread)
2901 break;
2902 }
2903 /* If the file matches the buffer completely,
2904 there's no need to replace anything. */
2905 if (same_at_start - BUF_BEGV (buf) == st.st_size)
2906 {
2907 retry_close (fd);
2908 unbind_to (speccount);
2909 /* Truncate the buffer to the size of the file. */
2910 buffer_delete_range (buf, same_at_start, same_at_end,
2911 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2912 goto handled;
2913 }
2914 /* Count how many chars at the end of the file
2915 match the text at the end of the buffer. */
2916 while (1)
2917 {
2918 int total_read, nread;
2919 Charbpos charbpos, curpos, trial;
2920
2921 /* At what file position are we now scanning? */
2922 curpos = st.st_size - (BUF_ZV (buf) - same_at_end);
2923 /* If the entire file matches the buffer tail, stop the scan. */
2924 if (curpos == 0)
2925 break;
2926 /* How much can we scan in the next step? */
2927 trial = min (curpos, (Charbpos) sizeof (buffer));
2928 if (lseek (fd, curpos - trial, 0) < 0)
2929 report_file_error ("Setting file position", filename);
2930
2931 total_read = 0;
2932 while (total_read < trial)
2933 {
2934 nread = read_allowing_quit (fd, buffer + total_read,
2935 trial - total_read);
2936 if (nread <= 0)
2937 report_file_error ("IO error reading file", filename);
2938 total_read += nread;
2939 }
2940 /* Scan this bufferful from the end, comparing with
2941 the Emacs buffer. */
2942 charbpos = total_read;
2943 /* Compare with same_at_start to avoid counting some buffer text
2944 as matching both at the file's beginning and at the end. */
2945 while (charbpos > 0 && same_at_end > same_at_start
2946 && BUF_FETCH_CHAR (buf, same_at_end - 1) ==
2947 buffer[charbpos - 1])
2948 same_at_end--, charbpos--;
2949 /* If we found a discrepancy, stop the scan.
2950 Otherwise loop around and scan the preceding bufferful. */
2951 if (charbpos != 0)
2952 break;
2953 /* If display current starts at beginning of line,
2954 keep it that way. */
2955 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf)
2956 XWINDOW (Fselected_window (Qnil))->start_at_line_beg =
2957 !NILP (Fbolp (wrap_buffer (buf)));
2958 }
2959
2960 /* Don't try to reuse the same piece of text twice. */
2961 overlap = same_at_start - BUF_BEGV (buf) -
2962 (same_at_end + st.st_size - BUF_ZV (buf));
2963 if (overlap > 0)
2964 same_at_end += overlap;
2965
2966 /* Arrange to read only the nonmatching middle part of the file. */
2967 start = make_int (same_at_start - BUF_BEGV (buf));
2968 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end));
2969
2850 buffer_delete_range (buf, same_at_start, same_at_end, 2970 buffer_delete_range (buf, same_at_start, same_at_end,
2851 !NILP (visit) ? INSDEL_NO_LOCKING : 0); 2971 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2852 goto handled; 2972 /* Insert from the file at the proper position. */
2973 BUF_SET_PT (buf, same_at_start);
2853 } 2974 }
2854 /* Count how many chars at the end of the file 2975 }
2855 match the text at the end of the buffer. */
2856 while (1)
2857 {
2858 int total_read, nread;
2859 Charbpos charbpos, curpos, trial;
2860
2861 /* At what file position are we now scanning? */
2862 curpos = st.st_size - (BUF_ZV (buf) - same_at_end);
2863 /* If the entire file matches the buffer tail, stop the scan. */
2864 if (curpos == 0)
2865 break;
2866 /* How much can we scan in the next step? */
2867 trial = min (curpos, (Charbpos) sizeof (buffer));
2868 if (lseek (fd, curpos - trial, 0) < 0)
2869 report_file_error ("Setting file position", filename);
2870
2871 total_read = 0;
2872 while (total_read < trial)
2873 {
2874 nread = read_allowing_quit (fd, buffer + total_read,
2875 trial - total_read);
2876 if (nread <= 0)
2877 report_file_error ("IO error reading file", filename);
2878 total_read += nread;
2879 }
2880 /* Scan this bufferful from the end, comparing with
2881 the Emacs buffer. */
2882 charbpos = total_read;
2883 /* Compare with same_at_start to avoid counting some buffer text
2884 as matching both at the file's beginning and at the end. */
2885 while (charbpos > 0 && same_at_end > same_at_start
2886 && BUF_FETCH_CHAR (buf, same_at_end - 1) ==
2887 buffer[charbpos - 1])
2888 same_at_end--, charbpos--;
2889 /* If we found a discrepancy, stop the scan.
2890 Otherwise loop around and scan the preceding bufferful. */
2891 if (charbpos != 0)
2892 break;
2893 /* If display current starts at beginning of line,
2894 keep it that way. */
2895 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf)
2896 XWINDOW (Fselected_window (Qnil))->start_at_line_beg =
2897 !NILP (Fbolp (make_buffer (buf)));
2898 }
2899
2900 /* Don't try to reuse the same piece of text twice. */
2901 overlap = same_at_start - BUF_BEGV (buf) -
2902 (same_at_end + st.st_size - BUF_ZV (buf));
2903 if (overlap > 0)
2904 same_at_end += overlap;
2905
2906 /* Arrange to read only the nonmatching middle part of the file. */
2907 start = make_int (same_at_start - BUF_BEGV (buf));
2908 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end));
2909
2910 buffer_delete_range (buf, same_at_start, same_at_end,
2911 !NILP (visit) ? INSDEL_NO_LOCKING : 0);
2912 /* Insert from the file at the proper position. */
2913 BUF_SET_PT (buf, same_at_start);
2914 }
2915 #endif /* FSFMACS_SPEEDY_INSERT */
2916 2976
2917 if (!not_regular) 2977 if (!not_regular)
2918 { 2978 {
2919 total = XINT (end) - XINT (start); 2979 total = XINT (end) - XINT (start);
2920 2980
2926 /* For a special file, all we can do is guess. The value of -1 2986 /* For a special file, all we can do is guess. The value of -1
2927 will make the stream functions read as much as possible. */ 2987 will make the stream functions read as much as possible. */
2928 total = -1; 2988 total = -1;
2929 2989
2930 if (XINT (start) != 0 2990 if (XINT (start) != 0
2931 #ifdef FSFMACS_SPEEDY_INSERT
2932 /* why was this here? asked jwz. The reason is that the replace-mode 2991 /* why was this here? asked jwz. The reason is that the replace-mode
2933 connivings above will normally put the file pointer other than 2992 connivings above will normally put the file pointer other than
2934 where it should be. */ 2993 where it should be. */
2935 || !NILP (replace) 2994 || (!NILP (replace) && do_speedy_insert))
2936 #endif /* !FSFMACS_SPEEDY_INSERT */
2937 )
2938 { 2995 {
2939 if (lseek (fd, XINT (start), 0) < 0) 2996 if (lseek (fd, XINT (start), 0) < 0)
2940 report_file_error ("Setting file position", filename); 2997 report_file_error ("Setting file position", filename);
2941 } 2998 }
2942 2999
2946 Lisp_Object stream = make_filedesc_input_stream (fd, 0, total, 3003 Lisp_Object stream = make_filedesc_input_stream (fd, 0, total,
2947 LSTR_ALLOW_QUIT); 3004 LSTR_ALLOW_QUIT);
2948 3005
2949 NGCPRO1 (stream); 3006 NGCPRO1 (stream);
2950 Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536); 3007 Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536);
2951 #ifdef FILE_CODING 3008 stream = make_coding_input_stream
2952 stream = make_decoding_input_stream 3009 (XLSTREAM (stream), get_coding_system_for_text_file (codesys, 1),
2953 (XLSTREAM (stream), Fget_coding_system (codesys)); 3010 CODING_DECODE);
2954 Lstream_set_character_mode (XLSTREAM (stream)); 3011 Lstream_set_character_mode (XLSTREAM (stream));
2955 Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536); 3012 Lstream_set_buffering (XLSTREAM (stream), LSTREAM_BLOCKN_BUFFERED, 65536);
2956 #endif /* FILE_CODING */
2957 3013
2958 record_unwind_protect (delete_stream_unwind, stream); 3014 record_unwind_protect (delete_stream_unwind, stream);
2959 3015
2960 /* No need to limit the amount of stuff we attempt to read. (It would 3016 /* No need to limit the amount of stuff we attempt to read. (It would
2961 be incorrect, anyway, when Mule is enabled.) Instead, the limiting 3017 be incorrect, anyway, when Mule is enabled.) Instead, the limiting
2981 !NILP (visit) 3037 !NILP (visit)
2982 ? INSDEL_NO_LOCKING : 0); 3038 ? INSDEL_NO_LOCKING : 0);
2983 inserted += cc_inserted; 3039 inserted += cc_inserted;
2984 cur_point += cc_inserted; 3040 cur_point += cc_inserted;
2985 } 3041 }
2986 #ifdef FILE_CODING
2987 if (!NILP (used_codesys)) 3042 if (!NILP (used_codesys))
2988 { 3043 {
2989 Fset (used_codesys, 3044 Fset (used_codesys,
2990 XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream)))); 3045 XCODING_SYSTEM_NAME
3046 (coding_stream_detected_coding_system (XLSTREAM (stream))));
2991 } 3047 }
2992 #endif /* FILE_CODING */
2993 NUNGCPRO; 3048 NUNGCPRO;
2994 } 3049 }
2995 3050
2996 /* Close the file/stream */ 3051 /* Close the file/stream */
2997 unbind_to (speccount, Qnil); 3052 unbind_to (speccount);
2998 3053
2999 if (saverrno != 0) 3054 if (saverrno != 0)
3000 { 3055 {
3001 errno = saverrno; 3056 errno = saverrno;
3002 report_file_error ("Reading", filename); 3057 report_file_error ("Reading", filename);
3022 code, and it's a lot cleaner this way. */ 3077 code, and it's a lot cleaner this way. */
3023 /* Note: compute-buffer-file-truename is called for 3078 /* Note: compute-buffer-file-truename is called for
3024 side-effect! Its return value is intentionally 3079 side-effect! Its return value is intentionally
3025 ignored. */ 3080 ignored. */
3026 if (!NILP (Ffboundp (Qcompute_buffer_file_truename))) 3081 if (!NILP (Ffboundp (Qcompute_buffer_file_truename)))
3027 call1 (Qcompute_buffer_file_truename, make_buffer (buf)); 3082 call1 (Qcompute_buffer_file_truename, wrap_buffer (buf));
3028 } 3083 }
3029 BUF_SAVE_MODIFF (buf) = BUF_MODIFF (buf); 3084 BUF_SAVE_MODIFF (buf) = BUF_MODIFF (buf);
3030 buf->auto_save_modified = BUF_MODIFF (buf); 3085 buf->auto_save_modified = BUF_MODIFF (buf);
3031 buf->saved_size = make_int (BUF_SIZE (buf)); 3086 buf->saved_size = make_int (BUF_SIZE (buf));
3032 #ifdef CLASH_DETECTION 3087 #ifdef CLASH_DETECTION
3037 unlock_file (filename); 3092 unlock_file (filename);
3038 } 3093 }
3039 #endif /* CLASH_DETECTION */ 3094 #endif /* CLASH_DETECTION */
3040 if (not_regular) 3095 if (not_regular)
3041 RETURN_UNGCPRO (Fsignal (Qfile_error, 3096 RETURN_UNGCPRO (Fsignal (Qfile_error,
3042 list2 (build_string ("not a regular file"), 3097 list2 (build_msg_string ("not a regular file"),
3043 filename))); 3098 filename)));
3044 3099
3045 /* If visiting nonexistent file, return nil. */ 3100 /* If visiting nonexistent file, return nil. */
3046 if (buf->modtime == -1) 3101 if (buf->modtime == -1)
3047 report_file_error ("Opening input file", 3102 report_file_error ("Opening input file",
3152 along. ARGH, this function is going to lose lose lose. We need 3207 along. ARGH, this function is going to lose lose lose. We need
3153 to protect the current_buffer from being destroyed, but the 3208 to protect the current_buffer from being destroyed, but the
3154 multiple return points make this a pain in the butt. ]] we do 3209 multiple return points make this a pain in the butt. ]] we do
3155 protect curbuf now. --ben */ 3210 protect curbuf now. --ben */
3156 3211
3157 #ifdef FILE_CODING 3212 codesys = get_coding_system_for_text_file (codesys, 0);
3158 codesys = Fget_coding_system (codesys);
3159 #endif /* FILE_CODING */
3160 3213
3161 if (current_buffer->base_buffer && ! NILP (visit)) 3214 if (current_buffer->base_buffer && ! NILP (visit))
3162 invalid_operation ("Cannot do file visiting in an indirect buffer", 3215 invalid_operation ("Cannot do file visiting in an indirect buffer",
3163 curbuf); 3216 curbuf);
3164 3217
3227 3280
3228 fn = filename; 3281 fn = filename;
3229 desc = -1; 3282 desc = -1;
3230 if (!NILP (append)) 3283 if (!NILP (append))
3231 { 3284 {
3232 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY, 0); 3285 desc = qxe_open (XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY, 0);
3233 } 3286 }
3234 if (desc < 0) 3287 if (desc < 0)
3235 { 3288 {
3236 desc = open ((char *) XSTRING_DATA (fn), 3289 desc = qxe_open (XSTRING_DATA (fn),
3237 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, 3290 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
3238 auto_saving ? auto_save_mode_bits : CREAT_MODE); 3291 auto_saving ? auto_save_mode_bits : CREAT_MODE);
3239 } 3292 }
3240 3293
3241 if (desc < 0) 3294 if (desc < 0)
3242 { 3295 {
3243 #ifdef CLASH_DETECTION 3296 #ifdef CLASH_DETECTION
3250 3303
3251 { 3304 {
3252 Lisp_Object desc_locative = Fcons (make_int (desc), Qnil); 3305 Lisp_Object desc_locative = Fcons (make_int (desc), Qnil);
3253 Lisp_Object instream = Qnil, outstream = Qnil; 3306 Lisp_Object instream = Qnil, outstream = Qnil;
3254 struct gcpro nngcpro1, nngcpro2; 3307 struct gcpro nngcpro1, nngcpro2;
3255 /* need to gcpro; QUIT could happen out of call to write() */ 3308 /* need to gcpro; QUIT could happen out of call to retry_write() */
3256 NNGCPRO2 (instream, outstream); 3309 NNGCPRO2 (instream, outstream);
3257 3310
3258 record_unwind_protect (close_file_unwind, desc_locative); 3311 record_unwind_protect (close_file_unwind, desc_locative);
3259 3312
3260 if (!NILP (append)) 3313 if (!NILP (append))
3282 for each request. So I've increased the buffer size 3335 for each request. So I've increased the buffer size
3283 to 64K.) */ 3336 to 64K.) */
3284 outstream = make_filedesc_output_stream (desc, 0, -1, 0); 3337 outstream = make_filedesc_output_stream (desc, 0, -1, 0);
3285 Lstream_set_buffering (XLSTREAM (outstream), 3338 Lstream_set_buffering (XLSTREAM (outstream),
3286 LSTREAM_BLOCKN_BUFFERED, 65536); 3339 LSTREAM_BLOCKN_BUFFERED, 65536);
3287 #ifdef FILE_CODING
3288 outstream = 3340 outstream =
3289 make_encoding_output_stream (XLSTREAM (outstream), codesys); 3341 make_coding_output_stream (XLSTREAM (outstream), codesys, CODING_ENCODE);
3290 Lstream_set_buffering (XLSTREAM (outstream), 3342 Lstream_set_buffering (XLSTREAM (outstream),
3291 LSTREAM_BLOCKN_BUFFERED, 65536); 3343 LSTREAM_BLOCKN_BUFFERED, 65536);
3292 #endif /* FILE_CODING */
3293 if (STRINGP (start)) 3344 if (STRINGP (start))
3294 { 3345 {
3295 instream = make_lisp_string_input_stream (start, 0, -1); 3346 instream = make_lisp_string_input_stream (start, 0, -1);
3296 start1 = 0; 3347 start1 = 0;
3297 } 3348 }
3328 3379
3329 /* Spurious "file has changed on disk" warnings used to be seen on 3380 /* Spurious "file has changed on disk" warnings used to be seen on
3330 systems where close() can change the modtime. This is known to 3381 systems where close() can change the modtime. This is known to
3331 happen on various NFS file systems, on Windows, and on Linux. 3382 happen on various NFS file systems, on Windows, and on Linux.
3332 Rather than handling this on a per-system basis, we 3383 Rather than handling this on a per-system basis, we
3333 unconditionally do the xemacs_stat() after the close(). */ 3384 unconditionally do the qxe_stat() after the retry_close(). */
3334 3385
3335 /* NFS can report a write failure now. */ 3386 /* NFS can report a write failure now. */
3336 if (close (desc) < 0) 3387 if (retry_close (desc) < 0)
3337 { 3388 {
3338 failure = 1; 3389 failure = 1;
3339 save_errno = errno; 3390 save_errno = errno;
3340 } 3391 }
3341 3392
3342 /* Discard the close unwind-protect. Execute the one for 3393 /* Discard the close unwind-protect. Execute the one for
3343 build_annotations (switches back to the original current buffer 3394 build_annotations (switches back to the original current buffer
3344 as necessary). */ 3395 as necessary). */
3345 XCAR (desc_locative) = Qnil; 3396 XCAR (desc_locative) = Qnil;
3346 unbind_to (speccount, Qnil); 3397 unbind_to (speccount);
3347 3398
3348 NNUNGCPRO; 3399 NNUNGCPRO;
3349 } 3400 }
3350 3401
3351 xemacs_stat ((char *) XSTRING_DATA (fn), &st); 3402 qxe_stat (XSTRING_DATA (fn), &st);
3352 3403
3353 #ifdef CLASH_DETECTION 3404 #ifdef CLASH_DETECTION
3354 if (!auto_saving) 3405 if (!auto_saving)
3355 unlock_file (lockname); 3406 unlock_file (lockname);
3356 #endif /* CLASH_DETECTION */ 3407 #endif /* CLASH_DETECTION */
3557 chunk = Lstream_read (instr, largebuf, chunk); 3608 chunk = Lstream_read (instr, largebuf, chunk);
3558 if (chunk < 0) 3609 if (chunk < 0)
3559 return -1; 3610 return -1;
3560 if (chunk == 0) /* EOF */ 3611 if (chunk == 0) /* EOF */
3561 break; 3612 break;
3562 if (Lstream_write (outstr, largebuf, chunk) < chunk) 3613 if (Lstream_write (outstr, largebuf, chunk) < 0)
3563 return -1; 3614 return -1;
3564 pos += chunk; 3615 pos += chunk;
3565 } 3616 }
3566 } 3617 }
3567 if (pos == nextpos) 3618 if (pos == nextpos)
3621 DEFUN ("decrypt-string", Fdecrypt_string, 2, 2, 0, /* 3672 DEFUN ("decrypt-string", Fdecrypt_string, 2, 2, 0, /*
3622 Decrypt STRING using KEY. 3673 Decrypt STRING using KEY.
3623 */ 3674 */
3624 (string, key)) 3675 (string, key))
3625 { 3676 {
3677 /* !!#### May produce bogus data under Mule. */
3626 char *decrypted_string, *raw_key; 3678 char *decrypted_string, *raw_key;
3627 int string_size, key_size; 3679 int string_size, key_size;
3628 3680
3629 CHECK_STRING (string); 3681 CHECK_STRING (string);
3630 CHECK_STRING (key); 3682 CHECK_STRING (key);
3669 handler = Ffind_file_name_handler (b->filename, 3721 handler = Ffind_file_name_handler (b->filename,
3670 Qverify_visited_file_modtime); 3722 Qverify_visited_file_modtime);
3671 if (!NILP (handler)) 3723 if (!NILP (handler))
3672 return call2 (handler, Qverify_visited_file_modtime, buffer); 3724 return call2 (handler, Qverify_visited_file_modtime, buffer);
3673 3725
3674 if (xemacs_stat ((char *) XSTRING_DATA (b->filename), &st) < 0) 3726 if (qxe_stat (XSTRING_DATA (b->filename), &st) < 0)
3675 { 3727 {
3676 /* If the file doesn't exist now and didn't exist before, 3728 /* If the file doesn't exist now and didn't exist before,
3677 we say that it isn't modified, provided the error is a tame one. */ 3729 we say that it isn't modified, provided the error is a tame one. */
3678 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR) 3730 if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
3679 st.st_mtime = -1; 3731 st.st_mtime = -1;
3741 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime); 3793 handler = Ffind_file_name_handler (filename, Qset_visited_file_modtime);
3742 UNGCPRO; 3794 UNGCPRO;
3743 if (!NILP (handler)) 3795 if (!NILP (handler))
3744 /* The handler can find the file name the same way we did. */ 3796 /* The handler can find the file name the same way we did. */
3745 return call2 (handler, Qset_visited_file_modtime, Qnil); 3797 return call2 (handler, Qset_visited_file_modtime, Qnil);
3746 else if (xemacs_stat ((char *) XSTRING_DATA (filename), &st) >= 0) 3798 else if (qxe_stat (XSTRING_DATA (filename), &st) >= 0)
3747 current_buffer->modtime = st.st_mtime; 3799 current_buffer->modtime = st.st_mtime;
3748 } 3800 }
3749 3801
3750 return Qnil; 3802 return Qnil;
3751 } 3803 }
3782 if (!STRINGP (a)) 3834 if (!STRINGP (a))
3783 return (Qnil); 3835 return (Qnil);
3784 3836
3785 /* Get visited file's mode to become the auto save file's mode. */ 3837 /* Get visited file's mode to become the auto save file's mode. */
3786 if (STRINGP (fn) && 3838 if (STRINGP (fn) &&
3787 xemacs_stat ((char *) XSTRING_DATA (fn), &st) >= 0) 3839 qxe_stat (XSTRING_DATA (fn), &st) >= 0)
3788 /* But make sure we can overwrite it later! */ 3840 /* But make sure we can overwrite it later! */
3789 auto_save_mode_bits = st.st_mode | 0600; 3841 auto_save_mode_bits = st.st_mode | 0600;
3790 else 3842 else
3791 /* default mode for auto-save files of buffers with no file is 3843 /* default mode for auto-save files of buffers with no file is
3792 readable by owner only. This may annoy some small number of 3844 readable by owner only. This may annoy some small number of
3793 people, but the alternative removes all privacy from email. */ 3845 people, but the alternative removes all privacy from email. */
3794 auto_save_mode_bits = 0600; 3846 auto_save_mode_bits = 0600;
3795 3847
3796 return 3848 return
3797 /* !!#### need to deal with this 'escape-quoted everywhere */
3798 Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil, 3849 Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil,
3799 #ifdef FILE_CODING 3850 #if 1 /* #### Kyle wants it changed to not use escape-quoted. Think
3851 carefully about how this works. */
3852 Qescape_quoted
3853 #else
3800 current_buffer->buffer_file_coding_system 3854 current_buffer->buffer_file_coding_system
3801 #else
3802 Qnil
3803 #endif 3855 #endif
3804 ); 3856 );
3805 } 3857 }
3806 3858
3807 static Lisp_Object 3859 static Lisp_Object
3808 auto_save_expand_name_error (Lisp_Object condition_object, Lisp_Object ignored) 3860 auto_save_expand_name_error (Lisp_Object condition_object, Lisp_Object ignored)
3809 { 3861 {
3810 /* #### this function should spew an error message about not being 3862 warn_when_safe_lispobj
3811 able to open the .saves file. */ 3863 (Qfile, Qwarning,
3864 Fcons (build_msg_string ("Invalid auto-save list-file"),
3865 Fcons (Vauto_save_list_file_name,
3866 condition_object)));
3812 return Qnil; 3867 return Qnil;
3813 } 3868 }
3814 3869
3815 static Lisp_Object 3870 static Lisp_Object
3816 auto_save_expand_name (Lisp_Object name) 3871 auto_save_expand_name (Lisp_Object name)
3817 { 3872 {
3818 struct gcpro gcpro1; 3873 struct gcpro gcpro1;
3819 3874
3820 /* note that caller did NOT gc protect name, so we do it. */ 3875 /* note that caller did NOT gc protect name, so we do it. */
3821 /* #### dmoore - this might not be necessary, if condition_case_1 3876 /* [[dmoore - this might not be necessary, if condition_case_1
3822 protects it. but I don't think it does. */ 3877 protects it. but I don't think it does.]] indeed it doesn't. --ben */
3823 GCPRO1 (name); 3878 GCPRO1 (name);
3824 RETURN_UNGCPRO (Fexpand_file_name (name, Qnil)); 3879 RETURN_UNGCPRO (Fexpand_file_name (name, Qnil));
3825 } 3880 }
3826 3881
3827 3882
3828 static Lisp_Object 3883 static Lisp_Object
3829 do_auto_save_unwind (Lisp_Object fd) 3884 do_auto_save_unwind (Lisp_Object fd)
3830 { 3885 {
3831 close (XINT (fd)); 3886 retry_close (XINT (fd));
3832 return (fd); 3887 return (fd);
3833 } 3888 }
3834 3889
3835 static Lisp_Object 3890 static Lisp_Object
3836 do_auto_save_unwind_2 (Lisp_Object old_auto_saving) 3891 do_auto_save_unwind_2 (Lisp_Object old_auto_saving)
3985 if we actually auto-saved any files. */ 4040 if we actually auto-saved any files. */
3986 if (!auto_saved && !inhibit_auto_save_session 4041 if (!auto_saved && !inhibit_auto_save_session
3987 && !NILP (Vauto_save_list_file_prefix) 4042 && !NILP (Vauto_save_list_file_prefix)
3988 && STRINGP (listfile) && listdesc < 0) 4043 && STRINGP (listfile) && listdesc < 0)
3989 { 4044 {
3990 listdesc = open ((char *) XSTRING_DATA (listfile), 4045 listdesc =
3991 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, 4046 qxe_open (XSTRING_DATA (listfile),
3992 CREAT_MODE); 4047 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
4048 CREAT_MODE);
3993 4049
3994 /* Arrange to close that file whether or not we get 4050 /* Arrange to close that file whether or not we get
3995 an error. */ 4051 an error. */
3996 if (listdesc >= 0) 4052 if (listdesc >= 0)
3997 record_unwind_protect (do_auto_save_unwind, 4053 record_unwind_protect (do_auto_save_unwind,
4008 Bytecount auto_save_file_name_ext_len; 4064 Bytecount auto_save_file_name_ext_len;
4009 4065
4010 TO_EXTERNAL_FORMAT (LISP_STRING, b->auto_save_file_name, 4066 TO_EXTERNAL_FORMAT (LISP_STRING, b->auto_save_file_name,
4011 ALLOCA, (auto_save_file_name_ext, 4067 ALLOCA, (auto_save_file_name_ext,
4012 auto_save_file_name_ext_len), 4068 auto_save_file_name_ext_len),
4013 Qfile_name); 4069 Qescape_quoted);
4014 if (!NILP (b->filename)) 4070 if (!NILP (b->filename))
4015 { 4071 {
4016 const Extbyte *filename_ext; 4072 const Extbyte *filename_ext;
4017 Bytecount filename_ext_len; 4073 Bytecount filename_ext_len;
4018 4074
4019 TO_EXTERNAL_FORMAT (LISP_STRING, b->filename, 4075 TO_EXTERNAL_FORMAT (LISP_STRING, b->filename,
4020 ALLOCA, (filename_ext, 4076 ALLOCA, (filename_ext,
4021 filename_ext_len), 4077 filename_ext_len),
4022 Qfile_name); 4078 Qescape_quoted);
4023 write (listdesc, filename_ext, filename_ext_len); 4079 retry_write (listdesc, filename_ext, filename_ext_len);
4024 } 4080 }
4025 write (listdesc, "\n", 1); 4081 retry_write (listdesc, "\n", 1);
4026 write (listdesc, auto_save_file_name_ext, 4082 retry_write (listdesc, auto_save_file_name_ext,
4027 auto_save_file_name_ext_len); 4083 auto_save_file_name_ext_len);
4028 write (listdesc, "\n", 1); 4084 retry_write (listdesc, "\n", 1);
4029 } 4085 }
4030 4086
4031 /* dmoore - In a bad scenario we've set b=XBUFFER(buf) 4087 /* dmoore - In a bad scenario we've set b=XBUFFER(buf)
4032 based on values in Vbuffer_alist. auto_save_1 may 4088 based on values in Vbuffer_alist. auto_save_1 may
4033 cause lisp handlers to run. Those handlers may kill 4089 cause lisp handlers to run. Those handlers may kill
4074 /* If we didn't save anything into the listfile, remove the old 4130 /* If we didn't save anything into the listfile, remove the old
4075 one because nothing needed to be auto-saved. Do this afterwards 4131 one because nothing needed to be auto-saved. Do this afterwards
4076 rather than before in case we get a crash attempting to autosave 4132 rather than before in case we get a crash attempting to autosave
4077 (in that case we'd still want the old one around). */ 4133 (in that case we'd still want the old one around). */
4078 if (listdesc < 0 && !auto_saved && STRINGP (listfile)) 4134 if (listdesc < 0 && !auto_saved && STRINGP (listfile))
4079 unlink ((char *) XSTRING_DATA (listfile)); 4135 qxe_unlink (XSTRING_DATA (listfile));
4080 4136
4081 /* Show "...done" only if the echo area would otherwise be empty. */ 4137 /* Show "...done" only if the echo area would otherwise be empty. */
4082 if (auto_saved && NILP (no_message) 4138 if (auto_saved && NILP (no_message)
4083 && NILP (clear_echo_area (selected_frame (), Qauto_saving, 0))) 4139 && NILP (clear_echo_area (selected_frame (), Qauto_saving, 0)))
4084 { 4140 {
4088 strlen ((const char *) msg), Qauto_saving); 4144 strlen ((const char *) msg), Qauto_saving);
4089 } 4145 }
4090 4146
4091 Vquit_flag = oquit; 4147 Vquit_flag = oquit;
4092 4148
4093 RETURN_UNGCPRO (unbind_to (speccount, Qnil)); 4149 RETURN_UNGCPRO (unbind_to (speccount));
4094 } 4150 }
4095 4151
4096 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved, 0, 0, 0, /* 4152 DEFUN ("set-buffer-auto-saved", Fset_buffer_auto_saved, 0, 0, 0, /*
4097 Mark current buffer as auto-saved with its current text. 4153 Mark current buffer as auto-saved with its current text.
4098 No auto-save file will be written until the buffer changes again. 4154 No auto-save file will be written until the buffer changes again.
4327 The value should be either ?/ or ?\\ (any other value is treated as ?\\). 4383 The value should be either ?/ or ?\\ (any other value is treated as ?\\).
4328 This variable affects the built-in functions only on Windows, 4384 This variable affects the built-in functions only on Windows,
4329 on other platforms, it is initialized so that Lisp code can find out 4385 on other platforms, it is initialized so that Lisp code can find out
4330 what the normal separator is. 4386 what the normal separator is.
4331 */ ); 4387 */ );
4332 #ifdef WIN32_NATIVE 4388 Vdirectory_sep_char = make_char (DEFAULT_DIRECTORY_SEP);
4333 Vdirectory_sep_char = make_char ('\\');
4334 #else
4335 Vdirectory_sep_char = make_char ('/');
4336 #endif
4337 4389
4338 reinit_vars_of_fileio (); 4390 reinit_vars_of_fileio ();
4339 } 4391 }
4340 4392
4341 void 4393 void