]> code.delx.au - gnu-emacs/blob - src/w32.c
(sys_chown): New function.
[gnu-emacs] / src / w32.c
1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
22 */
23
24
25 #include <stddef.h> /* for offsetof */
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <io.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <signal.h>
33 #include <sys/file.h>
34 #include <sys/time.h>
35 #include <sys/utime.h>
36
37 /* must include CRT headers *before* config.h */
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #undef access
44 #undef chdir
45 #undef chmod
46 #undef creat
47 #undef ctime
48 #undef fopen
49 #undef link
50 #undef mkdir
51 #undef mktemp
52 #undef open
53 #undef rename
54 #undef rmdir
55 #undef unlink
56
57 #undef close
58 #undef dup
59 #undef dup2
60 #undef pipe
61 #undef read
62 #undef write
63
64 #undef strerror
65
66 #include "lisp.h"
67
68 #include <pwd.h>
69 #include <grp.h>
70
71 #ifdef __GNUC__
72 #define _ANONYMOUS_UNION
73 #define _ANONYMOUS_STRUCT
74 #endif
75 #include <windows.h>
76
77 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
78 #include <sys/socket.h>
79 #undef socket
80 #undef bind
81 #undef connect
82 #undef htons
83 #undef ntohs
84 #undef inet_addr
85 #undef gethostname
86 #undef gethostbyname
87 #undef getservbyname
88 #undef getpeername
89 #undef shutdown
90 #undef setsockopt
91 #undef listen
92 #undef getsockname
93 #undef accept
94 #undef recvfrom
95 #undef sendto
96 #endif
97
98 #include "w32.h"
99 #include "ndir.h"
100 #include "w32heap.h"
101 #include "systime.h"
102
103 void globals_of_w32 ();
104
105 extern Lisp_Object Vw32_downcase_file_names;
106 extern Lisp_Object Vw32_generate_fake_inodes;
107 extern Lisp_Object Vw32_get_true_file_attributes;
108 extern int w32_num_mouse_buttons;
109
110 \f
111 /*
112 Initialization states
113 */
114 static BOOL g_b_init_is_windows_9x;
115 static BOOL g_b_init_open_process_token;
116 static BOOL g_b_init_get_token_information;
117 static BOOL g_b_init_lookup_account_sid;
118 static BOOL g_b_init_get_sid_identifier_authority;
119
120 /*
121 BEGIN: Wrapper functions around OpenProcessToken
122 and other functions in advapi32.dll that are only
123 supported in Windows NT / 2k / XP
124 */
125 /* ** Function pointer typedefs ** */
126 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
127 HANDLE ProcessHandle,
128 DWORD DesiredAccess,
129 PHANDLE TokenHandle);
130 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
131 HANDLE TokenHandle,
132 TOKEN_INFORMATION_CLASS TokenInformationClass,
133 LPVOID TokenInformation,
134 DWORD TokenInformationLength,
135 PDWORD ReturnLength);
136 #ifdef _UNICODE
137 const char * const LookupAccountSid_Name = "LookupAccountSidW";
138 #else
139 const char * const LookupAccountSid_Name = "LookupAccountSidA";
140 #endif
141 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
142 LPCTSTR lpSystemName,
143 PSID Sid,
144 LPTSTR Name,
145 LPDWORD cbName,
146 LPTSTR DomainName,
147 LPDWORD cbDomainName,
148 PSID_NAME_USE peUse);
149 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
150 PSID pSid);
151
152 /* ** A utility function ** */
153 static BOOL is_windows_9x ()
154 {
155 static BOOL s_b_ret=0;
156 OSVERSIONINFO os_ver;
157 if (g_b_init_is_windows_9x == 0)
158 {
159 g_b_init_is_windows_9x = 1;
160 ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
161 os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
162 if (GetVersionEx (&os_ver))
163 {
164 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
165 }
166 }
167 return s_b_ret;
168 }
169
170 /* ** The wrapper functions ** */
171
172 BOOL WINAPI open_process_token (
173 HANDLE ProcessHandle,
174 DWORD DesiredAccess,
175 PHANDLE TokenHandle)
176 {
177 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
178 HMODULE hm_advapi32 = NULL;
179 if (is_windows_9x () == TRUE)
180 {
181 return FALSE;
182 }
183 if (g_b_init_open_process_token == 0)
184 {
185 g_b_init_open_process_token = 1;
186 hm_advapi32 = LoadLibrary ("Advapi32.dll");
187 s_pfn_Open_Process_Token =
188 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
189 }
190 if (s_pfn_Open_Process_Token == NULL)
191 {
192 return FALSE;
193 }
194 return (
195 s_pfn_Open_Process_Token (
196 ProcessHandle,
197 DesiredAccess,
198 TokenHandle)
199 );
200 }
201
202 BOOL WINAPI get_token_information (
203 HANDLE TokenHandle,
204 TOKEN_INFORMATION_CLASS TokenInformationClass,
205 LPVOID TokenInformation,
206 DWORD TokenInformationLength,
207 PDWORD ReturnLength)
208 {
209 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
210 HMODULE hm_advapi32 = NULL;
211 if (is_windows_9x () == TRUE)
212 {
213 return FALSE;
214 }
215 if (g_b_init_get_token_information == 0)
216 {
217 g_b_init_get_token_information = 1;
218 hm_advapi32 = LoadLibrary ("Advapi32.dll");
219 s_pfn_Get_Token_Information =
220 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
221 }
222 if (s_pfn_Get_Token_Information == NULL)
223 {
224 return FALSE;
225 }
226 return (
227 s_pfn_Get_Token_Information (
228 TokenHandle,
229 TokenInformationClass,
230 TokenInformation,
231 TokenInformationLength,
232 ReturnLength)
233 );
234 }
235
236 BOOL WINAPI lookup_account_sid (
237 LPCTSTR lpSystemName,
238 PSID Sid,
239 LPTSTR Name,
240 LPDWORD cbName,
241 LPTSTR DomainName,
242 LPDWORD cbDomainName,
243 PSID_NAME_USE peUse)
244 {
245 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
246 HMODULE hm_advapi32 = NULL;
247 if (is_windows_9x () == TRUE)
248 {
249 return FALSE;
250 }
251 if (g_b_init_lookup_account_sid == 0)
252 {
253 g_b_init_lookup_account_sid = 1;
254 hm_advapi32 = LoadLibrary ("Advapi32.dll");
255 s_pfn_Lookup_Account_Sid =
256 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
257 }
258 if (s_pfn_Lookup_Account_Sid == NULL)
259 {
260 return FALSE;
261 }
262 return (
263 s_pfn_Lookup_Account_Sid (
264 lpSystemName,
265 Sid,
266 Name,
267 cbName,
268 DomainName,
269 cbDomainName,
270 peUse)
271 );
272 }
273
274 PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
275 PSID pSid)
276 {
277 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
278 HMODULE hm_advapi32 = NULL;
279 if (is_windows_9x () == TRUE)
280 {
281 return NULL;
282 }
283 if (g_b_init_get_sid_identifier_authority == 0)
284 {
285 g_b_init_get_sid_identifier_authority = 1;
286 hm_advapi32 = LoadLibrary ("Advapi32.dll");
287 s_pfn_Get_Sid_Identifier_Authority =
288 (GetSidIdentifierAuthority_Proc) GetProcAddress (
289 hm_advapi32, "GetSidIdentifierAuthority");
290 }
291 if (s_pfn_Get_Sid_Identifier_Authority == NULL)
292 {
293 return NULL;
294 }
295 return (s_pfn_Get_Sid_Identifier_Authority (pSid));
296 }
297
298 /*
299 END: Wrapper functions around OpenProcessToken
300 and other functions in advapi32.dll that are only
301 supported in Windows NT / 2k / XP
302 */
303
304 \f
305 /* Equivalent of strerror for W32 error codes. */
306 char *
307 w32_strerror (int error_no)
308 {
309 static char buf[500];
310
311 if (error_no == 0)
312 error_no = GetLastError ();
313
314 buf[0] = '\0';
315 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
316 error_no,
317 0, /* choose most suitable language */
318 buf, sizeof (buf), NULL))
319 sprintf (buf, "w32 error %u", error_no);
320 return buf;
321 }
322
323 static char startup_dir[MAXPATHLEN];
324
325 /* Get the current working directory. */
326 char *
327 getwd (char *dir)
328 {
329 #if 0
330 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
331 return dir;
332 return NULL;
333 #else
334 /* Emacs doesn't actually change directory itself, and we want to
335 force our real wd to be where emacs.exe is to avoid unnecessary
336 conflicts when trying to rename or delete directories. */
337 strcpy (dir, startup_dir);
338 return dir;
339 #endif
340 }
341
342 #ifndef HAVE_SOCKETS
343 /* Emulate gethostname. */
344 int
345 gethostname (char *buffer, int size)
346 {
347 /* NT only allows small host names, so the buffer is
348 certainly large enough. */
349 return !GetComputerName (buffer, &size);
350 }
351 #endif /* HAVE_SOCKETS */
352
353 /* Emulate getloadavg. */
354 int
355 getloadavg (double loadavg[], int nelem)
356 {
357 int i;
358
359 /* A faithful emulation is going to have to be saved for a rainy day. */
360 for (i = 0; i < nelem; i++)
361 {
362 loadavg[i] = 0.0;
363 }
364 return i;
365 }
366
367 /* Emulate getpwuid, getpwnam and others. */
368
369 #define PASSWD_FIELD_SIZE 256
370
371 static char the_passwd_name[PASSWD_FIELD_SIZE];
372 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
373 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
374 static char the_passwd_dir[PASSWD_FIELD_SIZE];
375 static char the_passwd_shell[PASSWD_FIELD_SIZE];
376
377 static struct passwd the_passwd =
378 {
379 the_passwd_name,
380 the_passwd_passwd,
381 0,
382 0,
383 0,
384 the_passwd_gecos,
385 the_passwd_dir,
386 the_passwd_shell,
387 };
388
389 static struct group the_group =
390 {
391 /* There are no groups on NT, so we just return "root" as the
392 group name. */
393 "root",
394 };
395
396 int
397 getuid ()
398 {
399 return the_passwd.pw_uid;
400 }
401
402 int
403 geteuid ()
404 {
405 /* I could imagine arguing for checking to see whether the user is
406 in the Administrators group and returning a UID of 0 for that
407 case, but I don't know how wise that would be in the long run. */
408 return getuid ();
409 }
410
411 int
412 getgid ()
413 {
414 return the_passwd.pw_gid;
415 }
416
417 int
418 getegid ()
419 {
420 return getgid ();
421 }
422
423 struct passwd *
424 getpwuid (int uid)
425 {
426 if (uid == the_passwd.pw_uid)
427 return &the_passwd;
428 return NULL;
429 }
430
431 struct group *
432 getgrgid (gid_t gid)
433 {
434 return &the_group;
435 }
436
437 struct passwd *
438 getpwnam (char *name)
439 {
440 struct passwd *pw;
441
442 pw = getpwuid (getuid ());
443 if (!pw)
444 return pw;
445
446 if (stricmp (name, pw->pw_name))
447 return NULL;
448
449 return pw;
450 }
451
452 void
453 init_user_info ()
454 {
455 /* Find the user's real name by opening the process token and
456 looking up the name associated with the user-sid in that token.
457
458 Use the relative portion of the identifier authority value from
459 the user-sid as the user id value (same for group id using the
460 primary group sid from the process token). */
461
462 char user_sid[256], name[256], domain[256];
463 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
464 HANDLE token = NULL;
465 SID_NAME_USE user_type;
466
467 if (
468 open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
469 && get_token_information (
470 token, TokenUser,
471 (PVOID) user_sid, sizeof (user_sid), &trash)
472 && lookup_account_sid (
473 NULL, *((PSID *) user_sid), name, &length,
474 domain, &dlength, &user_type)
475 )
476 {
477 strcpy (the_passwd.pw_name, name);
478 /* Determine a reasonable uid value. */
479 if (stricmp ("administrator", name) == 0)
480 {
481 the_passwd.pw_uid = 0;
482 the_passwd.pw_gid = 0;
483 }
484 else
485 {
486 SID_IDENTIFIER_AUTHORITY * pSIA;
487
488 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
489 /* I believe the relative portion is the last 4 bytes (of 6)
490 with msb first. */
491 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
492 (pSIA->Value[3] << 16) +
493 (pSIA->Value[4] << 8) +
494 (pSIA->Value[5] << 0));
495 /* restrict to conventional uid range for normal users */
496 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
497
498 /* Get group id */
499 if (get_token_information (token, TokenPrimaryGroup,
500 (PVOID) user_sid, sizeof (user_sid), &trash))
501 {
502 SID_IDENTIFIER_AUTHORITY * pSIA;
503
504 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
505 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
506 (pSIA->Value[3] << 16) +
507 (pSIA->Value[4] << 8) +
508 (pSIA->Value[5] << 0));
509 /* I don't know if this is necessary, but for safety... */
510 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
511 }
512 else
513 the_passwd.pw_gid = the_passwd.pw_uid;
514 }
515 }
516 /* If security calls are not supported (presumably because we
517 are running under Windows 95), fallback to this. */
518 else if (GetUserName (name, &length))
519 {
520 strcpy (the_passwd.pw_name, name);
521 if (stricmp ("administrator", name) == 0)
522 the_passwd.pw_uid = 0;
523 else
524 the_passwd.pw_uid = 123;
525 the_passwd.pw_gid = the_passwd.pw_uid;
526 }
527 else
528 {
529 strcpy (the_passwd.pw_name, "unknown");
530 the_passwd.pw_uid = 123;
531 the_passwd.pw_gid = 123;
532 }
533
534 /* Ensure HOME and SHELL are defined. */
535 if (getenv ("HOME") == NULL)
536 abort ();
537 if (getenv ("SHELL") == NULL)
538 abort ();
539
540 /* Set dir and shell from environment variables. */
541 strcpy (the_passwd.pw_dir, getenv ("HOME"));
542 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
543
544 if (token)
545 CloseHandle (token);
546 }
547
548 int
549 random ()
550 {
551 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
552 return ((rand () << 15) | rand ());
553 }
554
555 void
556 srandom (int seed)
557 {
558 srand (seed);
559 }
560
561
562 /* Normalize filename by converting all path separators to
563 the specified separator. Also conditionally convert upper
564 case path name components to lower case. */
565
566 static void
567 normalize_filename (fp, path_sep)
568 register char *fp;
569 char path_sep;
570 {
571 char sep;
572 char *elem;
573
574 /* Always lower-case drive letters a-z, even if the filesystem
575 preserves case in filenames.
576 This is so filenames can be compared by string comparison
577 functions that are case-sensitive. Even case-preserving filesystems
578 do not distinguish case in drive letters. */
579 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
580 {
581 *fp += 'a' - 'A';
582 fp += 2;
583 }
584
585 if (NILP (Vw32_downcase_file_names))
586 {
587 while (*fp)
588 {
589 if (*fp == '/' || *fp == '\\')
590 *fp = path_sep;
591 fp++;
592 }
593 return;
594 }
595
596 sep = path_sep; /* convert to this path separator */
597 elem = fp; /* start of current path element */
598
599 do {
600 if (*fp >= 'a' && *fp <= 'z')
601 elem = 0; /* don't convert this element */
602
603 if (*fp == 0 || *fp == ':')
604 {
605 sep = *fp; /* restore current separator (or 0) */
606 *fp = '/'; /* after conversion of this element */
607 }
608
609 if (*fp == '/' || *fp == '\\')
610 {
611 if (elem && elem != fp)
612 {
613 *fp = 0; /* temporary end of string */
614 _strlwr (elem); /* while we convert to lower case */
615 }
616 *fp = sep; /* convert (or restore) path separator */
617 elem = fp + 1; /* next element starts after separator */
618 sep = path_sep;
619 }
620 } while (*fp++);
621 }
622
623 /* Destructively turn backslashes into slashes. */
624 void
625 dostounix_filename (p)
626 register char *p;
627 {
628 normalize_filename (p, '/');
629 }
630
631 /* Destructively turn slashes into backslashes. */
632 void
633 unixtodos_filename (p)
634 register char *p;
635 {
636 normalize_filename (p, '\\');
637 }
638
639 /* Remove all CR's that are followed by a LF.
640 (From msdos.c...probably should figure out a way to share it,
641 although this code isn't going to ever change.) */
642 int
643 crlf_to_lf (n, buf)
644 register int n;
645 register unsigned char *buf;
646 {
647 unsigned char *np = buf;
648 unsigned char *startp = buf;
649 unsigned char *endp = buf + n;
650
651 if (n == 0)
652 return n;
653 while (buf < endp - 1)
654 {
655 if (*buf == 0x0d)
656 {
657 if (*(++buf) != 0x0a)
658 *np++ = 0x0d;
659 }
660 else
661 *np++ = *buf++;
662 }
663 if (buf < endp)
664 *np++ = *buf++;
665 return np - startp;
666 }
667
668 /* Parse the root part of file name, if present. Return length and
669 optionally store pointer to char after root. */
670 static int
671 parse_root (char * name, char ** pPath)
672 {
673 char * start = name;
674
675 if (name == NULL)
676 return 0;
677
678 /* find the root name of the volume if given */
679 if (isalpha (name[0]) && name[1] == ':')
680 {
681 /* skip past drive specifier */
682 name += 2;
683 if (IS_DIRECTORY_SEP (name[0]))
684 name++;
685 }
686 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
687 {
688 int slashes = 2;
689 name += 2;
690 do
691 {
692 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
693 break;
694 name++;
695 }
696 while ( *name );
697 if (IS_DIRECTORY_SEP (name[0]))
698 name++;
699 }
700
701 if (pPath)
702 *pPath = name;
703
704 return name - start;
705 }
706
707 /* Get long base name for name; name is assumed to be absolute. */
708 static int
709 get_long_basename (char * name, char * buf, int size)
710 {
711 WIN32_FIND_DATA find_data;
712 HANDLE dir_handle;
713 int len = 0;
714
715 /* must be valid filename, no wild cards or other invalid characters */
716 if (strpbrk (name, "*?|<>\""))
717 return 0;
718
719 dir_handle = FindFirstFile (name, &find_data);
720 if (dir_handle != INVALID_HANDLE_VALUE)
721 {
722 if ((len = strlen (find_data.cFileName)) < size)
723 memcpy (buf, find_data.cFileName, len + 1);
724 else
725 len = 0;
726 FindClose (dir_handle);
727 }
728 return len;
729 }
730
731 /* Get long name for file, if possible (assumed to be absolute). */
732 BOOL
733 w32_get_long_filename (char * name, char * buf, int size)
734 {
735 char * o = buf;
736 char * p;
737 char * q;
738 char full[ MAX_PATH ];
739 int len;
740
741 len = strlen (name);
742 if (len >= MAX_PATH)
743 return FALSE;
744
745 /* Use local copy for destructive modification. */
746 memcpy (full, name, len+1);
747 unixtodos_filename (full);
748
749 /* Copy root part verbatim. */
750 len = parse_root (full, &p);
751 memcpy (o, full, len);
752 o += len;
753 *o = '\0';
754 size -= len;
755
756 while (p != NULL && *p)
757 {
758 q = p;
759 p = strchr (q, '\\');
760 if (p) *p = '\0';
761 len = get_long_basename (full, o, size);
762 if (len > 0)
763 {
764 o += len;
765 size -= len;
766 if (p != NULL)
767 {
768 *p++ = '\\';
769 if (size < 2)
770 return FALSE;
771 *o++ = '\\';
772 size--;
773 *o = '\0';
774 }
775 }
776 else
777 return FALSE;
778 }
779
780 return TRUE;
781 }
782
783 int
784 is_unc_volume (const char *filename)
785 {
786 const char *ptr = filename;
787
788 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
789 return 0;
790
791 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
792 return 0;
793
794 return 1;
795 }
796
797 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
798
799 int
800 sigsetmask (int signal_mask)
801 {
802 return 0;
803 }
804
805 int
806 sigmask (int sig)
807 {
808 return 0;
809 }
810
811 int
812 sigblock (int sig)
813 {
814 return 0;
815 }
816
817 int
818 sigunblock (int sig)
819 {
820 return 0;
821 }
822
823 int
824 setpgrp (int pid, int gid)
825 {
826 return 0;
827 }
828
829 int
830 alarm (int seconds)
831 {
832 return 0;
833 }
834
835 void
836 unrequest_sigio (void)
837 {
838 return;
839 }
840
841 void
842 request_sigio (void)
843 {
844 return;
845 }
846
847 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
848
849 LPBYTE
850 w32_get_resource (key, lpdwtype)
851 char *key;
852 LPDWORD lpdwtype;
853 {
854 LPBYTE lpvalue;
855 HKEY hrootkey = NULL;
856 DWORD cbData;
857 BOOL ok = FALSE;
858
859 /* Check both the current user and the local machine to see if
860 we have any resources. */
861
862 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
863 {
864 lpvalue = NULL;
865
866 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
867 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
868 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
869 {
870 return (lpvalue);
871 }
872
873 if (lpvalue) xfree (lpvalue);
874
875 RegCloseKey (hrootkey);
876 }
877
878 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
879 {
880 lpvalue = NULL;
881
882 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
883 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
884 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
885 {
886 return (lpvalue);
887 }
888
889 if (lpvalue) xfree (lpvalue);
890
891 RegCloseKey (hrootkey);
892 }
893
894 return (NULL);
895 }
896
897 char *get_emacs_configuration (void);
898 extern Lisp_Object Vsystem_configuration;
899
900 void
901 init_environment (char ** argv)
902 {
903 static const char * const tempdirs[] = {
904 "$TMPDIR", "$TEMP", "$TMP", "c:/"
905 };
906 int i;
907 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
908
909 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
910 temporary files and assume "/tmp" if $TMPDIR is unset, which
911 will break on DOS/Windows. Refuse to work if we cannot find
912 a directory, not even "c:/", usable for that purpose. */
913 for (i = 0; i < imax ; i++)
914 {
915 const char *tmp = tempdirs[i];
916
917 if (*tmp == '$')
918 tmp = getenv (tmp + 1);
919 /* Note that `access' can lie to us if the directory resides on a
920 read-only filesystem, like CD-ROM or a write-protected floppy.
921 The only way to be really sure is to actually create a file and
922 see if it succeeds. But I think that's too much to ask. */
923 if (tmp && _access (tmp, D_OK) == 0)
924 {
925 char * var = alloca (strlen (tmp) + 8);
926 sprintf (var, "TMPDIR=%s", tmp);
927 _putenv (strdup (var));
928 break;
929 }
930 }
931 if (i >= imax)
932 cmd_error_internal
933 (Fcons (Qerror,
934 Fcons (build_string ("no usable temporary directories found!!"),
935 Qnil)),
936 "While setting TMPDIR: ");
937
938 /* Check for environment variables and use registry settings if they
939 don't exist. Fallback on default values where applicable. */
940 {
941 int i;
942 LPBYTE lpval;
943 DWORD dwType;
944 char locale_name[32];
945
946 static struct env_entry
947 {
948 char * name;
949 char * def_value;
950 } env_vars[] =
951 {
952 {"HOME", "C:/"},
953 {"PRELOAD_WINSOCK", NULL},
954 {"emacs_dir", "C:/emacs"},
955 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
956 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
957 {"EMACSDATA", "%emacs_dir%/etc"},
958 {"EMACSPATH", "%emacs_dir%/bin"},
959 /* We no longer set INFOPATH because Info-default-directory-list
960 is then ignored. */
961 /* {"INFOPATH", "%emacs_dir%/info"}, */
962 {"EMACSDOC", "%emacs_dir%/etc"},
963 {"TERM", "cmd"},
964 {"LANG", NULL},
965 };
966
967 /* Get default locale info and use it for LANG. */
968 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
969 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
970 locale_name, sizeof (locale_name)))
971 {
972 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
973 {
974 if (strcmp (env_vars[i].name, "LANG") == 0)
975 {
976 env_vars[i].def_value = locale_name;
977 break;
978 }
979 }
980 }
981
982 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
983
984 /* Treat emacs_dir specially: set it unconditionally based on our
985 location, if it appears that we are running from the bin subdir
986 of a standard installation. */
987 {
988 char *p;
989 char modname[MAX_PATH];
990
991 if (!GetModuleFileName (NULL, modname, MAX_PATH))
992 abort ();
993 if ((p = strrchr (modname, '\\')) == NULL)
994 abort ();
995 *p = 0;
996
997 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
998 {
999 char buf[SET_ENV_BUF_SIZE];
1000
1001 *p = 0;
1002 for (p = modname; *p; p++)
1003 if (*p == '\\') *p = '/';
1004
1005 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1006 _putenv (strdup (buf));
1007 }
1008 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1009
1010 /* FIXME: should use substring of get_emacs_configuration ().
1011 But I don't think the Windows build supports alpha, mips etc
1012 anymore, so have taken the easy option for now. */
1013 else if (p && stricmp (p, "\\i386") == 0)
1014 {
1015 *p = 0;
1016 p = strrchr (modname, '\\');
1017 if (p != NULL)
1018 {
1019 *p = 0;
1020 p = strrchr (modname, '\\');
1021 if (p && stricmp (p, "\\src") == 0)
1022 {
1023 char buf[SET_ENV_BUF_SIZE];
1024
1025 *p = 0;
1026 for (p = modname; *p; p++)
1027 if (*p == '\\') *p = '/';
1028
1029 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1030 _putenv (strdup (buf));
1031 }
1032 }
1033 }
1034 }
1035
1036 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
1037 {
1038 if (!getenv (env_vars[i].name))
1039 {
1040 int dont_free = 0;
1041
1042 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL)
1043 {
1044 lpval = env_vars[i].def_value;
1045 dwType = REG_EXPAND_SZ;
1046 dont_free = 1;
1047 }
1048
1049 if (lpval)
1050 {
1051 if (dwType == REG_EXPAND_SZ)
1052 {
1053 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1054
1055 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
1056 _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, buf1);
1057 _putenv (strdup (buf2));
1058 }
1059 else if (dwType == REG_SZ)
1060 {
1061 char buf[SET_ENV_BUF_SIZE];
1062
1063 _snprintf (buf, sizeof(buf)-1, "%s=%s", env_vars[i].name, lpval);
1064 _putenv (strdup (buf));
1065 }
1066
1067 if (!dont_free)
1068 xfree (lpval);
1069 }
1070 }
1071 }
1072 }
1073
1074 /* Rebuild system configuration to reflect invoking system. */
1075 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1076
1077 /* Another special case: on NT, the PATH variable is actually named
1078 "Path" although cmd.exe (perhaps NT itself) arranges for
1079 environment variable lookup and setting to be case insensitive.
1080 However, Emacs assumes a fully case sensitive environment, so we
1081 need to change "Path" to "PATH" to match the expectations of
1082 various elisp packages. We do this by the sneaky method of
1083 modifying the string in the C runtime environ entry.
1084
1085 The same applies to COMSPEC. */
1086 {
1087 char ** envp;
1088
1089 for (envp = environ; *envp; envp++)
1090 if (_strnicmp (*envp, "PATH=", 5) == 0)
1091 memcpy (*envp, "PATH=", 5);
1092 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
1093 memcpy (*envp, "COMSPEC=", 8);
1094 }
1095
1096 /* Remember the initial working directory for getwd, then make the
1097 real wd be the location of emacs.exe to avoid conflicts when
1098 renaming or deleting directories. (We also don't call chdir when
1099 running subprocesses for the same reason.) */
1100 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
1101 abort ();
1102
1103 {
1104 char *p;
1105 static char modname[MAX_PATH];
1106
1107 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1108 abort ();
1109 if ((p = strrchr (modname, '\\')) == NULL)
1110 abort ();
1111 *p = 0;
1112
1113 SetCurrentDirectory (modname);
1114
1115 /* Ensure argv[0] has the full path to Emacs. */
1116 *p = '\\';
1117 argv[0] = modname;
1118 }
1119
1120 /* Determine if there is a middle mouse button, to allow parse_button
1121 to decide whether right mouse events should be mouse-2 or
1122 mouse-3. */
1123 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
1124
1125 init_user_info ();
1126 }
1127
1128 char *
1129 emacs_root_dir (void)
1130 {
1131 static char root_dir[FILENAME_MAX];
1132 const char *p;
1133
1134 p = getenv ("emacs_dir");
1135 if (p == NULL)
1136 abort ();
1137 strcpy (root_dir, p);
1138 root_dir[parse_root (root_dir, NULL)] = '\0';
1139 dostounix_filename (root_dir);
1140 return root_dir;
1141 }
1142
1143 /* We don't have scripts to automatically determine the system configuration
1144 for Emacs before it's compiled, and we don't want to have to make the
1145 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1146 routine. */
1147
1148 char *
1149 get_emacs_configuration (void)
1150 {
1151 char *arch, *oem, *os;
1152 int build_num;
1153 static char configuration_buffer[32];
1154
1155 /* Determine the processor type. */
1156 switch (get_processor_type ())
1157 {
1158
1159 #ifdef PROCESSOR_INTEL_386
1160 case PROCESSOR_INTEL_386:
1161 case PROCESSOR_INTEL_486:
1162 case PROCESSOR_INTEL_PENTIUM:
1163 arch = "i386";
1164 break;
1165 #endif
1166
1167 #ifdef PROCESSOR_INTEL_860
1168 case PROCESSOR_INTEL_860:
1169 arch = "i860";
1170 break;
1171 #endif
1172
1173 #ifdef PROCESSOR_MIPS_R2000
1174 case PROCESSOR_MIPS_R2000:
1175 case PROCESSOR_MIPS_R3000:
1176 case PROCESSOR_MIPS_R4000:
1177 arch = "mips";
1178 break;
1179 #endif
1180
1181 #ifdef PROCESSOR_ALPHA_21064
1182 case PROCESSOR_ALPHA_21064:
1183 arch = "alpha";
1184 break;
1185 #endif
1186
1187 default:
1188 arch = "unknown";
1189 break;
1190 }
1191
1192 /* Use the OEM field to reflect the compiler/library combination. */
1193 #ifdef _MSC_VER
1194 #define COMPILER_NAME "msvc"
1195 #else
1196 #ifdef __GNUC__
1197 #define COMPILER_NAME "mingw"
1198 #else
1199 #define COMPILER_NAME "unknown"
1200 #endif
1201 #endif
1202 oem = COMPILER_NAME;
1203
1204 switch (osinfo_cache.dwPlatformId) {
1205 case VER_PLATFORM_WIN32_NT:
1206 os = "nt";
1207 build_num = osinfo_cache.dwBuildNumber;
1208 break;
1209 case VER_PLATFORM_WIN32_WINDOWS:
1210 if (osinfo_cache.dwMinorVersion == 0) {
1211 os = "windows95";
1212 } else {
1213 os = "windows98";
1214 }
1215 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1216 break;
1217 case VER_PLATFORM_WIN32s:
1218 /* Not supported, should not happen. */
1219 os = "windows32s";
1220 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1221 break;
1222 default:
1223 os = "unknown";
1224 build_num = 0;
1225 break;
1226 }
1227
1228 if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1229 sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
1230 get_w32_major_version (), get_w32_minor_version (), build_num);
1231 } else {
1232 sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1233 }
1234
1235 return configuration_buffer;
1236 }
1237
1238 char *
1239 get_emacs_configuration_options (void)
1240 {
1241 static char options_buffer[256];
1242
1243 /* Work out the effective configure options for this build. */
1244 #ifdef _MSC_VER
1245 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1246 #else
1247 #ifdef __GNUC__
1248 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1249 #else
1250 #define COMPILER_VERSION ""
1251 #endif
1252 #endif
1253
1254 sprintf (options_buffer, COMPILER_VERSION);
1255 #ifdef EMACSDEBUG
1256 strcat (options_buffer, " --no-opt");
1257 #endif
1258 #ifdef USER_CFLAGS
1259 strcat (options_buffer, " --cflags");
1260 strcat (options_buffer, USER_CFLAGS);
1261 #endif
1262 #ifdef USER_LDFLAGS
1263 strcat (options_buffer, " --ldflags");
1264 strcat (options_buffer, USER_LDFLAGS);
1265 #endif
1266 return options_buffer;
1267 }
1268
1269
1270 #include <sys/timeb.h>
1271
1272 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1273 void
1274 gettimeofday (struct timeval *tv, struct timezone *tz)
1275 {
1276 struct _timeb tb;
1277 _ftime (&tb);
1278
1279 tv->tv_sec = tb.time;
1280 tv->tv_usec = tb.millitm * 1000L;
1281 if (tz)
1282 {
1283 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
1284 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
1285 }
1286 }
1287
1288 /* ------------------------------------------------------------------------- */
1289 /* IO support and wrapper functions for W32 API. */
1290 /* ------------------------------------------------------------------------- */
1291
1292 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1293 on network directories, so we handle that case here.
1294 (Ulrich Leodolter, 1/11/95). */
1295 char *
1296 sys_ctime (const time_t *t)
1297 {
1298 char *str = (char *) ctime (t);
1299 return (str ? str : "Sun Jan 01 00:00:00 1970");
1300 }
1301
1302 /* Emulate sleep...we could have done this with a define, but that
1303 would necessitate including windows.h in the files that used it.
1304 This is much easier. */
1305 void
1306 sys_sleep (int seconds)
1307 {
1308 Sleep (seconds * 1000);
1309 }
1310
1311 /* Internal MSVC functions for low-level descriptor munging */
1312 extern int __cdecl _set_osfhnd (int fd, long h);
1313 extern int __cdecl _free_osfhnd (int fd);
1314
1315 /* parallel array of private info on file handles */
1316 filedesc fd_info [ MAXDESC ];
1317
1318 typedef struct volume_info_data {
1319 struct volume_info_data * next;
1320
1321 /* time when info was obtained */
1322 DWORD timestamp;
1323
1324 /* actual volume info */
1325 char * root_dir;
1326 DWORD serialnum;
1327 DWORD maxcomp;
1328 DWORD flags;
1329 char * name;
1330 char * type;
1331 } volume_info_data;
1332
1333 /* Global referenced by various functions. */
1334 static volume_info_data volume_info;
1335
1336 /* Vector to indicate which drives are local and fixed (for which cached
1337 data never expires). */
1338 static BOOL fixed_drives[26];
1339
1340 /* Consider cached volume information to be stale if older than 10s,
1341 at least for non-local drives. Info for fixed drives is never stale. */
1342 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1343 #define VOLINFO_STILL_VALID( root_dir, info ) \
1344 ( ( isalpha (root_dir[0]) && \
1345 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1346 || GetTickCount () - info->timestamp < 10000 )
1347
1348 /* Cache support functions. */
1349
1350 /* Simple linked list with linear search is sufficient. */
1351 static volume_info_data *volume_cache = NULL;
1352
1353 static volume_info_data *
1354 lookup_volume_info (char * root_dir)
1355 {
1356 volume_info_data * info;
1357
1358 for (info = volume_cache; info; info = info->next)
1359 if (stricmp (info->root_dir, root_dir) == 0)
1360 break;
1361 return info;
1362 }
1363
1364 static void
1365 add_volume_info (char * root_dir, volume_info_data * info)
1366 {
1367 info->root_dir = xstrdup (root_dir);
1368 info->next = volume_cache;
1369 volume_cache = info;
1370 }
1371
1372
1373 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1374 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1375 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1376 volume_info_data *
1377 GetCachedVolumeInformation (char * root_dir)
1378 {
1379 volume_info_data * info;
1380 char default_root[ MAX_PATH ];
1381
1382 /* NULL for root_dir means use root from current directory. */
1383 if (root_dir == NULL)
1384 {
1385 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1386 return NULL;
1387 parse_root (default_root, &root_dir);
1388 *root_dir = 0;
1389 root_dir = default_root;
1390 }
1391
1392 /* Local fixed drives can be cached permanently. Removable drives
1393 cannot be cached permanently, since the volume name and serial
1394 number (if nothing else) can change. Remote drives should be
1395 treated as if they are removable, since there is no sure way to
1396 tell whether they are or not. Also, the UNC association of drive
1397 letters mapped to remote volumes can be changed at any time (even
1398 by other processes) without notice.
1399
1400 As a compromise, so we can benefit from caching info for remote
1401 volumes, we use a simple expiry mechanism to invalidate cache
1402 entries that are more than ten seconds old. */
1403
1404 #if 0
1405 /* No point doing this, because WNetGetConnection is even slower than
1406 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1407 GetDriveType is about the only call of this type which does not
1408 involve network access, and so is extremely quick). */
1409
1410 /* Map drive letter to UNC if remote. */
1411 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1412 {
1413 char remote_name[ 256 ];
1414 char drive[3] = { root_dir[0], ':' };
1415
1416 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1417 == NO_ERROR)
1418 /* do something */ ;
1419 }
1420 #endif
1421
1422 info = lookup_volume_info (root_dir);
1423
1424 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1425 {
1426 char name[ 256 ];
1427 DWORD serialnum;
1428 DWORD maxcomp;
1429 DWORD flags;
1430 char type[ 256 ];
1431
1432 /* Info is not cached, or is stale. */
1433 if (!GetVolumeInformation (root_dir,
1434 name, sizeof (name),
1435 &serialnum,
1436 &maxcomp,
1437 &flags,
1438 type, sizeof (type)))
1439 return NULL;
1440
1441 /* Cache the volume information for future use, overwriting existing
1442 entry if present. */
1443 if (info == NULL)
1444 {
1445 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1446 add_volume_info (root_dir, info);
1447 }
1448 else
1449 {
1450 xfree (info->name);
1451 xfree (info->type);
1452 }
1453
1454 info->name = xstrdup (name);
1455 info->serialnum = serialnum;
1456 info->maxcomp = maxcomp;
1457 info->flags = flags;
1458 info->type = xstrdup (type);
1459 info->timestamp = GetTickCount ();
1460 }
1461
1462 return info;
1463 }
1464
1465 /* Get information on the volume where name is held; set path pointer to
1466 start of pathname in name (past UNC header\volume header if present). */
1467 int
1468 get_volume_info (const char * name, const char ** pPath)
1469 {
1470 char temp[MAX_PATH];
1471 char *rootname = NULL; /* default to current volume */
1472 volume_info_data * info;
1473
1474 if (name == NULL)
1475 return FALSE;
1476
1477 /* find the root name of the volume if given */
1478 if (isalpha (name[0]) && name[1] == ':')
1479 {
1480 rootname = temp;
1481 temp[0] = *name++;
1482 temp[1] = *name++;
1483 temp[2] = '\\';
1484 temp[3] = 0;
1485 }
1486 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1487 {
1488 char *str = temp;
1489 int slashes = 4;
1490 rootname = temp;
1491 do
1492 {
1493 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1494 break;
1495 *str++ = *name++;
1496 }
1497 while ( *name );
1498
1499 *str++ = '\\';
1500 *str = 0;
1501 }
1502
1503 if (pPath)
1504 *pPath = name;
1505
1506 info = GetCachedVolumeInformation (rootname);
1507 if (info != NULL)
1508 {
1509 /* Set global referenced by other functions. */
1510 volume_info = *info;
1511 return TRUE;
1512 }
1513 return FALSE;
1514 }
1515
1516 /* Determine if volume is FAT format (ie. only supports short 8.3
1517 names); also set path pointer to start of pathname in name. */
1518 int
1519 is_fat_volume (const char * name, const char ** pPath)
1520 {
1521 if (get_volume_info (name, pPath))
1522 return (volume_info.maxcomp == 12);
1523 return FALSE;
1524 }
1525
1526 /* Map filename to a legal 8.3 name if necessary. */
1527 const char *
1528 map_w32_filename (const char * name, const char ** pPath)
1529 {
1530 static char shortname[MAX_PATH];
1531 char * str = shortname;
1532 char c;
1533 char * path;
1534 const char * save_name = name;
1535
1536 if (strlen (name) >= MAX_PATH)
1537 {
1538 /* Return a filename which will cause callers to fail. */
1539 strcpy (shortname, "?");
1540 return shortname;
1541 }
1542
1543 if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1544 {
1545 register int left = 8; /* maximum number of chars in part */
1546 register int extn = 0; /* extension added? */
1547 register int dots = 2; /* maximum number of dots allowed */
1548
1549 while (name < path)
1550 *str++ = *name++; /* skip past UNC header */
1551
1552 while ((c = *name++))
1553 {
1554 switch ( c )
1555 {
1556 case '\\':
1557 case '/':
1558 *str++ = '\\';
1559 extn = 0; /* reset extension flags */
1560 dots = 2; /* max 2 dots */
1561 left = 8; /* max length 8 for main part */
1562 break;
1563 case ':':
1564 *str++ = ':';
1565 extn = 0; /* reset extension flags */
1566 dots = 2; /* max 2 dots */
1567 left = 8; /* max length 8 for main part */
1568 break;
1569 case '.':
1570 if ( dots )
1571 {
1572 /* Convert path components of the form .xxx to _xxx,
1573 but leave . and .. as they are. This allows .emacs
1574 to be read as _emacs, for example. */
1575
1576 if (! *name ||
1577 *name == '.' ||
1578 IS_DIRECTORY_SEP (*name))
1579 {
1580 *str++ = '.';
1581 dots--;
1582 }
1583 else
1584 {
1585 *str++ = '_';
1586 left--;
1587 dots = 0;
1588 }
1589 }
1590 else if ( !extn )
1591 {
1592 *str++ = '.';
1593 extn = 1; /* we've got an extension */
1594 left = 3; /* 3 chars in extension */
1595 }
1596 else
1597 {
1598 /* any embedded dots after the first are converted to _ */
1599 *str++ = '_';
1600 }
1601 break;
1602 case '~':
1603 case '#': /* don't lose these, they're important */
1604 if ( ! left )
1605 str[-1] = c; /* replace last character of part */
1606 /* FALLTHRU */
1607 default:
1608 if ( left )
1609 {
1610 *str++ = tolower (c); /* map to lower case (looks nicer) */
1611 left--;
1612 dots = 0; /* started a path component */
1613 }
1614 break;
1615 }
1616 }
1617 *str = '\0';
1618 }
1619 else
1620 {
1621 strcpy (shortname, name);
1622 unixtodos_filename (shortname);
1623 }
1624
1625 if (pPath)
1626 *pPath = shortname + (path - save_name);
1627
1628 return shortname;
1629 }
1630
1631 static int
1632 is_exec (const char * name)
1633 {
1634 char * p = strrchr (name, '.');
1635 return
1636 (p != NULL
1637 && (stricmp (p, ".exe") == 0 ||
1638 stricmp (p, ".com") == 0 ||
1639 stricmp (p, ".bat") == 0 ||
1640 stricmp (p, ".cmd") == 0));
1641 }
1642
1643 /* Emulate the Unix directory procedures opendir, closedir,
1644 and readdir. We can't use the procedures supplied in sysdep.c,
1645 so we provide them here. */
1646
1647 struct direct dir_static; /* simulated directory contents */
1648 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1649 static int dir_is_fat;
1650 static char dir_pathname[MAXPATHLEN+1];
1651 static WIN32_FIND_DATA dir_find_data;
1652
1653 /* Support shares on a network resource as subdirectories of a read-only
1654 root directory. */
1655 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1656 HANDLE open_unc_volume (const char *);
1657 char *read_unc_volume (HANDLE, char *, int);
1658 void close_unc_volume (HANDLE);
1659
1660 DIR *
1661 opendir (char *filename)
1662 {
1663 DIR *dirp;
1664
1665 /* Opening is done by FindFirstFile. However, a read is inherent to
1666 this operation, so we defer the open until read time. */
1667
1668 if (dir_find_handle != INVALID_HANDLE_VALUE)
1669 return NULL;
1670 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1671 return NULL;
1672
1673 if (is_unc_volume (filename))
1674 {
1675 wnet_enum_handle = open_unc_volume (filename);
1676 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1677 return NULL;
1678 }
1679
1680 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1681 return NULL;
1682
1683 dirp->dd_fd = 0;
1684 dirp->dd_loc = 0;
1685 dirp->dd_size = 0;
1686
1687 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1688 dir_pathname[MAXPATHLEN] = '\0';
1689 dir_is_fat = is_fat_volume (filename, NULL);
1690
1691 return dirp;
1692 }
1693
1694 void
1695 closedir (DIR *dirp)
1696 {
1697 /* If we have a find-handle open, close it. */
1698 if (dir_find_handle != INVALID_HANDLE_VALUE)
1699 {
1700 FindClose (dir_find_handle);
1701 dir_find_handle = INVALID_HANDLE_VALUE;
1702 }
1703 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1704 {
1705 close_unc_volume (wnet_enum_handle);
1706 wnet_enum_handle = INVALID_HANDLE_VALUE;
1707 }
1708 xfree ((char *) dirp);
1709 }
1710
1711 struct direct *
1712 readdir (DIR *dirp)
1713 {
1714 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1715 {
1716 if (!read_unc_volume (wnet_enum_handle,
1717 dir_find_data.cFileName,
1718 MAX_PATH))
1719 return NULL;
1720 }
1721 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1722 else if (dir_find_handle == INVALID_HANDLE_VALUE)
1723 {
1724 char filename[MAXNAMLEN + 3];
1725 int ln;
1726
1727 strcpy (filename, dir_pathname);
1728 ln = strlen (filename) - 1;
1729 if (!IS_DIRECTORY_SEP (filename[ln]))
1730 strcat (filename, "\\");
1731 strcat (filename, "*");
1732
1733 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1734
1735 if (dir_find_handle == INVALID_HANDLE_VALUE)
1736 return NULL;
1737 }
1738 else
1739 {
1740 if (!FindNextFile (dir_find_handle, &dir_find_data))
1741 return NULL;
1742 }
1743
1744 /* Emacs never uses this value, so don't bother making it match
1745 value returned by stat(). */
1746 dir_static.d_ino = 1;
1747
1748 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1749 dir_static.d_namlen - dir_static.d_namlen % 4;
1750
1751 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1752 strcpy (dir_static.d_name, dir_find_data.cFileName);
1753 if (dir_is_fat)
1754 _strlwr (dir_static.d_name);
1755 else if (!NILP (Vw32_downcase_file_names))
1756 {
1757 register char *p;
1758 for (p = dir_static.d_name; *p; p++)
1759 if (*p >= 'a' && *p <= 'z')
1760 break;
1761 if (!*p)
1762 _strlwr (dir_static.d_name);
1763 }
1764
1765 return &dir_static;
1766 }
1767
1768 HANDLE
1769 open_unc_volume (const char *path)
1770 {
1771 NETRESOURCE nr;
1772 HANDLE henum;
1773 int result;
1774
1775 nr.dwScope = RESOURCE_GLOBALNET;
1776 nr.dwType = RESOURCETYPE_DISK;
1777 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1778 nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1779 nr.lpLocalName = NULL;
1780 nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL);
1781 nr.lpComment = NULL;
1782 nr.lpProvider = NULL;
1783
1784 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1785 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1786
1787 if (result == NO_ERROR)
1788 return henum;
1789 else
1790 return INVALID_HANDLE_VALUE;
1791 }
1792
1793 char *
1794 read_unc_volume (HANDLE henum, char *readbuf, int size)
1795 {
1796 DWORD count;
1797 int result;
1798 DWORD bufsize = 512;
1799 char *buffer;
1800 char *ptr;
1801
1802 count = 1;
1803 buffer = alloca (bufsize);
1804 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1805 if (result != NO_ERROR)
1806 return NULL;
1807
1808 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1809 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1810 ptr += 2;
1811 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1812 ptr++;
1813
1814 strncpy (readbuf, ptr, size);
1815 return readbuf;
1816 }
1817
1818 void
1819 close_unc_volume (HANDLE henum)
1820 {
1821 if (henum != INVALID_HANDLE_VALUE)
1822 WNetCloseEnum (henum);
1823 }
1824
1825 DWORD
1826 unc_volume_file_attributes (const char *path)
1827 {
1828 HANDLE henum;
1829 DWORD attrs;
1830
1831 henum = open_unc_volume (path);
1832 if (henum == INVALID_HANDLE_VALUE)
1833 return -1;
1834
1835 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1836
1837 close_unc_volume (henum);
1838
1839 return attrs;
1840 }
1841
1842
1843 /* Shadow some MSVC runtime functions to map requests for long filenames
1844 to reasonable short names if necessary. This was originally added to
1845 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1846 long file names. */
1847
1848 int
1849 sys_access (const char * path, int mode)
1850 {
1851 DWORD attributes;
1852
1853 /* MSVC implementation doesn't recognize D_OK. */
1854 path = map_w32_filename (path, NULL);
1855 if (is_unc_volume (path))
1856 {
1857 attributes = unc_volume_file_attributes (path);
1858 if (attributes == -1) {
1859 errno = EACCES;
1860 return -1;
1861 }
1862 }
1863 else if ((attributes = GetFileAttributes (path)) == -1)
1864 {
1865 /* Should try mapping GetLastError to errno; for now just indicate
1866 that path doesn't exist. */
1867 errno = EACCES;
1868 return -1;
1869 }
1870 if ((mode & X_OK) != 0 && !is_exec (path))
1871 {
1872 errno = EACCES;
1873 return -1;
1874 }
1875 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1876 {
1877 errno = EACCES;
1878 return -1;
1879 }
1880 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1881 {
1882 errno = EACCES;
1883 return -1;
1884 }
1885 return 0;
1886 }
1887
1888 int
1889 sys_chdir (const char * path)
1890 {
1891 return _chdir (map_w32_filename (path, NULL));
1892 }
1893
1894 int
1895 sys_chmod (const char * path, int mode)
1896 {
1897 return _chmod (map_w32_filename (path, NULL), mode);
1898 }
1899
1900 int
1901 sys_chown (const char *path, uid_t owner, gid_t group)
1902 {
1903 if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
1904 return -1;
1905 return 0;
1906 }
1907
1908 int
1909 sys_creat (const char * path, int mode)
1910 {
1911 return _creat (map_w32_filename (path, NULL), mode);
1912 }
1913
1914 FILE *
1915 sys_fopen(const char * path, const char * mode)
1916 {
1917 int fd;
1918 int oflag;
1919 const char * mode_save = mode;
1920
1921 /* Force all file handles to be non-inheritable. This is necessary to
1922 ensure child processes don't unwittingly inherit handles that might
1923 prevent future file access. */
1924
1925 if (mode[0] == 'r')
1926 oflag = O_RDONLY;
1927 else if (mode[0] == 'w' || mode[0] == 'a')
1928 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1929 else
1930 return NULL;
1931
1932 /* Only do simplistic option parsing. */
1933 while (*++mode)
1934 if (mode[0] == '+')
1935 {
1936 oflag &= ~(O_RDONLY | O_WRONLY);
1937 oflag |= O_RDWR;
1938 }
1939 else if (mode[0] == 'b')
1940 {
1941 oflag &= ~O_TEXT;
1942 oflag |= O_BINARY;
1943 }
1944 else if (mode[0] == 't')
1945 {
1946 oflag &= ~O_BINARY;
1947 oflag |= O_TEXT;
1948 }
1949 else break;
1950
1951 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
1952 if (fd < 0)
1953 return NULL;
1954
1955 return _fdopen (fd, mode_save);
1956 }
1957
1958 /* This only works on NTFS volumes, but is useful to have. */
1959 int
1960 sys_link (const char * old, const char * new)
1961 {
1962 HANDLE fileh;
1963 int result = -1;
1964 char oldname[MAX_PATH], newname[MAX_PATH];
1965
1966 if (old == NULL || new == NULL)
1967 {
1968 errno = ENOENT;
1969 return -1;
1970 }
1971
1972 strcpy (oldname, map_w32_filename (old, NULL));
1973 strcpy (newname, map_w32_filename (new, NULL));
1974
1975 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1976 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1977 if (fileh != INVALID_HANDLE_VALUE)
1978 {
1979 int wlen;
1980
1981 /* Confusingly, the "alternate" stream name field does not apply
1982 when restoring a hard link, and instead contains the actual
1983 stream data for the link (ie. the name of the link to create).
1984 The WIN32_STREAM_ID structure before the cStreamName field is
1985 the stream header, which is then immediately followed by the
1986 stream data. */
1987
1988 struct {
1989 WIN32_STREAM_ID wid;
1990 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1991 } data;
1992
1993 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1994 data.wid.cStreamName, MAX_PATH);
1995 if (wlen > 0)
1996 {
1997 LPVOID context = NULL;
1998 DWORD wbytes = 0;
1999
2000 data.wid.dwStreamId = BACKUP_LINK;
2001 data.wid.dwStreamAttributes = 0;
2002 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
2003 data.wid.Size.HighPart = 0;
2004 data.wid.dwStreamNameSize = 0;
2005
2006 if (BackupWrite (fileh, (LPBYTE)&data,
2007 offsetof (WIN32_STREAM_ID, cStreamName)
2008 + data.wid.Size.LowPart,
2009 &wbytes, FALSE, FALSE, &context)
2010 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
2011 {
2012 /* succeeded */
2013 result = 0;
2014 }
2015 else
2016 {
2017 /* Should try mapping GetLastError to errno; for now just
2018 indicate a general error (eg. links not supported). */
2019 errno = EINVAL; // perhaps EMLINK?
2020 }
2021 }
2022
2023 CloseHandle (fileh);
2024 }
2025 else
2026 errno = ENOENT;
2027
2028 return result;
2029 }
2030
2031 int
2032 sys_mkdir (const char * path)
2033 {
2034 return _mkdir (map_w32_filename (path, NULL));
2035 }
2036
2037 /* Because of long name mapping issues, we need to implement this
2038 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2039 a unique name, instead of setting the input template to an empty
2040 string.
2041
2042 Standard algorithm seems to be use pid or tid with a letter on the
2043 front (in place of the 6 X's) and cycle through the letters to find a
2044 unique name. We extend that to allow any reasonable character as the
2045 first of the 6 X's. */
2046 char *
2047 sys_mktemp (char * template)
2048 {
2049 char * p;
2050 int i;
2051 unsigned uid = GetCurrentThreadId ();
2052 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2053
2054 if (template == NULL)
2055 return NULL;
2056 p = template + strlen (template);
2057 i = 5;
2058 /* replace up to the last 5 X's with uid in decimal */
2059 while (--p >= template && p[0] == 'X' && --i >= 0)
2060 {
2061 p[0] = '0' + uid % 10;
2062 uid /= 10;
2063 }
2064
2065 if (i < 0 && p[0] == 'X')
2066 {
2067 i = 0;
2068 do
2069 {
2070 int save_errno = errno;
2071 p[0] = first_char[i];
2072 if (sys_access (template, 0) < 0)
2073 {
2074 errno = save_errno;
2075 return template;
2076 }
2077 }
2078 while (++i < sizeof (first_char));
2079 }
2080
2081 /* Template is badly formed or else we can't generate a unique name,
2082 so return empty string */
2083 template[0] = 0;
2084 return template;
2085 }
2086
2087 int
2088 sys_open (const char * path, int oflag, int mode)
2089 {
2090 const char* mpath = map_w32_filename (path, NULL);
2091 /* Try to open file without _O_CREAT, to be able to write to hidden
2092 and system files. Force all file handles to be
2093 non-inheritable. */
2094 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2095 if (res >= 0)
2096 return res;
2097 return _open (mpath, oflag | _O_NOINHERIT, mode);
2098 }
2099
2100 int
2101 sys_rename (const char * oldname, const char * newname)
2102 {
2103 BOOL result;
2104 char temp[MAX_PATH];
2105
2106 /* MoveFile on Windows 95 doesn't correctly change the short file name
2107 alias in a number of circumstances (it is not easy to predict when
2108 just by looking at oldname and newname, unfortunately). In these
2109 cases, renaming through a temporary name avoids the problem.
2110
2111 A second problem on Windows 95 is that renaming through a temp name when
2112 newname is uppercase fails (the final long name ends up in
2113 lowercase, although the short alias might be uppercase) UNLESS the
2114 long temp name is not 8.3.
2115
2116 So, on Windows 95 we always rename through a temp name, and we make sure
2117 the temp name has a long extension to ensure correct renaming. */
2118
2119 strcpy (temp, map_w32_filename (oldname, NULL));
2120
2121 if (os_subtype == OS_WIN95)
2122 {
2123 char * o;
2124 char * p;
2125 int i = 0;
2126
2127 oldname = map_w32_filename (oldname, NULL);
2128 if (o = strrchr (oldname, '\\'))
2129 o++;
2130 else
2131 o = (char *) oldname;
2132
2133 if (p = strrchr (temp, '\\'))
2134 p++;
2135 else
2136 p = temp;
2137
2138 do
2139 {
2140 /* Force temp name to require a manufactured 8.3 alias - this
2141 seems to make the second rename work properly. */
2142 sprintf (p, "_.%s.%u", o, i);
2143 i++;
2144 result = rename (oldname, temp);
2145 }
2146 /* This loop must surely terminate! */
2147 while (result < 0 && errno == EEXIST);
2148 if (result < 0)
2149 return -1;
2150 }
2151
2152 /* Emulate Unix behaviour - newname is deleted if it already exists
2153 (at least if it is a file; don't do this for directories).
2154
2155 Since we mustn't do this if we are just changing the case of the
2156 file name (we would end up deleting the file we are trying to
2157 rename!), we let rename detect if the destination file already
2158 exists - that way we avoid the possible pitfalls of trying to
2159 determine ourselves whether two names really refer to the same
2160 file, which is not always possible in the general case. (Consider
2161 all the permutations of shared or subst'd drives, etc.) */
2162
2163 newname = map_w32_filename (newname, NULL);
2164 result = rename (temp, newname);
2165
2166 if (result < 0
2167 && errno == EEXIST
2168 && _chmod (newname, 0666) == 0
2169 && _unlink (newname) == 0)
2170 result = rename (temp, newname);
2171
2172 return result;
2173 }
2174
2175 int
2176 sys_rmdir (const char * path)
2177 {
2178 return _rmdir (map_w32_filename (path, NULL));
2179 }
2180
2181 int
2182 sys_unlink (const char * path)
2183 {
2184 path = map_w32_filename (path, NULL);
2185
2186 /* On Unix, unlink works without write permission. */
2187 _chmod (path, 0666);
2188 return _unlink (path);
2189 }
2190
2191 static FILETIME utc_base_ft;
2192 static long double utc_base;
2193 static int init = 0;
2194
2195 static time_t
2196 convert_time (FILETIME ft)
2197 {
2198 long double ret;
2199
2200 if (!init)
2201 {
2202 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2203 SYSTEMTIME st;
2204
2205 st.wYear = 1970;
2206 st.wMonth = 1;
2207 st.wDay = 1;
2208 st.wHour = 0;
2209 st.wMinute = 0;
2210 st.wSecond = 0;
2211 st.wMilliseconds = 0;
2212
2213 SystemTimeToFileTime (&st, &utc_base_ft);
2214 utc_base = (long double) utc_base_ft.dwHighDateTime
2215 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2216 init = 1;
2217 }
2218
2219 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2220 return 0;
2221
2222 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
2223 ret -= utc_base;
2224 return (time_t) (ret * 1e-7);
2225 }
2226
2227 void
2228 convert_from_time_t (time_t time, FILETIME * pft)
2229 {
2230 long double tmp;
2231
2232 if (!init)
2233 {
2234 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2235 SYSTEMTIME st;
2236
2237 st.wYear = 1970;
2238 st.wMonth = 1;
2239 st.wDay = 1;
2240 st.wHour = 0;
2241 st.wMinute = 0;
2242 st.wSecond = 0;
2243 st.wMilliseconds = 0;
2244
2245 SystemTimeToFileTime (&st, &utc_base_ft);
2246 utc_base = (long double) utc_base_ft.dwHighDateTime
2247 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2248 init = 1;
2249 }
2250
2251 /* time in 100ns units since 1-Jan-1601 */
2252 tmp = (long double) time * 1e7 + utc_base;
2253 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2254 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2255 }
2256
2257 #if 0
2258 /* No reason to keep this; faking inode values either by hashing or even
2259 using the file index from GetInformationByHandle, is not perfect and
2260 so by default Emacs doesn't use the inode values on Windows.
2261 Instead, we now determine file-truename correctly (except for
2262 possible drive aliasing etc). */
2263
2264 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2265 static unsigned
2266 hashval (const unsigned char * str)
2267 {
2268 unsigned h = 0;
2269 while (*str)
2270 {
2271 h = (h << 4) + *str++;
2272 h ^= (h >> 28);
2273 }
2274 return h;
2275 }
2276
2277 /* Return the hash value of the canonical pathname, excluding the
2278 drive/UNC header, to get a hopefully unique inode number. */
2279 static DWORD
2280 generate_inode_val (const char * name)
2281 {
2282 char fullname[ MAX_PATH ];
2283 char * p;
2284 unsigned hash;
2285
2286 /* Get the truly canonical filename, if it exists. (Note: this
2287 doesn't resolve aliasing due to subst commands, or recognise hard
2288 links. */
2289 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2290 abort ();
2291
2292 parse_root (fullname, &p);
2293 /* Normal W32 filesystems are still case insensitive. */
2294 _strlwr (p);
2295 return hashval (p);
2296 }
2297
2298 #endif
2299
2300 /* MSVC stat function can't cope with UNC names and has other bugs, so
2301 replace it with our own. This also allows us to calculate consistent
2302 inode values without hacks in the main Emacs code. */
2303 int
2304 stat (const char * path, struct stat * buf)
2305 {
2306 char *name, *r;
2307 WIN32_FIND_DATA wfd;
2308 HANDLE fh;
2309 DWORD fake_inode;
2310 int permission;
2311 int len;
2312 int rootdir = FALSE;
2313
2314 if (path == NULL || buf == NULL)
2315 {
2316 errno = EFAULT;
2317 return -1;
2318 }
2319
2320 name = (char *) map_w32_filename (path, &path);
2321 /* must be valid filename, no wild cards or other invalid characters */
2322 if (strpbrk (name, "*?|<>\""))
2323 {
2324 errno = ENOENT;
2325 return -1;
2326 }
2327
2328 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2329 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2330 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2331 {
2332 r[1] = r[2] = '\0';
2333 }
2334
2335 /* Remove trailing directory separator, unless name is the root
2336 directory of a drive or UNC volume in which case ensure there
2337 is a trailing separator. */
2338 len = strlen (name);
2339 rootdir = (path >= name + len - 1
2340 && (IS_DIRECTORY_SEP (*path) || *path == 0));
2341 name = strcpy (alloca (len + 2), name);
2342
2343 if (is_unc_volume (name))
2344 {
2345 DWORD attrs = unc_volume_file_attributes (name);
2346
2347 if (attrs == -1)
2348 return -1;
2349
2350 memset (&wfd, 0, sizeof (wfd));
2351 wfd.dwFileAttributes = attrs;
2352 wfd.ftCreationTime = utc_base_ft;
2353 wfd.ftLastAccessTime = utc_base_ft;
2354 wfd.ftLastWriteTime = utc_base_ft;
2355 strcpy (wfd.cFileName, name);
2356 }
2357 else if (rootdir)
2358 {
2359 if (!IS_DIRECTORY_SEP (name[len-1]))
2360 strcat (name, "\\");
2361 if (GetDriveType (name) < 2)
2362 {
2363 errno = ENOENT;
2364 return -1;
2365 }
2366 memset (&wfd, 0, sizeof (wfd));
2367 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2368 wfd.ftCreationTime = utc_base_ft;
2369 wfd.ftLastAccessTime = utc_base_ft;
2370 wfd.ftLastWriteTime = utc_base_ft;
2371 strcpy (wfd.cFileName, name);
2372 }
2373 else
2374 {
2375 if (IS_DIRECTORY_SEP (name[len-1]))
2376 name[len - 1] = 0;
2377
2378 /* (This is hacky, but helps when doing file completions on
2379 network drives.) Optimize by using information available from
2380 active readdir if possible. */
2381 len = strlen (dir_pathname);
2382 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2383 len--;
2384 if (dir_find_handle != INVALID_HANDLE_VALUE
2385 && strnicmp (name, dir_pathname, len) == 0
2386 && IS_DIRECTORY_SEP (name[len])
2387 && stricmp (name + len + 1, dir_static.d_name) == 0)
2388 {
2389 /* This was the last entry returned by readdir. */
2390 wfd = dir_find_data;
2391 }
2392 else
2393 {
2394 fh = FindFirstFile (name, &wfd);
2395 if (fh == INVALID_HANDLE_VALUE)
2396 {
2397 errno = ENOENT;
2398 return -1;
2399 }
2400 FindClose (fh);
2401 }
2402 }
2403
2404 if (!NILP (Vw32_get_true_file_attributes)
2405 /* No access rights required to get info. */
2406 && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2407 FILE_FLAG_BACKUP_SEMANTICS, NULL))
2408 != INVALID_HANDLE_VALUE)
2409 {
2410 /* This is more accurate in terms of gettting the correct number
2411 of links, but is quite slow (it is noticable when Emacs is
2412 making a list of file name completions). */
2413 BY_HANDLE_FILE_INFORMATION info;
2414
2415 if (GetFileInformationByHandle (fh, &info))
2416 {
2417 buf->st_nlink = info.nNumberOfLinks;
2418 /* Might as well use file index to fake inode values, but this
2419 is not guaranteed to be unique unless we keep a handle open
2420 all the time (even then there are situations where it is
2421 not unique). Reputedly, there are at most 48 bits of info
2422 (on NTFS, presumably less on FAT). */
2423 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2424 }
2425 else
2426 {
2427 buf->st_nlink = 1;
2428 fake_inode = 0;
2429 }
2430
2431 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2432 {
2433 buf->st_mode = _S_IFDIR;
2434 }
2435 else
2436 {
2437 switch (GetFileType (fh))
2438 {
2439 case FILE_TYPE_DISK:
2440 buf->st_mode = _S_IFREG;
2441 break;
2442 case FILE_TYPE_PIPE:
2443 buf->st_mode = _S_IFIFO;
2444 break;
2445 case FILE_TYPE_CHAR:
2446 case FILE_TYPE_UNKNOWN:
2447 default:
2448 buf->st_mode = _S_IFCHR;
2449 }
2450 }
2451 CloseHandle (fh);
2452 }
2453 else
2454 {
2455 /* Don't bother to make this information more accurate. */
2456 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2457 _S_IFDIR : _S_IFREG;
2458 buf->st_nlink = 1;
2459 fake_inode = 0;
2460 }
2461
2462 #if 0
2463 /* Not sure if there is any point in this. */
2464 if (!NILP (Vw32_generate_fake_inodes))
2465 fake_inode = generate_inode_val (name);
2466 else if (fake_inode == 0)
2467 {
2468 /* For want of something better, try to make everything unique. */
2469 static DWORD gen_num = 0;
2470 fake_inode = ++gen_num;
2471 }
2472 #endif
2473
2474 /* MSVC defines _ino_t to be short; other libc's might not. */
2475 if (sizeof (buf->st_ino) == 2)
2476 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2477 else
2478 buf->st_ino = fake_inode;
2479
2480 /* consider files to belong to current user */
2481 buf->st_uid = the_passwd.pw_uid;
2482 buf->st_gid = the_passwd.pw_gid;
2483
2484 /* volume_info is set indirectly by map_w32_filename */
2485 buf->st_dev = volume_info.serialnum;
2486 buf->st_rdev = volume_info.serialnum;
2487
2488
2489 buf->st_size = wfd.nFileSizeLow;
2490
2491 /* Convert timestamps to Unix format. */
2492 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2493 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2494 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2495 buf->st_ctime = convert_time (wfd.ftCreationTime);
2496 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2497
2498 /* determine rwx permissions */
2499 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2500 permission = _S_IREAD;
2501 else
2502 permission = _S_IREAD | _S_IWRITE;
2503
2504 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2505 permission |= _S_IEXEC;
2506 else if (is_exec (name))
2507 permission |= _S_IEXEC;
2508
2509 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2510
2511 return 0;
2512 }
2513
2514 /* Provide fstat and utime as well as stat for consistent handling of
2515 file timestamps. */
2516 int
2517 fstat (int desc, struct stat * buf)
2518 {
2519 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2520 BY_HANDLE_FILE_INFORMATION info;
2521 DWORD fake_inode;
2522 int permission;
2523
2524 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2525 {
2526 case FILE_TYPE_DISK:
2527 buf->st_mode = _S_IFREG;
2528 if (!GetFileInformationByHandle (fh, &info))
2529 {
2530 errno = EACCES;
2531 return -1;
2532 }
2533 break;
2534 case FILE_TYPE_PIPE:
2535 buf->st_mode = _S_IFIFO;
2536 goto non_disk;
2537 case FILE_TYPE_CHAR:
2538 case FILE_TYPE_UNKNOWN:
2539 default:
2540 buf->st_mode = _S_IFCHR;
2541 non_disk:
2542 memset (&info, 0, sizeof (info));
2543 info.dwFileAttributes = 0;
2544 info.ftCreationTime = utc_base_ft;
2545 info.ftLastAccessTime = utc_base_ft;
2546 info.ftLastWriteTime = utc_base_ft;
2547 }
2548
2549 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2550 buf->st_mode = _S_IFDIR;
2551
2552 buf->st_nlink = info.nNumberOfLinks;
2553 /* Might as well use file index to fake inode values, but this
2554 is not guaranteed to be unique unless we keep a handle open
2555 all the time (even then there are situations where it is
2556 not unique). Reputedly, there are at most 48 bits of info
2557 (on NTFS, presumably less on FAT). */
2558 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2559
2560 /* MSVC defines _ino_t to be short; other libc's might not. */
2561 if (sizeof (buf->st_ino) == 2)
2562 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2563 else
2564 buf->st_ino = fake_inode;
2565
2566 /* consider files to belong to current user */
2567 buf->st_uid = 0;
2568 buf->st_gid = 0;
2569
2570 buf->st_dev = info.dwVolumeSerialNumber;
2571 buf->st_rdev = info.dwVolumeSerialNumber;
2572
2573 buf->st_size = info.nFileSizeLow;
2574
2575 /* Convert timestamps to Unix format. */
2576 buf->st_mtime = convert_time (info.ftLastWriteTime);
2577 buf->st_atime = convert_time (info.ftLastAccessTime);
2578 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2579 buf->st_ctime = convert_time (info.ftCreationTime);
2580 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2581
2582 /* determine rwx permissions */
2583 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2584 permission = _S_IREAD;
2585 else
2586 permission = _S_IREAD | _S_IWRITE;
2587
2588 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2589 permission |= _S_IEXEC;
2590 else
2591 {
2592 #if 0 /* no way of knowing the filename */
2593 char * p = strrchr (name, '.');
2594 if (p != NULL &&
2595 (stricmp (p, ".exe") == 0 ||
2596 stricmp (p, ".com") == 0 ||
2597 stricmp (p, ".bat") == 0 ||
2598 stricmp (p, ".cmd") == 0))
2599 permission |= _S_IEXEC;
2600 #endif
2601 }
2602
2603 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2604
2605 return 0;
2606 }
2607
2608 int
2609 utime (const char *name, struct utimbuf *times)
2610 {
2611 struct utimbuf deftime;
2612 HANDLE fh;
2613 FILETIME mtime;
2614 FILETIME atime;
2615
2616 if (times == NULL)
2617 {
2618 deftime.modtime = deftime.actime = time (NULL);
2619 times = &deftime;
2620 }
2621
2622 /* Need write access to set times. */
2623 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2624 0, OPEN_EXISTING, 0, NULL);
2625 if (fh)
2626 {
2627 convert_from_time_t (times->actime, &atime);
2628 convert_from_time_t (times->modtime, &mtime);
2629 if (!SetFileTime (fh, NULL, &atime, &mtime))
2630 {
2631 CloseHandle (fh);
2632 errno = EACCES;
2633 return -1;
2634 }
2635 CloseHandle (fh);
2636 }
2637 else
2638 {
2639 errno = EINVAL;
2640 return -1;
2641 }
2642 return 0;
2643 }
2644
2645 #ifdef HAVE_SOCKETS
2646
2647 /* Wrappers for winsock functions to map between our file descriptors
2648 and winsock's handles; also set h_errno for convenience.
2649
2650 To allow Emacs to run on systems which don't have winsock support
2651 installed, we dynamically link to winsock on startup if present, and
2652 otherwise provide the minimum necessary functionality
2653 (eg. gethostname). */
2654
2655 /* function pointers for relevant socket functions */
2656 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2657 void (PASCAL *pfn_WSASetLastError) (int iError);
2658 int (PASCAL *pfn_WSAGetLastError) (void);
2659 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2660 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2661 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2662 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2663 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2664 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2665 int (PASCAL *pfn_closesocket) (SOCKET s);
2666 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2667 int (PASCAL *pfn_WSACleanup) (void);
2668
2669 u_short (PASCAL *pfn_htons) (u_short hostshort);
2670 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2671 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2672 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2673 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2674 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2675 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2676 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2677 const char * optval, int optlen);
2678 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2679 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2680 int * namelen);
2681 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2682 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2683 struct sockaddr * from, int * fromlen);
2684 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2685 const struct sockaddr * to, int tolen);
2686
2687 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2688 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2689 #ifndef HANDLE_FLAG_INHERIT
2690 #define HANDLE_FLAG_INHERIT 1
2691 #endif
2692
2693 HANDLE winsock_lib;
2694 static int winsock_inuse;
2695
2696 BOOL
2697 term_winsock (void)
2698 {
2699 if (winsock_lib != NULL && winsock_inuse == 0)
2700 {
2701 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2702 after WSAStartup returns successfully, but it seems reasonable
2703 to allow unloading winsock anyway in that case. */
2704 if (pfn_WSACleanup () == 0 ||
2705 pfn_WSAGetLastError () == WSAENETDOWN)
2706 {
2707 if (FreeLibrary (winsock_lib))
2708 winsock_lib = NULL;
2709 return TRUE;
2710 }
2711 }
2712 return FALSE;
2713 }
2714
2715 BOOL
2716 init_winsock (int load_now)
2717 {
2718 WSADATA winsockData;
2719
2720 if (winsock_lib != NULL)
2721 return TRUE;
2722
2723 pfn_SetHandleInformation = NULL;
2724 pfn_SetHandleInformation
2725 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2726 "SetHandleInformation");
2727
2728 winsock_lib = LoadLibrary ("wsock32.dll");
2729
2730 if (winsock_lib != NULL)
2731 {
2732 /* dynamically link to socket functions */
2733
2734 #define LOAD_PROC(fn) \
2735 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2736 goto fail;
2737
2738 LOAD_PROC( WSAStartup );
2739 LOAD_PROC( WSASetLastError );
2740 LOAD_PROC( WSAGetLastError );
2741 LOAD_PROC( socket );
2742 LOAD_PROC( bind );
2743 LOAD_PROC( connect );
2744 LOAD_PROC( ioctlsocket );
2745 LOAD_PROC( recv );
2746 LOAD_PROC( send );
2747 LOAD_PROC( closesocket );
2748 LOAD_PROC( shutdown );
2749 LOAD_PROC( htons );
2750 LOAD_PROC( ntohs );
2751 LOAD_PROC( inet_addr );
2752 LOAD_PROC( gethostname );
2753 LOAD_PROC( gethostbyname );
2754 LOAD_PROC( getservbyname );
2755 LOAD_PROC( getpeername );
2756 LOAD_PROC( WSACleanup );
2757 LOAD_PROC( setsockopt );
2758 LOAD_PROC( listen );
2759 LOAD_PROC( getsockname );
2760 LOAD_PROC( accept );
2761 LOAD_PROC( recvfrom );
2762 LOAD_PROC( sendto );
2763 #undef LOAD_PROC
2764
2765 /* specify version 1.1 of winsock */
2766 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2767 {
2768 if (winsockData.wVersion != 0x101)
2769 goto fail;
2770
2771 if (!load_now)
2772 {
2773 /* Report that winsock exists and is usable, but leave
2774 socket functions disabled. I am assuming that calling
2775 WSAStartup does not require any network interaction,
2776 and in particular does not cause or require a dial-up
2777 connection to be established. */
2778
2779 pfn_WSACleanup ();
2780 FreeLibrary (winsock_lib);
2781 winsock_lib = NULL;
2782 }
2783 winsock_inuse = 0;
2784 return TRUE;
2785 }
2786
2787 fail:
2788 FreeLibrary (winsock_lib);
2789 winsock_lib = NULL;
2790 }
2791
2792 return FALSE;
2793 }
2794
2795
2796 int h_errno = 0;
2797
2798 /* function to set h_errno for compatability; map winsock error codes to
2799 normal system codes where they overlap (non-overlapping definitions
2800 are already in <sys/socket.h> */
2801 static void set_errno ()
2802 {
2803 if (winsock_lib == NULL)
2804 h_errno = EINVAL;
2805 else
2806 h_errno = pfn_WSAGetLastError ();
2807
2808 switch (h_errno)
2809 {
2810 case WSAEACCES: h_errno = EACCES; break;
2811 case WSAEBADF: h_errno = EBADF; break;
2812 case WSAEFAULT: h_errno = EFAULT; break;
2813 case WSAEINTR: h_errno = EINTR; break;
2814 case WSAEINVAL: h_errno = EINVAL; break;
2815 case WSAEMFILE: h_errno = EMFILE; break;
2816 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2817 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2818 }
2819 errno = h_errno;
2820 }
2821
2822 static void check_errno ()
2823 {
2824 if (h_errno == 0 && winsock_lib != NULL)
2825 pfn_WSASetLastError (0);
2826 }
2827
2828 /* Extend strerror to handle the winsock-specific error codes. */
2829 struct {
2830 int errnum;
2831 char * msg;
2832 } _wsa_errlist[] = {
2833 WSAEINTR , "Interrupted function call",
2834 WSAEBADF , "Bad file descriptor",
2835 WSAEACCES , "Permission denied",
2836 WSAEFAULT , "Bad address",
2837 WSAEINVAL , "Invalid argument",
2838 WSAEMFILE , "Too many open files",
2839
2840 WSAEWOULDBLOCK , "Resource temporarily unavailable",
2841 WSAEINPROGRESS , "Operation now in progress",
2842 WSAEALREADY , "Operation already in progress",
2843 WSAENOTSOCK , "Socket operation on non-socket",
2844 WSAEDESTADDRREQ , "Destination address required",
2845 WSAEMSGSIZE , "Message too long",
2846 WSAEPROTOTYPE , "Protocol wrong type for socket",
2847 WSAENOPROTOOPT , "Bad protocol option",
2848 WSAEPROTONOSUPPORT , "Protocol not supported",
2849 WSAESOCKTNOSUPPORT , "Socket type not supported",
2850 WSAEOPNOTSUPP , "Operation not supported",
2851 WSAEPFNOSUPPORT , "Protocol family not supported",
2852 WSAEAFNOSUPPORT , "Address family not supported by protocol family",
2853 WSAEADDRINUSE , "Address already in use",
2854 WSAEADDRNOTAVAIL , "Cannot assign requested address",
2855 WSAENETDOWN , "Network is down",
2856 WSAENETUNREACH , "Network is unreachable",
2857 WSAENETRESET , "Network dropped connection on reset",
2858 WSAECONNABORTED , "Software caused connection abort",
2859 WSAECONNRESET , "Connection reset by peer",
2860 WSAENOBUFS , "No buffer space available",
2861 WSAEISCONN , "Socket is already connected",
2862 WSAENOTCONN , "Socket is not connected",
2863 WSAESHUTDOWN , "Cannot send after socket shutdown",
2864 WSAETOOMANYREFS , "Too many references", /* not sure */
2865 WSAETIMEDOUT , "Connection timed out",
2866 WSAECONNREFUSED , "Connection refused",
2867 WSAELOOP , "Network loop", /* not sure */
2868 WSAENAMETOOLONG , "Name is too long",
2869 WSAEHOSTDOWN , "Host is down",
2870 WSAEHOSTUNREACH , "No route to host",
2871 WSAENOTEMPTY , "Buffer not empty", /* not sure */
2872 WSAEPROCLIM , "Too many processes",
2873 WSAEUSERS , "Too many users", /* not sure */
2874 WSAEDQUOT , "Double quote in host name", /* really not sure */
2875 WSAESTALE , "Data is stale", /* not sure */
2876 WSAEREMOTE , "Remote error", /* not sure */
2877
2878 WSASYSNOTREADY , "Network subsystem is unavailable",
2879 WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
2880 WSANOTINITIALISED , "Winsock not initialized successfully",
2881 WSAEDISCON , "Graceful shutdown in progress",
2882 #ifdef WSAENOMORE
2883 WSAENOMORE , "No more operations allowed", /* not sure */
2884 WSAECANCELLED , "Operation cancelled", /* not sure */
2885 WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
2886 WSAEINVALIDPROVIDER , "Invalid service provider version number",
2887 WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
2888 WSASYSCALLFAILURE , "System call failured",
2889 WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
2890 WSATYPE_NOT_FOUND , "Class type not found",
2891 WSA_E_NO_MORE , "No more resources available", /* really not sure */
2892 WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
2893 WSAEREFUSED , "Operation refused", /* not sure */
2894 #endif
2895
2896 WSAHOST_NOT_FOUND , "Host not found",
2897 WSATRY_AGAIN , "Authoritative host not found during name lookup",
2898 WSANO_RECOVERY , "Non-recoverable error during name lookup",
2899 WSANO_DATA , "Valid name, no data record of requested type",
2900
2901 -1, NULL
2902 };
2903
2904 char *
2905 sys_strerror(int error_no)
2906 {
2907 int i;
2908 static char unknown_msg[40];
2909
2910 if (error_no >= 0 && error_no < sys_nerr)
2911 return sys_errlist[error_no];
2912
2913 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
2914 if (_wsa_errlist[i].errnum == error_no)
2915 return _wsa_errlist[i].msg;
2916
2917 sprintf(unknown_msg, "Unidentified error: %d", error_no);
2918 return unknown_msg;
2919 }
2920
2921 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2922 but I believe the method of keeping the socket handle separate (and
2923 insuring it is not inheritable) is the correct one. */
2924
2925 //#define SOCK_REPLACE_HANDLE
2926
2927 #ifdef SOCK_REPLACE_HANDLE
2928 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2929 #else
2930 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2931 #endif
2932
2933 int socket_to_fd (SOCKET s);
2934
2935 int
2936 sys_socket(int af, int type, int protocol)
2937 {
2938 SOCKET s;
2939
2940 if (winsock_lib == NULL)
2941 {
2942 h_errno = ENETDOWN;
2943 return INVALID_SOCKET;
2944 }
2945
2946 check_errno ();
2947
2948 /* call the real socket function */
2949 s = pfn_socket (af, type, protocol);
2950
2951 if (s != INVALID_SOCKET)
2952 return socket_to_fd (s);
2953
2954 set_errno ();
2955 return -1;
2956 }
2957
2958 /* Convert a SOCKET to a file descriptor. */
2959 int
2960 socket_to_fd (SOCKET s)
2961 {
2962 int fd;
2963 child_process * cp;
2964
2965 /* Although under NT 3.5 _open_osfhandle will accept a socket
2966 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2967 that does not work under NT 3.1. However, we can get the same
2968 effect by using a backdoor function to replace an existing
2969 descriptor handle with the one we want. */
2970
2971 /* allocate a file descriptor (with appropriate flags) */
2972 fd = _open ("NUL:", _O_RDWR);
2973 if (fd >= 0)
2974 {
2975 #ifdef SOCK_REPLACE_HANDLE
2976 /* now replace handle to NUL with our socket handle */
2977 CloseHandle ((HANDLE) _get_osfhandle (fd));
2978 _free_osfhnd (fd);
2979 _set_osfhnd (fd, s);
2980 /* setmode (fd, _O_BINARY); */
2981 #else
2982 /* Make a non-inheritable copy of the socket handle. Note
2983 that it is possible that sockets aren't actually kernel
2984 handles, which appears to be the case on Windows 9x when
2985 the MS Proxy winsock client is installed. */
2986 {
2987 /* Apparently there is a bug in NT 3.51 with some service
2988 packs, which prevents using DuplicateHandle to make a
2989 socket handle non-inheritable (causes WSACleanup to
2990 hang). The work-around is to use SetHandleInformation
2991 instead if it is available and implemented. */
2992 if (pfn_SetHandleInformation)
2993 {
2994 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
2995 }
2996 else
2997 {
2998 HANDLE parent = GetCurrentProcess ();
2999 HANDLE new_s = INVALID_HANDLE_VALUE;
3000
3001 if (DuplicateHandle (parent,
3002 (HANDLE) s,
3003 parent,
3004 &new_s,
3005 0,
3006 FALSE,
3007 DUPLICATE_SAME_ACCESS))
3008 {
3009 /* It is possible that DuplicateHandle succeeds even
3010 though the socket wasn't really a kernel handle,
3011 because a real handle has the same value. So
3012 test whether the new handle really is a socket. */
3013 long nonblocking = 0;
3014 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
3015 {
3016 pfn_closesocket (s);
3017 s = (SOCKET) new_s;
3018 }
3019 else
3020 {
3021 CloseHandle (new_s);
3022 }
3023 }
3024 }
3025 }
3026 fd_info[fd].hnd = (HANDLE) s;
3027 #endif
3028
3029 /* set our own internal flags */
3030 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
3031
3032 cp = new_child ();
3033 if (cp)
3034 {
3035 cp->fd = fd;
3036 cp->status = STATUS_READ_ACKNOWLEDGED;
3037
3038 /* attach child_process to fd_info */
3039 if (fd_info[ fd ].cp != NULL)
3040 {
3041 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
3042 abort ();
3043 }
3044
3045 fd_info[ fd ].cp = cp;
3046
3047 /* success! */
3048 winsock_inuse++; /* count open sockets */
3049 return fd;
3050 }
3051
3052 /* clean up */
3053 _close (fd);
3054 }
3055 pfn_closesocket (s);
3056 h_errno = EMFILE;
3057 return -1;
3058 }
3059
3060
3061 int
3062 sys_bind (int s, const struct sockaddr * addr, int namelen)
3063 {
3064 if (winsock_lib == NULL)
3065 {
3066 h_errno = ENOTSOCK;
3067 return SOCKET_ERROR;
3068 }
3069
3070 check_errno ();
3071 if (fd_info[s].flags & FILE_SOCKET)
3072 {
3073 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3074 if (rc == SOCKET_ERROR)
3075 set_errno ();
3076 return rc;
3077 }
3078 h_errno = ENOTSOCK;
3079 return SOCKET_ERROR;
3080 }
3081
3082
3083 int
3084 sys_connect (int s, const struct sockaddr * name, int namelen)
3085 {
3086 if (winsock_lib == NULL)
3087 {
3088 h_errno = ENOTSOCK;
3089 return SOCKET_ERROR;
3090 }
3091
3092 check_errno ();
3093 if (fd_info[s].flags & FILE_SOCKET)
3094 {
3095 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3096 if (rc == SOCKET_ERROR)
3097 set_errno ();
3098 return rc;
3099 }
3100 h_errno = ENOTSOCK;
3101 return SOCKET_ERROR;
3102 }
3103
3104 u_short
3105 sys_htons (u_short hostshort)
3106 {
3107 return (winsock_lib != NULL) ?
3108 pfn_htons (hostshort) : hostshort;
3109 }
3110
3111 u_short
3112 sys_ntohs (u_short netshort)
3113 {
3114 return (winsock_lib != NULL) ?
3115 pfn_ntohs (netshort) : netshort;
3116 }
3117
3118 unsigned long
3119 sys_inet_addr (const char * cp)
3120 {
3121 return (winsock_lib != NULL) ?
3122 pfn_inet_addr (cp) : INADDR_NONE;
3123 }
3124
3125 int
3126 sys_gethostname (char * name, int namelen)
3127 {
3128 if (winsock_lib != NULL)
3129 return pfn_gethostname (name, namelen);
3130
3131 if (namelen > MAX_COMPUTERNAME_LENGTH)
3132 return !GetComputerName (name, (DWORD *)&namelen);
3133
3134 h_errno = EFAULT;
3135 return SOCKET_ERROR;
3136 }
3137
3138 struct hostent *
3139 sys_gethostbyname(const char * name)
3140 {
3141 struct hostent * host;
3142
3143 if (winsock_lib == NULL)
3144 {
3145 h_errno = ENETDOWN;
3146 return NULL;
3147 }
3148
3149 check_errno ();
3150 host = pfn_gethostbyname (name);
3151 if (!host)
3152 set_errno ();
3153 return host;
3154 }
3155
3156 struct servent *
3157 sys_getservbyname(const char * name, const char * proto)
3158 {
3159 struct servent * serv;
3160
3161 if (winsock_lib == NULL)
3162 {
3163 h_errno = ENETDOWN;
3164 return NULL;
3165 }
3166
3167 check_errno ();
3168 serv = pfn_getservbyname (name, proto);
3169 if (!serv)
3170 set_errno ();
3171 return serv;
3172 }
3173
3174 int
3175 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3176 {
3177 if (winsock_lib == NULL)
3178 {
3179 h_errno = ENETDOWN;
3180 return SOCKET_ERROR;
3181 }
3182
3183 check_errno ();
3184 if (fd_info[s].flags & FILE_SOCKET)
3185 {
3186 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3187 if (rc == SOCKET_ERROR)
3188 set_errno ();
3189 return rc;
3190 }
3191 h_errno = ENOTSOCK;
3192 return SOCKET_ERROR;
3193 }
3194
3195
3196 int
3197 sys_shutdown (int s, int how)
3198 {
3199 if (winsock_lib == NULL)
3200 {
3201 h_errno = ENETDOWN;
3202 return SOCKET_ERROR;
3203 }
3204
3205 check_errno ();
3206 if (fd_info[s].flags & FILE_SOCKET)
3207 {
3208 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3209 if (rc == SOCKET_ERROR)
3210 set_errno ();
3211 return rc;
3212 }
3213 h_errno = ENOTSOCK;
3214 return SOCKET_ERROR;
3215 }
3216
3217 int
3218 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
3219 {
3220 if (winsock_lib == NULL)
3221 {
3222 h_errno = ENETDOWN;
3223 return SOCKET_ERROR;
3224 }
3225
3226 check_errno ();
3227 if (fd_info[s].flags & FILE_SOCKET)
3228 {
3229 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3230 (const char *)optval, optlen);
3231 if (rc == SOCKET_ERROR)
3232 set_errno ();
3233 return rc;
3234 }
3235 h_errno = ENOTSOCK;
3236 return SOCKET_ERROR;
3237 }
3238
3239 int
3240 sys_listen (int s, int backlog)
3241 {
3242 if (winsock_lib == NULL)
3243 {
3244 h_errno = ENETDOWN;
3245 return SOCKET_ERROR;
3246 }
3247
3248 check_errno ();
3249 if (fd_info[s].flags & FILE_SOCKET)
3250 {
3251 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3252 if (rc == SOCKET_ERROR)
3253 set_errno ();
3254 return rc;
3255 }
3256 h_errno = ENOTSOCK;
3257 return SOCKET_ERROR;
3258 }
3259
3260 int
3261 sys_getsockname (int s, struct sockaddr * name, int * namelen)
3262 {
3263 if (winsock_lib == NULL)
3264 {
3265 h_errno = ENETDOWN;
3266 return SOCKET_ERROR;
3267 }
3268
3269 check_errno ();
3270 if (fd_info[s].flags & FILE_SOCKET)
3271 {
3272 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3273 if (rc == SOCKET_ERROR)
3274 set_errno ();
3275 return rc;
3276 }
3277 h_errno = ENOTSOCK;
3278 return SOCKET_ERROR;
3279 }
3280
3281 int
3282 sys_accept (int s, struct sockaddr * addr, int * addrlen)
3283 {
3284 if (winsock_lib == NULL)
3285 {
3286 h_errno = ENETDOWN;
3287 return -1;
3288 }
3289
3290 check_errno ();
3291 if (fd_info[s].flags & FILE_SOCKET)
3292 {
3293 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3294 if (t != INVALID_SOCKET)
3295 return socket_to_fd (t);
3296
3297 set_errno ();
3298 return -1;
3299 }
3300 h_errno = ENOTSOCK;
3301 return -1;
3302 }
3303
3304 int
3305 sys_recvfrom (int s, char * buf, int len, int flags,
3306 struct sockaddr * from, int * fromlen)
3307 {
3308 if (winsock_lib == NULL)
3309 {
3310 h_errno = ENETDOWN;
3311 return SOCKET_ERROR;
3312 }
3313
3314 check_errno ();
3315 if (fd_info[s].flags & FILE_SOCKET)
3316 {
3317 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3318 if (rc == SOCKET_ERROR)
3319 set_errno ();
3320 return rc;
3321 }
3322 h_errno = ENOTSOCK;
3323 return SOCKET_ERROR;
3324 }
3325
3326 int
3327 sys_sendto (int s, const char * buf, int len, int flags,
3328 const struct sockaddr * to, int tolen)
3329 {
3330 if (winsock_lib == NULL)
3331 {
3332 h_errno = ENETDOWN;
3333 return SOCKET_ERROR;
3334 }
3335
3336 check_errno ();
3337 if (fd_info[s].flags & FILE_SOCKET)
3338 {
3339 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3340 if (rc == SOCKET_ERROR)
3341 set_errno ();
3342 return rc;
3343 }
3344 h_errno = ENOTSOCK;
3345 return SOCKET_ERROR;
3346 }
3347
3348 /* Windows does not have an fcntl function. Provide an implementation
3349 solely for making sockets non-blocking. */
3350 int
3351 fcntl (int s, int cmd, int options)
3352 {
3353 if (winsock_lib == NULL)
3354 {
3355 h_errno = ENETDOWN;
3356 return -1;
3357 }
3358
3359 check_errno ();
3360 if (fd_info[s].flags & FILE_SOCKET)
3361 {
3362 if (cmd == F_SETFL && options == O_NDELAY)
3363 {
3364 unsigned long nblock = 1;
3365 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3366 if (rc == SOCKET_ERROR)
3367 set_errno();
3368 /* Keep track of the fact that we set this to non-blocking. */
3369 fd_info[s].flags |= FILE_NDELAY;
3370 return rc;
3371 }
3372 else
3373 {
3374 h_errno = EINVAL;
3375 return SOCKET_ERROR;
3376 }
3377 }
3378 h_errno = ENOTSOCK;
3379 return SOCKET_ERROR;
3380 }
3381
3382 #endif /* HAVE_SOCKETS */
3383
3384
3385 /* Shadow main io functions: we need to handle pipes and sockets more
3386 intelligently, and implement non-blocking mode as well. */
3387
3388 int
3389 sys_close (int fd)
3390 {
3391 int rc;
3392
3393 if (fd < 0 || fd >= MAXDESC)
3394 {
3395 errno = EBADF;
3396 return -1;
3397 }
3398
3399 if (fd_info[fd].cp)
3400 {
3401 child_process * cp = fd_info[fd].cp;
3402
3403 fd_info[fd].cp = NULL;
3404
3405 if (CHILD_ACTIVE (cp))
3406 {
3407 /* if last descriptor to active child_process then cleanup */
3408 int i;
3409 for (i = 0; i < MAXDESC; i++)
3410 {
3411 if (i == fd)
3412 continue;
3413 if (fd_info[i].cp == cp)
3414 break;
3415 }
3416 if (i == MAXDESC)
3417 {
3418 #ifdef HAVE_SOCKETS
3419 if (fd_info[fd].flags & FILE_SOCKET)
3420 {
3421 #ifndef SOCK_REPLACE_HANDLE
3422 if (winsock_lib == NULL) abort ();
3423
3424 pfn_shutdown (SOCK_HANDLE (fd), 2);
3425 rc = pfn_closesocket (SOCK_HANDLE (fd));
3426 #endif
3427 winsock_inuse--; /* count open sockets */
3428 }
3429 #endif
3430 delete_child (cp);
3431 }
3432 }
3433 }
3434
3435 /* Note that sockets do not need special treatment here (at least on
3436 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3437 closesocket is equivalent to CloseHandle, which is to be expected
3438 because socket handles are fully fledged kernel handles. */
3439 rc = _close (fd);
3440
3441 if (rc == 0)
3442 fd_info[fd].flags = 0;
3443
3444 return rc;
3445 }
3446
3447 int
3448 sys_dup (int fd)
3449 {
3450 int new_fd;
3451
3452 new_fd = _dup (fd);
3453 if (new_fd >= 0)
3454 {
3455 /* duplicate our internal info as well */
3456 fd_info[new_fd] = fd_info[fd];
3457 }
3458 return new_fd;
3459 }
3460
3461
3462 int
3463 sys_dup2 (int src, int dst)
3464 {
3465 int rc;
3466
3467 if (dst < 0 || dst >= MAXDESC)
3468 {
3469 errno = EBADF;
3470 return -1;
3471 }
3472
3473 /* make sure we close the destination first if it's a pipe or socket */
3474 if (src != dst && fd_info[dst].flags != 0)
3475 sys_close (dst);
3476
3477 rc = _dup2 (src, dst);
3478 if (rc == 0)
3479 {
3480 /* duplicate our internal info as well */
3481 fd_info[dst] = fd_info[src];
3482 }
3483 return rc;
3484 }
3485
3486 /* Unix pipe() has only one arg */
3487 int
3488 sys_pipe (int * phandles)
3489 {
3490 int rc;
3491 unsigned flags;
3492
3493 /* make pipe handles non-inheritable; when we spawn a child, we
3494 replace the relevant handle with an inheritable one. Also put
3495 pipes into binary mode; we will do text mode translation ourselves
3496 if required. */
3497 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3498
3499 if (rc == 0)
3500 {
3501 /* Protect against overflow, since Windows can open more handles than
3502 our fd_info array has room for. */
3503 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
3504 {
3505 _close (phandles[0]);
3506 _close (phandles[1]);
3507 rc = -1;
3508 }
3509 else
3510 {
3511 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3512 fd_info[phandles[0]].flags = flags;
3513
3514 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3515 fd_info[phandles[1]].flags = flags;
3516 }
3517 }
3518
3519 return rc;
3520 }
3521
3522 /* From ntproc.c */
3523 extern int w32_pipe_read_delay;
3524
3525 /* Function to do blocking read of one byte, needed to implement
3526 select. It is only allowed on sockets and pipes. */
3527 int
3528 _sys_read_ahead (int fd)
3529 {
3530 child_process * cp;
3531 int rc;
3532
3533 if (fd < 0 || fd >= MAXDESC)
3534 return STATUS_READ_ERROR;
3535
3536 cp = fd_info[fd].cp;
3537
3538 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3539 return STATUS_READ_ERROR;
3540
3541 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3542 || (fd_info[fd].flags & FILE_READ) == 0)
3543 {
3544 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3545 abort ();
3546 }
3547
3548 cp->status = STATUS_READ_IN_PROGRESS;
3549
3550 if (fd_info[fd].flags & FILE_PIPE)
3551 {
3552 rc = _read (fd, &cp->chr, sizeof (char));
3553
3554 /* Give subprocess time to buffer some more output for us before
3555 reporting that input is available; we need this because Windows 95
3556 connects DOS programs to pipes by making the pipe appear to be
3557 the normal console stdout - as a result most DOS programs will
3558 write to stdout without buffering, ie. one character at a
3559 time. Even some W32 programs do this - "dir" in a command
3560 shell on NT is very slow if we don't do this. */
3561 if (rc > 0)
3562 {
3563 int wait = w32_pipe_read_delay;
3564
3565 if (wait > 0)
3566 Sleep (wait);
3567 else if (wait < 0)
3568 while (++wait <= 0)
3569 /* Yield remainder of our time slice, effectively giving a
3570 temporary priority boost to the child process. */
3571 Sleep (0);
3572 }
3573 }
3574 #ifdef HAVE_SOCKETS
3575 else if (fd_info[fd].flags & FILE_SOCKET)
3576 {
3577 unsigned long nblock = 0;
3578 /* We always want this to block, so temporarily disable NDELAY. */
3579 if (fd_info[fd].flags & FILE_NDELAY)
3580 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3581
3582 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3583
3584 if (fd_info[fd].flags & FILE_NDELAY)
3585 {
3586 nblock = 1;
3587 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3588 }
3589 }
3590 #endif
3591
3592 if (rc == sizeof (char))
3593 cp->status = STATUS_READ_SUCCEEDED;
3594 else
3595 cp->status = STATUS_READ_FAILED;
3596
3597 return cp->status;
3598 }
3599
3600 int
3601 sys_read (int fd, char * buffer, unsigned int count)
3602 {
3603 int nchars;
3604 int to_read;
3605 DWORD waiting;
3606 char * orig_buffer = buffer;
3607
3608 if (fd < 0 || fd >= MAXDESC)
3609 {
3610 errno = EBADF;
3611 return -1;
3612 }
3613
3614 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3615 {
3616 child_process *cp = fd_info[fd].cp;
3617
3618 if ((fd_info[fd].flags & FILE_READ) == 0)
3619 {
3620 errno = EBADF;
3621 return -1;
3622 }
3623
3624 nchars = 0;
3625
3626 /* re-read CR carried over from last read */
3627 if (fd_info[fd].flags & FILE_LAST_CR)
3628 {
3629 if (fd_info[fd].flags & FILE_BINARY) abort ();
3630 *buffer++ = 0x0d;
3631 count--;
3632 nchars++;
3633 fd_info[fd].flags &= ~FILE_LAST_CR;
3634 }
3635
3636 /* presence of a child_process structure means we are operating in
3637 non-blocking mode - otherwise we just call _read directly.
3638 Note that the child_process structure might be missing because
3639 reap_subprocess has been called; in this case the pipe is
3640 already broken, so calling _read on it is okay. */
3641 if (cp)
3642 {
3643 int current_status = cp->status;
3644
3645 switch (current_status)
3646 {
3647 case STATUS_READ_FAILED:
3648 case STATUS_READ_ERROR:
3649 /* report normal EOF if nothing in buffer */
3650 if (nchars <= 0)
3651 fd_info[fd].flags |= FILE_AT_EOF;
3652 return nchars;
3653
3654 case STATUS_READ_READY:
3655 case STATUS_READ_IN_PROGRESS:
3656 DebPrint (("sys_read called when read is in progress\n"));
3657 errno = EWOULDBLOCK;
3658 return -1;
3659
3660 case STATUS_READ_SUCCEEDED:
3661 /* consume read-ahead char */
3662 *buffer++ = cp->chr;
3663 count--;
3664 nchars++;
3665 cp->status = STATUS_READ_ACKNOWLEDGED;
3666 ResetEvent (cp->char_avail);
3667
3668 case STATUS_READ_ACKNOWLEDGED:
3669 break;
3670
3671 default:
3672 DebPrint (("sys_read: bad status %d\n", current_status));
3673 errno = EBADF;
3674 return -1;
3675 }
3676
3677 if (fd_info[fd].flags & FILE_PIPE)
3678 {
3679 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3680 to_read = min (waiting, (DWORD) count);
3681
3682 if (to_read > 0)
3683 nchars += _read (fd, buffer, to_read);
3684 }
3685 #ifdef HAVE_SOCKETS
3686 else /* FILE_SOCKET */
3687 {
3688 if (winsock_lib == NULL) abort ();
3689
3690 /* do the equivalent of a non-blocking read */
3691 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3692 if (waiting == 0 && nchars == 0)
3693 {
3694 h_errno = errno = EWOULDBLOCK;
3695 return -1;
3696 }
3697
3698 if (waiting)
3699 {
3700 /* always use binary mode for sockets */
3701 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3702 if (res == SOCKET_ERROR)
3703 {
3704 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3705 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3706 set_errno ();
3707 return -1;
3708 }
3709 nchars += res;
3710 }
3711 }
3712 #endif
3713 }
3714 else
3715 {
3716 int nread = _read (fd, buffer, count);
3717 if (nread >= 0)
3718 nchars += nread;
3719 else if (nchars == 0)
3720 nchars = nread;
3721 }
3722
3723 if (nchars <= 0)
3724 fd_info[fd].flags |= FILE_AT_EOF;
3725 /* Perform text mode translation if required. */
3726 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3727 {
3728 nchars = crlf_to_lf (nchars, orig_buffer);
3729 /* If buffer contains only CR, return that. To be absolutely
3730 sure we should attempt to read the next char, but in
3731 practice a CR to be followed by LF would not appear by
3732 itself in the buffer. */
3733 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3734 {
3735 fd_info[fd].flags |= FILE_LAST_CR;
3736 nchars--;
3737 }
3738 }
3739 }
3740 else
3741 nchars = _read (fd, buffer, count);
3742
3743 return nchars;
3744 }
3745
3746 /* For now, don't bother with a non-blocking mode */
3747 int
3748 sys_write (int fd, const void * buffer, unsigned int count)
3749 {
3750 int nchars;
3751
3752 if (fd < 0 || fd >= MAXDESC)
3753 {
3754 errno = EBADF;
3755 return -1;
3756 }
3757
3758 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3759 {
3760 if ((fd_info[fd].flags & FILE_WRITE) == 0)
3761 {
3762 errno = EBADF;
3763 return -1;
3764 }
3765
3766 /* Perform text mode translation if required. */
3767 if ((fd_info[fd].flags & FILE_BINARY) == 0)
3768 {
3769 char * tmpbuf = alloca (count * 2);
3770 unsigned char * src = (void *)buffer;
3771 unsigned char * dst = tmpbuf;
3772 int nbytes = count;
3773
3774 while (1)
3775 {
3776 unsigned char *next;
3777 /* copy next line or remaining bytes */
3778 next = _memccpy (dst, src, '\n', nbytes);
3779 if (next)
3780 {
3781 /* copied one line ending with '\n' */
3782 int copied = next - dst;
3783 nbytes -= copied;
3784 src += copied;
3785 /* insert '\r' before '\n' */
3786 next[-1] = '\r';
3787 next[0] = '\n';
3788 dst = next + 1;
3789 count++;
3790 }
3791 else
3792 /* copied remaining partial line -> now finished */
3793 break;
3794 }
3795 buffer = tmpbuf;
3796 }
3797 }
3798
3799 #ifdef HAVE_SOCKETS
3800 if (fd_info[fd].flags & FILE_SOCKET)
3801 {
3802 unsigned long nblock = 0;
3803 if (winsock_lib == NULL) abort ();
3804
3805 /* TODO: implement select() properly so non-blocking I/O works. */
3806 /* For now, make sure the write blocks. */
3807 if (fd_info[fd].flags & FILE_NDELAY)
3808 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3809
3810 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3811
3812 /* Set the socket back to non-blocking if it was before,
3813 for other operations that support it. */
3814 if (fd_info[fd].flags & FILE_NDELAY)
3815 {
3816 nblock = 1;
3817 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3818 }
3819
3820 if (nchars == SOCKET_ERROR)
3821 {
3822 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3823 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3824 set_errno ();
3825 }
3826 }
3827 else
3828 #endif
3829 nchars = _write (fd, buffer, count);
3830
3831 return nchars;
3832 }
3833
3834 static void
3835 check_windows_init_file ()
3836 {
3837 extern int noninteractive, inhibit_window_system;
3838
3839 /* A common indication that Emacs is not installed properly is when
3840 it cannot find the Windows installation file. If this file does
3841 not exist in the expected place, tell the user. */
3842
3843 if (!noninteractive && !inhibit_window_system)
3844 {
3845 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3846 Lisp_Object objs[2];
3847 Lisp_Object full_load_path;
3848 Lisp_Object init_file;
3849 int fd;
3850
3851 objs[0] = Vload_path;
3852 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3853 full_load_path = Fappend (2, objs);
3854 init_file = build_string ("term/w32-win");
3855 fd = openp (full_load_path, init_file, Vload_suffixes, NULL, Qnil);
3856 if (fd < 0)
3857 {
3858 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3859 char *init_file_name = SDATA (init_file);
3860 char *load_path = SDATA (load_path_print);
3861 char *buffer = alloca (1024);
3862
3863 sprintf (buffer,
3864 "The Emacs Windows initialization file \"%s.el\" "
3865 "could not be found in your Emacs installation. "
3866 "Emacs checked the following directories for this file:\n"
3867 "\n%s\n\n"
3868 "When Emacs cannot find this file, it usually means that it "
3869 "was not installed properly, or its distribution file was "
3870 "not unpacked properly.\nSee the README.W32 file in the "
3871 "top-level Emacs directory for more information.",
3872 init_file_name, load_path);
3873 MessageBox (NULL,
3874 buffer,
3875 "Emacs Abort Dialog",
3876 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3877 /* Use the low-level Emacs abort. */
3878 #undef abort
3879 abort ();
3880 }
3881 else
3882 {
3883 _close (fd);
3884 }
3885 }
3886 }
3887
3888 void
3889 term_ntproc ()
3890 {
3891 #ifdef HAVE_SOCKETS
3892 /* shutdown the socket interface if necessary */
3893 term_winsock ();
3894 #endif
3895
3896 term_w32select ();
3897 }
3898
3899 void
3900 init_ntproc ()
3901 {
3902 #ifdef HAVE_SOCKETS
3903 /* Initialise the socket interface now if available and requested by
3904 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3905 delayed until open-network-stream is called (w32-has-winsock can
3906 also be used to dynamically load or reload winsock).
3907
3908 Conveniently, init_environment is called before us, so
3909 PRELOAD_WINSOCK can be set in the registry. */
3910
3911 /* Always initialize this correctly. */
3912 winsock_lib = NULL;
3913
3914 if (getenv ("PRELOAD_WINSOCK") != NULL)
3915 init_winsock (TRUE);
3916 #endif
3917
3918 /* Initial preparation for subprocess support: replace our standard
3919 handles with non-inheritable versions. */
3920 {
3921 HANDLE parent;
3922 HANDLE stdin_save = INVALID_HANDLE_VALUE;
3923 HANDLE stdout_save = INVALID_HANDLE_VALUE;
3924 HANDLE stderr_save = INVALID_HANDLE_VALUE;
3925
3926 parent = GetCurrentProcess ();
3927
3928 /* ignore errors when duplicating and closing; typically the
3929 handles will be invalid when running as a gui program. */
3930 DuplicateHandle (parent,
3931 GetStdHandle (STD_INPUT_HANDLE),
3932 parent,
3933 &stdin_save,
3934 0,
3935 FALSE,
3936 DUPLICATE_SAME_ACCESS);
3937
3938 DuplicateHandle (parent,
3939 GetStdHandle (STD_OUTPUT_HANDLE),
3940 parent,
3941 &stdout_save,
3942 0,
3943 FALSE,
3944 DUPLICATE_SAME_ACCESS);
3945
3946 DuplicateHandle (parent,
3947 GetStdHandle (STD_ERROR_HANDLE),
3948 parent,
3949 &stderr_save,
3950 0,
3951 FALSE,
3952 DUPLICATE_SAME_ACCESS);
3953
3954 fclose (stdin);
3955 fclose (stdout);
3956 fclose (stderr);
3957
3958 if (stdin_save != INVALID_HANDLE_VALUE)
3959 _open_osfhandle ((long) stdin_save, O_TEXT);
3960 else
3961 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3962 _fdopen (0, "r");
3963
3964 if (stdout_save != INVALID_HANDLE_VALUE)
3965 _open_osfhandle ((long) stdout_save, O_TEXT);
3966 else
3967 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3968 _fdopen (1, "w");
3969
3970 if (stderr_save != INVALID_HANDLE_VALUE)
3971 _open_osfhandle ((long) stderr_save, O_TEXT);
3972 else
3973 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3974 _fdopen (2, "w");
3975 }
3976
3977 /* unfortunately, atexit depends on implementation of malloc */
3978 /* atexit (term_ntproc); */
3979 signal (SIGABRT, term_ntproc);
3980
3981 /* determine which drives are fixed, for GetCachedVolumeInformation */
3982 {
3983 /* GetDriveType must have trailing backslash. */
3984 char drive[] = "A:\\";
3985
3986 /* Loop over all possible drive letters */
3987 while (*drive <= 'Z')
3988 {
3989 /* Record if this drive letter refers to a fixed drive. */
3990 fixed_drives[DRIVE_INDEX (*drive)] =
3991 (GetDriveType (drive) == DRIVE_FIXED);
3992
3993 (*drive)++;
3994 }
3995
3996 /* Reset the volume info cache. */
3997 volume_cache = NULL;
3998 }
3999
4000 /* Check to see if Emacs has been installed correctly. */
4001 check_windows_init_file ();
4002 }
4003
4004 /*
4005 globals_of_w32 is used to initialize those global variables that
4006 must always be initialized on startup even when the global variable
4007 initialized is non zero (see the function main in emacs.c).
4008 */
4009 void globals_of_w32 ()
4010 {
4011 g_b_init_is_windows_9x = 0;
4012 g_b_init_open_process_token = 0;
4013 g_b_init_get_token_information = 0;
4014 g_b_init_lookup_account_sid = 0;
4015 g_b_init_get_sid_identifier_authority = 0;
4016 }
4017
4018 /* end of nt.c */
4019
4020 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4021 (do not change this comment) */