aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1996-04-27 01:14:17 +0000
committerRichard M. Stallman1996-04-27 01:14:17 +0000
commit199607e4f7b9c2378c61bfacce4792cb0c34a54d (patch)
tree75fb1d6fd9090ede195c31119b9d6e370681770d /src
parent37513bdf9313287dd166c52a291ce536ba2aa93d (diff)
downloademacs-199607e4f7b9c2378c61bfacce4792cb0c34a54d.tar.gz
emacs-199607e4f7b9c2378c61bfacce4792cb0c34a54d.zip
(Fexpand_file_name, Ffile_name_absolute_p): Doc fixes.
(Ffile_exists_p, Ffile_executable_p, Ffile_readable_p) (Ffile_writable_p, Ffile_directory_p, Ffile_regular_p) (Ffile_modes, Fset_file_modes, Ffile_newer_than_file_p) (expand_and_dir_to_file): Rename abspath to absname. (CORRECT_DIR_SEPS) [DOS_NT]: New macro. (IS_DRIVE) [DOS_NT]: Added separate definitions for DOS and NT. (Ffile_name_directory) [DOS_NT]: Simplify code to match change in getdefdir in msdos.c. Ignore embedded colons. Correct dir seps. (Ffile_name_nondirectory) [DOS_NT]: Ignore embedded colons. Correct IS_ANY_SEP to IS_DIRECTORY_SEP. (file_name_as_directory) [DOS_NT]: Correct dir seps. Correct IS_ANY_SEP to IS_DIRECTORY_SEP. (directory_file_name) [DOS_NT]: Correct dir seps. (Fmake_temp_name) [DOS_NT: Correct dir seps. (Fexpand_file_name) [mostly DOS_NT]: Remove relpath, tmp and defdir variables; init drive to 0. Correctly detect when default_directory is absolute. Be strict when looking for MSDOS drive specifier; defer calling getdefdir. Ignore drive specifier if name now has UNC prefix. Correctly recognise if name is not absolute when trying simple method to expand; return original string if possible. Skip dir sep after ~ or ~user. Use getpwnam instead of HOME for ~user on NT. Handle error return from getdefdir. Correctly detect if newdir is absolute before using default_directory. Handle case where newdir is not absolute - expand relative to current working dir if necessary (instead of calling getdisk later). Only keep UNC prefix if nm starts with dir sep. Replace kludgy handling of drive spec in newdir. Correct dir seps. (Fexpand_file_name) [!DOS_NT]: Fix incorrect expansion of "/foo/../bar" -> "//bar". (Fsubstitute_in_file_name) [DOS_NT]: Correct dir seps for NT as well. Merge equivalent #ifdef APOLLO and WINDOWSNT cases. Ignore embedded colons and be strict about drive specs. (Fcopy_file) [DOS_NT]: Do dev/inode check on NT. (Ffile_name_absolute_p) [DOS_NT]: Be strict about drive specs. (check_executable) [DOS_NT]: Test st_mode on NT. (Ffile_readable_p) [DOS_NT]: Use access instead of open on NT. (Ffile_modes) [DOS_NT]: Don't embelish st_mode value on NT. (Fread_file_name) [DOS_NT]: Correct dir seps in HOME. (syms_of_fileio): Add Vdirectory_sep_char.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c647
1 files changed, 414 insertions, 233 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 7493a29f1a4..d01b70c7af7 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1,5 +1,5 @@
1/* File IO for GNU Emacs. 1/* File IO for GNU Emacs.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc. 2 Copyright (C) 1985,86,87,88,93,94,95,96 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -93,6 +93,21 @@ extern char *strerror ();
93#include <fcntl.h> 93#include <fcntl.h>
94#endif /* not WINDOWSNT */ 94#endif /* not WINDOWSNT */
95 95
96#ifdef DOS_NT
97#define CORRECT_DIR_SEPS(s) \
98 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
99 else unixtodos_filename (s); \
100 } while (0)
101/* On Windows, drive letters must be alphabetic - on DOS, the Netware
102 redirector allows the six letters between 'Z' and 'a' as well. */
103#ifdef MSDOS
104#define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
105#endif
106#ifdef WINDOWSNT
107#define IS_DRIVE(x) isalpha (x)
108#endif
109#endif
110
96#ifdef VMS 111#ifdef VMS
97#include <file.h> 112#include <file.h>
98#include <rmsdef.h> 113#include <rmsdef.h>
@@ -129,7 +144,7 @@ int auto_saving;
129 a new file with the same mode as the original */ 144 a new file with the same mode as the original */
130int auto_save_mode_bits; 145int auto_save_mode_bits;
131 146
132/* Alist of elements (REGEXP . HANDLER) for file names 147/* Alist of elements (REGEXP . HANDLER) for file names
133 whose I/O is done with a special handler. */ 148 whose I/O is done with a special handler. */
134Lisp_Object Vfile_name_handler_alist; 149Lisp_Object Vfile_name_handler_alist;
135 150
@@ -160,6 +175,10 @@ int insert_default_directory;
160 Zero means use var format. */ 175 Zero means use var format. */
161int vms_stmlf_recfm; 176int vms_stmlf_recfm;
162 177
178/* On NT, specifies the directory separator character, used (eg.) when
179 expanding file names. This can be bound to / or \. */
180Lisp_Object Vdirectory_sep_char;
181
163/* These variables describe handlers that have "already" had a chance 182/* These variables describe handlers that have "already" had a chance
164 to handle the current operation. 183 to handle the current operation.
165 184
@@ -203,7 +222,7 @@ close_file_unwind (fd)
203/* Restore point, having saved it as a marker. */ 222/* Restore point, having saved it as a marker. */
204 223
205restore_point_unwind (location) 224restore_point_unwind (location)
206 Lisp_Object location; 225 Lisp_Object location;
207{ 226{
208 SET_PT (marker_position (location)); 227 SET_PT (marker_position (location));
209 Fset_marker (location, Qnil, Qnil); 228 Fset_marker (location, Qnil, Qnil);
@@ -312,44 +331,38 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.")
312 filename = FILE_SYSTEM_CASE (filename); 331 filename = FILE_SYSTEM_CASE (filename);
313#endif 332#endif
314 beg = XSTRING (filename)->data; 333 beg = XSTRING (filename)->data;
334#ifdef DOS_NT
335 beg = strcpy (alloca (strlen (beg) + 1), beg);
336#endif
315 p = beg + XSTRING (filename)->size; 337 p = beg + XSTRING (filename)->size;
316 338
317 while (p != beg && !IS_ANY_SEP (p[-1]) 339 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
318#ifdef VMS 340#ifdef VMS
319 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>' 341 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
320#endif /* VMS */ 342#endif /* VMS */
343#ifdef DOS_NT
344 /* only recognise drive specifier at beginning */
345 && !(p[-1] == ':' && p == beg + 2)
346#endif
321 ) p--; 347 ) p--;
322 348
323 if (p == beg) 349 if (p == beg)
324 return Qnil; 350 return Qnil;
325#ifdef DOS_NT 351#ifdef DOS_NT
326 /* Expansion of "c:" to drive and default directory. */ 352 /* Expansion of "c:" to drive and default directory. */
327 /* (NT does the right thing.) */
328 if (p == beg + 2 && beg[1] == ':') 353 if (p == beg + 2 && beg[1] == ':')
329 { 354 {
330 int drive = (*beg) - 'a';
331 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ 355 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
332 unsigned char *res = alloca (MAXPATHLEN + 5); 356 unsigned char *res = alloca (MAXPATHLEN + 1);
333 unsigned char *res1; 357 if (getdefdir (toupper (*beg) - 'A' + 1, res))
334#ifdef WINDOWSNT
335 res1 = res;
336 /* The NT version places the drive letter at the beginning already. */
337#else /* not WINDOWSNT */
338 /* On MSDOG we must put the drive letter in by hand. */
339 res1 = res + 2;
340#endif /* not WINDOWSNT */
341 if (getdefdir (drive + 1, res))
342 { 358 {
343#ifdef MSDOS 359 if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
344 res[0] = drive + 'a';
345 res[1] = ':';
346#endif /* MSDOS */
347 if (IS_DIRECTORY_SEP (res[strlen (res) - 1]))
348 strcat (res, "/"); 360 strcat (res, "/");
349 beg = res; 361 beg = res;
350 p = beg + strlen (beg); 362 p = beg + strlen (beg);
351 } 363 }
352 } 364 }
365 CORRECT_DIR_SEPS (beg);
353#endif /* DOS_NT */ 366#endif /* DOS_NT */
354 return make_string (beg, p - beg); 367 return make_string (beg, p - beg);
355} 368}
@@ -377,10 +390,14 @@ or the entire name if it contains no slash.")
377 beg = XSTRING (filename)->data; 390 beg = XSTRING (filename)->data;
378 end = p = beg + XSTRING (filename)->size; 391 end = p = beg + XSTRING (filename)->size;
379 392
380 while (p != beg && !IS_ANY_SEP (p[-1]) 393 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
381#ifdef VMS 394#ifdef VMS
382 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>' 395 && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
383#endif /* VMS */ 396#endif /* VMS */
397#ifdef DOS_NT
398 /* only recognise drive specifier at beginning */
399 && !(p[-1] == ':' && p == beg + 2)
400#endif
384 ) p--; 401 ) p--;
385 402
386 return make_string (p, end - p); 403 return make_string (p, end - p);
@@ -476,11 +493,14 @@ file_name_as_directory (out, in)
476 } 493 }
477#else /* not VMS */ 494#else /* not VMS */
478 /* For Unix syntax, Append a slash if necessary */ 495 /* For Unix syntax, Append a slash if necessary */
479 if (!IS_ANY_SEP (out[size])) 496 if (!IS_DIRECTORY_SEP (out[size]))
480 { 497 {
481 out[size + 1] = DIRECTORY_SEP; 498 out[size + 1] = DIRECTORY_SEP;
482 out[size + 2] = '\0'; 499 out[size + 2] = '\0';
483 } 500 }
501#ifdef DOS_NT
502 CORRECT_DIR_SEPS (out);
503#endif
484#endif /* not VMS */ 504#endif /* not VMS */
485 return out; 505 return out;
486} 506}
@@ -519,7 +539,7 @@ On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
519 * On VMS: 539 * On VMS:
520 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 540 * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
521 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 541 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
522 * On UNIX, it's simple: just make sure there is a terminating / 542 * On UNIX, it's simple: just make sure there isn't a terminating /
523 543
524 * Value is nonzero if the string output is different from the input. 544 * Value is nonzero if the string output is different from the input.
525 */ 545 */
@@ -555,7 +575,7 @@ directory_file_name (src, dst)
555 nam.nam$b_nop |= NAM$M_SYNCHK; 575 nam.nam$b_nop |= NAM$M_SYNCHK;
556 576
557 /* We call SYS$PARSE to handle such things as [--] for us. */ 577 /* We call SYS$PARSE to handle such things as [--] for us. */
558 if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL) 578 if (SYS$PARSE (&fab, 0, 0) == RMS$_NORMAL)
559 { 579 {
560 slen = nam.nam$b_esl; 580 slen = nam.nam$b_esl;
561 if (esa[slen - 1] == ';' && esa[slen - 2] == '.') 581 if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
@@ -624,7 +644,7 @@ directory_file_name (src, dst)
624 then translate the device and recurse. */ 644 then translate the device and recurse. */
625 if (dst[slen - 1] == ':' 645 if (dst[slen - 1] == ':'
626 && dst[slen - 2] != ':' /* skip decnet nodes */ 646 && dst[slen - 2] != ':' /* skip decnet nodes */
627 && strcmp(src + slen, "[000000]") == 0) 647 && strcmp (src + slen, "[000000]") == 0)
628 { 648 {
629 dst[slen - 1] = '\0'; 649 dst[slen - 1] = '\0';
630 if ((ptr = egetenv (dst)) 650 if ((ptr = egetenv (dst))
@@ -661,7 +681,7 @@ directory_file_name (src, dst)
661 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/')) 681 || (slen > 1 && dst[0] != '/' && dst[slen - 1] == '/'))
662 dst[slen - 1] = 0; 682 dst[slen - 1] = 0;
663#else 683#else
664 if (slen > 1 684 if (slen > 1
665 && IS_DIRECTORY_SEP (dst[slen - 1]) 685 && IS_DIRECTORY_SEP (dst[slen - 1])
666#ifdef DOS_NT 686#ifdef DOS_NT
667 && !IS_ANY_SEP (dst[slen - 2]) 687 && !IS_ANY_SEP (dst[slen - 2])
@@ -669,6 +689,9 @@ directory_file_name (src, dst)
669 ) 689 )
670 dst[slen - 1] = 0; 690 dst[slen - 1] = 0;
671#endif 691#endif
692#ifdef DOS_NT
693 CORRECT_DIR_SEPS (dst);
694#endif
672 return 1; 695 return 1;
673} 696}
674 697
@@ -726,6 +749,9 @@ so there is no danger of generating a name being used by another process.")
726 val = concat2 (prefix, build_string ("XXXXXX")); 749 val = concat2 (prefix, build_string ("XXXXXX"));
727#endif 750#endif
728 mktemp (XSTRING (val)->data); 751 mktemp (XSTRING (val)->data);
752#ifdef DOS_NT
753 CORRECT_DIR_SEPS (XSTRING (val)->data);
754#endif
729 return val; 755 return val;
730} 756}
731 757
@@ -734,10 +760,10 @@ DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
734Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\ 760Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative\n\
735 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\ 761 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing,\n\
736the current buffer's value of default-directory is used.\n\ 762the current buffer's value of default-directory is used.\n\
737Path components that are `.' are removed, and \n\ 763File name components that are `.' are removed, and \n\
738path components followed by `..' are removed, along with the `..' itself;\n\ 764so are file name components followed by `..', along with the `..' itself;\n\
739note that these simplifications are done without checking the resulting\n\ 765note that these simplifications are done without checking the resulting\n\
740paths in the file system.\n\ 766file names in the file system.\n\
741An initial `~/' expands to your home directory.\n\ 767An initial `~/' expands to your home directory.\n\
742An initial `~USER/' expands to USER's home directory.\n\ 768An initial `~USER/' expands to USER's home directory.\n\
743See also the function `substitute-in-file-name'.") 769See also the function `substitute-in-file-name'.")
@@ -745,7 +771,7 @@ See also the function `substitute-in-file-name'.")
745 Lisp_Object name, default_directory; 771 Lisp_Object name, default_directory;
746{ 772{
747 unsigned char *nm; 773 unsigned char *nm;
748 774
749 register unsigned char *newdir, *p, *o; 775 register unsigned char *newdir, *p, *o;
750 int tlen; 776 int tlen;
751 unsigned char *target; 777 unsigned char *target;
@@ -759,13 +785,11 @@ See also the function `substitute-in-file-name'.")
759 int dots = 0; 785 int dots = 0;
760#endif /* VMS */ 786#endif /* VMS */
761#ifdef DOS_NT 787#ifdef DOS_NT
762 /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 788 int drive = 0;
763 int drive = -1;
764 int relpath = 0;
765 unsigned char *tmp, *defdir;
766#endif /* DOS_NT */ 789#endif /* DOS_NT */
790 int length;
767 Lisp_Object handler; 791 Lisp_Object handler;
768 792
769 CHECK_STRING (name, 0); 793 CHECK_STRING (name, 0);
770 794
771 /* If the file name has special constructs in it, 795 /* If the file name has special constructs in it,
@@ -799,15 +823,22 @@ See also the function `substitute-in-file-name'.")
799 823
800 The EQ test avoids infinite recursion. */ 824 The EQ test avoids infinite recursion. */
801 if (! NILP (default_directory) && !EQ (default_directory, name) 825 if (! NILP (default_directory) && !EQ (default_directory, name)
802 /* Save time in some common cases. */ 826 /* Save time in some common cases - as long as default_directory
827 is not relative, it can be canonicalized with name below (if it
828 is needed at all) without requiring it to be expanded now. */
803#ifdef DOS_NT 829#ifdef DOS_NT
804 /* Detect MSDOS file names with device names. */ 830 /* Detect MSDOS file names with drive specifiers. */
805 && ! (XSTRING (default_directory)->size >= 3 831 && ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
806 && IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])) 832#ifdef WINDOWSNT
833 /* Detect Windows file names in UNC format. */
834 && ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
807#endif 835#endif
808 /* Detect Unix absolute file names. */ 836#else /* not DOS_NT */
809 && ! (XSTRING (default_directory)->size >= 2 837 /* Detect Unix absolute file names (/... alone is not absolute on
810 && IS_DIRECTORY_SEP (o[0]))) 838 DOS or Windows). */
839 && ! (IS_DIRECTORY_SEP (o[0]))
840#endif /* not DOS_NT */
841 )
811 { 842 {
812 struct gcpro gcpro1; 843 struct gcpro gcpro1;
813 844
@@ -825,29 +856,38 @@ See also the function `substitute-in-file-name'.")
825#endif 856#endif
826 857
827 nm = XSTRING (name)->data; 858 nm = XSTRING (name)->data;
828
829#ifdef MSDOS
830 /* First map all backslashes to slashes. */
831 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm));
832#endif
833 859
834#ifdef DOS_NT 860#ifdef DOS_NT
835 /* Now strip drive name. */ 861 /* We will force directory separators to be either all \ or /, so make
862 a local copy to modify, even if there ends up being no change. */
863 nm = strcpy (alloca (strlen (nm) + 1), nm);
864
865 /* Find and remove drive specifier if present; this makes nm absolute
866 even if the rest of the name appears to be relative. */
836 { 867 {
837 unsigned char *colon = rindex (nm, ':'); 868 unsigned char *colon = rindex (nm, ':');
869
838 if (colon) 870 if (colon)
871 /* Only recognize colon as part of drive specifier if there is a
872 single alphabetic character preceeding the colon (and if the
873 character before the drive letter, if present, is a directory
874 separator); this is to support the remote system syntax used by
875 ange-ftp, and the "po:username" syntax for POP mailboxes. */
876 look_again:
839 if (nm == colon) 877 if (nm == colon)
840 nm++; 878 nm++;
841 else 879 else if (IS_DRIVE (colon[-1])
880 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2])))
842 { 881 {
843 drive = colon[-1]; 882 drive = colon[-1];
844 nm = colon + 1; 883 nm = colon + 1;
845 if (!IS_DIRECTORY_SEP (*nm)) 884 }
846 { 885 else
847 defdir = alloca (MAXPATHLEN + 1); 886 {
848 relpath = getdefdir (tolower (drive) - 'a' + 1, defdir); 887 while (--colon >= nm)
849 } 888 if (colon[0] == ':')
850 } 889 goto look_again;
890 }
851 } 891 }
852#endif /* DOS_NT */ 892#endif /* DOS_NT */
853 893
@@ -856,31 +896,43 @@ See also the function `substitute-in-file-name'.")
856 p = nm; 896 p = nm;
857 while (*p) 897 while (*p)
858 { 898 {
859 /* Since we know the path is absolute, we can assume that each 899 /* Since we are expecting the name to be absolute, we can assume
860 element starts with a "/". */ 900 that each element starts with a "/". */
861 901
862 /* "//" anywhere isn't necessarily hairy; we just start afresh
863 with the second slash. */
864 if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) 902 if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
865#if defined (APOLLO) || defined (WINDOWSNT) 903#if defined (APOLLO) || defined (WINDOWSNT)
866 /* // at start of filename is meaningful on Apollo 904 /* // at start of filename is meaningful on Apollo
867 and WindowsNT systems */ 905 and WindowsNT systems */
868 && nm != p 906 && nm != p
869#endif /* APOLLO || WINDOWSNT */ 907#endif /* APOLLO || WINDOWSNT */
870 ) 908 )
871 nm = p + 1; 909 nm = p + 1;
872 910
873 /* "~" is hairy as the start of any path element. */
874 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~') 911 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~')
875 nm = p + 1; 912 nm = p + 1;
876 913
877 p++; 914 p++;
878 } 915 }
879 916
880 /* If nm is absolute, flush ...// and detect /./ and /../. 917#ifdef WINDOWSNT
881 If no /./ or /../ we can return right away. */ 918 /* Discard any previous drive specifier if nm is now in UNC format. */
919 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
920 {
921 drive = 0;
922 }
923#endif
924
925 /* If nm is absolute, look for /./ or /../ sequences; if none are
926 found, we can probably return right away. We will avoid allocating
927 a new string if name is already fully expanded. */
882 if ( 928 if (
883 IS_DIRECTORY_SEP (nm[0]) 929 IS_DIRECTORY_SEP (nm[0])
930#ifdef MSDOS
931 && drive
932#endif
933#ifdef WINDOWSNT
934 && (drive || IS_DIRECTORY_SEP (nm[1]))
935#endif
884#ifdef VMS 936#ifdef VMS
885 || index (nm, ':') 937 || index (nm, ':')
886#endif /* VMS */ 938#endif /* VMS */
@@ -897,7 +949,7 @@ See also the function `substitute-in-file-name'.")
897 p = nm; 949 p = nm;
898 while (*p) 950 while (*p)
899 { 951 {
900 /* Since we know the path is absolute, we can assume that each 952 /* Since we know the name is absolute, we can assume that each
901 element starts with a "/". */ 953 element starts with a "/". */
902 954
903 /* "." and ".." are hairy. */ 955 /* "." and ".." are hairy. */
@@ -957,7 +1009,7 @@ See also the function `substitute-in-file-name'.")
957 nm = brack + 1; 1009 nm = brack + 1;
958 brack = 0; 1010 brack = 0;
959 } 1011 }
960 /* if /pathname/dev:, move nm to dev: */ 1012 /* if /name/dev:, move nm to dev: */
961 else if (slash) 1013 else if (slash)
962 nm = slash + 1; 1014 nm = slash + 1;
963 /* if node::dev:, move colon following dev */ 1015 /* if node::dev:, move colon following dev */
@@ -989,7 +1041,28 @@ See also the function `substitute-in-file-name'.")
989 if (index (nm, '/')) 1041 if (index (nm, '/'))
990 return build_string (sys_translate_unix (nm)); 1042 return build_string (sys_translate_unix (nm));
991#endif /* VMS */ 1043#endif /* VMS */
992#ifndef DOS_NT 1044#ifdef DOS_NT
1045 /* Make sure directories are all separated with / or \ as
1046 desired, but avoid allocation of a new string when not
1047 required. */
1048 CORRECT_DIR_SEPS (nm);
1049#ifdef WINDOWSNT
1050 if (IS_DIRECTORY_SEP (nm[1]))
1051 {
1052 if (strcmp (nm, XSTRING (name)->data) != 0)
1053 name = build_string (nm);
1054 }
1055 else
1056#endif
1057 /* drive must be set, so this is okay */
1058 if (strcmp (nm - 2, XSTRING (name)->data) != 0)
1059 {
1060 name = make_string (nm - 2, p - nm + 2);
1061 XSTRING (name)->data[0] = drive;
1062 XSTRING (name)->data[1] = ':';
1063 }
1064 return name;
1065#else /* not DOS_NT */
993 if (nm == XSTRING (name)->data) 1066 if (nm == XSTRING (name)->data)
994 return name; 1067 return name;
995 return build_string (nm); 1068 return build_string (nm);
@@ -997,7 +1070,21 @@ See also the function `substitute-in-file-name'.")
997 } 1070 }
998 } 1071 }
999 1072
1000 /* Now determine directory to start with and put it in newdir */ 1073 /* At this point, nm might or might not be an absolute file name. We
1074 need to expand ~ or ~user if present, otherwise prefix nm with
1075 default_directory if nm is not absolute, and finally collapse /./
1076 and /foo/../ sequences.
1077
1078 We set newdir to be the appropriate prefix if one is needed:
1079 - the relevant user directory if nm starts with ~ or ~user
1080 - the specified drive's working dir (DOS/NT only) if nm does not
1081 start with /
1082 - the value of default_directory.
1083
1084 Note that these prefixes are not guaranteed to be absolute (except
1085 for the working dir of a drive). Therefore, to ensure we always
1086 return an absolute name, if the final prefix is not absolute we
1087 append it to the current working directory. */
1001 1088
1002 newdir = 0; 1089 newdir = 0;
1003 1090
@@ -1011,14 +1098,12 @@ See also the function `substitute-in-file-name'.")
1011 { 1098 {
1012 if (!(newdir = (unsigned char *) egetenv ("HOME"))) 1099 if (!(newdir = (unsigned char *) egetenv ("HOME")))
1013 newdir = (unsigned char *) ""; 1100 newdir = (unsigned char *) "";
1101 nm++;
1014#ifdef DOS_NT 1102#ifdef DOS_NT
1015 /* Problem when expanding "~\" if HOME is not on current drive. 1103 if (IS_DIRECTORY_SEP (nm[0]))
1016 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */ 1104 /* Make nm look like a relative file name. */
1017 if (newdir[1] == ':') 1105 nm++;
1018 drive = newdir[0];
1019 dostounix_filename (newdir);
1020#endif 1106#endif
1021 nm++;
1022#ifdef VMS 1107#ifdef VMS
1023 nm++; /* Don't leave the slash in nm. */ 1108 nm++; /* Don't leave the slash in nm. */
1024#endif /* VMS */ 1109#endif /* VMS */
@@ -1034,10 +1119,6 @@ See also the function `substitute-in-file-name'.")
1034 bcopy ((char *) nm, o, p - nm); 1119 bcopy ((char *) nm, o, p - nm);
1035 o [p - nm] = 0; 1120 o [p - nm] = 0;
1036 1121
1037#ifdef WINDOWSNT
1038 newdir = (unsigned char *) egetenv ("HOME");
1039 dostounix_filename (newdir);
1040#else /* not WINDOWSNT */
1041 pw = (struct passwd *) getpwnam (o + 1); 1122 pw = (struct passwd *) getpwnam (o + 1);
1042 if (pw) 1123 if (pw)
1043 { 1124 {
@@ -1046,41 +1127,136 @@ See also the function `substitute-in-file-name'.")
1046 nm = p + 1; /* skip the terminator */ 1127 nm = p + 1; /* skip the terminator */
1047#else 1128#else
1048 nm = p; 1129 nm = p;
1130#ifdef DOS_NT
1131 if (IS_DIRECTORY_SEP (nm[0]))
1132 /* Make nm look like a relative name. */
1133 nm++;
1134#endif
1049#endif /* VMS */ 1135#endif /* VMS */
1050 } 1136 }
1051#endif /* not WINDOWSNT */
1052 1137
1053 /* If we don't find a user of that name, leave the name 1138 /* If we don't find a user of that name, leave the name
1054 unchanged; don't move nm forward to p. */ 1139 unchanged; don't move nm forward to p. */
1055 } 1140 }
1056 } 1141 }
1057 1142
1058 if (!IS_ANY_SEP (nm[0])
1059#ifdef VMS
1060 && !index (nm, ':')
1061#endif /* not VMS */
1062#ifdef DOS_NT 1143#ifdef DOS_NT
1063 && drive == -1 1144 /* On DOS and Windows, nm is absolute if a drive name was specified;
1145 use the drive's current directory as the prefix if needed. */
1146 if (!newdir && drive)
1147 {
1148 /* Get default directory if needed to make nm absolute. */
1149 if (!IS_DIRECTORY_SEP (nm[0]))
1150 {
1151 newdir = alloca (MAXPATHLEN + 1);
1152 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1153 newdir = NULL;
1154 }
1155 if (!newdir)
1156 {
1157 /* Either nm starts with /, or drive isn't mounted. */
1158 newdir = alloca (4);
1159 newdir[0] = drive;
1160 newdir[1] = ':';
1161 newdir[2] = '/';
1162 newdir[3] = 0;
1163 }
1164 }
1064#endif /* DOS_NT */ 1165#endif /* DOS_NT */
1166
1167 /* Finally, if no prefix has been specified and nm is not absolute,
1168 then it must be expanded relative to default_directory. */
1169
1170 if (
1171#ifndef DOS_NT
1172 /* /... alone is not absolute on DOS and Windows. */
1173 !IS_DIRECTORY_SEP (nm[0])
1174#endif
1175#ifdef WINDOWSNT
1176 !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
1177#endif
1178#ifdef VMS
1179 && !index (nm, ':')
1180#endif
1065 && !newdir) 1181 && !newdir)
1066 { 1182 {
1067 newdir = XSTRING (default_directory)->data; 1183 newdir = XSTRING (default_directory)->data;
1068 } 1184 }
1069 1185
1070#ifdef DOS_NT 1186#ifdef DOS_NT
1071 if (newdir == 0 && relpath) 1187 if (newdir)
1072 newdir = defdir; 1188 {
1189 /* First ensure newdir is an absolute name. */
1190 if (
1191 /* Detect MSDOS file names with drive specifiers. */
1192 ! (IS_DRIVE (newdir[0])
1193 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
1194#ifdef WINDOWSNT
1195 /* Detect Windows file names in UNC format. */
1196 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1197#endif
1198 )
1199 {
1200 /* Effectively, let newdir be (expand-file-name newdir cwd).
1201 Because of the admonition against calling expand-file-name
1202 when we have pointers into lisp strings, we accomplish this
1203 indirectly by prepending newdir to nm if necessary, and using
1204 cwd (or the wd of newdir's drive) as the new newdir. */
1205
1206 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1207 {
1208 drive = newdir[0];
1209 newdir += 2;
1210 }
1211 if (!IS_DIRECTORY_SEP (nm[0]))
1212 {
1213 char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
1214 file_name_as_directory (tmp, newdir);
1215 strcat (tmp, nm);
1216 nm = tmp;
1217 }
1218 newdir = alloca (MAXPATHLEN + 1);
1219 if (drive)
1220 {
1221 if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
1222 newdir = "/";
1223 }
1224 else
1225 getwd (newdir);
1226 }
1227
1228 /* Strip off drive name from prefix, if present. */
1229 if (IS_DRIVE (newdir[0]) && newdir[1] == ':')
1230 {
1231 drive = newdir[0];
1232 newdir += 2;
1233 }
1234
1235 /* Keep only a prefix from newdir if nm starts with slash
1236 (//server/share for UNC, nothing otherwise). */
1237 if (IS_DIRECTORY_SEP (nm[0]))
1238 {
1239#ifdef WINDOWSNT
1240 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]))
1241 {
1242 newdir = strcpy (alloca (strlen (newdir) + 1), newdir);
1243 p = newdir + 2;
1244 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1245 p++;
1246 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1247 *p = 0;
1248 }
1249 else
1250#endif
1251 newdir = "";
1252 }
1253 }
1073#endif /* DOS_NT */ 1254#endif /* DOS_NT */
1074 if (newdir != 0) 1255
1256 if (newdir)
1075 { 1257 {
1076 /* Get rid of any slash at the end of newdir. */ 1258 /* Get rid of any slash at the end of newdir. */
1077 int length = strlen (newdir); 1259 length = strlen (newdir);
1078 /* Adding `length > 1 &&' makes ~ expand into / when homedir
1079 is the root dir. People disagree about whether that is right.
1080 Anyway, we can't take the risk of this change now. */
1081#ifdef DOS_NT
1082 if (newdir[1] != ':' && length > 1)
1083#endif
1084 if (IS_DIRECTORY_SEP (newdir[length - 1])) 1260 if (IS_DIRECTORY_SEP (newdir[length - 1]))
1085 { 1261 {
1086 unsigned char *temp = (unsigned char *) alloca (length); 1262 unsigned char *temp = (unsigned char *) alloca (length);
@@ -1096,7 +1272,7 @@ See also the function `substitute-in-file-name'.")
1096 /* Now concatenate the directory and name to new space in the stack frame */ 1272 /* Now concatenate the directory and name to new space in the stack frame */
1097 tlen += strlen (nm) + 1; 1273 tlen += strlen (nm) + 1;
1098#ifdef DOS_NT 1274#ifdef DOS_NT
1099 /* Add reserved space for drive name. (The Microsoft x86 compiler 1275 /* Add reserved space for drive name. (The Microsoft x86 compiler
1100 produces incorrect code if the following two lines are combined.) */ 1276 produces incorrect code if the following two lines are combined.) */
1101 target = (unsigned char *) alloca (tlen + 2); 1277 target = (unsigned char *) alloca (tlen + 2);
1102 target += 2; 1278 target += 2;
@@ -1121,6 +1297,8 @@ See also the function `substitute-in-file-name'.")
1121 strcpy (target, sys_translate_unix (target)); 1297 strcpy (target, sys_translate_unix (target));
1122#endif /* VMS */ 1298#endif /* VMS */
1123 1299
1300 /* ASSERT (IS_DIRECTORY_SEP (target[0])) if not VMS */
1301
1124 /* Now canonicalize by removing /. and /foo/.. if they appear. */ 1302 /* Now canonicalize by removing /. and /foo/.. if they appear. */
1125 1303
1126 p = target; 1304 p = target;
@@ -1176,10 +1354,10 @@ See also the function `substitute-in-file-name'.")
1176 } 1354 }
1177 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) 1355 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1])
1178#if defined (APOLLO) || defined (WINDOWSNT) 1356#if defined (APOLLO) || defined (WINDOWSNT)
1179 /* // at start of filename is meaningful in Apollo 1357 /* // at start of filename is meaningful in Apollo
1180 and WindowsNT systems */ 1358 and WindowsNT systems */
1181 && o != target 1359 && o != target
1182#endif /* APOLLO */ 1360#endif /* APOLLO || WINDOWSNT */
1183 ) 1361 )
1184 { 1362 {
1185 o = target; 1363 o = target;
@@ -1203,14 +1381,6 @@ See also the function `substitute-in-file-name'.")
1203 { 1381 {
1204 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) 1382 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
1205 ; 1383 ;
1206#if defined (APOLLO) || defined (WINDOWSNT)
1207 if (o == target + 1
1208 && IS_DIRECTORY_SEP (o[-1]) && IS_DIRECTORY_SEP (o[0]))
1209 ++o;
1210 else
1211#endif /* APOLLO || WINDOWSNT */
1212 if (o == target && IS_ANY_SEP (*o))
1213 ++o;
1214 p += 3; 1384 p += 3;
1215 } 1385 }
1216 else 1386 else
@@ -1221,18 +1391,18 @@ See also the function `substitute-in-file-name'.")
1221 } 1391 }
1222 1392
1223#ifdef DOS_NT 1393#ifdef DOS_NT
1224 /* at last, set drive name. */ 1394 /* At last, set drive name. */
1225 if (target[1] != ':'
1226#ifdef WINDOWSNT 1395#ifdef WINDOWSNT
1227 /* Allow network paths that look like "\\foo" */ 1396 /* Except for network file name. */
1228 && !(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])) 1397 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
1229#endif /* WINDOWSNT */ 1398#endif /* WINDOWSNT */
1230 )
1231 { 1399 {
1400 if (!drive) abort ();
1232 target -= 2; 1401 target -= 2;
1233 target[0] = (drive < 0 ? getdisk () + 'A' : drive); 1402 target[0] = drive;
1234 target[1] = ':'; 1403 target[1] = ':';
1235 } 1404 }
1405 CORRECT_DIR_SEPS (target);
1236#endif /* DOS_NT */ 1406#endif /* DOS_NT */
1237 1407
1238 return make_string (target, o - target); 1408 return make_string (target, o - target);
@@ -1252,7 +1422,7 @@ See also the function `substitute-in-file-name'.")
1252 Lisp_Object name, defalt; 1422 Lisp_Object name, defalt;
1253{ 1423{
1254 unsigned char *nm; 1424 unsigned char *nm;
1255 1425
1256 register unsigned char *newdir, *p, *o; 1426 register unsigned char *newdir, *p, *o;
1257 int tlen; 1427 int tlen;
1258 unsigned char *target; 1428 unsigned char *target;
@@ -1266,7 +1436,7 @@ See also the function `substitute-in-file-name'.")
1266 int lbrack = 0, rbrack = 0; 1436 int lbrack = 0, rbrack = 0;
1267 int dots = 0; 1437 int dots = 0;
1268#endif /* VMS */ 1438#endif /* VMS */
1269 1439
1270 CHECK_STRING (name, 0); 1440 CHECK_STRING (name, 0);
1271 1441
1272#ifdef VMS 1442#ifdef VMS
@@ -1275,7 +1445,7 @@ See also the function `substitute-in-file-name'.")
1275#endif 1445#endif
1276 1446
1277 nm = XSTRING (name)->data; 1447 nm = XSTRING (name)->data;
1278 1448
1279 /* If nm is absolute, flush ...// and detect /./ and /../. 1449 /* If nm is absolute, flush ...// and detect /./ and /../.
1280 If no /./ or /../ we can return right away. */ 1450 If no /./ or /../ we can return right away. */
1281 if ( 1451 if (
@@ -1351,13 +1521,13 @@ See also the function `substitute-in-file-name'.")
1351 nm = brack + 1; 1521 nm = brack + 1;
1352 brack = 0; 1522 brack = 0;
1353 } 1523 }
1354 /* if /pathname/dev:, move nm to dev: */ 1524 /* If /name/dev:, move nm to dev: */
1355 else if (slash) 1525 else if (slash)
1356 nm = slash + 1; 1526 nm = slash + 1;
1357 /* if node::dev:, move colon following dev */ 1527 /* If node::dev:, move colon following dev */
1358 else if (colon && colon[-1] == ':') 1528 else if (colon && colon[-1] == ':')
1359 colon = p; 1529 colon = p;
1360 /* if dev1:dev2:, move nm to dev2: */ 1530 /* If dev1:dev2:, move nm to dev2: */
1361 else if (colon && colon[-1] != ':') 1531 else if (colon && colon[-1] != ':')
1362 { 1532 {
1363 nm = colon + 1; 1533 nm = colon + 1;
@@ -1593,9 +1763,10 @@ duplicates what `expand-file-name' does.")
1593 return call2 (handler, Qsubstitute_in_file_name, filename); 1763 return call2 (handler, Qsubstitute_in_file_name, filename);
1594 1764
1595 nm = XSTRING (filename)->data; 1765 nm = XSTRING (filename)->data;
1596#ifdef MSDOS 1766#ifdef DOS_NT
1597 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm)); 1767 nm = strcpy (alloca (strlen (nm) + 1), nm);
1598 substituted = !strcmp (nm, XSTRING (filename)->data); 1768 CORRECT_DIR_SEPS (nm);
1769 substituted = (strcmp (nm, XSTRING (filename)->data) != 0);
1599#endif 1770#endif
1600 endp = nm + XSTRING (filename)->size; 1771 endp = nm + XSTRING (filename)->size;
1601 1772
@@ -1603,17 +1774,14 @@ duplicates what `expand-file-name' does.")
1603 1774
1604 for (p = nm; p != endp; p++) 1775 for (p = nm; p != endp; p++)
1605 { 1776 {
1606 if ((p[0] == '~' || 1777 if ((p[0] == '~'
1607#ifdef APOLLO 1778#if defined (APOLLO) || defined (WINDOWSNT)
1608 /* // at start of file name is meaningful in Apollo system */ 1779 /* // at start of file name is meaningful in Apollo and
1609 (p[0] == '/' && p - 1 != nm) 1780 WindowsNT systems */
1610#else /* not APOLLO */ 1781 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
1611#ifdef WINDOWSNT 1782#else /* not (APOLLO || WINDOWSNT) */
1612 (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) 1783 || IS_DIRECTORY_SEP (p[0])
1613#else /* not WINDOWSNT */ 1784#endif /* not (APOLLO || WINDOWSNT) */
1614 p[0] == '/'
1615#endif /* not WINDOWSNT */
1616#endif /* not APOLLO */
1617 ) 1785 )
1618 && p != nm 1786 && p != nm
1619 && (0 1787 && (0
@@ -1626,7 +1794,9 @@ duplicates what `expand-file-name' does.")
1626 substituted = 1; 1794 substituted = 1;
1627 } 1795 }
1628#ifdef DOS_NT 1796#ifdef DOS_NT
1629 if (p[0] && p[1] == ':') 1797 /* see comment in expand-file-name about drive specifiers */
1798 else if (IS_DRIVE (p[0]) && p[1] == ':'
1799 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1630 { 1800 {
1631 nm = p; 1801 nm = p;
1632 substituted = 1; 1802 substituted = 1;
@@ -1745,22 +1915,18 @@ duplicates what `expand-file-name' does.")
1745 1915
1746 for (p = xnm; p != x; p++) 1916 for (p = xnm; p != x; p++)
1747 if ((p[0] == '~' 1917 if ((p[0] == '~'
1748#ifdef APOLLO 1918#if defined (APOLLO) || defined (WINDOWSNT)
1749 /* // at start of file name is meaningful in Apollo system */
1750 || (p[0] == '/' && p - 1 != xnm)
1751#else /* not APOLLO */
1752#ifdef WINDOWSNT
1753 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) 1919 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
1754#else /* not WINDOWSNT */ 1920#else /* not (APOLLO || WINDOWSNT) */
1755 || p[0] == '/' 1921 || IS_DIRECTORY_SEP (p[0])
1756#endif /* not WINDOWSNT */ 1922#endif /* not (APOLLO || WINDOWSNT) */
1757#endif /* not APOLLO */
1758 ) 1923 )
1759 && p != nm && IS_DIRECTORY_SEP (p[-1])) 1924 && p != nm && IS_DIRECTORY_SEP (p[-1]))
1760 xnm = p; 1925 xnm = p;
1761#ifdef DOS_NT 1926#ifdef DOS_NT
1762 else if (p[0] && p[1] == ':') 1927 else if (IS_DRIVE (p[0]) && p[1] == ':'
1763 xnm = p; 1928 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1929 xnm = p;
1764#endif 1930#endif
1765 1931
1766 return make_string (xnm, x - xnm); 1932 return make_string (xnm, x - xnm);
@@ -1783,25 +1949,25 @@ Lisp_Object
1783expand_and_dir_to_file (filename, defdir) 1949expand_and_dir_to_file (filename, defdir)
1784 Lisp_Object filename, defdir; 1950 Lisp_Object filename, defdir;
1785{ 1951{
1786 register Lisp_Object abspath; 1952 register Lisp_Object absname;
1787 1953
1788 abspath = Fexpand_file_name (filename, defdir); 1954 absname = Fexpand_file_name (filename, defdir);
1789#ifdef VMS 1955#ifdef VMS
1790 { 1956 {
1791 register int c = XSTRING (abspath)->data[XSTRING (abspath)->size - 1]; 1957 register int c = XSTRING (absname)->data[XSTRING (absname)->size - 1];
1792 if (c == ':' || c == ']' || c == '>') 1958 if (c == ':' || c == ']' || c == '>')
1793 abspath = Fdirectory_file_name (abspath); 1959 absname = Fdirectory_file_name (absname);
1794 } 1960 }
1795#else 1961#else
1796 /* Remove final slash, if any (unless path is root). 1962 /* Remove final slash, if any (unless this is the root dir).
1797 stat behaves differently depending! */ 1963 stat behaves differently depending! */
1798 if (XSTRING (abspath)->size > 1 1964 if (XSTRING (absname)->size > 1
1799 && IS_DIRECTORY_SEP (XSTRING (abspath)->data[XSTRING (abspath)->size - 1]) 1965 && IS_DIRECTORY_SEP (XSTRING (absname)->data[XSTRING (absname)->size - 1])
1800 && !IS_DEVICE_SEP (XSTRING (abspath)->data[XSTRING (abspath)->size-2])) 1966 && !IS_DEVICE_SEP (XSTRING (absname)->data[XSTRING (absname)->size-2]))
1801 /* We cannot take shortcuts; they might be wrong for magic file names. */ 1967 /* We cannot take shortcuts; they might be wrong for magic file names. */
1802 abspath = Fdirectory_file_name (abspath); 1968 absname = Fdirectory_file_name (absname);
1803#endif 1969#endif
1804 return abspath; 1970 return absname;
1805} 1971}
1806 1972
1807/* Signal an error if the file ABSNAME already exists. 1973/* Signal an error if the file ABSNAME already exists.
@@ -1904,7 +2070,7 @@ A prefix arg makes KEEP-TIME non-nil.")
1904 copyable by us. */ 2070 copyable by us. */
1905 input_file_statable_p = (fstat (ifd, &st) >= 0); 2071 input_file_statable_p = (fstat (ifd, &st) >= 0);
1906 2072
1907#ifndef DOS_NT 2073#ifndef MSDOS
1908 if (out_st.st_mode != 0 2074 if (out_st.st_mode != 0
1909 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 2075 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
1910 { 2076 {
@@ -2308,10 +2474,10 @@ DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2308 Lisp_Object path, login; 2474 Lisp_Object path, login;
2309{ 2475{
2310 int netresult; 2476 int netresult;
2311 2477
2312 CHECK_STRING (path, 0); 2478 CHECK_STRING (path, 0);
2313 CHECK_STRING (login, 0); 2479 CHECK_STRING (login, 0);
2314 2480
2315 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data); 2481 netresult = netunam (XSTRING (path)->data, XSTRING (login)->data);
2316 2482
2317 if (netresult == -1) 2483 if (netresult == -1)
@@ -2323,7 +2489,7 @@ DEFUN ("sysnetunam", Fsysnetunam, Ssysnetunam, 2, 2, 0,
2323 2489
2324DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p, 2490DEFUN ("file-name-absolute-p", Ffile_name_absolute_p, Sfile_name_absolute_p,
2325 1, 1, 0, 2491 1, 1, 0,
2326 "Return t if file FILENAME specifies an absolute path name.\n\ 2492 "Return t if file FILENAME specifies an absolute file name.\n\
2327On Unix, this is a name starting with a `/' or a `~'.") 2493On Unix, this is a name starting with a `/' or a `~'.")
2328 (filename) 2494 (filename)
2329 Lisp_Object filename; 2495 Lisp_Object filename;
@@ -2340,7 +2506,7 @@ On Unix, this is a name starting with a `/' or a `~'.")
2340 && ptr[1] != '.') 2506 && ptr[1] != '.')
2341#endif /* VMS */ 2507#endif /* VMS */
2342#ifdef DOS_NT 2508#ifdef DOS_NT
2343 || (*ptr != 0 && ptr[1] == ':' && (ptr[2] == '/' || ptr[2] == '\\')) 2509 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
2344#endif 2510#endif
2345 ) 2511 )
2346 return Qt; 2512 return Qt;
@@ -2360,12 +2526,16 @@ check_executable (filename)
2360 struct stat st; 2526 struct stat st;
2361 if (stat (filename, &st) < 0) 2527 if (stat (filename, &st) < 0)
2362 return 0; 2528 return 0;
2529#ifdef WINDOWSNT
2530 return ((st.st_mode & S_IEXEC) != 0);
2531#else
2363 return (S_ISREG (st.st_mode) 2532 return (S_ISREG (st.st_mode)
2364 && len >= 5 2533 && len >= 5
2365 && (stricmp ((suffix = filename + len-4), ".com") == 0 2534 && (stricmp ((suffix = filename + len-4), ".com") == 0
2366 || stricmp (suffix, ".exe") == 0 2535 || stricmp (suffix, ".exe") == 0
2367 || stricmp (suffix, ".bat") == 0) 2536 || stricmp (suffix, ".bat") == 0)
2368 || (st.st_mode & S_IFMT) == S_IFDIR); 2537 || (st.st_mode & S_IFMT) == S_IFDIR);
2538#endif /* not WINDOWSNT */
2369#else /* not DOS_NT */ 2539#else /* not DOS_NT */
2370#ifdef HAVE_EACCESS 2540#ifdef HAVE_EACCESS
2371 return (eaccess (filename, 1) >= 0); 2541 return (eaccess (filename, 1) >= 0);
@@ -2409,20 +2579,20 @@ See also `file-readable-p' and `file-attributes'.")
2409 (filename) 2579 (filename)
2410 Lisp_Object filename; 2580 Lisp_Object filename;
2411{ 2581{
2412 Lisp_Object abspath; 2582 Lisp_Object absname;
2413 Lisp_Object handler; 2583 Lisp_Object handler;
2414 struct stat statbuf; 2584 struct stat statbuf;
2415 2585
2416 CHECK_STRING (filename, 0); 2586 CHECK_STRING (filename, 0);
2417 abspath = Fexpand_file_name (filename, Qnil); 2587 absname = Fexpand_file_name (filename, Qnil);
2418 2588
2419 /* If the file name has special constructs in it, 2589 /* If the file name has special constructs in it,
2420 call the corresponding file handler. */ 2590 call the corresponding file handler. */
2421 handler = Ffind_file_name_handler (abspath, Qfile_exists_p); 2591 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2422 if (!NILP (handler)) 2592 if (!NILP (handler))
2423 return call2 (handler, Qfile_exists_p, abspath); 2593 return call2 (handler, Qfile_exists_p, absname);
2424 2594
2425 return (stat (XSTRING (abspath)->data, &statbuf) >= 0) ? Qt : Qnil; 2595 return (stat (XSTRING (absname)->data, &statbuf) >= 0) ? Qt : Qnil;
2426} 2596}
2427 2597
2428DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, 2598DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2432,19 +2602,19 @@ For a directory, this means you can access files in that directory.")
2432 Lisp_Object filename; 2602 Lisp_Object filename;
2433 2603
2434{ 2604{
2435 Lisp_Object abspath; 2605 Lisp_Object absname;
2436 Lisp_Object handler; 2606 Lisp_Object handler;
2437 2607
2438 CHECK_STRING (filename, 0); 2608 CHECK_STRING (filename, 0);
2439 abspath = Fexpand_file_name (filename, Qnil); 2609 absname = Fexpand_file_name (filename, Qnil);
2440 2610
2441 /* If the file name has special constructs in it, 2611 /* If the file name has special constructs in it,
2442 call the corresponding file handler. */ 2612 call the corresponding file handler. */
2443 handler = Ffind_file_name_handler (abspath, Qfile_executable_p); 2613 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
2444 if (!NILP (handler)) 2614 if (!NILP (handler))
2445 return call2 (handler, Qfile_executable_p, abspath); 2615 return call2 (handler, Qfile_executable_p, absname);
2446 2616
2447 return (check_executable (XSTRING (abspath)->data) ? Qt : Qnil); 2617 return (check_executable (XSTRING (absname)->data) ? Qt : Qnil);
2448} 2618}
2449 2619
2450DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0, 2620DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
@@ -2453,32 +2623,31 @@ See also `file-exists-p' and `file-attributes'.")
2453 (filename) 2623 (filename)
2454 Lisp_Object filename; 2624 Lisp_Object filename;
2455{ 2625{
2456 Lisp_Object abspath; 2626 Lisp_Object absname;
2457 Lisp_Object handler; 2627 Lisp_Object handler;
2458 int desc; 2628 int desc;
2459 2629
2460 CHECK_STRING (filename, 0); 2630 CHECK_STRING (filename, 0);
2461 abspath = Fexpand_file_name (filename, Qnil); 2631 absname = Fexpand_file_name (filename, Qnil);
2462 2632
2463 /* If the file name has special constructs in it, 2633 /* If the file name has special constructs in it,
2464 call the corresponding file handler. */ 2634 call the corresponding file handler. */
2465 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); 2635 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
2466 if (!NILP (handler)) 2636 if (!NILP (handler))
2467 return call2 (handler, Qfile_readable_p, abspath); 2637 return call2 (handler, Qfile_readable_p, absname);
2468 2638
2469#ifdef MSDOS 2639#ifdef DOS_NT
2470 /* Under MS-DOS, open does not work't right, because it doesn't work for 2640 /* Under MS-DOS and Windows, open does not work for directories. */
2471 directories (MS-DOS won't let you open a directory). */ 2641 if (access (XSTRING (absname)->data, 0) == 0)
2472 if (access (XSTRING (abspath)->data, 0) == 0)
2473 return Qt; 2642 return Qt;
2474 return Qnil; 2643 return Qnil;
2475#else /* not MSDOS */ 2644#else /* not DOS_NT */
2476 desc = open (XSTRING (abspath)->data, O_RDONLY); 2645 desc = open (XSTRING (absname)->data, O_RDONLY);
2477 if (desc < 0) 2646 if (desc < 0)
2478 return Qnil; 2647 return Qnil;
2479 close (desc); 2648 close (desc);
2480 return Qt; 2649 return Qt;
2481#endif /* not MSDOS */ 2650#endif /* not DOS_NT */
2482} 2651}
2483 2652
2484/* Having this before file-symlink-p mysteriously caused it to be forgotten 2653/* Having this before file-symlink-p mysteriously caused it to be forgotten
@@ -2488,23 +2657,23 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2488 (filename) 2657 (filename)
2489 Lisp_Object filename; 2658 Lisp_Object filename;
2490{ 2659{
2491 Lisp_Object abspath, dir; 2660 Lisp_Object absname, dir;
2492 Lisp_Object handler; 2661 Lisp_Object handler;
2493 struct stat statbuf; 2662 struct stat statbuf;
2494 2663
2495 CHECK_STRING (filename, 0); 2664 CHECK_STRING (filename, 0);
2496 abspath = Fexpand_file_name (filename, Qnil); 2665 absname = Fexpand_file_name (filename, Qnil);
2497 2666
2498 /* If the file name has special constructs in it, 2667 /* If the file name has special constructs in it,
2499 call the corresponding file handler. */ 2668 call the corresponding file handler. */
2500 handler = Ffind_file_name_handler (abspath, Qfile_writable_p); 2669 handler = Ffind_file_name_handler (absname, Qfile_writable_p);
2501 if (!NILP (handler)) 2670 if (!NILP (handler))
2502 return call2 (handler, Qfile_writable_p, abspath); 2671 return call2 (handler, Qfile_writable_p, absname);
2503 2672
2504 if (stat (XSTRING (abspath)->data, &statbuf) >= 0) 2673 if (stat (XSTRING (absname)->data, &statbuf) >= 0)
2505 return (check_writable (XSTRING (abspath)->data) 2674 return (check_writable (XSTRING (absname)->data)
2506 ? Qt : Qnil); 2675 ? Qt : Qnil);
2507 dir = Ffile_name_directory (abspath); 2676 dir = Ffile_name_directory (absname);
2508#ifdef VMS 2677#ifdef VMS
2509 if (!NILP (dir)) 2678 if (!NILP (dir))
2510 dir = Fdirectory_file_name (dir); 2679 dir = Fdirectory_file_name (dir);
@@ -2571,19 +2740,19 @@ if the directory so specified exists and really is a directory.")
2571 (filename) 2740 (filename)
2572 Lisp_Object filename; 2741 Lisp_Object filename;
2573{ 2742{
2574 register Lisp_Object abspath; 2743 register Lisp_Object absname;
2575 struct stat st; 2744 struct stat st;
2576 Lisp_Object handler; 2745 Lisp_Object handler;
2577 2746
2578 abspath = expand_and_dir_to_file (filename, current_buffer->directory); 2747 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2579 2748
2580 /* If the file name has special constructs in it, 2749 /* If the file name has special constructs in it,
2581 call the corresponding file handler. */ 2750 call the corresponding file handler. */
2582 handler = Ffind_file_name_handler (abspath, Qfile_directory_p); 2751 handler = Ffind_file_name_handler (absname, Qfile_directory_p);
2583 if (!NILP (handler)) 2752 if (!NILP (handler))
2584 return call2 (handler, Qfile_directory_p, abspath); 2753 return call2 (handler, Qfile_directory_p, absname);
2585 2754
2586 if (stat (XSTRING (abspath)->data, &st) < 0) 2755 if (stat (XSTRING (absname)->data, &st) < 0)
2587 return Qnil; 2756 return Qnil;
2588 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil; 2757 return (st.st_mode & S_IFMT) == S_IFDIR ? Qt : Qnil;
2589} 2758}
@@ -2627,19 +2796,19 @@ This is the sort of file that holds an ordinary stream of data bytes.")
2627 (filename) 2796 (filename)
2628 Lisp_Object filename; 2797 Lisp_Object filename;
2629{ 2798{
2630 register Lisp_Object abspath; 2799 register Lisp_Object absname;
2631 struct stat st; 2800 struct stat st;
2632 Lisp_Object handler; 2801 Lisp_Object handler;
2633 2802
2634 abspath = expand_and_dir_to_file (filename, current_buffer->directory); 2803 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2635 2804
2636 /* If the file name has special constructs in it, 2805 /* If the file name has special constructs in it,
2637 call the corresponding file handler. */ 2806 call the corresponding file handler. */
2638 handler = Ffind_file_name_handler (abspath, Qfile_regular_p); 2807 handler = Ffind_file_name_handler (absname, Qfile_regular_p);
2639 if (!NILP (handler)) 2808 if (!NILP (handler))
2640 return call2 (handler, Qfile_regular_p, abspath); 2809 return call2 (handler, Qfile_regular_p, absname);
2641 2810
2642 if (stat (XSTRING (abspath)->data, &st) < 0) 2811 if (stat (XSTRING (absname)->data, &st) < 0)
2643 return Qnil; 2812 return Qnil;
2644 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil; 2813 return (st.st_mode & S_IFMT) == S_IFREG ? Qt : Qnil;
2645} 2814}
@@ -2649,24 +2818,24 @@ DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2649 (filename) 2818 (filename)
2650 Lisp_Object filename; 2819 Lisp_Object filename;
2651{ 2820{
2652 Lisp_Object abspath; 2821 Lisp_Object absname;
2653 struct stat st; 2822 struct stat st;
2654 Lisp_Object handler; 2823 Lisp_Object handler;
2655 2824
2656 abspath = expand_and_dir_to_file (filename, current_buffer->directory); 2825 absname = expand_and_dir_to_file (filename, current_buffer->directory);
2657 2826
2658 /* If the file name has special constructs in it, 2827 /* If the file name has special constructs in it,
2659 call the corresponding file handler. */ 2828 call the corresponding file handler. */
2660 handler = Ffind_file_name_handler (abspath, Qfile_modes); 2829 handler = Ffind_file_name_handler (absname, Qfile_modes);
2661 if (!NILP (handler)) 2830 if (!NILP (handler))
2662 return call2 (handler, Qfile_modes, abspath); 2831 return call2 (handler, Qfile_modes, absname);
2663 2832
2664 if (stat (XSTRING (abspath)->data, &st) < 0) 2833 if (stat (XSTRING (absname)->data, &st) < 0)
2665 return Qnil; 2834 return Qnil;
2666#ifdef DOS_NT 2835#ifdef MSDOS
2667 if (check_executable (XSTRING (abspath)->data)) 2836 if (check_executable (XSTRING (absname)->data))
2668 st.st_mode |= S_IEXEC; 2837 st.st_mode |= S_IEXEC;
2669#endif /* DOS_NT */ 2838#endif /* MSDOS */
2670 2839
2671 return make_number (st.st_mode & 07777); 2840 return make_number (st.st_mode & 07777);
2672} 2841}
@@ -2677,20 +2846,20 @@ Only the 12 low bits of MODE are used.")
2677 (filename, mode) 2846 (filename, mode)
2678 Lisp_Object filename, mode; 2847 Lisp_Object filename, mode;
2679{ 2848{
2680 Lisp_Object abspath; 2849 Lisp_Object absname;
2681 Lisp_Object handler; 2850 Lisp_Object handler;
2682 2851
2683 abspath = Fexpand_file_name (filename, current_buffer->directory); 2852 absname = Fexpand_file_name (filename, current_buffer->directory);
2684 CHECK_NUMBER (mode, 1); 2853 CHECK_NUMBER (mode, 1);
2685 2854
2686 /* If the file name has special constructs in it, 2855 /* If the file name has special constructs in it,
2687 call the corresponding file handler. */ 2856 call the corresponding file handler. */
2688 handler = Ffind_file_name_handler (abspath, Qset_file_modes); 2857 handler = Ffind_file_name_handler (absname, Qset_file_modes);
2689 if (!NILP (handler)) 2858 if (!NILP (handler))
2690 return call3 (handler, Qset_file_modes, abspath, mode); 2859 return call3 (handler, Qset_file_modes, absname, mode);
2691 2860
2692 if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0) 2861 if (chmod (XSTRING (absname)->data, XINT (mode)) < 0)
2693 report_file_error ("Doing chmod", Fcons (abspath, Qnil)); 2862 report_file_error ("Doing chmod", Fcons (absname, Qnil));
2694 2863
2695 return Qnil; 2864 return Qnil;
2696} 2865}
@@ -2703,7 +2872,7 @@ This setting is inherited by subprocesses.")
2703 Lisp_Object mode; 2872 Lisp_Object mode;
2704{ 2873{
2705 CHECK_NUMBER (mode, 0); 2874 CHECK_NUMBER (mode, 0);
2706 2875
2707 umask ((~ XINT (mode)) & 0777); 2876 umask ((~ XINT (mode)) & 0777);
2708 2877
2709 return Qnil; 2878 return Qnil;
@@ -2743,7 +2912,7 @@ otherwise, if FILE2 does not exist, the answer is t.")
2743 (file1, file2) 2912 (file1, file2)
2744 Lisp_Object file1, file2; 2913 Lisp_Object file1, file2;
2745{ 2914{
2746 Lisp_Object abspath1, abspath2; 2915 Lisp_Object absname1, absname2;
2747 struct stat st; 2916 struct stat st;
2748 int mtime1; 2917 int mtime1;
2749 Lisp_Object handler; 2918 Lisp_Object handler;
@@ -2752,26 +2921,26 @@ otherwise, if FILE2 does not exist, the answer is t.")
2752 CHECK_STRING (file1, 0); 2921 CHECK_STRING (file1, 0);
2753 CHECK_STRING (file2, 0); 2922 CHECK_STRING (file2, 0);
2754 2923
2755 abspath1 = Qnil; 2924 absname1 = Qnil;
2756 GCPRO2 (abspath1, file2); 2925 GCPRO2 (absname1, file2);
2757 abspath1 = expand_and_dir_to_file (file1, current_buffer->directory); 2926 absname1 = expand_and_dir_to_file (file1, current_buffer->directory);
2758 abspath2 = expand_and_dir_to_file (file2, current_buffer->directory); 2927 absname2 = expand_and_dir_to_file (file2, current_buffer->directory);
2759 UNGCPRO; 2928 UNGCPRO;
2760 2929
2761 /* If the file name has special constructs in it, 2930 /* If the file name has special constructs in it,
2762 call the corresponding file handler. */ 2931 call the corresponding file handler. */
2763 handler = Ffind_file_name_handler (abspath1, Qfile_newer_than_file_p); 2932 handler = Ffind_file_name_handler (absname1, Qfile_newer_than_file_p);
2764 if (NILP (handler)) 2933 if (NILP (handler))
2765 handler = Ffind_file_name_handler (abspath2, Qfile_newer_than_file_p); 2934 handler = Ffind_file_name_handler (absname2, Qfile_newer_than_file_p);
2766 if (!NILP (handler)) 2935 if (!NILP (handler))
2767 return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2); 2936 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
2768 2937
2769 if (stat (XSTRING (abspath1)->data, &st) < 0) 2938 if (stat (XSTRING (absname1)->data, &st) < 0)
2770 return Qnil; 2939 return Qnil;
2771 2940
2772 mtime1 = st.st_mtime; 2941 mtime1 = st.st_mtime;
2773 2942
2774 if (stat (XSTRING (abspath2)->data, &st) < 0) 2943 if (stat (XSTRING (absname2)->data, &st) < 0)
2775 return Qt; 2944 return Qt;
2776 2945
2777 return (mtime1 > st.st_mtime) ? Qt : Qnil; 2946 return (mtime1 > st.st_mtime) ? Qt : Qnil;
@@ -3148,7 +3317,7 @@ and (2) it puts less data in the undo list.")
3148 /* Decode file format */ 3317 /* Decode file format */
3149 if (inserted > 0) 3318 if (inserted > 0)
3150 { 3319 {
3151 insval = call3 (Qformat_decode, 3320 insval = call3 (Qformat_decode,
3152 Qnil, make_number (inserted), visit); 3321 Qnil, make_number (inserted), visit);
3153 CHECK_NUMBER (insval, 0); 3322 CHECK_NUMBER (insval, 0);
3154 inserted = XFASTINT (insval); 3323 inserted = XFASTINT (insval);
@@ -3156,7 +3325,7 @@ and (2) it puts less data in the undo list.")
3156 3325
3157 if (inserted > 0 && NILP (visit) && total > 0) 3326 if (inserted > 0 && NILP (visit) && total > 0)
3158 signal_after_change (point, 0, inserted); 3327 signal_after_change (point, 0, inserted);
3159 3328
3160 if (inserted > 0) 3329 if (inserted > 0)
3161 { 3330 {
3162 p = Vafter_insert_file_functions; 3331 p = Vafter_insert_file_functions;
@@ -3186,7 +3355,7 @@ static Lisp_Object build_annotations ();
3186/* If build_annotations switched buffers, switch back to BUF. 3355/* If build_annotations switched buffers, switch back to BUF.
3187 Kill the temporary buffer that was selected in the meantime. */ 3356 Kill the temporary buffer that was selected in the meantime. */
3188 3357
3189static Lisp_Object 3358static Lisp_Object
3190build_annotations_unwind (buf) 3359build_annotations_unwind (buf)
3191 Lisp_Object buf; 3360 Lisp_Object buf;
3192{ 3361{
@@ -3273,7 +3442,7 @@ to the file, instead of any buffer contents, and END is ignored.")
3273 handler = Ffind_file_name_handler (filename, Qwrite_region); 3442 handler = Ffind_file_name_handler (filename, Qwrite_region);
3274 /* If FILENAME has no handler, see if VISIT has one. */ 3443 /* If FILENAME has no handler, see if VISIT has one. */
3275 if (NILP (handler) && STRINGP (visit)) 3444 if (NILP (handler) && STRINGP (visit))
3276 handler = Ffind_file_name_handler (visit, Qwrite_region); 3445 handler = Ffind_file_name_handler (visit, Qwrite_region);
3277 3446
3278 if (!NILP (handler)) 3447 if (!NILP (handler))
3279 { 3448 {
@@ -3371,8 +3540,8 @@ to the file, instead of any buffer contents, and END is ignored.")
3371 } 3540 }
3372#else /* not VMS */ 3541#else /* not VMS */
3373#ifdef DOS_NT 3542#ifdef DOS_NT
3374 desc = open (fn, 3543 desc = open (fn,
3375 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type, 3544 O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type,
3376 S_IREAD | S_IWRITE); 3545 S_IREAD | S_IWRITE);
3377#else /* not DOS_NT */ 3546#else /* not DOS_NT */
3378 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666); 3547 desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
@@ -3476,7 +3645,7 @@ to the file, instead of any buffer contents, and END is ignored.")
3476 } 3645 }
3477#endif 3646#endif
3478 3647
3479 /* Spurious "file has changed on disk" warnings have been 3648 /* Spurious "file has changed on disk" warnings have been
3480 observed on Suns as well. 3649 observed on Suns as well.
3481 It seems that `close' can change the modtime, under nfs. 3650 It seems that `close' can change the modtime, under nfs.
3482 3651
@@ -3882,7 +4051,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
3882 Lisp_Object listfile; 4051 Lisp_Object listfile;
3883 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil); 4052 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
3884#ifdef DOS_NT 4053#ifdef DOS_NT
3885 listdesc = open (XSTRING (listfile)->data, 4054 listdesc = open (XSTRING (listfile)->data,
3886 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT, 4055 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
3887 S_IREAD | S_IWRITE); 4056 S_IREAD | S_IWRITE);
3888#else /* not DOS_NT */ 4057#else /* not DOS_NT */
@@ -3891,7 +4060,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
3891 } 4060 }
3892 else 4061 else
3893 listdesc = -1; 4062 listdesc = -1;
3894 4063
3895 /* Arrange to close that file whether or not we get an error. 4064 /* Arrange to close that file whether or not we get an error.
3896 Also reset auto_saving to 0. */ 4065 Also reset auto_saving to 0. */
3897 record_unwind_protect (do_auto_save_unwind, make_number (listdesc)); 4066 record_unwind_protect (do_auto_save_unwind, make_number (listdesc));
@@ -3908,7 +4077,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.")
3908 { 4077 {
3909 buf = XCONS (XCONS (tail)->car)->cdr; 4078 buf = XCONS (XCONS (tail)->car)->cdr;
3910 b = XBUFFER (buf); 4079 b = XBUFFER (buf);
3911 4080
3912 /* Record all the buffers that have auto save mode 4081 /* Record all the buffers that have auto save mode
3913 in the special file that lists them. For each of these buffers, 4082 in the special file that lists them. For each of these buffers,
3914 Record visited name (if any) and auto save name. */ 4083 Record visited name (if any) and auto save name. */
@@ -4179,6 +4348,10 @@ DIR defaults to current buffer's directory default.")
4179 4348
4180 /* If dir starts with user's homedir, change that to ~. */ 4349 /* If dir starts with user's homedir, change that to ~. */
4181 homedir = (char *) egetenv ("HOME"); 4350 homedir = (char *) egetenv ("HOME");
4351#ifdef DOS_NT
4352 homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
4353 CORRECT_DIR_SEPS (homedir);
4354#endif
4182 if (homedir != 0 4355 if (homedir != 0
4183 && STRINGP (dir) 4356 && STRINGP (dir)
4184 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir)) 4357 && !strncmp (homedir, XSTRING (dir)->data, strlen (homedir))
@@ -4372,7 +4545,7 @@ syms_of_fileio ()
4372 4545
4373 Qfile_error = intern ("file-error"); 4546 Qfile_error = intern ("file-error");
4374 staticpro (&Qfile_error); 4547 staticpro (&Qfile_error);
4375 Qfile_already_exists = intern("file-already-exists"); 4548 Qfile_already_exists = intern ("file-already-exists");
4376 staticpro (&Qfile_already_exists); 4549 staticpro (&Qfile_already_exists);
4377 4550
4378#ifdef DOS_NT 4551#ifdef DOS_NT
@@ -4415,6 +4588,14 @@ same format as a regular save would use.");
4415nil means use format `var'. This variable is meaningful only on VMS."); 4588nil means use format `var'. This variable is meaningful only on VMS.");
4416 vms_stmlf_recfm = 0; 4589 vms_stmlf_recfm = 0;
4417 4590
4591 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
4592 "Directory separator character for built-in functions that return file names.\n\
4593The value should be either ?/ or ?\\ (any other value is treated as ?\\).\n\
4594This variable affects the built-in functions only on Windows,\n\
4595on other platforms, it is initialized so that Lisp code can find out\n\
4596what the normal separator is.");
4597 Vdirectory_sep_char = '/';
4598
4418 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist, 4599 DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
4419 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\ 4600 "*Alist of elements (REGEXP . HANDLER) for file names handled specially.\n\
4420If a file name matches REGEXP, then all I/O on that file is done by calling\n\ 4601If a file name matches REGEXP, then all I/O on that file is done by calling\n\