Mercurial > hg > xemacs-beta
comparison src/nt.c @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | 850242ba4a81 |
children | 78478c60bfcd |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
20 | 20 |
21 | 21 |
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ | 22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ |
23 | 23 |
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | 24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ |
25 | 25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ |
26 | |
27 #include <stddef.h> /* for offsetof */ | |
28 #include <string.h> | |
26 #include <stdlib.h> | 29 #include <stdlib.h> |
27 #include <stdio.h> | 30 #include <stdio.h> |
28 #include <io.h> | 31 #include <io.h> |
29 #include <errno.h> | 32 #include <errno.h> |
30 #include <fcntl.h> | 33 #include <fcntl.h> |
79 | 82 |
80 #include "nt.h" | 83 #include "nt.h" |
81 #include <sys/dir.h> | 84 #include <sys/dir.h> |
82 #include "ntheap.h" | 85 #include "ntheap.h" |
83 | 86 |
87 | |
88 extern Lisp_Object Vwin32_downcase_file_names; | |
89 extern Lisp_Object Vwin32_generate_fake_inodes; | |
90 extern Lisp_Object Vwin32_get_true_file_attributes; | |
91 | |
92 static char startup_dir[ MAXPATHLEN ]; | |
93 | |
84 /* Get the current working directory. */ | 94 /* Get the current working directory. */ |
85 char * | 95 char * |
86 getwd (char *dir) | 96 getwd (char *dir) |
87 { | 97 { |
98 #if 0 | |
88 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0) | 99 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0) |
89 return dir; | 100 return dir; |
90 return NULL; | 101 return NULL; |
102 #else | |
103 /* Emacs doesn't actually change directory itself, and we want to | |
104 force our real wd to be where emacs.exe is to avoid unnecessary | |
105 conflicts when trying to rename or delete directories. */ | |
106 strcpy (dir, startup_dir); | |
107 return dir; | |
108 #endif | |
91 } | 109 } |
92 | 110 |
93 #ifndef HAVE_SOCKETS | 111 #ifndef HAVE_SOCKETS |
94 /* Emulate gethostname. */ | 112 /* Emulate gethostname. */ |
95 int | 113 int |
111 for (i = 0; i < nelem; i++) | 129 for (i = 0; i < nelem; i++) |
112 { | 130 { |
113 loadavg[i] = 0.0; | 131 loadavg[i] = 0.0; |
114 } | 132 } |
115 return i; | 133 return i; |
116 } | |
117 | |
118 /* Emulate the Unix directory procedures opendir, closedir, | |
119 and readdir. We can't use the procedures supplied in sysdep.c, | |
120 so we provide them here. */ | |
121 | |
122 struct direct dir_static; /* simulated directory contents */ | |
123 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; | |
124 static int dir_is_fat; | |
125 static char dir_pathname[MAXPATHLEN+1]; | |
126 | |
127 extern Lisp_Object Vwin32_downcase_file_names; | |
128 | |
129 DIR * | |
130 opendir (char *filename) | |
131 { | |
132 DIR *dirp; | |
133 | |
134 /* Opening is done by FindFirstFile. However, a read is inherent to | |
135 this operation, so we defer the open until read time. */ | |
136 | |
137 if (!(dirp = (DIR *) xmalloc (sizeof (DIR)))) | |
138 return NULL; | |
139 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
140 return NULL; | |
141 | |
142 dirp->dd_fd = 0; | |
143 dirp->dd_loc = 0; | |
144 dirp->dd_size = 0; | |
145 | |
146 strncpy (dir_pathname, filename, MAXPATHLEN); | |
147 dir_pathname[MAXPATHLEN] = '\0'; | |
148 dir_is_fat = is_fat_volume (filename, NULL); | |
149 | |
150 return dirp; | |
151 } | |
152 | |
153 void | |
154 closedir (DIR *dirp) | |
155 { | |
156 /* If we have a find-handle open, close it. */ | |
157 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
158 { | |
159 FindClose (dir_find_handle); | |
160 dir_find_handle = INVALID_HANDLE_VALUE; | |
161 } | |
162 xfree ((char *) dirp); | |
163 } | |
164 | |
165 struct direct * | |
166 readdir (DIR *dirp) | |
167 { | |
168 WIN32_FIND_DATA find_data; | |
169 | |
170 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ | |
171 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
172 { | |
173 char filename[MAXNAMLEN + 3]; | |
174 int ln; | |
175 | |
176 strcpy (filename, dir_pathname); | |
177 ln = strlen (filename) - 1; | |
178 if (!IS_DIRECTORY_SEP (filename[ln])) | |
179 strcat (filename, "\\"); | |
180 strcat (filename, "*"); | |
181 | |
182 dir_find_handle = FindFirstFile (filename, &find_data); | |
183 | |
184 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
185 return NULL; | |
186 } | |
187 else | |
188 { | |
189 if (!FindNextFile (dir_find_handle, &find_data)) | |
190 return NULL; | |
191 } | |
192 | |
193 /* Emacs never uses this value, so don't bother making it match | |
194 value returned by stat(). */ | |
195 dir_static.d_ino = 1; | |
196 | |
197 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + | |
198 dir_static.d_namlen - dir_static.d_namlen % 4; | |
199 | |
200 dir_static.d_namlen = strlen (find_data.cFileName); | |
201 strcpy (dir_static.d_name, find_data.cFileName); | |
202 if (dir_is_fat) | |
203 _strlwr (dir_static.d_name); | |
204 else if (!NILP (Vwin32_downcase_file_names)) | |
205 { | |
206 REGISTER char *p; | |
207 for (p = dir_static.d_name; *p; p++) | |
208 if (*p >= 'a' && *p <= 'z') | |
209 break; | |
210 if (!*p) | |
211 _strlwr (dir_static.d_name); | |
212 } | |
213 | |
214 return &dir_static; | |
215 } | 134 } |
216 | 135 |
217 /* Emulate getpwuid, getpwnam and others. */ | 136 /* Emulate getpwuid, getpwnam and others. */ |
218 | 137 |
219 #define PASSWD_FIELD_SIZE 256 | 138 #define PASSWD_FIELD_SIZE 256 |
470 | 389 |
471 /* Remove all CR's that are followed by a LF. | 390 /* Remove all CR's that are followed by a LF. |
472 (From msdos.c...probably should figure out a way to share it, | 391 (From msdos.c...probably should figure out a way to share it, |
473 although this code isn't going to ever change.) */ | 392 although this code isn't going to ever change.) */ |
474 int | 393 int |
475 crlf_to_lf (n, buf) | 394 crlf_to_lf (n, buf, lf_count) |
476 REGISTER int n; | 395 REGISTER int n; |
477 REGISTER unsigned char *buf; | 396 REGISTER unsigned char *buf; |
397 REGISTER unsigned *lf_count; | |
478 { | 398 { |
479 unsigned char *np = buf; | 399 unsigned char *np = buf; |
480 unsigned char *startp = buf; | 400 unsigned char *startp = buf; |
481 unsigned char *endp = buf + n; | 401 unsigned char *endp = buf + n; |
482 | 402 |
483 if (n == 0) | 403 if (n == 0) |
484 return n; | 404 return n; |
485 while (buf < endp - 1) | 405 while (buf < endp - 1) |
486 { | 406 { |
407 if (*buf == 0x0a) | |
408 (*lf_count)++; | |
487 if (*buf == 0x0d) | 409 if (*buf == 0x0d) |
488 { | 410 { |
489 if (*(++buf) != 0x0a) | 411 if (*(++buf) != 0x0a) |
490 *np++ = 0x0d; | 412 *np++ = 0x0d; |
491 } | 413 } |
492 else | 414 else |
493 *np++ = *buf++; | 415 *np++ = *buf++; |
494 } | 416 } |
495 if (buf < endp) | 417 if (buf < endp) |
418 { | |
419 if (*buf == 0x0a) | |
420 (*lf_count)++; | |
496 *np++ = *buf++; | 421 *np++ = *buf++; |
422 } | |
497 return np - startp; | 423 return np - startp; |
498 } | 424 } |
425 | |
426 /* Parse the root part of file name, if present. Return length and | |
427 optionally store pointer to char after root. */ | |
428 static int | |
429 parse_root (char * name, char ** pPath) | |
430 { | |
431 char * start = name; | |
432 | |
433 if (name == NULL) | |
434 return 0; | |
435 | |
436 /* find the root name of the volume if given */ | |
437 if (isalpha (name[0]) && name[1] == ':') | |
438 { | |
439 /* skip past drive specifier */ | |
440 name += 2; | |
441 if (IS_DIRECTORY_SEP (name[0])) | |
442 name++; | |
443 } | |
444 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | |
445 { | |
446 int slashes = 2; | |
447 name += 2; | |
448 do | |
449 { | |
450 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | |
451 break; | |
452 name++; | |
453 } | |
454 while ( *name ); | |
455 if (IS_DIRECTORY_SEP (name[0])) | |
456 name++; | |
457 } | |
458 | |
459 if (pPath) | |
460 *pPath = name; | |
461 | |
462 return name - start; | |
463 } | |
464 | |
465 /* Get long base name for name; name is assumed to be absolute. */ | |
466 static int | |
467 get_long_basename (char * name, char * buf, int size) | |
468 { | |
469 WIN32_FIND_DATA find_data; | |
470 HANDLE dir_handle; | |
471 int len = 0; | |
472 #ifdef PIGSFLY | |
473 char *p; | |
474 | |
475 /* If the last component of NAME has a wildcard character, | |
476 return it as the basename. */ | |
477 p = name + strlen (name); | |
478 while (*p != '\\' && *p != ':' && p > name) p--; | |
479 if (p > name) p++; | |
480 if (strchr (p, '*') || strchr (p, '?')) | |
481 { | |
482 if ((len = strlen (p)) < size) | |
483 memcpy (buf, p, len + 1); | |
484 else | |
485 len = 0; | |
486 return len; | |
487 } | |
488 #endif | |
489 | |
490 dir_handle = FindFirstFile (name, &find_data); | |
491 if (dir_handle != INVALID_HANDLE_VALUE) | |
492 { | |
493 if ((len = strlen (find_data.cFileName)) < size) | |
494 memcpy (buf, find_data.cFileName, len + 1); | |
495 else | |
496 len = 0; | |
497 FindClose (dir_handle); | |
498 } | |
499 return len; | |
500 } | |
501 | |
502 /* Get long name for file, if possible (assumed to be absolute). */ | |
503 BOOL | |
504 win32_get_long_filename (char * name, char * buf, int size) | |
505 { | |
506 char * o = buf; | |
507 char * p; | |
508 char * q; | |
509 char full[ MAX_PATH ]; | |
510 int len; | |
511 | |
512 len = strlen (name); | |
513 if (len >= MAX_PATH) | |
514 return FALSE; | |
515 | |
516 /* Use local copy for destructive modification. */ | |
517 memcpy (full, name, len+1); | |
518 unixtodos_filename (full); | |
519 | |
520 /* Copy root part verbatim. */ | |
521 len = parse_root (full, &p); | |
522 memcpy (o, full, len); | |
523 o += len; | |
524 size -= len; | |
525 | |
526 do | |
527 { | |
528 q = p; | |
529 p = strchr (q, '\\'); | |
530 if (p) *p = '\0'; | |
531 len = get_long_basename (full, o, size); | |
532 if (len > 0) | |
533 { | |
534 o += len; | |
535 size -= len; | |
536 if (p != NULL) | |
537 { | |
538 *p++ = '\\'; | |
539 if (size < 2) | |
540 return FALSE; | |
541 *o++ = '\\'; | |
542 size--; | |
543 *o = '\0'; | |
544 } | |
545 } | |
546 else | |
547 return FALSE; | |
548 } | |
549 while (p != NULL && *p); | |
550 | |
551 return TRUE; | |
552 } | |
553 | |
499 | 554 |
500 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */ | 555 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */ |
501 | 556 |
502 int | 557 int |
503 sigsetmask (int signal_mask) | 558 sigsetmask (int signal_mask) |
599 "HOME", | 654 "HOME", |
600 "PRELOAD_WINSOCK", | 655 "PRELOAD_WINSOCK", |
601 "emacs_dir", | 656 "emacs_dir", |
602 "EMACSLOADPATH", | 657 "EMACSLOADPATH", |
603 "SHELL", | 658 "SHELL", |
659 "CMDPROXY", | |
604 "EMACSDATA", | 660 "EMACSDATA", |
605 "EMACSPATH", | 661 "EMACSPATH", |
606 "EMACSLOCKDIR", | 662 "EMACSLOCKDIR", |
607 "INFOPATH", | 663 /* We no longer set INFOPATH because Info-default-directory-list |
664 is then ignored. We use a hook in winnt.el instead. */ | |
665 /* "INFOPATH", */ | |
608 "EMACSDOC", | 666 "EMACSDOC", |
609 "TERM", | 667 "TERM", |
610 }; | 668 }; |
611 | 669 |
612 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) | 670 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) |
633 xfree (lpval); | 691 xfree (lpval); |
634 } | 692 } |
635 } | 693 } |
636 } | 694 } |
637 | 695 |
696 /* Another special case: on NT, the PATH variable is actually named | |
697 "Path" although cmd.exe (perhaps NT itself) arranges for | |
698 environment variable lookup and setting to be case insensitive. | |
699 However, Emacs assumes a fully case sensitive environment, so we | |
700 need to change "Path" to "PATH" to match the expectations of | |
701 various elisp packages. We do this by the sneaky method of | |
702 modifying the string in the C runtime environ entry. | |
703 | |
704 The same applies to COMSPEC. */ | |
705 { | |
706 char ** envp; | |
707 | |
708 for (envp = environ; *envp; envp++) | |
709 if (_strnicmp (*envp, "PATH=", 5) == 0) | |
710 memcpy (*envp, "PATH=", 5); | |
711 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0) | |
712 memcpy (*envp, "COMSPEC=", 8); | |
713 } | |
714 | |
715 /* Remember the initial working directory for getwd, then make the | |
716 real wd be the location of emacs.exe to avoid conflicts when | |
717 renaming or deleting directories. (We also don't call chdir when | |
718 running subprocesses for the same reason.) */ | |
719 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir)) | |
720 abort (); | |
721 | |
722 { | |
723 char *p; | |
724 char modname[MAX_PATH]; | |
725 | |
726 if (!GetModuleFileName (NULL, modname, MAX_PATH)) | |
727 abort (); | |
728 if ((p = strrchr (modname, '\\')) == NULL) | |
729 abort (); | |
730 *p = 0; | |
731 | |
732 SetCurrentDirectory (modname); | |
733 } | |
734 | |
638 init_user_info (); | 735 init_user_info (); |
639 } | 736 } |
640 | 737 |
641 /* We don't have scripts to automatically determine the system configuration | 738 /* We don't have scripts to automatically determine the system configuration |
642 for Emacs before it's compiled, and we don't want to have to make the | 739 for Emacs before it's compiled, and we don't want to have to make the |
754 extern int __cdecl _free_osfhnd (int fd); | 851 extern int __cdecl _free_osfhnd (int fd); |
755 | 852 |
756 /* parallel array of private info on file handles */ | 853 /* parallel array of private info on file handles */ |
757 filedesc fd_info [ MAXDESC ]; | 854 filedesc fd_info [ MAXDESC ]; |
758 | 855 |
759 static struct { | 856 typedef struct volume_info_data { |
857 struct volume_info_data * next; | |
858 | |
859 /* time when info was obtained */ | |
860 DWORD timestamp; | |
861 | |
862 /* actual volume info */ | |
863 char * root_dir; | |
760 DWORD serialnum; | 864 DWORD serialnum; |
761 DWORD maxcomp; | 865 DWORD maxcomp; |
762 DWORD flags; | 866 DWORD flags; |
763 char name[32]; | 867 char * name; |
764 char type[32]; | 868 char * type; |
765 } volume_info; | 869 } volume_info_data; |
870 | |
871 /* Global referenced by various functions. */ | |
872 static volume_info_data volume_info; | |
873 | |
874 /* Vector to indicate which drives are local and fixed (for which cached | |
875 data never expires). */ | |
876 static BOOL fixed_drives[26]; | |
877 | |
878 /* Consider cached volume information to be stale if older than 10s, | |
879 at least for non-local drives. Info for fixed drives is never stale. */ | |
880 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' ) | |
881 #define VOLINFO_STILL_VALID( root_dir, info ) \ | |
882 ( ( isalpha (root_dir[0]) && \ | |
883 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \ | |
884 || GetTickCount () - info->timestamp < 10000 ) | |
885 | |
886 /* Cache support functions. */ | |
887 | |
888 /* Simple linked list with linear search is sufficient. */ | |
889 static volume_info_data *volume_cache = NULL; | |
890 | |
891 static volume_info_data * | |
892 lookup_volume_info (char * root_dir) | |
893 { | |
894 volume_info_data * info; | |
895 | |
896 for (info = volume_cache; info; info = info->next) | |
897 if (stricmp (info->root_dir, root_dir) == 0) | |
898 break; | |
899 return info; | |
900 } | |
901 | |
902 static void | |
903 add_volume_info (char * root_dir, volume_info_data * info) | |
904 { | |
905 info->root_dir = xstrdup (root_dir); | |
906 info->next = volume_cache; | |
907 volume_cache = info; | |
908 } | |
909 | |
910 | |
911 /* Wrapper for GetVolumeInformation, which uses caching to avoid | |
912 performance penalty (~2ms on 486 for local drives, 7.5ms for local | |
913 cdrom drive, ~5-10ms or more for remote drives on LAN). */ | |
914 volume_info_data * | |
915 GetCachedVolumeInformation (char * root_dir) | |
916 { | |
917 volume_info_data * info; | |
918 char default_root[ MAX_PATH ]; | |
919 | |
920 /* NULL for root_dir means use root from current directory. */ | |
921 if (root_dir == NULL) | |
922 { | |
923 if (GetCurrentDirectory (MAX_PATH, default_root) == 0) | |
924 return NULL; | |
925 parse_root (default_root, &root_dir); | |
926 *root_dir = 0; | |
927 root_dir = default_root; | |
928 } | |
929 | |
930 /* Local fixed drives can be cached permanently. Removable drives | |
931 cannot be cached permanently, since the volume name and serial | |
932 number (if nothing else) can change. Remote drives should be | |
933 treated as if they are removable, since there is no sure way to | |
934 tell whether they are or not. Also, the UNC association of drive | |
935 letters mapped to remote volumes can be changed at any time (even | |
936 by other processes) without notice. | |
937 | |
938 As a compromise, so we can benefit from caching info for remote | |
939 volumes, we use a simple expiry mechanism to invalidate cache | |
940 entries that are more than ten seconds old. */ | |
941 | |
942 #if 0 | |
943 /* No point doing this, because WNetGetConnection is even slower than | |
944 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW, | |
945 GetDriveType is about the only call of this type which does not | |
946 involve network access, and so is extremely quick). */ | |
947 | |
948 /* Map drive letter to UNC if remote. */ | |
949 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] ) | |
950 { | |
951 char remote_name[ 256 ]; | |
952 char drive[3] = { root_dir[0], ':' }; | |
953 | |
954 if (WNetGetConnection (drive, remote_name, sizeof (remote_name)) | |
955 == NO_ERROR) | |
956 /* do something */ ; | |
957 } | |
958 #endif | |
959 | |
960 info = lookup_volume_info (root_dir); | |
961 | |
962 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info)) | |
963 { | |
964 char name[ 256 ]; | |
965 DWORD serialnum; | |
966 DWORD maxcomp; | |
967 DWORD flags; | |
968 char type[ 256 ]; | |
969 | |
970 /* Info is not cached, or is stale. */ | |
971 if (!GetVolumeInformation (root_dir, | |
972 name, sizeof (name), | |
973 &serialnum, | |
974 &maxcomp, | |
975 &flags, | |
976 type, sizeof (type))) | |
977 return NULL; | |
978 | |
979 /* Cache the volume information for future use, overwriting existing | |
980 entry if present. */ | |
981 if (info == NULL) | |
982 { | |
983 info = (volume_info_data *) xmalloc (sizeof (volume_info_data)); | |
984 add_volume_info (root_dir, info); | |
985 } | |
986 else | |
987 { | |
988 free (info->name); | |
989 free (info->type); | |
990 } | |
991 | |
992 info->name = xstrdup (name); | |
993 info->serialnum = serialnum; | |
994 info->maxcomp = maxcomp; | |
995 info->flags = flags; | |
996 info->type = xstrdup (type); | |
997 info->timestamp = GetTickCount (); | |
998 } | |
999 | |
1000 return info; | |
1001 } | |
766 | 1002 |
767 /* Get information on the volume where name is held; set path pointer to | 1003 /* Get information on the volume where name is held; set path pointer to |
768 start of pathname in name (past UNC header\volume header if present). */ | 1004 start of pathname in name (past UNC header\volume header if present). */ |
769 int | 1005 int |
770 get_volume_info (const char * name, const char ** pPath) | 1006 get_volume_info (const char * name, const char ** pPath) |
771 { | 1007 { |
772 char temp[MAX_PATH]; | 1008 char temp[MAX_PATH]; |
773 char *rootname = NULL; /* default to current volume */ | 1009 char *rootname = NULL; /* default to current volume */ |
1010 volume_info_data * info; | |
774 | 1011 |
775 if (name == NULL) | 1012 if (name == NULL) |
776 return FALSE; | 1013 return FALSE; |
777 | 1014 |
778 /* find the root name of the volume if given */ | 1015 /* find the root name of the volume if given */ |
802 } | 1039 } |
803 | 1040 |
804 if (pPath) | 1041 if (pPath) |
805 *pPath = name; | 1042 *pPath = name; |
806 | 1043 |
807 if (GetVolumeInformation (rootname, | 1044 info = GetCachedVolumeInformation (rootname); |
808 volume_info.name, 32, | 1045 if (info != NULL) |
809 &volume_info.serialnum, | 1046 { |
810 &volume_info.maxcomp, | 1047 /* Set global referenced by other functions. */ |
811 &volume_info.flags, | 1048 volume_info = *info; |
812 volume_info.type, 32)) | |
813 { | |
814 return TRUE; | 1049 return TRUE; |
815 } | 1050 } |
816 return FALSE; | 1051 return FALSE; |
817 } | 1052 } |
818 | 1053 |
832 { | 1067 { |
833 static char shortname[MAX_PATH]; | 1068 static char shortname[MAX_PATH]; |
834 char * str = shortname; | 1069 char * str = shortname; |
835 char c; | 1070 char c; |
836 char * path; | 1071 char * path; |
1072 const char * save_name = name; | |
837 | 1073 |
838 if (is_fat_volume (name, &path)) /* truncate to 8.3 */ | 1074 if (is_fat_volume (name, &path)) /* truncate to 8.3 */ |
839 { | 1075 { |
840 REGISTER int left = 8; /* maximum number of chars in part */ | 1076 REGISTER int left = 8; /* maximum number of chars in part */ |
841 REGISTER int extn = 0; /* extension added? */ | 1077 REGISTER int extn = 0; /* extension added? */ |
916 strcpy (shortname, name); | 1152 strcpy (shortname, name); |
917 unixtodos_filename (shortname); | 1153 unixtodos_filename (shortname); |
918 } | 1154 } |
919 | 1155 |
920 if (pPath) | 1156 if (pPath) |
921 *pPath = shortname + (path - name); | 1157 *pPath = shortname + (path - save_name); |
922 | 1158 |
923 return shortname; | 1159 return shortname; |
924 } | 1160 } |
925 | 1161 |
1162 | |
1163 /* Emulate the Unix directory procedures opendir, closedir, | |
1164 and readdir. We can't use the procedures supplied in sysdep.c, | |
1165 so we provide them here. */ | |
1166 | |
1167 struct direct dir_static; /* simulated directory contents */ | |
1168 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; | |
1169 static int dir_is_fat; | |
1170 static char dir_pathname[MAXPATHLEN+1]; | |
1171 static WIN32_FIND_DATA dir_find_data; | |
1172 | |
1173 DIR * | |
1174 opendir (char *filename) | |
1175 { | |
1176 DIR *dirp; | |
1177 | |
1178 /* Opening is done by FindFirstFile. However, a read is inherent to | |
1179 this operation, so we defer the open until read time. */ | |
1180 | |
1181 if (!(dirp = (DIR *) xmalloc (sizeof (DIR)))) | |
1182 return NULL; | |
1183 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
1184 return NULL; | |
1185 | |
1186 dirp->dd_fd = 0; | |
1187 dirp->dd_loc = 0; | |
1188 dirp->dd_size = 0; | |
1189 | |
1190 strncpy (dir_pathname, map_win32_filename (filename, NULL), MAXPATHLEN); | |
1191 dir_pathname[MAXPATHLEN] = '\0'; | |
1192 dir_is_fat = is_fat_volume (filename, NULL); | |
1193 | |
1194 return dirp; | |
1195 } | |
1196 | |
1197 void | |
1198 closedir (DIR *dirp) | |
1199 { | |
1200 /* If we have a find-handle open, close it. */ | |
1201 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
1202 { | |
1203 FindClose (dir_find_handle); | |
1204 dir_find_handle = INVALID_HANDLE_VALUE; | |
1205 } | |
1206 xfree ((char *) dirp); | |
1207 } | |
1208 | |
1209 struct direct * | |
1210 readdir (DIR *dirp) | |
1211 { | |
1212 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ | |
1213 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
1214 { | |
1215 char filename[MAXNAMLEN + 3]; | |
1216 int ln; | |
1217 | |
1218 strcpy (filename, dir_pathname); | |
1219 ln = strlen (filename) - 1; | |
1220 if (!IS_DIRECTORY_SEP (filename[ln])) | |
1221 strcat (filename, "\\"); | |
1222 strcat (filename, "*"); | |
1223 | |
1224 dir_find_handle = FindFirstFile (filename, &dir_find_data); | |
1225 | |
1226 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
1227 return NULL; | |
1228 } | |
1229 else | |
1230 { | |
1231 if (!FindNextFile (dir_find_handle, &dir_find_data)) | |
1232 return NULL; | |
1233 } | |
1234 | |
1235 /* Emacs never uses this value, so don't bother making it match | |
1236 value returned by stat(). */ | |
1237 dir_static.d_ino = 1; | |
1238 | |
1239 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + | |
1240 dir_static.d_namlen - dir_static.d_namlen % 4; | |
1241 | |
1242 dir_static.d_namlen = strlen (dir_find_data.cFileName); | |
1243 strcpy (dir_static.d_name, dir_find_data.cFileName); | |
1244 if (dir_is_fat) | |
1245 _strlwr (dir_static.d_name); | |
1246 else if (!NILP (Vwin32_downcase_file_names)) | |
1247 { | |
1248 REGISTER char *p; | |
1249 for (p = dir_static.d_name; *p; p++) | |
1250 if (*p >= 'a' && *p <= 'z') | |
1251 break; | |
1252 if (!*p) | |
1253 _strlwr (dir_static.d_name); | |
1254 } | |
1255 | |
1256 return &dir_static; | |
1257 } | |
926 | 1258 |
927 /* Shadow some MSVC runtime functions to map requests for long filenames | 1259 /* Shadow some MSVC runtime functions to map requests for long filenames |
928 to reasonable short names if necessary. This was originally added to | 1260 to reasonable short names if necessary. This was originally added to |
929 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support | 1261 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support |
930 long file names. */ | 1262 long file names. */ |
992 | 1324 |
993 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644); | 1325 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644); |
994 if (fd < 0) | 1326 if (fd < 0) |
995 return NULL; | 1327 return NULL; |
996 | 1328 |
997 return fdopen (fd, mode_save); | 1329 return _fdopen (fd, mode_save); |
998 } | 1330 } |
999 | 1331 |
1332 /* This only works on NTFS volumes, but is useful to have. */ | |
1000 int | 1333 int |
1001 sys_link (const char * path1, const char * path2) | 1334 sys_link (const char * old, const char * new) |
1002 { | 1335 { |
1003 errno = EINVAL; | 1336 HANDLE fileh; |
1337 int result = -1; | |
1338 char oldname[MAX_PATH], newname[MAX_PATH]; | |
1339 | |
1340 if (old == NULL || new == NULL) | |
1341 { | |
1342 errno = ENOENT; | |
1004 return -1; | 1343 return -1; |
1344 } | |
1345 | |
1346 strcpy (oldname, map_win32_filename (old, NULL)); | |
1347 strcpy (newname, map_win32_filename (new, NULL)); | |
1348 | |
1349 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING, | |
1350 FILE_FLAG_BACKUP_SEMANTICS, NULL); | |
1351 if (fileh != INVALID_HANDLE_VALUE) | |
1352 { | |
1353 int wlen; | |
1354 | |
1355 /* Confusingly, the "alternate" stream name field does not apply | |
1356 when restoring a hard link, and instead contains the actual | |
1357 stream data for the link (ie. the name of the link to create). | |
1358 The WIN32_STREAM_ID structure before the cStreamName field is | |
1359 the stream header, which is then immediately followed by the | |
1360 stream data. */ | |
1361 | |
1362 struct { | |
1363 WIN32_STREAM_ID wid; | |
1364 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */ | |
1365 } data; | |
1366 | |
1367 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1, | |
1368 data.wid.cStreamName, MAX_PATH); | |
1369 if (wlen > 0) | |
1370 { | |
1371 LPVOID context = NULL; | |
1372 DWORD wbytes = 0; | |
1373 | |
1374 data.wid.dwStreamId = BACKUP_LINK; | |
1375 data.wid.dwStreamAttributes = 0; | |
1376 data.wid.Size.LowPart = wlen * sizeof(WCHAR); | |
1377 data.wid.Size.HighPart = 0; | |
1378 data.wid.dwStreamNameSize = 0; | |
1379 | |
1380 if (BackupWrite (fileh, (LPBYTE)&data, | |
1381 offsetof (WIN32_STREAM_ID, cStreamName) | |
1382 + data.wid.Size.LowPart, | |
1383 &wbytes, FALSE, FALSE, &context) | |
1384 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context)) | |
1385 { | |
1386 /* succeeded */ | |
1387 result = 0; | |
1388 } | |
1389 else | |
1390 { | |
1391 /* Should try mapping GetLastError to errno; for now just | |
1392 indicate a general error (eg. links not supported). */ | |
1393 errno = EINVAL; // perhaps EMLINK? | |
1394 } | |
1395 } | |
1396 | |
1397 CloseHandle (fileh); | |
1398 } | |
1399 else | |
1400 errno = ENOENT; | |
1401 | |
1402 return result; | |
1005 } | 1403 } |
1006 | 1404 |
1007 int | 1405 int |
1008 sys_mkdir (const char * path) | 1406 sys_mkdir (const char * path) |
1009 { | 1407 { |
1094 | 1492 |
1095 if (p = strrchr (temp, '\\')) | 1493 if (p = strrchr (temp, '\\')) |
1096 p++; | 1494 p++; |
1097 else | 1495 else |
1098 p = temp; | 1496 p = temp; |
1099 strcpy (p, "__XXXXXX"); | |
1100 sys_mktemp (temp); | |
1101 /* Force temp name to require a manufactured 8.3 alias - this | 1497 /* Force temp name to require a manufactured 8.3 alias - this |
1102 seems to make the second rename work properly. */ | 1498 seems to make the second rename work properly. */ |
1103 strcat (temp, ".long"); | 1499 strcpy (p, "_rename_temp.XXXXXX"); |
1500 sys_mktemp (temp); | |
1104 if (rename (map_win32_filename (oldname, NULL), temp) < 0) | 1501 if (rename (map_win32_filename (oldname, NULL), temp) < 0) |
1105 return -1; | 1502 return -1; |
1106 } | 1503 } |
1107 | 1504 |
1108 /* Emulate Unix behaviour - newname is deleted if it already exists | 1505 /* Emulate Unix behaviour - newname is deleted if it already exists |
1109 (at least if it is a file; don't do this for directories). | 1506 (at least if it is a file; don't do this for directories). |
1110 However, don't do this if we are just changing the case of the file | 1507 However, don't do this if we are just changing the case of the file |
1111 name - we will end up deleting the file we are trying to rename! */ | 1508 name - we will end up deleting the file we are trying to rename! */ |
1112 newname = map_win32_filename (newname, NULL); | 1509 newname = map_win32_filename (newname, NULL); |
1510 | |
1511 /* TODO: Use GetInformationByHandle (on NT) to ensure newname and temp | |
1512 do not refer to the same file, eg. through share aliases. */ | |
1113 if (stricmp (newname, temp) != 0 | 1513 if (stricmp (newname, temp) != 0 |
1114 && (attr = GetFileAttributes (newname)) != -1 | 1514 && (attr = GetFileAttributes (newname)) != -1 |
1115 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) | 1515 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) |
1116 { | 1516 { |
1117 _chmod (newname, 0666); | 1517 _chmod (newname, 0666); |
1200 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); | 1600 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); |
1201 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime); | 1601 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime); |
1202 } | 1602 } |
1203 #endif | 1603 #endif |
1204 | 1604 |
1205 /* "PJW" algorithm (see the "Dragon" compiler book). */ | 1605 #if 0 |
1606 /* No reason to keep this; faking inode values either by hashing or even | |
1607 using the file index from GetInformationByHandle, is not perfect and | |
1608 so by default Emacs doesn't use the inode values on Windows. | |
1609 Instead, we now determine file-truename correctly (except for | |
1610 possible drive aliasing etc). */ | |
1611 | |
1612 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */ | |
1206 static unsigned | 1613 static unsigned |
1207 hashval (const char * str) | 1614 hashval (const unsigned char * str) |
1208 { | 1615 { |
1209 unsigned h = 0; | 1616 unsigned h = 0; |
1210 unsigned g; | |
1211 while (*str) | 1617 while (*str) |
1212 { | 1618 { |
1213 h = (h << 4) + *str++; | 1619 h = (h << 4) + *str++; |
1214 if ((g = h & 0xf0000000) != 0) | 1620 h ^= (h >> 28); |
1215 h = (h ^ (g >> 24)) & 0x0fffffff; | |
1216 } | 1621 } |
1217 return h; | 1622 return h; |
1218 } | 1623 } |
1219 | 1624 |
1220 /* Return the hash value of the canonical pathname, excluding the | 1625 /* Return the hash value of the canonical pathname, excluding the |
1221 drive/UNC header, to get a hopefully unique inode number. */ | 1626 drive/UNC header, to get a hopefully unique inode number. */ |
1222 static _ino_t | 1627 static DWORD |
1223 generate_inode_val (const char * name) | 1628 generate_inode_val (const char * name) |
1224 { | 1629 { |
1225 char fullname[ MAX_PATH ]; | 1630 char fullname[ MAX_PATH ]; |
1226 char * p; | 1631 char * p; |
1227 unsigned hash; | 1632 unsigned hash; |
1228 | 1633 |
1229 GetFullPathName (name, sizeof (fullname), fullname, &p); | 1634 /* Get the truly canonical filename, if it exists. (Note: this |
1230 get_volume_info (fullname, &p); | 1635 doesn't resolve aliasing due to subst commands, or recognise hard |
1636 links. */ | |
1637 if (!win32_get_long_filename ((char *)name, fullname, MAX_PATH)) | |
1638 abort (); | |
1639 | |
1640 parse_root (fullname, &p); | |
1231 /* Normal Win32 filesystems are still case insensitive. */ | 1641 /* Normal Win32 filesystems are still case insensitive. */ |
1232 _strlwr (p); | 1642 _strlwr (p); |
1233 hash = hashval (p); | 1643 return hashval (p); |
1234 return (_ino_t) (hash ^ (hash >> 16)); | 1644 } |
1235 } | 1645 |
1646 #endif | |
1236 | 1647 |
1237 /* MSVC stat function can't cope with UNC names and has other bugs, so | 1648 /* MSVC stat function can't cope with UNC names and has other bugs, so |
1238 replace it with our own. This also allows us to calculate consistent | 1649 replace it with our own. This also allows us to calculate consistent |
1239 inode values without hacks in the main Emacs code. */ | 1650 inode values without hacks in the main Emacs code. */ |
1240 int | 1651 int |
1241 stat (const char * path, struct stat * buf) | 1652 stat (const char * path, struct stat * buf) |
1242 { | 1653 { |
1243 char * name; | 1654 char * name; |
1244 WIN32_FIND_DATA wfd; | 1655 WIN32_FIND_DATA wfd; |
1245 HANDLE fh; | 1656 HANDLE fh; |
1657 DWORD fake_inode; | |
1246 int permission; | 1658 int permission; |
1247 int len; | 1659 int len; |
1248 int rootdir = FALSE; | 1660 int rootdir = FALSE; |
1249 | 1661 |
1250 if (path == NULL || buf == NULL) | 1662 if (path == NULL || buf == NULL) |
1287 } | 1699 } |
1288 else | 1700 else |
1289 { | 1701 { |
1290 if (IS_DIRECTORY_SEP (name[len-1])) | 1702 if (IS_DIRECTORY_SEP (name[len-1])) |
1291 name[len - 1] = 0; | 1703 name[len - 1] = 0; |
1704 | |
1705 /* (This is hacky, but helps when doing file completions on | |
1706 network drives.) Optimize by using information available from | |
1707 active readdir if possible. */ | |
1708 if (dir_find_handle != INVALID_HANDLE_VALUE && | |
1709 (len = strlen (dir_pathname)), | |
1710 strnicmp (name, dir_pathname, len) == 0 && | |
1711 IS_DIRECTORY_SEP (name[len]) && | |
1712 stricmp (name + len + 1, dir_static.d_name) == 0) | |
1713 { | |
1714 /* This was the last entry returned by readdir. */ | |
1715 wfd = dir_find_data; | |
1716 } | |
1717 else | |
1718 { | |
1292 fh = FindFirstFile (name, &wfd); | 1719 fh = FindFirstFile (name, &wfd); |
1293 if (fh == INVALID_HANDLE_VALUE) | 1720 if (fh == INVALID_HANDLE_VALUE) |
1294 { | 1721 { |
1295 errno = ENOENT; | 1722 errno = ENOENT; |
1296 return -1; | 1723 return -1; |
1297 } | 1724 } |
1298 FindClose (fh); | 1725 FindClose (fh); |
1299 } | 1726 } |
1727 } | |
1300 | 1728 |
1301 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | 1729 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
1302 { | 1730 { |
1303 buf->st_mode = _S_IFDIR; | 1731 buf->st_mode = _S_IFDIR; |
1304 buf->st_nlink = 2; /* doesn't really matter */ | 1732 buf->st_nlink = 2; /* doesn't really matter */ |
1305 } | 1733 fake_inode = 0; /* this doesn't either I think */ |
1306 else | 1734 } |
1307 { | 1735 else if (!NILP (Vwin32_get_true_file_attributes)) |
1308 #if 0 | 1736 { |
1309 /* This is more accurate in terms of gettting the correct number | 1737 /* This is more accurate in terms of gettting the correct number |
1310 of links, but is quite slow (it is noticable when Emacs is | 1738 of links, but is quite slow (it is noticable when Emacs is |
1311 making a list of file name completions). */ | 1739 making a list of file name completions). */ |
1312 BY_HANDLE_FILE_INFORMATION info; | 1740 BY_HANDLE_FILE_INFORMATION info; |
1313 | 1741 |
1314 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, | 1742 /* No access rights required to get info. */ |
1315 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 1743 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL); |
1316 | 1744 |
1317 if (GetFileInformationByHandle (fh, &info)) | 1745 if (GetFileInformationByHandle (fh, &info)) |
1318 { | 1746 { |
1319 switch (GetFileType (fh)) | 1747 switch (GetFileType (fh)) |
1320 { | 1748 { |
1328 case FILE_TYPE_UNKNOWN: | 1756 case FILE_TYPE_UNKNOWN: |
1329 default: | 1757 default: |
1330 buf->st_mode = _S_IFCHR; | 1758 buf->st_mode = _S_IFCHR; |
1331 } | 1759 } |
1332 buf->st_nlink = info.nNumberOfLinks; | 1760 buf->st_nlink = info.nNumberOfLinks; |
1333 /* Could use file index, but this is not guaranteed to be | 1761 /* Might as well use file index to fake inode values, but this |
1334 unique unless we keep a handle open all the time. */ | 1762 is not guaranteed to be unique unless we keep a handle open |
1335 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */ | 1763 all the time (even then there are situations where it is |
1764 not unique). Reputedly, there are at most 48 bits of info | |
1765 (on NTFS, presumably less on FAT). */ | |
1766 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | |
1336 CloseHandle (fh); | 1767 CloseHandle (fh); |
1337 } | 1768 } |
1338 else | 1769 else |
1339 { | 1770 { |
1340 errno = EACCES; | 1771 errno = EACCES; |
1341 return -1; | 1772 return -1; |
1342 } | 1773 } |
1343 #else | 1774 } |
1775 else | |
1776 { | |
1777 /* Don't bother to make this information more accurate. */ | |
1344 buf->st_mode = _S_IFREG; | 1778 buf->st_mode = _S_IFREG; |
1345 buf->st_nlink = 1; | 1779 buf->st_nlink = 1; |
1780 fake_inode = 0; | |
1781 } | |
1782 | |
1783 #if 0 | |
1784 /* Not sure if there is any point in this. */ | |
1785 if (!NILP (Vwin32_generate_fake_inodes)) | |
1786 fake_inode = generate_inode_val (name); | |
1787 else if (fake_inode == 0) | |
1788 { | |
1789 /* For want of something better, try to make everything unique. */ | |
1790 static DWORD gen_num = 0; | |
1791 fake_inode = ++gen_num; | |
1792 } | |
1346 #endif | 1793 #endif |
1347 } | 1794 |
1795 /* MSVC defines _ino_t to be short; other libc's might not. */ | |
1796 if (sizeof (buf->st_ino) == 2) | |
1797 buf->st_ino = fake_inode ^ (fake_inode >> 16); | |
1798 else | |
1799 buf->st_ino = fake_inode; | |
1348 | 1800 |
1349 /* consider files to belong to current user */ | 1801 /* consider files to belong to current user */ |
1350 buf->st_uid = the_passwd.pw_uid; | 1802 buf->st_uid = the_passwd.pw_uid; |
1351 buf->st_gid = the_passwd.pw_gid; | 1803 buf->st_gid = the_passwd.pw_gid; |
1352 | 1804 |
1353 /* volume_info is set indirectly by map_win32_filename */ | 1805 /* volume_info is set indirectly by map_win32_filename */ |
1354 buf->st_dev = volume_info.serialnum; | 1806 buf->st_dev = volume_info.serialnum; |
1355 buf->st_rdev = volume_info.serialnum; | 1807 buf->st_rdev = volume_info.serialnum; |
1356 | 1808 |
1357 buf->st_ino = generate_inode_val (name); | |
1358 | 1809 |
1359 buf->st_size = wfd.nFileSizeLow; | 1810 buf->st_size = wfd.nFileSizeLow; |
1360 | 1811 |
1361 /* Convert timestamps to Unix format. */ | 1812 /* Convert timestamps to Unix format. */ |
1362 buf->st_mtime = convert_time (wfd.ftLastWriteTime); | 1813 buf->st_mtime = convert_time (wfd.ftLastWriteTime); |
1897 { | 2348 { |
1898 int rc; | 2349 int rc; |
1899 unsigned flags; | 2350 unsigned flags; |
1900 child_process * cp; | 2351 child_process * cp; |
1901 | 2352 |
1902 /* make pipe handles non-inheritable; when we spawn a child, | 2353 /* make pipe handles non-inheritable; when we spawn a child, we |
1903 we replace the relevant handle with an inheritable one. */ | 2354 replace the relevant handle with an inheritable one. Also put |
1904 rc = _pipe (phandles, 0, _O_NOINHERIT); | 2355 pipes into binary mode; we will do text mode translation ourselves |
2356 if required. */ | |
2357 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY); | |
1905 | 2358 |
1906 if (rc == 0) | 2359 if (rc == 0) |
1907 { | 2360 { |
1908 /* set internal flags, and put read and write handles into binary | |
1909 mode as necessary; if not in binary mode, set the MSVC internal | |
1910 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this | |
1911 could otherwise allow Emacs to hang because it then waits | |
1912 indefinitely for the child process to exit, when it might not be | |
1913 finished). */ | |
1914 flags = FILE_PIPE | FILE_READ; | 2361 flags = FILE_PIPE | FILE_READ; |
1915 if (!NILP (Vbinary_process_output)) | 2362 if (!NILP (Vbinary_process_output)) |
1916 { | |
1917 flags |= FILE_BINARY; | 2363 flags |= FILE_BINARY; |
1918 setmode (phandles[0], _O_BINARY); | |
1919 } | |
1920 #if (_MSC_VER == 900) | |
1921 else | |
1922 _osfile[phandles[0]] |= 0x40; | |
1923 #endif | |
1924 | |
1925 fd_info[phandles[0]].flags = flags; | 2364 fd_info[phandles[0]].flags = flags; |
1926 | 2365 |
1927 flags = FILE_PIPE | FILE_WRITE; | 2366 flags = FILE_PIPE | FILE_WRITE; |
1928 if (!NILP (Vbinary_process_input)) | 2367 if (!NILP (Vbinary_process_input)) |
1929 { | |
1930 flags |= FILE_BINARY; | 2368 flags |= FILE_BINARY; |
1931 setmode (phandles[1], _O_BINARY); | |
1932 } | |
1933 #if (_MSC_VER == 900) | |
1934 else | |
1935 _osfile[phandles[1]] |= 0x40; | |
1936 #endif | |
1937 | |
1938 fd_info[phandles[1]].flags = flags; | 2369 fd_info[phandles[1]].flags = flags; |
1939 } | 2370 } |
1940 | 2371 |
1941 return rc; | 2372 return rc; |
1942 } | 2373 } |
1969 | 2400 |
1970 cp->status = STATUS_READ_IN_PROGRESS; | 2401 cp->status = STATUS_READ_IN_PROGRESS; |
1971 | 2402 |
1972 if (fd_info[fd].flags & FILE_PIPE) | 2403 if (fd_info[fd].flags & FILE_PIPE) |
1973 { | 2404 { |
1974 /* Use read to get CRLF translation */ | |
1975 rc = _read (fd, &cp->chr, sizeof (char)); | 2405 rc = _read (fd, &cp->chr, sizeof (char)); |
1976 | 2406 |
1977 /* Give subprocess time to buffer some more output for us before | 2407 /* Give subprocess time to buffer some more output for us before |
1978 reporting that input is available; we need this because Win95 | 2408 reporting that input is available; we need this because Win95 |
1979 connects DOS programs to pipes by making the pipe appear to be | 2409 connects DOS programs to pipes by making the pipe appear to be |
2009 | 2439 |
2010 int | 2440 int |
2011 sys_read (int fd, char * buffer, unsigned int count) | 2441 sys_read (int fd, char * buffer, unsigned int count) |
2012 { | 2442 { |
2013 int nchars; | 2443 int nchars; |
2014 int extra = 0; | |
2015 int to_read; | 2444 int to_read; |
2016 DWORD waiting; | 2445 DWORD waiting; |
2446 char * orig_buffer = buffer; | |
2017 | 2447 |
2018 if (fd < 0 || fd >= MAXDESC) | 2448 if (fd < 0 || fd >= MAXDESC) |
2019 { | 2449 { |
2020 errno = EBADF; | 2450 errno = EBADF; |
2021 return -1; | 2451 return -1; |
2027 | 2457 |
2028 if ((fd_info[fd].flags & FILE_READ) == 0) | 2458 if ((fd_info[fd].flags & FILE_READ) == 0) |
2029 { | 2459 { |
2030 errno = EBADF; | 2460 errno = EBADF; |
2031 return -1; | 2461 return -1; |
2462 } | |
2463 | |
2464 nchars = 0; | |
2465 | |
2466 /* re-read CR carried over from last read */ | |
2467 if (fd_info[fd].flags & FILE_LAST_CR) | |
2468 { | |
2469 if (fd_info[fd].flags & FILE_BINARY) abort (); | |
2470 *buffer++ = 0x0d; | |
2471 count--; | |
2472 nchars++; | |
2473 fd_info[fd].flags &= ~FILE_LAST_CR; | |
2032 } | 2474 } |
2033 | 2475 |
2034 /* presence of a child_process structure means we are operating in | 2476 /* presence of a child_process structure means we are operating in |
2035 non-blocking mode - otherwise we just call _read directly. | 2477 non-blocking mode - otherwise we just call _read directly. |
2036 Note that the child_process structure might be missing because | 2478 Note that the child_process structure might be missing because |
2042 | 2484 |
2043 switch (current_status) | 2485 switch (current_status) |
2044 { | 2486 { |
2045 case STATUS_READ_FAILED: | 2487 case STATUS_READ_FAILED: |
2046 case STATUS_READ_ERROR: | 2488 case STATUS_READ_ERROR: |
2047 /* report normal EOF */ | 2489 /* report normal EOF if nothing in buffer */ |
2048 return 0; | 2490 if (nchars <= 0) |
2491 fd_info[fd].flags |= FILE_AT_EOF; | |
2492 return nchars; | |
2049 | 2493 |
2050 case STATUS_READ_READY: | 2494 case STATUS_READ_READY: |
2051 case STATUS_READ_IN_PROGRESS: | 2495 case STATUS_READ_IN_PROGRESS: |
2052 DebPrint (("sys_read called when read is in progress\n")); | 2496 DebPrint (("sys_read called when read is in progress\n")); |
2053 errno = EWOULDBLOCK; | 2497 errno = EWOULDBLOCK; |
2055 | 2499 |
2056 case STATUS_READ_SUCCEEDED: | 2500 case STATUS_READ_SUCCEEDED: |
2057 /* consume read-ahead char */ | 2501 /* consume read-ahead char */ |
2058 *buffer++ = cp->chr; | 2502 *buffer++ = cp->chr; |
2059 count--; | 2503 count--; |
2060 extra = 1; | 2504 nchars++; |
2061 cp->status = STATUS_READ_ACKNOWLEDGED; | 2505 cp->status = STATUS_READ_ACKNOWLEDGED; |
2062 ResetEvent (cp->char_avail); | 2506 ResetEvent (cp->char_avail); |
2063 | 2507 |
2064 case STATUS_READ_ACKNOWLEDGED: | 2508 case STATUS_READ_ACKNOWLEDGED: |
2065 break; | 2509 break; |
2073 if (fd_info[fd].flags & FILE_PIPE) | 2517 if (fd_info[fd].flags & FILE_PIPE) |
2074 { | 2518 { |
2075 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL); | 2519 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL); |
2076 to_read = min (waiting, (DWORD) count); | 2520 to_read = min (waiting, (DWORD) count); |
2077 | 2521 |
2078 /* Use read to get CRLF translation */ | 2522 if (to_read > 0) |
2079 nchars = _read (fd, buffer, to_read); | 2523 nchars += _read (fd, buffer, to_read); |
2080 } | 2524 } |
2081 #ifdef HAVE_SOCKETS | 2525 #ifdef HAVE_SOCKETS |
2082 else /* FILE_SOCKET */ | 2526 else /* FILE_SOCKET */ |
2083 { | 2527 { |
2084 if (winsock_lib == NULL) abort (); | 2528 if (winsock_lib == NULL) abort (); |
2085 | 2529 |
2086 /* do the equivalent of a non-blocking read */ | 2530 /* do the equivalent of a non-blocking read */ |
2087 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); | 2531 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); |
2088 if (waiting == 0 && extra == 0) | 2532 if (waiting == 0 && nchars == 0) |
2089 { | 2533 { |
2090 h_errno = errno = EWOULDBLOCK; | 2534 h_errno = errno = EWOULDBLOCK; |
2091 return -1; | 2535 return -1; |
2092 } | 2536 } |
2093 | 2537 |
2094 nchars = 0; | |
2095 if (waiting) | 2538 if (waiting) |
2096 { | 2539 { |
2097 /* always use binary mode for sockets */ | 2540 /* always use binary mode for sockets */ |
2098 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0); | 2541 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0); |
2099 if (nchars == SOCKET_ERROR) | 2542 if (res == SOCKET_ERROR) |
2100 { | 2543 { |
2101 DebPrint(("sys_read.recv failed with error %d on socket %ld\n", | 2544 DebPrint(("sys_read.recv failed with error %d on socket %ld\n", |
2102 pfn_WSAGetLastError (), SOCK_HANDLE (fd))); | 2545 pfn_WSAGetLastError (), SOCK_HANDLE (fd))); |
2103 if (extra == 0) | |
2104 { | |
2105 set_errno (); | 2546 set_errno (); |
2106 return -1; | 2547 return -1; |
2107 } | 2548 } |
2108 nchars = 0; | 2549 nchars += res; |
2109 } | |
2110 } | 2550 } |
2111 } | 2551 } |
2112 #endif | 2552 #endif |
2113 } | 2553 } |
2114 else | 2554 else |
2115 nchars = _read (fd, buffer, count); | 2555 { |
2556 int nread = _read (fd, buffer, count); | |
2557 if (nread >= 0) | |
2558 nchars += nread; | |
2559 else if (nchars == 0) | |
2560 nchars = nread; | |
2561 } | |
2562 | |
2563 if (nchars <= 0) | |
2564 fd_info[fd].flags |= FILE_AT_EOF; | |
2565 /* Perform text mode translation if required. */ | |
2566 else if ((fd_info[fd].flags & FILE_BINARY) == 0) | |
2567 { | |
2568 unsigned lf_count = 0; | |
2569 nchars = crlf_to_lf (nchars, orig_buffer, &lf_count); | |
2570 /* If buffer contains only CR, return that. To be absolutely | |
2571 sure we should attempt to read the next char, but in | |
2572 practice a CR to be followed by LF would not appear by | |
2573 itself in the buffer. */ | |
2574 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d) | |
2575 { | |
2576 fd_info[fd].flags |= FILE_LAST_CR; | |
2577 nchars--; | |
2578 } | |
2579 } | |
2116 } | 2580 } |
2117 else | 2581 else |
2118 nchars = _read (fd, buffer, count); | 2582 nchars = _read (fd, buffer, count); |
2119 | 2583 |
2120 return nchars + extra; | 2584 return nchars; |
2121 } | 2585 } |
2122 | 2586 |
2123 /* For now, don't bother with a non-blocking mode */ | 2587 /* For now, don't bother with a non-blocking mode */ |
2124 int | 2588 int |
2125 sys_write (int fd, const void * buffer, unsigned int count) | 2589 sys_write (int fd, const void * buffer, unsigned int count) |
2131 errno = EBADF; | 2595 errno = EBADF; |
2132 return -1; | 2596 return -1; |
2133 } | 2597 } |
2134 | 2598 |
2135 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) | 2599 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) |
2600 { | |
2136 if ((fd_info[fd].flags & FILE_WRITE) == 0) | 2601 if ((fd_info[fd].flags & FILE_WRITE) == 0) |
2137 { | 2602 { |
2138 errno = EBADF; | 2603 errno = EBADF; |
2139 return -1; | 2604 return -1; |
2140 } | 2605 } |
2606 | |
2607 /* Perform text mode translation if required. */ | |
2608 if ((fd_info[fd].flags & FILE_BINARY) == 0) | |
2609 { | |
2610 char * tmpbuf = alloca (count * 2); | |
2611 unsigned char * src = (void *)buffer; | |
2612 unsigned char * dst = tmpbuf; | |
2613 int nbytes = count; | |
2614 | |
2615 while (1) | |
2616 { | |
2617 unsigned char *next; | |
2618 /* copy next line or remaining bytes */ | |
2619 next = _memccpy (dst, src, '\n', nbytes); | |
2620 if (next) | |
2621 { | |
2622 /* copied one line ending with '\n' */ | |
2623 int copied = next - dst; | |
2624 nbytes -= copied; | |
2625 src += copied; | |
2626 /* insert '\r' before '\n' */ | |
2627 next[-1] = '\r'; | |
2628 next[0] = '\n'; | |
2629 dst = next + 1; | |
2630 count++; | |
2631 } | |
2632 else | |
2633 /* copied remaining partial line -> now finished */ | |
2634 break; | |
2635 } | |
2636 buffer = tmpbuf; | |
2637 } | |
2638 } | |
2639 | |
2141 #ifdef HAVE_SOCKETS | 2640 #ifdef HAVE_SOCKETS |
2142 if (fd_info[fd].flags & FILE_SOCKET) | 2641 if (fd_info[fd].flags & FILE_SOCKET) |
2143 { | 2642 { |
2144 if (winsock_lib == NULL) abort (); | 2643 if (winsock_lib == NULL) abort (); |
2145 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0); | 2644 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0); |
2164 #ifdef HAVE_SOCKETS | 2663 #ifdef HAVE_SOCKETS |
2165 /* shutdown the socket interface if necessary */ | 2664 /* shutdown the socket interface if necessary */ |
2166 term_winsock (); | 2665 term_winsock (); |
2167 #endif | 2666 #endif |
2168 } | 2667 } |
2169 | |
2170 extern BOOL dos_process_running; | |
2171 | 2668 |
2172 void | 2669 void |
2173 init_ntproc () | 2670 init_ntproc () |
2174 { | 2671 { |
2175 #ifdef HAVE_SOCKETS | 2672 #ifdef HAVE_SOCKETS |
2230 | 2727 |
2231 if (stdin_save != INVALID_HANDLE_VALUE) | 2728 if (stdin_save != INVALID_HANDLE_VALUE) |
2232 _open_osfhandle ((long) stdin_save, O_TEXT); | 2729 _open_osfhandle ((long) stdin_save, O_TEXT); |
2233 else | 2730 else |
2234 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY); | 2731 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY); |
2235 fdopen (0, "r"); | 2732 _fdopen (0, "r"); |
2236 | 2733 |
2237 if (stdout_save != INVALID_HANDLE_VALUE) | 2734 if (stdout_save != INVALID_HANDLE_VALUE) |
2238 _open_osfhandle ((long) stdout_save, O_TEXT); | 2735 _open_osfhandle ((long) stdout_save, O_TEXT); |
2239 else | 2736 else |
2240 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | 2737 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); |
2241 fdopen (1, "w"); | 2738 _fdopen (1, "w"); |
2242 | 2739 |
2243 if (stderr_save != INVALID_HANDLE_VALUE) | 2740 if (stderr_save != INVALID_HANDLE_VALUE) |
2244 _open_osfhandle ((long) stderr_save, O_TEXT); | 2741 _open_osfhandle ((long) stderr_save, O_TEXT); |
2245 else | 2742 else |
2246 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | 2743 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); |
2247 fdopen (2, "w"); | 2744 _fdopen (2, "w"); |
2248 } | 2745 } |
2249 | |
2250 /* Restrict Emacs to running only one DOS program at a time (with any | |
2251 number of Win32 programs). This is to prevent the user from | |
2252 running into problems with DOS programs being run in the same VDM | |
2253 under both Windows 95 and Windows NT. | |
2254 | |
2255 Note that it is possible for Emacs to run DOS programs in separate | |
2256 VDMs, but unfortunately the pipe implementation on Windows 95 then | |
2257 fails to report when the DOS process exits (which is supposed to | |
2258 break the pipe). Until this bug is fixed, or we can devise a | |
2259 work-around, we must try to avoid letting the user start more than | |
2260 one DOS program if possible. */ | |
2261 | |
2262 dos_process_running = FALSE; | |
2263 | 2746 |
2264 /* unfortunately, atexit depends on implementation of malloc */ | 2747 /* unfortunately, atexit depends on implementation of malloc */ |
2265 /* atexit (term_ntproc); */ | 2748 /* atexit (term_ntproc); */ |
2266 signal (SIGABRT, term_ntproc); | 2749 signal (SIGABRT, term_ntproc); |
2267 } | 2750 |
2268 | 2751 /* determine which drives are fixed, for GetCachedVolumeInformation */ |
2752 { | |
2753 /* GetDriveType must have trailing backslash. */ | |
2754 char drive[] = "A:\\"; | |
2755 | |
2756 /* Loop over all possible drive letters */ | |
2757 while ( *drive <= 'Z' ) | |
2758 { | |
2759 /* Record if this drive letter refers to a fixed drive. */ | |
2760 fixed_drives[ DRIVE_INDEX (*drive) ] = | |
2761 (GetDriveType (drive) == DRIVE_FIXED); | |
2762 | |
2763 (*drive)++; | |
2764 } | |
2765 } | |
2766 } | |
2269 #ifndef HAVE_TTY | 2767 #ifndef HAVE_TTY |
2270 Lisp_Object Vstdio_str; | 2768 Lisp_Object Vstdio_str; |
2271 | 2769 |
2272 Lisp_Object | 2770 Lisp_Object |
2273 tty_semi_canonicalize_console_connection (Lisp_Object connection, | 2771 tty_semi_canonicalize_console_connection (Lisp_Object connection, |