aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1997-09-03 00:43:20 +0000
committerGeoff Voelker1997-09-03 00:43:20 +0000
commit76b3903d852a0c33964da1e73a7d8e152ef8189a (patch)
treef637f4ec058446fb60a54fe4f3574630d28e2215 /src
parent43640c4dfeec138b7c789f998062e94e7d61303b (diff)
downloademacs-76b3903d852a0c33964da1e73a7d8e152ef8189a.tar.gz
emacs-76b3903d852a0c33964da1e73a7d8e152ef8189a.zip
Include stddef.h.
(getwd): Delete macro. (startup_dir): New variable. (getwd): Return directory in which Emacs started. (init_user_info): Set SHELL environment variable if not set. (parse_root, get_long_basename, w32_get_long_filename): New functions. (init_environment): Look for CMDPROXY. Make sure that PATH and COMSPEC are capitalized in the environment. Record startup directory. (get_emacs_configuration, sys_rename): Use OS_WIN95. (map_w32_filename): Calculate returned string correctly. (sys_fopen): Use _fdopen. (sys_link): Support NTFS links. (sys_rename): Use a long file name for temporary name. (sys_pipe): Make pipes binary and non-inheritable. (sys_read, sys_write): Spoof text mode translation for pipes and sockets. (hashval): Simplify. (generate_inode_val): Use long file name version of file. (stat): Optimize by using active readdir info. Set fake_inode to 0 for directories. Set fake_inode to xor of file indexes for files. Don't use generate_inode_val to set inode value. (volume_info_data): Renamed from volume_info. (volume_info, fixed_drives, volume_cache): New variables. (DRIVE_INDEX, VOLINFO_STILL_VALID): New macros. (lookup_volume_info, add_volume_info, GetCachedVolumeInformation): New functions. (get_volume_info): Use volume_info_data. Use GetCachedVolumeInformation. (init_ntproc): No longer restrict to one DOS subprocess. Use CRT _open and _fdopen. Cache fixed drive information.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c923
1 files changed, 690 insertions, 233 deletions
diff --git a/src/w32.c b/src/w32.c
index b0646c91e96..ddac8be44dd 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA.
22*/ 22*/
23 23
24 24
25#include <stddef.h> /* for offsetof */
25#include <stdlib.h> 26#include <stdlib.h>
26#include <stdio.h> 27#include <stdio.h>
27#include <io.h> 28#include <io.h>
@@ -54,9 +55,7 @@ Boston, MA 02111-1307, USA.
54#undef read 55#undef read
55#undef write 56#undef write
56 57
57#define getwd _getwd
58#include "lisp.h" 58#include "lisp.h"
59#undef getwd
60 59
61#include <pwd.h> 60#include <pwd.h>
62 61
@@ -79,14 +78,28 @@ Boston, MA 02111-1307, USA.
79#include "w32.h" 78#include "w32.h"
80#include "ndir.h" 79#include "ndir.h"
81#include "w32heap.h" 80#include "w32heap.h"
81
82extern Lisp_Object Vw32_downcase_file_names;
83extern Lisp_Object Vw32_generate_fake_inodes;
84extern Lisp_Object Vw32_get_true_file_attributes;
85
86static char startup_dir[MAXPATHLEN];
82 87
83/* Get the current working directory. */ 88/* Get the current working directory. */
84char * 89char *
85getwd (char *dir) 90getwd (char *dir)
86{ 91{
92#if 0
87 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0) 93 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
88 return dir; 94 return dir;
89 return NULL; 95 return NULL;
96#else
97 /* Emacs doesn't actually change directory itself, and we want to
98 force our real wd to be where emacs.exe is to avoid unnecessary
99 conflicts when trying to rename or delete directories. */
100 strcpy (dir, startup_dir);
101 return dir;
102#endif
90} 103}
91 104
92#ifndef HAVE_SOCKETS 105#ifndef HAVE_SOCKETS
@@ -114,105 +127,6 @@ getloadavg (double loadavg[], int nelem)
114 return i; 127 return i;
115} 128}
116 129
117/* Emulate the Unix directory procedures opendir, closedir,
118 and readdir. We can't use the procedures supplied in sysdep.c,
119 so we provide them here. */
120
121struct direct dir_static; /* simulated directory contents */
122static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
123static int dir_is_fat;
124static char dir_pathname[MAXPATHLEN+1];
125
126extern Lisp_Object Vw32_downcase_file_names;
127
128DIR *
129opendir (char *filename)
130{
131 DIR *dirp;
132
133 /* Opening is done by FindFirstFile. However, a read is inherent to
134 this operation, so we defer the open until read time. */
135
136 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
137 return NULL;
138 if (dir_find_handle != INVALID_HANDLE_VALUE)
139 return NULL;
140
141 dirp->dd_fd = 0;
142 dirp->dd_loc = 0;
143 dirp->dd_size = 0;
144
145 strncpy (dir_pathname, filename, MAXPATHLEN);
146 dir_pathname[MAXPATHLEN] = '\0';
147 dir_is_fat = is_fat_volume (filename, NULL);
148
149 return dirp;
150}
151
152void
153closedir (DIR *dirp)
154{
155 /* If we have a find-handle open, close it. */
156 if (dir_find_handle != INVALID_HANDLE_VALUE)
157 {
158 FindClose (dir_find_handle);
159 dir_find_handle = INVALID_HANDLE_VALUE;
160 }
161 xfree ((char *) dirp);
162}
163
164struct direct *
165readdir (DIR *dirp)
166{
167 WIN32_FIND_DATA find_data;
168
169 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
170 if (dir_find_handle == INVALID_HANDLE_VALUE)
171 {
172 char filename[MAXNAMLEN + 3];
173 int ln;
174
175 strcpy (filename, dir_pathname);
176 ln = strlen (filename) - 1;
177 if (!IS_DIRECTORY_SEP (filename[ln]))
178 strcat (filename, "\\");
179 strcat (filename, "*");
180
181 dir_find_handle = FindFirstFile (filename, &find_data);
182
183 if (dir_find_handle == INVALID_HANDLE_VALUE)
184 return NULL;
185 }
186 else
187 {
188 if (!FindNextFile (dir_find_handle, &find_data))
189 return NULL;
190 }
191
192 /* Emacs never uses this value, so don't bother making it match
193 value returned by stat(). */
194 dir_static.d_ino = 1;
195
196 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
197 dir_static.d_namlen - dir_static.d_namlen % 4;
198
199 dir_static.d_namlen = strlen (find_data.cFileName);
200 strcpy (dir_static.d_name, find_data.cFileName);
201 if (dir_is_fat)
202 _strlwr (dir_static.d_name);
203 else if (!NILP (Vw32_downcase_file_names))
204 {
205 register char *p;
206 for (p = dir_static.d_name; *p; p++)
207 if (*p >= 'a' && *p <= 'z')
208 break;
209 if (!*p)
210 _strlwr (dir_static.d_name);
211 }
212
213 return &dir_static;
214}
215
216/* Emulate getpwuid, getpwnam and others. */ 130/* Emulate getpwuid, getpwnam and others. */
217 131
218#define PASSWD_FIELD_SIZE 256 132#define PASSWD_FIELD_SIZE 256
@@ -367,7 +281,7 @@ init_user_info ()
367 if (getenv ("HOME") == NULL) 281 if (getenv ("HOME") == NULL)
368 putenv ("HOME=c:/"); 282 putenv ("HOME=c:/");
369 if (getenv ("SHELL") == NULL) 283 if (getenv ("SHELL") == NULL)
370 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); 284 putenv (os_subtype == OS_WIN95 ? "SHELL=command" : "SHELL=cmd");
371 285
372 /* Set dir and shell from environment variables. */ 286 /* Set dir and shell from environment variables. */
373 strcpy (the_passwd.pw_dir, getenv ("HOME")); 287 strcpy (the_passwd.pw_dir, getenv ("HOME"));
@@ -390,6 +304,7 @@ srandom (int seed)
390 srand (seed); 304 srand (seed);
391} 305}
392 306
307
393/* Normalize filename by converting all path separators to 308/* Normalize filename by converting all path separators to
394 the specified separator. Also conditionally convert upper 309 the specified separator. Also conditionally convert upper
395 case path name components to lower case. */ 310 case path name components to lower case. */
@@ -496,6 +411,118 @@ crlf_to_lf (n, buf)
496 return np - startp; 411 return np - startp;
497} 412}
498 413
414/* Parse the root part of file name, if present. Return length and
415 optionally store pointer to char after root. */
416static int
417parse_root (char * name, char ** pPath)
418{
419 char * start = name;
420
421 if (name == NULL)
422 return 0;
423
424 /* find the root name of the volume if given */
425 if (isalpha (name[0]) && name[1] == ':')
426 {
427 /* skip past drive specifier */
428 name += 2;
429 if (IS_DIRECTORY_SEP (name[0]))
430 name++;
431 }
432 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
433 {
434 int slashes = 2;
435 name += 2;
436 do
437 {
438 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
439 break;
440 name++;
441 }
442 while ( *name );
443 if (IS_DIRECTORY_SEP (name[0]))
444 name++;
445 }
446
447 if (pPath)
448 *pPath = name;
449
450 return name - start;
451}
452
453/* Get long base name for name; name is assumed to be absolute. */
454static int
455get_long_basename (char * name, char * buf, int size)
456{
457 WIN32_FIND_DATA find_data;
458 HANDLE dir_handle;
459 int len = 0;
460
461 dir_handle = FindFirstFile (name, &find_data);
462 if (dir_handle != INVALID_HANDLE_VALUE)
463 {
464 if ((len = strlen (find_data.cFileName)) < size)
465 memcpy (buf, find_data.cFileName, len + 1);
466 else
467 len = 0;
468 FindClose (dir_handle);
469 }
470 return len;
471}
472
473/* Get long name for file, if possible (assumed to be absolute). */
474BOOL
475w32_get_long_filename (char * name, char * buf, int size)
476{
477 char * o = buf;
478 char * p;
479 char * q;
480 char full[ MAX_PATH ];
481 int len;
482
483 len = strlen (name);
484 if (len >= MAX_PATH)
485 return FALSE;
486
487 /* Use local copy for destructive modification. */
488 memcpy (full, name, len+1);
489 unixtodos_filename (full);
490
491 /* Copy root part verbatim. */
492 len = parse_root (full, &p);
493 memcpy (o, full, len);
494 o += len;
495 size -= len;
496
497 do
498 {
499 q = p;
500 p = strchr (q, '\\');
501 if (p) *p = '\0';
502 len = get_long_basename (full, o, size);
503 if (len > 0)
504 {
505 o += len;
506 size -= len;
507 if (p != NULL)
508 {
509 *p++ = '\\';
510 if (size < 2)
511 return FALSE;
512 *o++ = '\\';
513 size--;
514 *o = '\0';
515 }
516 }
517 else
518 return FALSE;
519 }
520 while (p != NULL && *p);
521
522 return TRUE;
523}
524
525
499/* Routines that are no-ops on NT but are defined to get Emacs to compile. */ 526/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
500 527
501int 528int
@@ -569,9 +596,9 @@ w32_get_resource (key, lpdwtype)
569 { 596 {
570 lpvalue = NULL; 597 lpvalue = NULL;
571 598
572 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS && 599 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
573 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL && 600 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
574 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS) 601 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
575 { 602 {
576 return (lpvalue); 603 return (lpvalue);
577 } 604 }
@@ -603,18 +630,21 @@ init_environment ()
603 "emacs_dir", 630 "emacs_dir",
604 "EMACSLOADPATH", 631 "EMACSLOADPATH",
605 "SHELL", 632 "SHELL",
633 "CMDPROXY",
606 "EMACSDATA", 634 "EMACSDATA",
607 "EMACSPATH", 635 "EMACSPATH",
608 "EMACSLOCKDIR", 636 "EMACSLOCKDIR",
609 "INFOPATH", 637 /* We no longer set INFOPATH because Info-default-directory-list
638 is then ignored. We use a hook in winnt.el instead. */
639 /* "INFOPATH", */
610 "EMACSDOC", 640 "EMACSDOC",
611 "TERM", 641 "TERM",
612 }; 642 };
613 643
614 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) 644 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
615 { 645 {
616 if (!getenv (env_vars[i]) && 646 if (!getenv (env_vars[i])
617 (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL) 647 && (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL)
618 { 648 {
619 if (dwType == REG_EXPAND_SZ) 649 if (dwType == REG_EXPAND_SZ)
620 { 650 {
@@ -640,6 +670,45 @@ init_environment ()
640 /* Rebuild system configuration to reflect invoking system. */ 670 /* Rebuild system configuration to reflect invoking system. */
641 Vsystem_configuration = build_string (EMACS_CONFIGURATION); 671 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
642 672
673 /* Another special case: on NT, the PATH variable is actually named
674 "Path" although cmd.exe (perhaps NT itself) arranges for
675 environment variable lookup and setting to be case insensitive.
676 However, Emacs assumes a fully case sensitive environment, so we
677 need to change "Path" to "PATH" to match the expectations of
678 various elisp packages. We do this by the sneaky method of
679 modifying the string in the C runtime environ entry.
680
681 The same applies to COMSPEC. */
682 {
683 char ** envp;
684
685 for (envp = environ; *envp; envp++)
686 if (_strnicmp (*envp, "PATH=", 5) == 0)
687 memcpy (*envp, "PATH=", 5);
688 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
689 memcpy (*envp, "COMSPEC=", 8);
690 }
691
692 /* Remember the initial working directory for getwd, then make the
693 real wd be the location of emacs.exe to avoid conflicts when
694 renaming or deleting directories. (We also don't call chdir when
695 running subprocesses for the same reason.) */
696 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
697 abort ();
698
699 {
700 char *p;
701 char modname[MAX_PATH];
702
703 if (!GetModuleFileName (NULL, modname, MAX_PATH))
704 abort ();
705 if ((p = strrchr (modname, '\\')) == NULL)
706 abort ();
707 *p = 0;
708
709 SetCurrentDirectory (modname);
710 }
711
643 init_user_info (); 712 init_user_info ();
644} 713}
645 714
@@ -695,7 +764,7 @@ get_emacs_configuration (void)
695 /* Let oem be "*" until we figure out how to decode the OEM field. */ 764 /* Let oem be "*" until we figure out how to decode the OEM field. */
696 oem = "*"; 765 oem = "*";
697 766
698 os = (GetVersion () & 0x80000000) ? "windows95" : "nt"; 767 os = (GetVersion () & OS_WIN95) ? "windows95" : "nt";
699 768
700 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os, 769 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
701 get_w32_major_version (), get_w32_minor_version ()); 770 get_w32_major_version (), get_w32_minor_version ());
@@ -743,23 +812,159 @@ sys_sleep (int seconds)
743 Sleep (seconds * 1000); 812 Sleep (seconds * 1000);
744} 813}
745 814
746/* Internal MSVC data and functions for low-level descriptor munging */ 815/* Internal MSVC functions for low-level descriptor munging */
747#if (_MSC_VER == 900)
748extern char _osfile[];
749#endif
750extern int __cdecl _set_osfhnd (int fd, long h); 816extern int __cdecl _set_osfhnd (int fd, long h);
751extern int __cdecl _free_osfhnd (int fd); 817extern int __cdecl _free_osfhnd (int fd);
752 818
753/* parallel array of private info on file handles */ 819/* parallel array of private info on file handles */
754filedesc fd_info [ MAXDESC ]; 820filedesc fd_info [ MAXDESC ];
755 821
756static struct { 822typedef struct volume_info_data {
823 struct volume_info_data * next;
824
825 /* time when info was obtained */
826 DWORD timestamp;
827
828 /* actual volume info */
829 char * root_dir;
757 DWORD serialnum; 830 DWORD serialnum;
758 DWORD maxcomp; 831 DWORD maxcomp;
759 DWORD flags; 832 DWORD flags;
760 char name[32]; 833 char * name;
761 char type[32]; 834 char * type;
762} volume_info; 835} volume_info_data;
836
837/* Global referenced by various functions. */
838static volume_info_data volume_info;
839
840/* Vector to indicate which drives are local and fixed (for which cached
841 data never expires). */
842static BOOL fixed_drives[26];
843
844/* Consider cached volume information to be stale if older than 10s,
845 at least for non-local drives. Info for fixed drives is never stale. */
846#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
847#define VOLINFO_STILL_VALID( root_dir, info ) \
848 ( ( isalpha (root_dir[0]) && \
849 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
850 || GetTickCount () - info->timestamp < 10000 )
851
852/* Cache support functions. */
853
854/* Simple linked list with linear search is sufficient. */
855static volume_info_data *volume_cache = NULL;
856
857static volume_info_data *
858lookup_volume_info (char * root_dir)
859{
860 volume_info_data * info;
861
862 for (info = volume_cache; info; info = info->next)
863 if (stricmp (info->root_dir, root_dir) == 0)
864 break;
865 return info;
866}
867
868static void
869add_volume_info (char * root_dir, volume_info_data * info)
870{
871 info->root_dir = strdup (root_dir);
872 info->next = volume_cache;
873 volume_cache = info;
874}
875
876
877/* Wrapper for GetVolumeInformation, which uses caching to avoid
878 performance penalty (~2ms on 486 for local drives, 7.5ms for local
879 cdrom drive, ~5-10ms or more for remote drives on LAN). */
880volume_info_data *
881GetCachedVolumeInformation (char * root_dir)
882{
883 volume_info_data * info;
884 char default_root[ MAX_PATH ];
885
886 /* NULL for root_dir means use root from current directory. */
887 if (root_dir == NULL)
888 {
889 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
890 return NULL;
891 parse_root (default_root, &root_dir);
892 *root_dir = 0;
893 root_dir = default_root;
894 }
895
896 /* Local fixed drives can be cached permanently. Removable drives
897 cannot be cached permanently, since the volume name and serial
898 number (if nothing else) can change. Remote drives should be
899 treated as if they are removable, since there is no sure way to
900 tell whether they are or not. Also, the UNC association of drive
901 letters mapped to remote volumes can be changed at any time (even
902 by other processes) without notice.
903
904 As a compromise, so we can benefit from caching info for remote
905 volumes, we use a simple expiry mechanism to invalidate cache
906 entries that are more than ten seconds old. */
907
908#if 0
909 /* No point doing this, because WNetGetConnection is even slower than
910 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
911 GetDriveType is about the only call of this type which does not
912 involve network access, and so is extremely quick). */
913
914 /* Map drive letter to UNC if remote. */
915 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
916 {
917 char remote_name[ 256 ];
918 char drive[3] = { root_dir[0], ':' };
919
920 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
921 == NO_ERROR)
922 /* do something */ ;
923 }
924#endif
925
926 info = lookup_volume_info (root_dir);
927
928 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
929 {
930 char name[ 256 ];
931 DWORD serialnum;
932 DWORD maxcomp;
933 DWORD flags;
934 char type[ 256 ];
935
936 /* Info is not cached, or is stale. */
937 if (!GetVolumeInformation (root_dir,
938 name, sizeof (name),
939 &serialnum,
940 &maxcomp,
941 &flags,
942 type, sizeof (type)))
943 return NULL;
944
945 /* Cache the volume information for future use, overwriting existing
946 entry if present. */
947 if (info == NULL)
948 {
949 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
950 add_volume_info (root_dir, info);
951 }
952 else
953 {
954 free (info->name);
955 free (info->type);
956 }
957
958 info->name = strdup (name);
959 info->serialnum = serialnum;
960 info->maxcomp = maxcomp;
961 info->flags = flags;
962 info->type = strdup (type);
963 info->timestamp = GetTickCount ();
964 }
965
966 return info;
967}
763 968
764/* Get information on the volume where name is held; set path pointer to 969/* Get information on the volume where name is held; set path pointer to
765 start of pathname in name (past UNC header\volume header if present). */ 970 start of pathname in name (past UNC header\volume header if present). */
@@ -768,6 +973,7 @@ get_volume_info (const char * name, const char ** pPath)
768{ 973{
769 char temp[MAX_PATH]; 974 char temp[MAX_PATH];
770 char *rootname = NULL; /* default to current volume */ 975 char *rootname = NULL; /* default to current volume */
976 volume_info_data * info;
771 977
772 if (name == NULL) 978 if (name == NULL)
773 return FALSE; 979 return FALSE;
@@ -801,13 +1007,11 @@ get_volume_info (const char * name, const char ** pPath)
801 if (pPath) 1007 if (pPath)
802 *pPath = name; 1008 *pPath = name;
803 1009
804 if (GetVolumeInformation (rootname, 1010 info = GetCachedVolumeInformation (rootname);
805 volume_info.name, 32, 1011 if (info != NULL)
806 &volume_info.serialnum,
807 &volume_info.maxcomp,
808 &volume_info.flags,
809 volume_info.type, 32))
810 { 1012 {
1013 /* Set global referenced by other functions. */
1014 volume_info = *info;
811 return TRUE; 1015 return TRUE;
812 } 1016 }
813 return FALSE; 1017 return FALSE;
@@ -831,6 +1035,7 @@ map_w32_filename (const char * name, const char ** pPath)
831 char * str = shortname; 1035 char * str = shortname;
832 char c; 1036 char c;
833 char * path; 1037 char * path;
1038 const char * save_name = name;
834 1039
835 if (is_fat_volume (name, &path)) /* truncate to 8.3 */ 1040 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
836 { 1041 {
@@ -915,11 +1120,107 @@ map_w32_filename (const char * name, const char ** pPath)
915 } 1120 }
916 1121
917 if (pPath) 1122 if (pPath)
918 *pPath = shortname + (path - name); 1123 *pPath = shortname + (path - save_name);
919 1124
920 return shortname; 1125 return shortname;
921} 1126}
922 1127
1128/* Emulate the Unix directory procedures opendir, closedir,
1129 and readdir. We can't use the procedures supplied in sysdep.c,
1130 so we provide them here. */
1131
1132struct direct dir_static; /* simulated directory contents */
1133static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1134static int dir_is_fat;
1135static char dir_pathname[MAXPATHLEN+1];
1136static WIN32_FIND_DATA dir_find_data;
1137
1138DIR *
1139opendir (char *filename)
1140{
1141 DIR *dirp;
1142
1143 /* Opening is done by FindFirstFile. However, a read is inherent to
1144 this operation, so we defer the open until read time. */
1145
1146 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1147 return NULL;
1148 if (dir_find_handle != INVALID_HANDLE_VALUE)
1149 return NULL;
1150
1151 dirp->dd_fd = 0;
1152 dirp->dd_loc = 0;
1153 dirp->dd_size = 0;
1154
1155 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1156 dir_pathname[MAXPATHLEN] = '\0';
1157 dir_is_fat = is_fat_volume (filename, NULL);
1158
1159 return dirp;
1160}
1161
1162void
1163closedir (DIR *dirp)
1164{
1165 /* If we have a find-handle open, close it. */
1166 if (dir_find_handle != INVALID_HANDLE_VALUE)
1167 {
1168 FindClose (dir_find_handle);
1169 dir_find_handle = INVALID_HANDLE_VALUE;
1170 }
1171 xfree ((char *) dirp);
1172}
1173
1174struct direct *
1175readdir (DIR *dirp)
1176{
1177 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1178 if (dir_find_handle == INVALID_HANDLE_VALUE)
1179 {
1180 char filename[MAXNAMLEN + 3];
1181 int ln;
1182
1183 strcpy (filename, dir_pathname);
1184 ln = strlen (filename) - 1;
1185 if (!IS_DIRECTORY_SEP (filename[ln]))
1186 strcat (filename, "\\");
1187 strcat (filename, "*");
1188
1189 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1190
1191 if (dir_find_handle == INVALID_HANDLE_VALUE)
1192 return NULL;
1193 }
1194 else
1195 {
1196 if (!FindNextFile (dir_find_handle, &dir_find_data))
1197 return NULL;
1198 }
1199
1200 /* Emacs never uses this value, so don't bother making it match
1201 value returned by stat(). */
1202 dir_static.d_ino = 1;
1203
1204 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1205 dir_static.d_namlen - dir_static.d_namlen % 4;
1206
1207 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1208 strcpy (dir_static.d_name, dir_find_data.cFileName);
1209 if (dir_is_fat)
1210 _strlwr (dir_static.d_name);
1211 else if (!NILP (Vw32_downcase_file_names))
1212 {
1213 register char *p;
1214 for (p = dir_static.d_name; *p; p++)
1215 if (*p >= 'a' && *p <= 'z')
1216 break;
1217 if (!*p)
1218 _strlwr (dir_static.d_name);
1219 }
1220
1221 return &dir_static;
1222}
1223
923 1224
924/* Shadow some MSVC runtime functions to map requests for long filenames 1225/* Shadow some MSVC runtime functions to map requests for long filenames
925 to reasonable short names if necessary. This was originally added to 1226 to reasonable short names if necessary. This was originally added to
@@ -991,14 +1292,80 @@ sys_fopen(const char * path, const char * mode)
991 if (fd < 0) 1292 if (fd < 0)
992 return NULL; 1293 return NULL;
993 1294
994 return fdopen (fd, mode_save); 1295 return _fdopen (fd, mode_save);
995} 1296}
996 1297
1298/* This only works on NTFS volumes, but is useful to have. */
997int 1299int
998sys_link (const char * path1, const char * path2) 1300sys_link (const char * old, const char * new)
999{ 1301{
1000 errno = EINVAL; 1302 HANDLE fileh;
1001 return -1; 1303 int result = -1;
1304 char oldname[MAX_PATH], newname[MAX_PATH];
1305
1306 if (old == NULL || new == NULL)
1307 {
1308 errno = ENOENT;
1309 return -1;
1310 }
1311
1312 strcpy (oldname, map_w32_filename (old, NULL));
1313 strcpy (newname, map_w32_filename (new, NULL));
1314
1315 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1316 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1317 if (fileh != INVALID_HANDLE_VALUE)
1318 {
1319 int wlen;
1320
1321 /* Confusingly, the "alternate" stream name field does not apply
1322 when restoring a hard link, and instead contains the actual
1323 stream data for the link (ie. the name of the link to create).
1324 The WIN32_STREAM_ID structure before the cStreamName field is
1325 the stream header, which is then immediately followed by the
1326 stream data. */
1327
1328 struct {
1329 WIN32_STREAM_ID wid;
1330 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1331 } data;
1332
1333 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1334 data.wid.cStreamName, MAX_PATH);
1335 if (wlen > 0)
1336 {
1337 LPVOID context = NULL;
1338 DWORD wbytes = 0;
1339
1340 data.wid.dwStreamId = BACKUP_LINK;
1341 data.wid.dwStreamAttributes = 0;
1342 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
1343 data.wid.Size.HighPart = 0;
1344 data.wid.dwStreamNameSize = 0;
1345
1346 if (BackupWrite (fileh, (LPBYTE)&data,
1347 offsetof (WIN32_STREAM_ID, cStreamName)
1348 + data.wid.Size.LowPart,
1349 &wbytes, FALSE, FALSE, &context)
1350 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
1351 {
1352 /* succeeded */
1353 result = 0;
1354 }
1355 else
1356 {
1357 /* Should try mapping GetLastError to errno; for now just
1358 indicate a general error (eg. links not supported). */
1359 errno = EINVAL; // perhaps EMLINK?
1360 }
1361 }
1362
1363 CloseHandle (fileh);
1364 }
1365 else
1366 errno = ENOENT;
1367
1368 return result;
1002} 1369}
1003 1370
1004int 1371int
@@ -1085,7 +1452,7 @@ sys_rename (const char * oldname, const char * newname)
1085 1452
1086 strcpy (temp, map_w32_filename (oldname, NULL)); 1453 strcpy (temp, map_w32_filename (oldname, NULL));
1087 1454
1088 if (GetVersion () & 0x80000000) 1455 if (os_subtype == OS_WIN95)
1089 { 1456 {
1090 char * p; 1457 char * p;
1091 1458
@@ -1093,11 +1460,10 @@ sys_rename (const char * oldname, const char * newname)
1093 p++; 1460 p++;
1094 else 1461 else
1095 p = temp; 1462 p = temp;
1096 strcpy (p, "__XXXXXX");
1097 sys_mktemp (temp);
1098 /* Force temp name to require a manufactured 8.3 alias - this 1463 /* Force temp name to require a manufactured 8.3 alias - this
1099 seems to make the second rename work properly. */ 1464 seems to make the second rename work properly. */
1100 strcat (temp, ".long"); 1465 strcpy (p, "_rename_temp.XXXXXX");
1466 sys_mktemp (temp);
1101 if (rename (map_w32_filename (oldname, NULL), temp) < 0) 1467 if (rename (map_w32_filename (oldname, NULL), temp) < 0)
1102 return -1; 1468 return -1;
1103 } 1469 }
@@ -1107,6 +1473,9 @@ sys_rename (const char * oldname, const char * newname)
1107 However, don't do this if we are just changing the case of the file 1473 However, don't do this if we are just changing the case of the file
1108 name - we will end up deleting the file we are trying to rename! */ 1474 name - we will end up deleting the file we are trying to rename! */
1109 newname = map_w32_filename (newname, NULL); 1475 newname = map_w32_filename (newname, NULL);
1476
1477 /* TODO: Use GetInformationByHandle (on NT) to ensure newname and temp
1478 do not refer to the same file, eg. through share aliases. */
1110 if (stricmp (newname, temp) != 0 1479 if (stricmp (newname, temp) != 0
1111 && (attr = GetFileAttributes (newname)) != -1 1480 && (attr = GetFileAttributes (newname)) != -1
1112 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) 1481 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
@@ -1199,38 +1568,49 @@ convert_from_time_t (time_t time, FILETIME * pft)
1199} 1568}
1200#endif 1569#endif
1201 1570
1202/* "PJW" algorithm (see the "Dragon" compiler book). */ 1571#if 0
1572/* No reason to keep this; faking inode values either by hashing or even
1573 using the file index from GetInformationByHandle, is not perfect and
1574 so by default Emacs doesn't use the inode values on Windows.
1575 Instead, we now determine file-truename correctly (except for
1576 possible drive aliasing etc). */
1577
1578/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
1203static unsigned 1579static unsigned
1204hashval (const char * str) 1580hashval (const unsigned char * str)
1205{ 1581{
1206 unsigned h = 0; 1582 unsigned h = 0;
1207 unsigned g;
1208 while (*str) 1583 while (*str)
1209 { 1584 {
1210 h = (h << 4) + *str++; 1585 h = (h << 4) + *str++;
1211 if ((g = h & 0xf0000000) != 0) 1586 h ^= (h >> 28);
1212 h = (h ^ (g >> 24)) & 0x0fffffff;
1213 } 1587 }
1214 return h; 1588 return h;
1215} 1589}
1216 1590
1217/* Return the hash value of the canonical pathname, excluding the 1591/* Return the hash value of the canonical pathname, excluding the
1218 drive/UNC header, to get a hopefully unique inode number. */ 1592 drive/UNC header, to get a hopefully unique inode number. */
1219static _ino_t 1593static DWORD
1220generate_inode_val (const char * name) 1594generate_inode_val (const char * name)
1221{ 1595{
1222 char fullname[ MAX_PATH ]; 1596 char fullname[ MAX_PATH ];
1223 char * p; 1597 char * p;
1224 unsigned hash; 1598 unsigned hash;
1225 1599
1226 GetFullPathName (name, sizeof (fullname), fullname, &p); 1600 /* Get the truly canonical filename, if it exists. (Note: this
1227 get_volume_info (fullname, &p); 1601 doesn't resolve aliasing due to subst commands, or recognise hard
1602 links. */
1603 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
1604 abort ();
1605
1606 parse_root (fullname, &p);
1228 /* Normal W32 filesystems are still case insensitive. */ 1607 /* Normal W32 filesystems are still case insensitive. */
1229 _strlwr (p); 1608 _strlwr (p);
1230 hash = hashval (p); 1609 return hashval (p);
1231 return (_ino_t) (hash ^ (hash >> 16));
1232} 1610}
1233 1611
1612#endif
1613
1234/* MSVC stat function can't cope with UNC names and has other bugs, so 1614/* MSVC stat function can't cope with UNC names and has other bugs, so
1235 replace it with our own. This also allows us to calculate consistent 1615 replace it with our own. This also allows us to calculate consistent
1236 inode values without hacks in the main Emacs code. */ 1616 inode values without hacks in the main Emacs code. */
@@ -1240,6 +1620,7 @@ stat (const char * path, struct stat * buf)
1240 char * name; 1620 char * name;
1241 WIN32_FIND_DATA wfd; 1621 WIN32_FIND_DATA wfd;
1242 HANDLE fh; 1622 HANDLE fh;
1623 DWORD fake_inode;
1243 int permission; 1624 int permission;
1244 int len; 1625 int len;
1245 int rootdir = FALSE; 1626 int rootdir = FALSE;
@@ -1286,30 +1667,46 @@ stat (const char * path, struct stat * buf)
1286 { 1667 {
1287 if (IS_DIRECTORY_SEP (name[len-1])) 1668 if (IS_DIRECTORY_SEP (name[len-1]))
1288 name[len - 1] = 0; 1669 name[len - 1] = 0;
1289 fh = FindFirstFile (name, &wfd); 1670
1290 if (fh == INVALID_HANDLE_VALUE) 1671 /* (This is hacky, but helps when doing file completions on
1672 network drives.) Optimize by using information available from
1673 active readdir if possible. */
1674 if (dir_find_handle != INVALID_HANDLE_VALUE
1675 && (len = strlen (dir_pathname)),
1676 strnicmp (name, dir_pathname, len) == 0
1677 && IS_DIRECTORY_SEP (name[len])
1678 && stricmp (name + len + 1, dir_static.d_name) == 0)
1291 { 1679 {
1292 errno = ENOENT; 1680 /* This was the last entry returned by readdir. */
1293 return -1; 1681 wfd = dir_find_data;
1682 }
1683 else
1684 {
1685 fh = FindFirstFile (name, &wfd);
1686 if (fh == INVALID_HANDLE_VALUE)
1687 {
1688 errno = ENOENT;
1689 return -1;
1690 }
1691 FindClose (fh);
1294 } 1692 }
1295 FindClose (fh);
1296 } 1693 }
1297 1694
1298 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 1695 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1299 { 1696 {
1300 buf->st_mode = _S_IFDIR; 1697 buf->st_mode = _S_IFDIR;
1301 buf->st_nlink = 2; /* doesn't really matter */ 1698 buf->st_nlink = 2; /* doesn't really matter */
1699 fake_inode = 0; /* this doesn't either I think */
1302 } 1700 }
1303 else 1701 else if (!NILP (Vw32_get_true_file_attributes))
1304 { 1702 {
1305#if 0
1306 /* This is more accurate in terms of gettting the correct number 1703 /* This is more accurate in terms of gettting the correct number
1307 of links, but is quite slow (it is noticable when Emacs is 1704 of links, but is quite slow (it is noticable when Emacs is
1308 making a list of file name completions). */ 1705 making a list of file name completions). */
1309 BY_HANDLE_FILE_INFORMATION info; 1706 BY_HANDLE_FILE_INFORMATION info;
1310 1707
1311 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 1708 /* No access rights required to get info. */
1312 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1709 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1313 1710
1314 if (GetFileInformationByHandle (fh, &info)) 1711 if (GetFileInformationByHandle (fh, &info))
1315 { 1712 {
@@ -1327,9 +1724,12 @@ stat (const char * path, struct stat * buf)
1327 buf->st_mode = _S_IFCHR; 1724 buf->st_mode = _S_IFCHR;
1328 } 1725 }
1329 buf->st_nlink = info.nNumberOfLinks; 1726 buf->st_nlink = info.nNumberOfLinks;
1330 /* Could use file index, but this is not guaranteed to be 1727 /* Might as well use file index to fake inode values, but this
1331 unique unless we keep a handle open all the time. */ 1728 is not guaranteed to be unique unless we keep a handle open
1332 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */ 1729 all the time (even then there are situations where it is
1730 not unique). Reputedly, there are at most 48 bits of info
1731 (on NTFS, presumably less on FAT). */
1732 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1333 CloseHandle (fh); 1733 CloseHandle (fh);
1334 } 1734 }
1335 else 1735 else
@@ -1337,11 +1737,32 @@ stat (const char * path, struct stat * buf)
1337 errno = EACCES; 1737 errno = EACCES;
1338 return -1; 1738 return -1;
1339 } 1739 }
1340#else 1740 }
1741 else
1742 {
1743 /* Don't bother to make this information more accurate. */
1341 buf->st_mode = _S_IFREG; 1744 buf->st_mode = _S_IFREG;
1342 buf->st_nlink = 1; 1745 buf->st_nlink = 1;
1343#endif 1746 fake_inode = 0;
1747 }
1748
1749#if 0
1750 /* Not sure if there is any point in this. */
1751 if (!NILP (Vw32_generate_fake_inodes))
1752 fake_inode = generate_inode_val (name);
1753 else if (fake_inode == 0)
1754 {
1755 /* For want of something better, try to make everything unique. */
1756 static DWORD gen_num = 0;
1757 fake_inode = ++gen_num;
1344 } 1758 }
1759#endif
1760
1761 /* MSVC defines _ino_t to be short; other libc's might not. */
1762 if (sizeof (buf->st_ino) == 2)
1763 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1764 else
1765 buf->st_ino = fake_inode;
1345 1766
1346 /* consider files to belong to current user */ 1767 /* consider files to belong to current user */
1347 buf->st_uid = the_passwd.pw_uid; 1768 buf->st_uid = the_passwd.pw_uid;
@@ -1351,7 +1772,6 @@ stat (const char * path, struct stat * buf)
1351 buf->st_dev = volume_info.serialnum; 1772 buf->st_dev = volume_info.serialnum;
1352 buf->st_rdev = volume_info.serialnum; 1773 buf->st_rdev = volume_info.serialnum;
1353 1774
1354 buf->st_ino = generate_inode_val (name);
1355 1775
1356 buf->st_size = wfd.nFileSizeLow; 1776 buf->st_size = wfd.nFileSizeLow;
1357 1777
@@ -1373,11 +1793,11 @@ stat (const char * path, struct stat * buf)
1373 else 1793 else
1374 { 1794 {
1375 char * p = strrchr (name, '.'); 1795 char * p = strrchr (name, '.');
1376 if (p != NULL && 1796 if (p != NULL
1377 (stricmp (p, ".exe") == 0 || 1797 && (stricmp (p, ".exe") == 0 ||
1378 stricmp (p, ".com") == 0 || 1798 stricmp (p, ".com") == 0 ||
1379 stricmp (p, ".bat") == 0 || 1799 stricmp (p, ".bat") == 0 ||
1380 stricmp (p, ".cmd") == 0)) 1800 stricmp (p, ".cmd") == 0))
1381 permission |= _S_IEXEC; 1801 permission |= _S_IEXEC;
1382 } 1802 }
1383 1803
@@ -1919,42 +2339,22 @@ sys_pipe (int * phandles)
1919 unsigned flags; 2339 unsigned flags;
1920 child_process * cp; 2340 child_process * cp;
1921 2341
1922 /* make pipe handles non-inheritable; when we spawn a child, 2342 /* make pipe handles non-inheritable; when we spawn a child, we
1923 we replace the relevant handle with an inheritable one. */ 2343 replace the relevant handle with an inheritable one. Also put
1924 rc = _pipe (phandles, 0, _O_NOINHERIT); 2344 pipes into binary mode; we will do text mode translation ourselves
2345 if required. */
2346 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
1925 2347
1926 if (rc == 0) 2348 if (rc == 0)
1927 { 2349 {
1928 /* set internal flags, and put read and write handles into binary
1929 mode as necessary; if not in binary mode, set the MSVC internal
1930 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1931 could otherwise allow Emacs to hang because it then waits
1932 indefinitely for the child process to exit, when it might not be
1933 finished). */
1934 flags = FILE_PIPE | FILE_READ; 2350 flags = FILE_PIPE | FILE_READ;
1935 if (!NILP (Vbinary_process_output)) 2351 if (!NILP (Vbinary_process_output))
1936 { 2352 flags |= FILE_BINARY;
1937 flags |= FILE_BINARY;
1938 setmode (phandles[0], _O_BINARY);
1939 }
1940#if (_MSC_VER == 900)
1941 else
1942 _osfile[phandles[0]] |= 0x40;
1943#endif
1944
1945 fd_info[phandles[0]].flags = flags; 2353 fd_info[phandles[0]].flags = flags;
1946 2354
1947 flags = FILE_PIPE | FILE_WRITE; 2355 flags = FILE_PIPE | FILE_WRITE;
1948 if (!NILP (Vbinary_process_input)) 2356 if (!NILP (Vbinary_process_input))
1949 { 2357 flags |= FILE_BINARY;
1950 flags |= FILE_BINARY;
1951 setmode (phandles[1], _O_BINARY);
1952 }
1953#if (_MSC_VER == 900)
1954 else
1955 _osfile[phandles[1]] |= 0x40;
1956#endif
1957
1958 fd_info[phandles[1]].flags = flags; 2358 fd_info[phandles[1]].flags = flags;
1959 } 2359 }
1960 2360
@@ -1991,7 +2391,6 @@ _sys_read_ahead (int fd)
1991 2391
1992 if (fd_info[fd].flags & FILE_PIPE) 2392 if (fd_info[fd].flags & FILE_PIPE)
1993 { 2393 {
1994 /* Use read to get CRLF translation */
1995 rc = _read (fd, &cp->chr, sizeof (char)); 2394 rc = _read (fd, &cp->chr, sizeof (char));
1996 2395
1997 /* Give subprocess time to buffer some more output for us before 2396 /* Give subprocess time to buffer some more output for us before
@@ -2031,9 +2430,9 @@ int
2031sys_read (int fd, char * buffer, unsigned int count) 2430sys_read (int fd, char * buffer, unsigned int count)
2032{ 2431{
2033 int nchars; 2432 int nchars;
2034 int extra = 0;
2035 int to_read; 2433 int to_read;
2036 DWORD waiting; 2434 DWORD waiting;
2435 char * orig_buffer = buffer;
2037 2436
2038 if (fd < 0 || fd >= MAXDESC) 2437 if (fd < 0 || fd >= MAXDESC)
2039 { 2438 {
@@ -2051,6 +2450,17 @@ sys_read (int fd, char * buffer, unsigned int count)
2051 return -1; 2450 return -1;
2052 } 2451 }
2053 2452
2453 nchars = 0;
2454
2455 /* re-read CR carried over from last read */
2456 if (fd_info[fd].flags & FILE_LAST_CR)
2457 {
2458 if (fd_info[fd].flags & FILE_BINARY) abort ();
2459 *buffer++ = 0x0d;
2460 count--;
2461 nchars++;
2462 }
2463
2054 /* presence of a child_process structure means we are operating in 2464 /* presence of a child_process structure means we are operating in
2055 non-blocking mode - otherwise we just call _read directly. 2465 non-blocking mode - otherwise we just call _read directly.
2056 Note that the child_process structure might be missing because 2466 Note that the child_process structure might be missing because
@@ -2077,7 +2487,7 @@ sys_read (int fd, char * buffer, unsigned int count)
2077 /* consume read-ahead char */ 2487 /* consume read-ahead char */
2078 *buffer++ = cp->chr; 2488 *buffer++ = cp->chr;
2079 count--; 2489 count--;
2080 extra = 1; 2490 nchars++;
2081 cp->status = STATUS_READ_ACKNOWLEDGED; 2491 cp->status = STATUS_READ_ACKNOWLEDGED;
2082 ResetEvent (cp->char_avail); 2492 ResetEvent (cp->char_avail);
2083 2493
@@ -2095,8 +2505,7 @@ sys_read (int fd, char * buffer, unsigned int count)
2095 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL); 2505 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2096 to_read = min (waiting, (DWORD) count); 2506 to_read = min (waiting, (DWORD) count);
2097 2507
2098 /* Use read to get CRLF translation */ 2508 nchars += _read (fd, buffer, to_read);
2099 nchars = _read (fd, buffer, to_read);
2100 } 2509 }
2101#ifdef HAVE_SOCKETS 2510#ifdef HAVE_SOCKETS
2102 else /* FILE_SOCKET */ 2511 else /* FILE_SOCKET */
@@ -2105,39 +2514,52 @@ sys_read (int fd, char * buffer, unsigned int count)
2105 2514
2106 /* do the equivalent of a non-blocking read */ 2515 /* do the equivalent of a non-blocking read */
2107 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); 2516 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2108 if (waiting == 0 && extra == 0) 2517 if (waiting == 0 && nchars == 0)
2109 { 2518 {
2110 h_errno = errno = EWOULDBLOCK; 2519 h_errno = errno = EWOULDBLOCK;
2111 return -1; 2520 return -1;
2112 } 2521 }
2113 2522
2114 nchars = 0;
2115 if (waiting) 2523 if (waiting)
2116 { 2524 {
2117 /* always use binary mode for sockets */ 2525 /* always use binary mode for sockets */
2118 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0); 2526 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2119 if (nchars == SOCKET_ERROR) 2527 if (res == SOCKET_ERROR)
2120 { 2528 {
2121 DebPrint(("sys_read.recv failed with error %d on socket %ld\n", 2529 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2122 pfn_WSAGetLastError (), SOCK_HANDLE (fd))); 2530 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2123 if (extra == 0) 2531 set_errno ();
2124 { 2532 return -1;
2125 set_errno ();
2126 return -1;
2127 }
2128 nchars = 0;
2129 } 2533 }
2534 nchars += res;
2130 } 2535 }
2131 } 2536 }
2132#endif 2537#endif
2133 } 2538 }
2134 else 2539 else
2135 nchars = _read (fd, buffer, count); 2540 nchars += _read (fd, buffer, count);
2541
2542 /* Perform text mode translation if required. */
2543 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2544 {
2545 nchars = crlf_to_lf (nchars, orig_buffer);
2546 /* If buffer contains only CR, return that. To be absolutely
2547 sure we should attempt to read the next char, but in
2548 practice a CR to be followed by LF would not appear by
2549 itself in the buffer. */
2550 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2551 {
2552 fd_info[fd].flags |= FILE_LAST_CR;
2553 nchars--;
2554 }
2555 else
2556 fd_info[fd].flags &= ~FILE_LAST_CR;
2557 }
2136 } 2558 }
2137 else 2559 else
2138 nchars = _read (fd, buffer, count); 2560 nchars = _read (fd, buffer, count);
2139 2561
2140 return nchars + extra; 2562 return nchars;
2141} 2563}
2142 2564
2143/* For now, don't bother with a non-blocking mode */ 2565/* For now, don't bother with a non-blocking mode */
@@ -2153,11 +2575,46 @@ sys_write (int fd, const void * buffer, unsigned int count)
2153 } 2575 }
2154 2576
2155 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) 2577 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2156 if ((fd_info[fd].flags & FILE_WRITE) == 0) 2578 {
2157 { 2579 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2158 errno = EBADF; 2580 {
2159 return -1; 2581 errno = EBADF;
2160 } 2582 return -1;
2583 }
2584
2585 /* Perform text mode translation if required. */
2586 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2587 {
2588 char * tmpbuf = alloca (count * 2);
2589 unsigned char * src = (void *)buffer;
2590 unsigned char * dst = tmpbuf;
2591 int nbytes = count;
2592
2593 while (1)
2594 {
2595 unsigned char *next;
2596 /* copy next line or remaining bytes */
2597 next = _memccpy (dst, src, '\n', nbytes);
2598 if (next)
2599 {
2600 /* copied one line ending with '\n' */
2601 int copied = next - dst;
2602 nbytes -= copied;
2603 src += copied;
2604 /* insert '\r' before '\n' */
2605 next[-1] = '\r';
2606 next[0] = '\n';
2607 dst = next + 1;
2608 count++;
2609 }
2610 else
2611 /* copied remaining partial line -> now finished */
2612 break;
2613 }
2614 buffer = tmpbuf;
2615 }
2616 }
2617
2161#ifdef HAVE_SOCKETS 2618#ifdef HAVE_SOCKETS
2162 if (fd_info[fd].flags & FILE_SOCKET) 2619 if (fd_info[fd].flags & FILE_SOCKET)
2163 { 2620 {
@@ -2187,8 +2644,6 @@ term_ntproc ()
2187#endif 2644#endif
2188} 2645}
2189 2646
2190extern BOOL dos_process_running;
2191
2192void 2647void
2193init_ntproc () 2648init_ntproc ()
2194{ 2649{
@@ -2251,39 +2706,41 @@ init_ntproc ()
2251 if (stdin_save != INVALID_HANDLE_VALUE) 2706 if (stdin_save != INVALID_HANDLE_VALUE)
2252 _open_osfhandle ((long) stdin_save, O_TEXT); 2707 _open_osfhandle ((long) stdin_save, O_TEXT);
2253 else 2708 else
2254 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY); 2709 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2255 fdopen (0, "r"); 2710 _fdopen (0, "r");
2256 2711
2257 if (stdout_save != INVALID_HANDLE_VALUE) 2712 if (stdout_save != INVALID_HANDLE_VALUE)
2258 _open_osfhandle ((long) stdout_save, O_TEXT); 2713 _open_osfhandle ((long) stdout_save, O_TEXT);
2259 else 2714 else
2260 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); 2715 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2261 fdopen (1, "w"); 2716 _fdopen (1, "w");
2262 2717
2263 if (stderr_save != INVALID_HANDLE_VALUE) 2718 if (stderr_save != INVALID_HANDLE_VALUE)
2264 _open_osfhandle ((long) stderr_save, O_TEXT); 2719 _open_osfhandle ((long) stderr_save, O_TEXT);
2265 else 2720 else
2266 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); 2721 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2267 fdopen (2, "w"); 2722 _fdopen (2, "w");
2268 } 2723 }
2269 2724
2270 /* Restrict Emacs to running only one DOS program at a time (with any
2271 number of W32 programs). This is to prevent the user from
2272 running into problems with DOS programs being run in the same VDM
2273 under both Windows 95 and Windows NT.
2274
2275 Note that it is possible for Emacs to run DOS programs in separate
2276 VDMs, but unfortunately the pipe implementation on Windows 95 then
2277 fails to report when the DOS process exits (which is supposed to
2278 break the pipe). Until this bug is fixed, or we can devise a
2279 work-around, we must try to avoid letting the user start more than
2280 one DOS program if possible. */
2281
2282 dos_process_running = FALSE;
2283
2284 /* unfortunately, atexit depends on implementation of malloc */ 2725 /* unfortunately, atexit depends on implementation of malloc */
2285 /* atexit (term_ntproc); */ 2726 /* atexit (term_ntproc); */
2286 signal (SIGABRT, term_ntproc); 2727 signal (SIGABRT, term_ntproc);
2728
2729 /* determine which drives are fixed, for GetCachedVolumeInformation */
2730 {
2731 /* GetDriveType must have trailing backslash. */
2732 char drive[] = "A:\\";
2733
2734 /* Loop over all possible drive letters */
2735 while (*drive <= 'Z')
2736 {
2737 /* Record if this drive letter refers to a fixed drive. */
2738 fixed_drives[DRIVE_INDEX (*drive)] =
2739 (GetDriveType (drive) == DRIVE_FIXED);
2740
2741 (*drive)++;
2742 }
2743 }
2287} 2744}
2288 2745
2289/* end of nt.c */ 2746/* end of nt.c */