(Fset_window_scroll_bars): Fix typo in argument name.
[emacs.git] / src / w32.c
blob744cc5931339437a8ce0983f76605c55c111f813
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.
4 This file is part of GNU Emacs.
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.
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.
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.
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
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>
37 /* must include CRT headers *before* config.h */
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
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
57 #undef close
58 #undef dup
59 #undef dup2
60 #undef pipe
61 #undef read
62 #undef write
64 #undef strerror
66 #include "lisp.h"
68 #include <pwd.h>
70 #ifdef __GNUC__
71 #define _ANONYMOUS_UNION
72 #define _ANONYMOUS_STRUCT
73 #endif
74 #include <windows.h>
76 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
77 #include <sys/socket.h>
78 #undef socket
79 #undef bind
80 #undef connect
81 #undef htons
82 #undef ntohs
83 #undef inet_addr
84 #undef gethostname
85 #undef gethostbyname
86 #undef getservbyname
87 #undef getpeername
88 #undef shutdown
89 #undef setsockopt
90 #undef listen
91 #undef getsockname
92 #undef accept
93 #undef recvfrom
94 #undef sendto
95 #endif
97 #include "w32.h"
98 #include "ndir.h"
99 #include "w32heap.h"
100 #include "systime.h"
102 void globals_of_w32 ();
104 extern Lisp_Object Vw32_downcase_file_names;
105 extern Lisp_Object Vw32_generate_fake_inodes;
106 extern Lisp_Object Vw32_get_true_file_attributes;
107 extern Lisp_Object Vw32_num_mouse_buttons;
111 Initialization states
113 static BOOL g_b_init_is_windows_9x;
114 static BOOL g_b_init_open_process_token;
115 static BOOL g_b_init_get_token_information;
116 static BOOL g_b_init_lookup_account_sid;
117 static BOOL g_b_init_get_sid_identifier_authority;
120 BEGIN: Wrapper functions around OpenProcessToken
121 and other functions in advapi32.dll that are only
122 supported in Windows NT / 2k / XP
124 /* ** Function pointer typedefs ** */
125 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
126 HANDLE ProcessHandle,
127 DWORD DesiredAccess,
128 PHANDLE TokenHandle);
129 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
130 HANDLE TokenHandle,
131 TOKEN_INFORMATION_CLASS TokenInformationClass,
132 LPVOID TokenInformation,
133 DWORD TokenInformationLength,
134 PDWORD ReturnLength);
135 #ifdef _UNICODE
136 const char * const LookupAccountSid_Name = "LookupAccountSidW";
137 #else
138 const char * const LookupAccountSid_Name = "LookupAccountSidA";
139 #endif
140 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
141 LPCTSTR lpSystemName,
142 PSID Sid,
143 LPTSTR Name,
144 LPDWORD cbName,
145 LPTSTR DomainName,
146 LPDWORD cbDomainName,
147 PSID_NAME_USE peUse);
148 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
149 PSID pSid);
151 /* ** A utility function ** */
152 static BOOL is_windows_9x ()
154 static BOOL s_b_ret=0;
155 OSVERSIONINFO os_ver;
156 if (g_b_init_is_windows_9x == 0)
158 g_b_init_is_windows_9x = 1;
159 ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
160 os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
161 if (GetVersionEx (&os_ver))
163 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
166 return s_b_ret;
169 /* ** The wrapper functions ** */
171 BOOL WINAPI open_process_token (
172 HANDLE ProcessHandle,
173 DWORD DesiredAccess,
174 PHANDLE TokenHandle)
176 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
177 HMODULE hm_advapi32 = NULL;
178 if (is_windows_9x () == TRUE)
180 return FALSE;
182 if (g_b_init_open_process_token == 0)
184 g_b_init_open_process_token = 1;
185 hm_advapi32 = LoadLibrary ("Advapi32.dll");
186 s_pfn_Open_Process_Token =
187 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
189 if (s_pfn_Open_Process_Token == NULL)
191 return FALSE;
193 return (
194 s_pfn_Open_Process_Token (
195 ProcessHandle,
196 DesiredAccess,
197 TokenHandle)
201 BOOL WINAPI get_token_information (
202 HANDLE TokenHandle,
203 TOKEN_INFORMATION_CLASS TokenInformationClass,
204 LPVOID TokenInformation,
205 DWORD TokenInformationLength,
206 PDWORD ReturnLength)
208 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
209 HMODULE hm_advapi32 = NULL;
210 if (is_windows_9x () == TRUE)
212 return FALSE;
214 if (g_b_init_get_token_information == 0)
216 g_b_init_get_token_information = 1;
217 hm_advapi32 = LoadLibrary ("Advapi32.dll");
218 s_pfn_Get_Token_Information =
219 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
221 if (s_pfn_Get_Token_Information == NULL)
223 return FALSE;
225 return (
226 s_pfn_Get_Token_Information (
227 TokenHandle,
228 TokenInformationClass,
229 TokenInformation,
230 TokenInformationLength,
231 ReturnLength)
235 BOOL WINAPI lookup_account_sid (
236 LPCTSTR lpSystemName,
237 PSID Sid,
238 LPTSTR Name,
239 LPDWORD cbName,
240 LPTSTR DomainName,
241 LPDWORD cbDomainName,
242 PSID_NAME_USE peUse)
244 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
245 HMODULE hm_advapi32 = NULL;
246 if (is_windows_9x () == TRUE)
248 return FALSE;
250 if (g_b_init_lookup_account_sid == 0)
252 g_b_init_lookup_account_sid = 1;
253 hm_advapi32 = LoadLibrary ("Advapi32.dll");
254 s_pfn_Lookup_Account_Sid =
255 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
257 if (s_pfn_Lookup_Account_Sid == NULL)
259 return FALSE;
261 return (
262 s_pfn_Lookup_Account_Sid (
263 lpSystemName,
264 Sid,
265 Name,
266 cbName,
267 DomainName,
268 cbDomainName,
269 peUse)
273 PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
274 PSID pSid)
276 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
277 HMODULE hm_advapi32 = NULL;
278 if (is_windows_9x () == TRUE)
280 return NULL;
282 if (g_b_init_get_sid_identifier_authority == 0)
284 g_b_init_get_sid_identifier_authority = 1;
285 hm_advapi32 = LoadLibrary ("Advapi32.dll");
286 s_pfn_Get_Sid_Identifier_Authority =
287 (GetSidIdentifierAuthority_Proc) GetProcAddress (
288 hm_advapi32, "GetSidIdentifierAuthority");
290 if (s_pfn_Get_Sid_Identifier_Authority == NULL)
292 return NULL;
294 return (s_pfn_Get_Sid_Identifier_Authority (pSid));
298 END: Wrapper functions around OpenProcessToken
299 and other functions in advapi32.dll that are only
300 supported in Windows NT / 2k / XP
304 /* Equivalent of strerror for W32 error codes. */
305 char *
306 w32_strerror (int error_no)
308 static char buf[500];
310 if (error_no == 0)
311 error_no = GetLastError ();
313 buf[0] = '\0';
314 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
315 error_no,
316 0, /* choose most suitable language */
317 buf, sizeof (buf), NULL))
318 sprintf (buf, "w32 error %u", error_no);
319 return buf;
322 static char startup_dir[MAXPATHLEN];
324 /* Get the current working directory. */
325 char *
326 getwd (char *dir)
328 #if 0
329 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
330 return dir;
331 return NULL;
332 #else
333 /* Emacs doesn't actually change directory itself, and we want to
334 force our real wd to be where emacs.exe is to avoid unnecessary
335 conflicts when trying to rename or delete directories. */
336 strcpy (dir, startup_dir);
337 return dir;
338 #endif
341 #ifndef HAVE_SOCKETS
342 /* Emulate gethostname. */
344 gethostname (char *buffer, int size)
346 /* NT only allows small host names, so the buffer is
347 certainly large enough. */
348 return !GetComputerName (buffer, &size);
350 #endif /* HAVE_SOCKETS */
352 /* Emulate getloadavg. */
354 getloadavg (double loadavg[], int nelem)
356 int i;
358 /* A faithful emulation is going to have to be saved for a rainy day. */
359 for (i = 0; i < nelem; i++)
361 loadavg[i] = 0.0;
363 return i;
366 /* Emulate getpwuid, getpwnam and others. */
368 #define PASSWD_FIELD_SIZE 256
370 static char the_passwd_name[PASSWD_FIELD_SIZE];
371 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
372 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
373 static char the_passwd_dir[PASSWD_FIELD_SIZE];
374 static char the_passwd_shell[PASSWD_FIELD_SIZE];
376 static struct passwd the_passwd =
378 the_passwd_name,
379 the_passwd_passwd,
383 the_passwd_gecos,
384 the_passwd_dir,
385 the_passwd_shell,
389 getuid ()
391 return the_passwd.pw_uid;
395 geteuid ()
397 /* I could imagine arguing for checking to see whether the user is
398 in the Administrators group and returning a UID of 0 for that
399 case, but I don't know how wise that would be in the long run. */
400 return getuid ();
404 getgid ()
406 return the_passwd.pw_gid;
410 getegid ()
412 return getgid ();
415 struct passwd *
416 getpwuid (int uid)
418 if (uid == the_passwd.pw_uid)
419 return &the_passwd;
420 return NULL;
423 struct passwd *
424 getpwnam (char *name)
426 struct passwd *pw;
428 pw = getpwuid (getuid ());
429 if (!pw)
430 return pw;
432 if (stricmp (name, pw->pw_name))
433 return NULL;
435 return pw;
438 void
439 init_user_info ()
441 /* Find the user's real name by opening the process token and
442 looking up the name associated with the user-sid in that token.
444 Use the relative portion of the identifier authority value from
445 the user-sid as the user id value (same for group id using the
446 primary group sid from the process token). */
448 char user_sid[256], name[256], domain[256];
449 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
450 HANDLE token = NULL;
451 SID_NAME_USE user_type;
453 if (
454 open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
455 && get_token_information (
456 token, TokenUser,
457 (PVOID) user_sid, sizeof (user_sid), &trash)
458 && lookup_account_sid (
459 NULL, *((PSID *) user_sid), name, &length,
460 domain, &dlength, &user_type)
463 strcpy (the_passwd.pw_name, name);
464 /* Determine a reasonable uid value. */
465 if (stricmp ("administrator", name) == 0)
467 the_passwd.pw_uid = 0;
468 the_passwd.pw_gid = 0;
470 else
472 SID_IDENTIFIER_AUTHORITY * pSIA;
474 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
475 /* I believe the relative portion is the last 4 bytes (of 6)
476 with msb first. */
477 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
478 (pSIA->Value[3] << 16) +
479 (pSIA->Value[4] << 8) +
480 (pSIA->Value[5] << 0));
481 /* restrict to conventional uid range for normal users */
482 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
484 /* Get group id */
485 if (get_token_information (token, TokenPrimaryGroup,
486 (PVOID) user_sid, sizeof (user_sid), &trash))
488 SID_IDENTIFIER_AUTHORITY * pSIA;
490 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
491 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
492 (pSIA->Value[3] << 16) +
493 (pSIA->Value[4] << 8) +
494 (pSIA->Value[5] << 0));
495 /* I don't know if this is necessary, but for safety... */
496 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
498 else
499 the_passwd.pw_gid = the_passwd.pw_uid;
502 /* If security calls are not supported (presumably because we
503 are running under Windows 95), fallback to this. */
504 else if (GetUserName (name, &length))
506 strcpy (the_passwd.pw_name, name);
507 if (stricmp ("administrator", name) == 0)
508 the_passwd.pw_uid = 0;
509 else
510 the_passwd.pw_uid = 123;
511 the_passwd.pw_gid = the_passwd.pw_uid;
513 else
515 strcpy (the_passwd.pw_name, "unknown");
516 the_passwd.pw_uid = 123;
517 the_passwd.pw_gid = 123;
520 /* Ensure HOME and SHELL are defined. */
521 if (getenv ("HOME") == NULL)
522 abort ();
523 if (getenv ("SHELL") == NULL)
524 abort ();
526 /* Set dir and shell from environment variables. */
527 strcpy (the_passwd.pw_dir, getenv ("HOME"));
528 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
530 if (token)
531 CloseHandle (token);
535 random ()
537 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
538 return ((rand () << 15) | rand ());
541 void
542 srandom (int seed)
544 srand (seed);
548 /* Normalize filename by converting all path separators to
549 the specified separator. Also conditionally convert upper
550 case path name components to lower case. */
552 static void
553 normalize_filename (fp, path_sep)
554 register char *fp;
555 char path_sep;
557 char sep;
558 char *elem;
560 /* Always lower-case drive letters a-z, even if the filesystem
561 preserves case in filenames.
562 This is so filenames can be compared by string comparison
563 functions that are case-sensitive. Even case-preserving filesystems
564 do not distinguish case in drive letters. */
565 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
567 *fp += 'a' - 'A';
568 fp += 2;
571 if (NILP (Vw32_downcase_file_names))
573 while (*fp)
575 if (*fp == '/' || *fp == '\\')
576 *fp = path_sep;
577 fp++;
579 return;
582 sep = path_sep; /* convert to this path separator */
583 elem = fp; /* start of current path element */
585 do {
586 if (*fp >= 'a' && *fp <= 'z')
587 elem = 0; /* don't convert this element */
589 if (*fp == 0 || *fp == ':')
591 sep = *fp; /* restore current separator (or 0) */
592 *fp = '/'; /* after conversion of this element */
595 if (*fp == '/' || *fp == '\\')
597 if (elem && elem != fp)
599 *fp = 0; /* temporary end of string */
600 _strlwr (elem); /* while we convert to lower case */
602 *fp = sep; /* convert (or restore) path separator */
603 elem = fp + 1; /* next element starts after separator */
604 sep = path_sep;
606 } while (*fp++);
609 /* Destructively turn backslashes into slashes. */
610 void
611 dostounix_filename (p)
612 register char *p;
614 normalize_filename (p, '/');
617 /* Destructively turn slashes into backslashes. */
618 void
619 unixtodos_filename (p)
620 register char *p;
622 normalize_filename (p, '\\');
625 /* Remove all CR's that are followed by a LF.
626 (From msdos.c...probably should figure out a way to share it,
627 although this code isn't going to ever change.) */
629 crlf_to_lf (n, buf)
630 register int n;
631 register unsigned char *buf;
633 unsigned char *np = buf;
634 unsigned char *startp = buf;
635 unsigned char *endp = buf + n;
637 if (n == 0)
638 return n;
639 while (buf < endp - 1)
641 if (*buf == 0x0d)
643 if (*(++buf) != 0x0a)
644 *np++ = 0x0d;
646 else
647 *np++ = *buf++;
649 if (buf < endp)
650 *np++ = *buf++;
651 return np - startp;
654 /* Parse the root part of file name, if present. Return length and
655 optionally store pointer to char after root. */
656 static int
657 parse_root (char * name, char ** pPath)
659 char * start = name;
661 if (name == NULL)
662 return 0;
664 /* find the root name of the volume if given */
665 if (isalpha (name[0]) && name[1] == ':')
667 /* skip past drive specifier */
668 name += 2;
669 if (IS_DIRECTORY_SEP (name[0]))
670 name++;
672 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
674 int slashes = 2;
675 name += 2;
678 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
679 break;
680 name++;
682 while ( *name );
683 if (IS_DIRECTORY_SEP (name[0]))
684 name++;
687 if (pPath)
688 *pPath = name;
690 return name - start;
693 /* Get long base name for name; name is assumed to be absolute. */
694 static int
695 get_long_basename (char * name, char * buf, int size)
697 WIN32_FIND_DATA find_data;
698 HANDLE dir_handle;
699 int len = 0;
701 /* must be valid filename, no wild cards or other invalid characters */
702 if (strpbrk (name, "*?|<>\""))
703 return 0;
705 dir_handle = FindFirstFile (name, &find_data);
706 if (dir_handle != INVALID_HANDLE_VALUE)
708 if ((len = strlen (find_data.cFileName)) < size)
709 memcpy (buf, find_data.cFileName, len + 1);
710 else
711 len = 0;
712 FindClose (dir_handle);
714 return len;
717 /* Get long name for file, if possible (assumed to be absolute). */
718 BOOL
719 w32_get_long_filename (char * name, char * buf, int size)
721 char * o = buf;
722 char * p;
723 char * q;
724 char full[ MAX_PATH ];
725 int len;
727 len = strlen (name);
728 if (len >= MAX_PATH)
729 return FALSE;
731 /* Use local copy for destructive modification. */
732 memcpy (full, name, len+1);
733 unixtodos_filename (full);
735 /* Copy root part verbatim. */
736 len = parse_root (full, &p);
737 memcpy (o, full, len);
738 o += len;
739 *o = '\0';
740 size -= len;
742 while (p != NULL && *p)
744 q = p;
745 p = strchr (q, '\\');
746 if (p) *p = '\0';
747 len = get_long_basename (full, o, size);
748 if (len > 0)
750 o += len;
751 size -= len;
752 if (p != NULL)
754 *p++ = '\\';
755 if (size < 2)
756 return FALSE;
757 *o++ = '\\';
758 size--;
759 *o = '\0';
762 else
763 return FALSE;
766 return TRUE;
770 is_unc_volume (const char *filename)
772 const char *ptr = filename;
774 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
775 return 0;
777 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
778 return 0;
780 return 1;
783 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
786 sigsetmask (int signal_mask)
788 return 0;
792 sigmask (int sig)
794 return 0;
798 sigblock (int sig)
800 return 0;
804 sigunblock (int sig)
806 return 0;
810 setpgrp (int pid, int gid)
812 return 0;
816 alarm (int seconds)
818 return 0;
821 void
822 unrequest_sigio (void)
824 return;
827 void
828 request_sigio (void)
830 return;
833 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
835 LPBYTE
836 w32_get_resource (key, lpdwtype)
837 char *key;
838 LPDWORD lpdwtype;
840 LPBYTE lpvalue;
841 HKEY hrootkey = NULL;
842 DWORD cbData;
843 BOOL ok = FALSE;
845 /* Check both the current user and the local machine to see if
846 we have any resources. */
848 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
850 lpvalue = NULL;
852 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
853 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
854 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
856 return (lpvalue);
859 if (lpvalue) xfree (lpvalue);
861 RegCloseKey (hrootkey);
864 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
866 lpvalue = NULL;
868 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
869 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
870 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
872 return (lpvalue);
875 if (lpvalue) xfree (lpvalue);
877 RegCloseKey (hrootkey);
880 return (NULL);
883 char *get_emacs_configuration (void);
884 extern Lisp_Object Vsystem_configuration;
886 void
887 init_environment (char ** argv)
889 static const char * const tempdirs[] = {
890 "$TMPDIR", "$TEMP", "$TMP", "c:/"
892 int i;
893 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
895 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
896 temporary files and assume "/tmp" if $TMPDIR is unset, which
897 will break on DOS/Windows. Refuse to work if we cannot find
898 a directory, not even "c:/", usable for that purpose. */
899 for (i = 0; i < imax ; i++)
901 const char *tmp = tempdirs[i];
903 if (*tmp == '$')
904 tmp = getenv (tmp + 1);
905 /* Note that `access' can lie to us if the directory resides on a
906 read-only filesystem, like CD-ROM or a write-protected floppy.
907 The only way to be really sure is to actually create a file and
908 see if it succeeds. But I think that's too much to ask. */
909 if (tmp && _access (tmp, D_OK) == 0)
911 char * var = alloca (strlen (tmp) + 8);
912 sprintf (var, "TMPDIR=%s", tmp);
913 _putenv (strdup (var));
914 break;
917 if (i >= imax)
918 cmd_error_internal
919 (Fcons (Qerror,
920 Fcons (build_string ("no usable temporary directories found!!"),
921 Qnil)),
922 "While setting TMPDIR: ");
924 /* Check for environment variables and use registry settings if they
925 don't exist. Fallback on default values where applicable. */
927 int i;
928 LPBYTE lpval;
929 DWORD dwType;
930 char locale_name[32];
932 static struct env_entry
934 char * name;
935 char * def_value;
936 } env_vars[] =
938 {"HOME", "C:/"},
939 {"PRELOAD_WINSOCK", NULL},
940 {"emacs_dir", "C:/emacs"},
941 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
942 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
943 {"EMACSDATA", "%emacs_dir%/etc"},
944 {"EMACSPATH", "%emacs_dir%/bin"},
945 /* We no longer set INFOPATH because Info-default-directory-list
946 is then ignored. */
947 /* {"INFOPATH", "%emacs_dir%/info"}, */
948 {"EMACSDOC", "%emacs_dir%/etc"},
949 {"TERM", "cmd"},
950 {"LANG", NULL},
953 /* Get default locale info and use it for LANG. */
954 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
955 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
956 locale_name, sizeof (locale_name)))
958 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
960 if (strcmp (env_vars[i].name, "LANG") == 0)
962 env_vars[i].def_value = locale_name;
963 break;
968 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
970 /* Treat emacs_dir specially: set it unconditionally based on our
971 location, if it appears that we are running from the bin subdir
972 of a standard installation. */
974 char *p;
975 char modname[MAX_PATH];
977 if (!GetModuleFileName (NULL, modname, MAX_PATH))
978 abort ();
979 if ((p = strrchr (modname, '\\')) == NULL)
980 abort ();
981 *p = 0;
983 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
985 char buf[SET_ENV_BUF_SIZE];
987 *p = 0;
988 for (p = modname; *p; p++)
989 if (*p == '\\') *p = '/';
991 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
992 _putenv (strdup (buf));
996 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
998 if (!getenv (env_vars[i].name))
1000 int dont_free = 0;
1002 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL)
1004 lpval = env_vars[i].def_value;
1005 dwType = REG_EXPAND_SZ;
1006 dont_free = 1;
1009 if (lpval)
1011 if (dwType == REG_EXPAND_SZ)
1013 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1015 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
1016 _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, buf1);
1017 _putenv (strdup (buf2));
1019 else if (dwType == REG_SZ)
1021 char buf[SET_ENV_BUF_SIZE];
1023 _snprintf (buf, sizeof(buf)-1, "%s=%s", env_vars[i].name, lpval);
1024 _putenv (strdup (buf));
1027 if (!dont_free)
1028 xfree (lpval);
1034 /* Rebuild system configuration to reflect invoking system. */
1035 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1037 /* Another special case: on NT, the PATH variable is actually named
1038 "Path" although cmd.exe (perhaps NT itself) arranges for
1039 environment variable lookup and setting to be case insensitive.
1040 However, Emacs assumes a fully case sensitive environment, so we
1041 need to change "Path" to "PATH" to match the expectations of
1042 various elisp packages. We do this by the sneaky method of
1043 modifying the string in the C runtime environ entry.
1045 The same applies to COMSPEC. */
1047 char ** envp;
1049 for (envp = environ; *envp; envp++)
1050 if (_strnicmp (*envp, "PATH=", 5) == 0)
1051 memcpy (*envp, "PATH=", 5);
1052 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
1053 memcpy (*envp, "COMSPEC=", 8);
1056 /* Remember the initial working directory for getwd, then make the
1057 real wd be the location of emacs.exe to avoid conflicts when
1058 renaming or deleting directories. (We also don't call chdir when
1059 running subprocesses for the same reason.) */
1060 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
1061 abort ();
1064 char *p;
1065 static char modname[MAX_PATH];
1067 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1068 abort ();
1069 if ((p = strrchr (modname, '\\')) == NULL)
1070 abort ();
1071 *p = 0;
1073 SetCurrentDirectory (modname);
1075 /* Ensure argv[0] has the full path to Emacs. */
1076 *p = '\\';
1077 argv[0] = modname;
1080 /* Determine if there is a middle mouse button, to allow parse_button
1081 to decide whether right mouse events should be mouse-2 or
1082 mouse-3. */
1083 XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
1085 init_user_info ();
1088 char *
1089 emacs_root_dir (void)
1091 static char root_dir[FILENAME_MAX];
1092 const char *p;
1094 p = getenv ("emacs_dir");
1095 if (p == NULL)
1096 abort ();
1097 strcpy (root_dir, p);
1098 root_dir[parse_root (root_dir, NULL)] = '\0';
1099 dostounix_filename (root_dir);
1100 return root_dir;
1103 /* We don't have scripts to automatically determine the system configuration
1104 for Emacs before it's compiled, and we don't want to have to make the
1105 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1106 routine. */
1108 char *
1109 get_emacs_configuration (void)
1111 char *arch, *oem, *os;
1112 int build_num;
1113 static char configuration_buffer[32];
1115 /* Determine the processor type. */
1116 switch (get_processor_type ())
1119 #ifdef PROCESSOR_INTEL_386
1120 case PROCESSOR_INTEL_386:
1121 case PROCESSOR_INTEL_486:
1122 case PROCESSOR_INTEL_PENTIUM:
1123 arch = "i386";
1124 break;
1125 #endif
1127 #ifdef PROCESSOR_INTEL_860
1128 case PROCESSOR_INTEL_860:
1129 arch = "i860";
1130 break;
1131 #endif
1133 #ifdef PROCESSOR_MIPS_R2000
1134 case PROCESSOR_MIPS_R2000:
1135 case PROCESSOR_MIPS_R3000:
1136 case PROCESSOR_MIPS_R4000:
1137 arch = "mips";
1138 break;
1139 #endif
1141 #ifdef PROCESSOR_ALPHA_21064
1142 case PROCESSOR_ALPHA_21064:
1143 arch = "alpha";
1144 break;
1145 #endif
1147 default:
1148 arch = "unknown";
1149 break;
1152 /* Use the OEM field to reflect the compiler/library combination. */
1153 #ifdef _MSC_VER
1154 #define COMPILER_NAME "msvc"
1155 #else
1156 #ifdef __GNUC__
1157 #define COMPILER_NAME "mingw"
1158 #else
1159 #define COMPILER_NAME "unknown"
1160 #endif
1161 #endif
1162 oem = COMPILER_NAME;
1164 switch (osinfo_cache.dwPlatformId) {
1165 case VER_PLATFORM_WIN32_NT:
1166 os = "nt";
1167 build_num = osinfo_cache.dwBuildNumber;
1168 break;
1169 case VER_PLATFORM_WIN32_WINDOWS:
1170 if (osinfo_cache.dwMinorVersion == 0) {
1171 os = "windows95";
1172 } else {
1173 os = "windows98";
1175 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1176 break;
1177 case VER_PLATFORM_WIN32s:
1178 /* Not supported, should not happen. */
1179 os = "windows32s";
1180 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1181 break;
1182 default:
1183 os = "unknown";
1184 build_num = 0;
1185 break;
1188 if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1189 sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
1190 get_w32_major_version (), get_w32_minor_version (), build_num);
1191 } else {
1192 sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1195 return configuration_buffer;
1198 char *
1199 get_emacs_configuration_options (void)
1201 static char options_buffer[256];
1203 /* Work out the effective configure options for this build. */
1204 #ifdef _MSC_VER
1205 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1206 #else
1207 #ifdef __GNUC__
1208 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1209 #else
1210 #define COMPILER_VERSION ""
1211 #endif
1212 #endif
1214 sprintf (options_buffer, COMPILER_VERSION);
1215 #ifdef EMACSDEBUG
1216 strcat (options_buffer, " --no-opt");
1217 #endif
1218 #ifdef USER_CFLAGS
1219 strcat (options_buffer, " --cflags");
1220 strcat (options_buffer, USER_CFLAGS);
1221 #endif
1222 #ifdef USER_LDFLAGS
1223 strcat (options_buffer, " --ldflags");
1224 strcat (options_buffer, USER_LDFLAGS);
1225 #endif
1226 return options_buffer;
1230 #include <sys/timeb.h>
1232 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1233 void
1234 gettimeofday (struct timeval *tv, struct timezone *tz)
1236 struct timeb tb;
1237 _ftime (&tb);
1239 tv->tv_sec = tb.time;
1240 tv->tv_usec = tb.millitm * 1000L;
1241 if (tz)
1243 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
1244 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
1248 /* ------------------------------------------------------------------------- */
1249 /* IO support and wrapper functions for W32 API. */
1250 /* ------------------------------------------------------------------------- */
1252 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1253 on network directories, so we handle that case here.
1254 (Ulrich Leodolter, 1/11/95). */
1255 char *
1256 sys_ctime (const time_t *t)
1258 char *str = (char *) ctime (t);
1259 return (str ? str : "Sun Jan 01 00:00:00 1970");
1262 /* Emulate sleep...we could have done this with a define, but that
1263 would necessitate including windows.h in the files that used it.
1264 This is much easier. */
1265 void
1266 sys_sleep (int seconds)
1268 Sleep (seconds * 1000);
1271 /* Internal MSVC functions for low-level descriptor munging */
1272 extern int __cdecl _set_osfhnd (int fd, long h);
1273 extern int __cdecl _free_osfhnd (int fd);
1275 /* parallel array of private info on file handles */
1276 filedesc fd_info [ MAXDESC ];
1278 typedef struct volume_info_data {
1279 struct volume_info_data * next;
1281 /* time when info was obtained */
1282 DWORD timestamp;
1284 /* actual volume info */
1285 char * root_dir;
1286 DWORD serialnum;
1287 DWORD maxcomp;
1288 DWORD flags;
1289 char * name;
1290 char * type;
1291 } volume_info_data;
1293 /* Global referenced by various functions. */
1294 static volume_info_data volume_info;
1296 /* Vector to indicate which drives are local and fixed (for which cached
1297 data never expires). */
1298 static BOOL fixed_drives[26];
1300 /* Consider cached volume information to be stale if older than 10s,
1301 at least for non-local drives. Info for fixed drives is never stale. */
1302 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1303 #define VOLINFO_STILL_VALID( root_dir, info ) \
1304 ( ( isalpha (root_dir[0]) && \
1305 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1306 || GetTickCount () - info->timestamp < 10000 )
1308 /* Cache support functions. */
1310 /* Simple linked list with linear search is sufficient. */
1311 static volume_info_data *volume_cache = NULL;
1313 static volume_info_data *
1314 lookup_volume_info (char * root_dir)
1316 volume_info_data * info;
1318 for (info = volume_cache; info; info = info->next)
1319 if (stricmp (info->root_dir, root_dir) == 0)
1320 break;
1321 return info;
1324 static void
1325 add_volume_info (char * root_dir, volume_info_data * info)
1327 info->root_dir = xstrdup (root_dir);
1328 info->next = volume_cache;
1329 volume_cache = info;
1333 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1334 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1335 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1336 volume_info_data *
1337 GetCachedVolumeInformation (char * root_dir)
1339 volume_info_data * info;
1340 char default_root[ MAX_PATH ];
1342 /* NULL for root_dir means use root from current directory. */
1343 if (root_dir == NULL)
1345 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1346 return NULL;
1347 parse_root (default_root, &root_dir);
1348 *root_dir = 0;
1349 root_dir = default_root;
1352 /* Local fixed drives can be cached permanently. Removable drives
1353 cannot be cached permanently, since the volume name and serial
1354 number (if nothing else) can change. Remote drives should be
1355 treated as if they are removable, since there is no sure way to
1356 tell whether they are or not. Also, the UNC association of drive
1357 letters mapped to remote volumes can be changed at any time (even
1358 by other processes) without notice.
1360 As a compromise, so we can benefit from caching info for remote
1361 volumes, we use a simple expiry mechanism to invalidate cache
1362 entries that are more than ten seconds old. */
1364 #if 0
1365 /* No point doing this, because WNetGetConnection is even slower than
1366 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1367 GetDriveType is about the only call of this type which does not
1368 involve network access, and so is extremely quick). */
1370 /* Map drive letter to UNC if remote. */
1371 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1373 char remote_name[ 256 ];
1374 char drive[3] = { root_dir[0], ':' };
1376 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1377 == NO_ERROR)
1378 /* do something */ ;
1380 #endif
1382 info = lookup_volume_info (root_dir);
1384 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1386 char name[ 256 ];
1387 DWORD serialnum;
1388 DWORD maxcomp;
1389 DWORD flags;
1390 char type[ 256 ];
1392 /* Info is not cached, or is stale. */
1393 if (!GetVolumeInformation (root_dir,
1394 name, sizeof (name),
1395 &serialnum,
1396 &maxcomp,
1397 &flags,
1398 type, sizeof (type)))
1399 return NULL;
1401 /* Cache the volume information for future use, overwriting existing
1402 entry if present. */
1403 if (info == NULL)
1405 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1406 add_volume_info (root_dir, info);
1408 else
1410 xfree (info->name);
1411 xfree (info->type);
1414 info->name = xstrdup (name);
1415 info->serialnum = serialnum;
1416 info->maxcomp = maxcomp;
1417 info->flags = flags;
1418 info->type = xstrdup (type);
1419 info->timestamp = GetTickCount ();
1422 return info;
1425 /* Get information on the volume where name is held; set path pointer to
1426 start of pathname in name (past UNC header\volume header if present). */
1428 get_volume_info (const char * name, const char ** pPath)
1430 char temp[MAX_PATH];
1431 char *rootname = NULL; /* default to current volume */
1432 volume_info_data * info;
1434 if (name == NULL)
1435 return FALSE;
1437 /* find the root name of the volume if given */
1438 if (isalpha (name[0]) && name[1] == ':')
1440 rootname = temp;
1441 temp[0] = *name++;
1442 temp[1] = *name++;
1443 temp[2] = '\\';
1444 temp[3] = 0;
1446 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1448 char *str = temp;
1449 int slashes = 4;
1450 rootname = temp;
1453 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1454 break;
1455 *str++ = *name++;
1457 while ( *name );
1459 *str++ = '\\';
1460 *str = 0;
1463 if (pPath)
1464 *pPath = name;
1466 info = GetCachedVolumeInformation (rootname);
1467 if (info != NULL)
1469 /* Set global referenced by other functions. */
1470 volume_info = *info;
1471 return TRUE;
1473 return FALSE;
1476 /* Determine if volume is FAT format (ie. only supports short 8.3
1477 names); also set path pointer to start of pathname in name. */
1479 is_fat_volume (const char * name, const char ** pPath)
1481 if (get_volume_info (name, pPath))
1482 return (volume_info.maxcomp == 12);
1483 return FALSE;
1486 /* Map filename to a legal 8.3 name if necessary. */
1487 const char *
1488 map_w32_filename (const char * name, const char ** pPath)
1490 static char shortname[MAX_PATH];
1491 char * str = shortname;
1492 char c;
1493 char * path;
1494 const char * save_name = name;
1496 if (strlen (name) >= MAX_PATH)
1498 /* Return a filename which will cause callers to fail. */
1499 strcpy (shortname, "?");
1500 return shortname;
1503 if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1505 register int left = 8; /* maximum number of chars in part */
1506 register int extn = 0; /* extension added? */
1507 register int dots = 2; /* maximum number of dots allowed */
1509 while (name < path)
1510 *str++ = *name++; /* skip past UNC header */
1512 while ((c = *name++))
1514 switch ( c )
1516 case '\\':
1517 case '/':
1518 *str++ = '\\';
1519 extn = 0; /* reset extension flags */
1520 dots = 2; /* max 2 dots */
1521 left = 8; /* max length 8 for main part */
1522 break;
1523 case ':':
1524 *str++ = ':';
1525 extn = 0; /* reset extension flags */
1526 dots = 2; /* max 2 dots */
1527 left = 8; /* max length 8 for main part */
1528 break;
1529 case '.':
1530 if ( dots )
1532 /* Convert path components of the form .xxx to _xxx,
1533 but leave . and .. as they are. This allows .emacs
1534 to be read as _emacs, for example. */
1536 if (! *name ||
1537 *name == '.' ||
1538 IS_DIRECTORY_SEP (*name))
1540 *str++ = '.';
1541 dots--;
1543 else
1545 *str++ = '_';
1546 left--;
1547 dots = 0;
1550 else if ( !extn )
1552 *str++ = '.';
1553 extn = 1; /* we've got an extension */
1554 left = 3; /* 3 chars in extension */
1556 else
1558 /* any embedded dots after the first are converted to _ */
1559 *str++ = '_';
1561 break;
1562 case '~':
1563 case '#': /* don't lose these, they're important */
1564 if ( ! left )
1565 str[-1] = c; /* replace last character of part */
1566 /* FALLTHRU */
1567 default:
1568 if ( left )
1570 *str++ = tolower (c); /* map to lower case (looks nicer) */
1571 left--;
1572 dots = 0; /* started a path component */
1574 break;
1577 *str = '\0';
1579 else
1581 strcpy (shortname, name);
1582 unixtodos_filename (shortname);
1585 if (pPath)
1586 *pPath = shortname + (path - save_name);
1588 return shortname;
1591 static int
1592 is_exec (const char * name)
1594 char * p = strrchr (name, '.');
1595 return
1596 (p != NULL
1597 && (stricmp (p, ".exe") == 0 ||
1598 stricmp (p, ".com") == 0 ||
1599 stricmp (p, ".bat") == 0 ||
1600 stricmp (p, ".cmd") == 0));
1603 /* Emulate the Unix directory procedures opendir, closedir,
1604 and readdir. We can't use the procedures supplied in sysdep.c,
1605 so we provide them here. */
1607 struct direct dir_static; /* simulated directory contents */
1608 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1609 static int dir_is_fat;
1610 static char dir_pathname[MAXPATHLEN+1];
1611 static WIN32_FIND_DATA dir_find_data;
1613 /* Support shares on a network resource as subdirectories of a read-only
1614 root directory. */
1615 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1616 HANDLE open_unc_volume (char *);
1617 char *read_unc_volume (HANDLE, char *, int);
1618 void close_unc_volume (HANDLE);
1620 DIR *
1621 opendir (char *filename)
1623 DIR *dirp;
1625 /* Opening is done by FindFirstFile. However, a read is inherent to
1626 this operation, so we defer the open until read time. */
1628 if (dir_find_handle != INVALID_HANDLE_VALUE)
1629 return NULL;
1630 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1631 return NULL;
1633 if (is_unc_volume (filename))
1635 wnet_enum_handle = open_unc_volume (filename);
1636 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1637 return NULL;
1640 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1641 return NULL;
1643 dirp->dd_fd = 0;
1644 dirp->dd_loc = 0;
1645 dirp->dd_size = 0;
1647 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1648 dir_pathname[MAXPATHLEN] = '\0';
1649 dir_is_fat = is_fat_volume (filename, NULL);
1651 return dirp;
1654 void
1655 closedir (DIR *dirp)
1657 /* If we have a find-handle open, close it. */
1658 if (dir_find_handle != INVALID_HANDLE_VALUE)
1660 FindClose (dir_find_handle);
1661 dir_find_handle = INVALID_HANDLE_VALUE;
1663 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1665 close_unc_volume (wnet_enum_handle);
1666 wnet_enum_handle = INVALID_HANDLE_VALUE;
1668 xfree ((char *) dirp);
1671 struct direct *
1672 readdir (DIR *dirp)
1674 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1676 if (!read_unc_volume (wnet_enum_handle,
1677 dir_find_data.cFileName,
1678 MAX_PATH))
1679 return NULL;
1681 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1682 else if (dir_find_handle == INVALID_HANDLE_VALUE)
1684 char filename[MAXNAMLEN + 3];
1685 int ln;
1687 strcpy (filename, dir_pathname);
1688 ln = strlen (filename) - 1;
1689 if (!IS_DIRECTORY_SEP (filename[ln]))
1690 strcat (filename, "\\");
1691 strcat (filename, "*");
1693 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1695 if (dir_find_handle == INVALID_HANDLE_VALUE)
1696 return NULL;
1698 else
1700 if (!FindNextFile (dir_find_handle, &dir_find_data))
1701 return NULL;
1704 /* Emacs never uses this value, so don't bother making it match
1705 value returned by stat(). */
1706 dir_static.d_ino = 1;
1708 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1709 dir_static.d_namlen - dir_static.d_namlen % 4;
1711 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1712 strcpy (dir_static.d_name, dir_find_data.cFileName);
1713 if (dir_is_fat)
1714 _strlwr (dir_static.d_name);
1715 else if (!NILP (Vw32_downcase_file_names))
1717 register char *p;
1718 for (p = dir_static.d_name; *p; p++)
1719 if (*p >= 'a' && *p <= 'z')
1720 break;
1721 if (!*p)
1722 _strlwr (dir_static.d_name);
1725 return &dir_static;
1728 HANDLE
1729 open_unc_volume (char *path)
1731 NETRESOURCE nr;
1732 HANDLE henum;
1733 int result;
1735 nr.dwScope = RESOURCE_GLOBALNET;
1736 nr.dwType = RESOURCETYPE_DISK;
1737 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1738 nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1739 nr.lpLocalName = NULL;
1740 nr.lpRemoteName = map_w32_filename (path, NULL);
1741 nr.lpComment = NULL;
1742 nr.lpProvider = NULL;
1744 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1745 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1747 if (result == NO_ERROR)
1748 return henum;
1749 else
1750 return INVALID_HANDLE_VALUE;
1753 char *
1754 read_unc_volume (HANDLE henum, char *readbuf, int size)
1756 DWORD count;
1757 int result;
1758 DWORD bufsize = 512;
1759 char *buffer;
1760 char *ptr;
1762 count = 1;
1763 buffer = alloca (bufsize);
1764 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1765 if (result != NO_ERROR)
1766 return NULL;
1768 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1769 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1770 ptr += 2;
1771 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1772 ptr++;
1774 strncpy (readbuf, ptr, size);
1775 return readbuf;
1778 void
1779 close_unc_volume (HANDLE henum)
1781 if (henum != INVALID_HANDLE_VALUE)
1782 WNetCloseEnum (henum);
1785 DWORD
1786 unc_volume_file_attributes (char *path)
1788 HANDLE henum;
1789 DWORD attrs;
1791 henum = open_unc_volume (path);
1792 if (henum == INVALID_HANDLE_VALUE)
1793 return -1;
1795 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1797 close_unc_volume (henum);
1799 return attrs;
1803 /* Shadow some MSVC runtime functions to map requests for long filenames
1804 to reasonable short names if necessary. This was originally added to
1805 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1806 long file names. */
1809 sys_access (const char * path, int mode)
1811 DWORD attributes;
1813 /* MSVC implementation doesn't recognize D_OK. */
1814 path = map_w32_filename (path, NULL);
1815 if (is_unc_volume (path))
1817 attributes = unc_volume_file_attributes (path);
1818 if (attributes == -1) {
1819 errno = EACCES;
1820 return -1;
1823 else if ((attributes = GetFileAttributes (path)) == -1)
1825 /* Should try mapping GetLastError to errno; for now just indicate
1826 that path doesn't exist. */
1827 errno = EACCES;
1828 return -1;
1830 if ((mode & X_OK) != 0 && !is_exec (path))
1832 errno = EACCES;
1833 return -1;
1835 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1837 errno = EACCES;
1838 return -1;
1840 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1842 errno = EACCES;
1843 return -1;
1845 return 0;
1849 sys_chdir (const char * path)
1851 return _chdir (map_w32_filename (path, NULL));
1855 sys_chmod (const char * path, int mode)
1857 return _chmod (map_w32_filename (path, NULL), mode);
1861 sys_creat (const char * path, int mode)
1863 return _creat (map_w32_filename (path, NULL), mode);
1866 FILE *
1867 sys_fopen(const char * path, const char * mode)
1869 int fd;
1870 int oflag;
1871 const char * mode_save = mode;
1873 /* Force all file handles to be non-inheritable. This is necessary to
1874 ensure child processes don't unwittingly inherit handles that might
1875 prevent future file access. */
1877 if (mode[0] == 'r')
1878 oflag = O_RDONLY;
1879 else if (mode[0] == 'w' || mode[0] == 'a')
1880 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1881 else
1882 return NULL;
1884 /* Only do simplistic option parsing. */
1885 while (*++mode)
1886 if (mode[0] == '+')
1888 oflag &= ~(O_RDONLY | O_WRONLY);
1889 oflag |= O_RDWR;
1891 else if (mode[0] == 'b')
1893 oflag &= ~O_TEXT;
1894 oflag |= O_BINARY;
1896 else if (mode[0] == 't')
1898 oflag &= ~O_BINARY;
1899 oflag |= O_TEXT;
1901 else break;
1903 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
1904 if (fd < 0)
1905 return NULL;
1907 return _fdopen (fd, mode_save);
1910 /* This only works on NTFS volumes, but is useful to have. */
1912 sys_link (const char * old, const char * new)
1914 HANDLE fileh;
1915 int result = -1;
1916 char oldname[MAX_PATH], newname[MAX_PATH];
1918 if (old == NULL || new == NULL)
1920 errno = ENOENT;
1921 return -1;
1924 strcpy (oldname, map_w32_filename (old, NULL));
1925 strcpy (newname, map_w32_filename (new, NULL));
1927 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1928 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1929 if (fileh != INVALID_HANDLE_VALUE)
1931 int wlen;
1933 /* Confusingly, the "alternate" stream name field does not apply
1934 when restoring a hard link, and instead contains the actual
1935 stream data for the link (ie. the name of the link to create).
1936 The WIN32_STREAM_ID structure before the cStreamName field is
1937 the stream header, which is then immediately followed by the
1938 stream data. */
1940 struct {
1941 WIN32_STREAM_ID wid;
1942 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1943 } data;
1945 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1946 data.wid.cStreamName, MAX_PATH);
1947 if (wlen > 0)
1949 LPVOID context = NULL;
1950 DWORD wbytes = 0;
1952 data.wid.dwStreamId = BACKUP_LINK;
1953 data.wid.dwStreamAttributes = 0;
1954 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
1955 data.wid.Size.HighPart = 0;
1956 data.wid.dwStreamNameSize = 0;
1958 if (BackupWrite (fileh, (LPBYTE)&data,
1959 offsetof (WIN32_STREAM_ID, cStreamName)
1960 + data.wid.Size.LowPart,
1961 &wbytes, FALSE, FALSE, &context)
1962 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
1964 /* succeeded */
1965 result = 0;
1967 else
1969 /* Should try mapping GetLastError to errno; for now just
1970 indicate a general error (eg. links not supported). */
1971 errno = EINVAL; // perhaps EMLINK?
1975 CloseHandle (fileh);
1977 else
1978 errno = ENOENT;
1980 return result;
1984 sys_mkdir (const char * path)
1986 return _mkdir (map_w32_filename (path, NULL));
1989 /* Because of long name mapping issues, we need to implement this
1990 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1991 a unique name, instead of setting the input template to an empty
1992 string.
1994 Standard algorithm seems to be use pid or tid with a letter on the
1995 front (in place of the 6 X's) and cycle through the letters to find a
1996 unique name. We extend that to allow any reasonable character as the
1997 first of the 6 X's. */
1998 char *
1999 sys_mktemp (char * template)
2001 char * p;
2002 int i;
2003 unsigned uid = GetCurrentThreadId ();
2004 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2006 if (template == NULL)
2007 return NULL;
2008 p = template + strlen (template);
2009 i = 5;
2010 /* replace up to the last 5 X's with uid in decimal */
2011 while (--p >= template && p[0] == 'X' && --i >= 0)
2013 p[0] = '0' + uid % 10;
2014 uid /= 10;
2017 if (i < 0 && p[0] == 'X')
2019 i = 0;
2022 int save_errno = errno;
2023 p[0] = first_char[i];
2024 if (sys_access (template, 0) < 0)
2026 errno = save_errno;
2027 return template;
2030 while (++i < sizeof (first_char));
2033 /* Template is badly formed or else we can't generate a unique name,
2034 so return empty string */
2035 template[0] = 0;
2036 return template;
2040 sys_open (const char * path, int oflag, int mode)
2042 const char* mpath = map_w32_filename (path, NULL);
2043 /* Try to open file without _O_CREAT, to be able to write to hidden
2044 and system files. Force all file handles to be
2045 non-inheritable. */
2046 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2047 if (res >= 0)
2048 return res;
2049 return _open (mpath, oflag | _O_NOINHERIT, mode);
2053 sys_rename (const char * oldname, const char * newname)
2055 BOOL result;
2056 char temp[MAX_PATH];
2058 /* MoveFile on Windows 95 doesn't correctly change the short file name
2059 alias in a number of circumstances (it is not easy to predict when
2060 just by looking at oldname and newname, unfortunately). In these
2061 cases, renaming through a temporary name avoids the problem.
2063 A second problem on Windows 95 is that renaming through a temp name when
2064 newname is uppercase fails (the final long name ends up in
2065 lowercase, although the short alias might be uppercase) UNLESS the
2066 long temp name is not 8.3.
2068 So, on Windows 95 we always rename through a temp name, and we make sure
2069 the temp name has a long extension to ensure correct renaming. */
2071 strcpy (temp, map_w32_filename (oldname, NULL));
2073 if (os_subtype == OS_WIN95)
2075 char * o;
2076 char * p;
2077 int i = 0;
2079 oldname = map_w32_filename (oldname, NULL);
2080 if (o = strrchr (oldname, '\\'))
2081 o++;
2082 else
2083 o = (char *) oldname;
2085 if (p = strrchr (temp, '\\'))
2086 p++;
2087 else
2088 p = temp;
2092 /* Force temp name to require a manufactured 8.3 alias - this
2093 seems to make the second rename work properly. */
2094 sprintf (p, "_.%s.%u", o, i);
2095 i++;
2096 result = rename (oldname, temp);
2098 /* This loop must surely terminate! */
2099 while (result < 0 && errno == EEXIST);
2100 if (result < 0)
2101 return -1;
2104 /* Emulate Unix behaviour - newname is deleted if it already exists
2105 (at least if it is a file; don't do this for directories).
2107 Since we mustn't do this if we are just changing the case of the
2108 file name (we would end up deleting the file we are trying to
2109 rename!), we let rename detect if the destination file already
2110 exists - that way we avoid the possible pitfalls of trying to
2111 determine ourselves whether two names really refer to the same
2112 file, which is not always possible in the general case. (Consider
2113 all the permutations of shared or subst'd drives, etc.) */
2115 newname = map_w32_filename (newname, NULL);
2116 result = rename (temp, newname);
2118 if (result < 0
2119 && errno == EEXIST
2120 && _chmod (newname, 0666) == 0
2121 && _unlink (newname) == 0)
2122 result = rename (temp, newname);
2124 return result;
2128 sys_rmdir (const char * path)
2130 return _rmdir (map_w32_filename (path, NULL));
2134 sys_unlink (const char * path)
2136 path = map_w32_filename (path, NULL);
2138 /* On Unix, unlink works without write permission. */
2139 _chmod (path, 0666);
2140 return _unlink (path);
2143 static FILETIME utc_base_ft;
2144 static long double utc_base;
2145 static int init = 0;
2147 static time_t
2148 convert_time (FILETIME ft)
2150 long double ret;
2152 if (!init)
2154 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2155 SYSTEMTIME st;
2157 st.wYear = 1970;
2158 st.wMonth = 1;
2159 st.wDay = 1;
2160 st.wHour = 0;
2161 st.wMinute = 0;
2162 st.wSecond = 0;
2163 st.wMilliseconds = 0;
2165 SystemTimeToFileTime (&st, &utc_base_ft);
2166 utc_base = (long double) utc_base_ft.dwHighDateTime
2167 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2168 init = 1;
2171 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2172 return 0;
2174 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
2175 ret -= utc_base;
2176 return (time_t) (ret * 1e-7);
2179 void
2180 convert_from_time_t (time_t time, FILETIME * pft)
2182 long double tmp;
2184 if (!init)
2186 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2187 SYSTEMTIME st;
2189 st.wYear = 1970;
2190 st.wMonth = 1;
2191 st.wDay = 1;
2192 st.wHour = 0;
2193 st.wMinute = 0;
2194 st.wSecond = 0;
2195 st.wMilliseconds = 0;
2197 SystemTimeToFileTime (&st, &utc_base_ft);
2198 utc_base = (long double) utc_base_ft.dwHighDateTime
2199 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2200 init = 1;
2203 /* time in 100ns units since 1-Jan-1601 */
2204 tmp = (long double) time * 1e7 + utc_base;
2205 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2206 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2209 #if 0
2210 /* No reason to keep this; faking inode values either by hashing or even
2211 using the file index from GetInformationByHandle, is not perfect and
2212 so by default Emacs doesn't use the inode values on Windows.
2213 Instead, we now determine file-truename correctly (except for
2214 possible drive aliasing etc). */
2216 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2217 static unsigned
2218 hashval (const unsigned char * str)
2220 unsigned h = 0;
2221 while (*str)
2223 h = (h << 4) + *str++;
2224 h ^= (h >> 28);
2226 return h;
2229 /* Return the hash value of the canonical pathname, excluding the
2230 drive/UNC header, to get a hopefully unique inode number. */
2231 static DWORD
2232 generate_inode_val (const char * name)
2234 char fullname[ MAX_PATH ];
2235 char * p;
2236 unsigned hash;
2238 /* Get the truly canonical filename, if it exists. (Note: this
2239 doesn't resolve aliasing due to subst commands, or recognise hard
2240 links. */
2241 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2242 abort ();
2244 parse_root (fullname, &p);
2245 /* Normal W32 filesystems are still case insensitive. */
2246 _strlwr (p);
2247 return hashval (p);
2250 #endif
2252 /* MSVC stat function can't cope with UNC names and has other bugs, so
2253 replace it with our own. This also allows us to calculate consistent
2254 inode values without hacks in the main Emacs code. */
2256 stat (const char * path, struct stat * buf)
2258 char *name, *r;
2259 WIN32_FIND_DATA wfd;
2260 HANDLE fh;
2261 DWORD fake_inode;
2262 int permission;
2263 int len;
2264 int rootdir = FALSE;
2266 if (path == NULL || buf == NULL)
2268 errno = EFAULT;
2269 return -1;
2272 name = (char *) map_w32_filename (path, &path);
2273 /* must be valid filename, no wild cards or other invalid characters */
2274 if (strpbrk (name, "*?|<>\""))
2276 errno = ENOENT;
2277 return -1;
2280 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2281 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2282 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2284 r[1] = r[2] = '\0';
2287 /* Remove trailing directory separator, unless name is the root
2288 directory of a drive or UNC volume in which case ensure there
2289 is a trailing separator. */
2290 len = strlen (name);
2291 rootdir = (path >= name + len - 1
2292 && (IS_DIRECTORY_SEP (*path) || *path == 0));
2293 name = strcpy (alloca (len + 2), name);
2295 if (is_unc_volume (name))
2297 DWORD attrs = unc_volume_file_attributes (name);
2299 if (attrs == -1)
2300 return -1;
2302 memset (&wfd, 0, sizeof (wfd));
2303 wfd.dwFileAttributes = attrs;
2304 wfd.ftCreationTime = utc_base_ft;
2305 wfd.ftLastAccessTime = utc_base_ft;
2306 wfd.ftLastWriteTime = utc_base_ft;
2307 strcpy (wfd.cFileName, name);
2309 else if (rootdir)
2311 if (!IS_DIRECTORY_SEP (name[len-1]))
2312 strcat (name, "\\");
2313 if (GetDriveType (name) < 2)
2315 errno = ENOENT;
2316 return -1;
2318 memset (&wfd, 0, sizeof (wfd));
2319 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2320 wfd.ftCreationTime = utc_base_ft;
2321 wfd.ftLastAccessTime = utc_base_ft;
2322 wfd.ftLastWriteTime = utc_base_ft;
2323 strcpy (wfd.cFileName, name);
2325 else
2327 if (IS_DIRECTORY_SEP (name[len-1]))
2328 name[len - 1] = 0;
2330 /* (This is hacky, but helps when doing file completions on
2331 network drives.) Optimize by using information available from
2332 active readdir if possible. */
2333 len = strlen (dir_pathname);
2334 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2335 len--;
2336 if (dir_find_handle != INVALID_HANDLE_VALUE
2337 && strnicmp (name, dir_pathname, len) == 0
2338 && IS_DIRECTORY_SEP (name[len])
2339 && stricmp (name + len + 1, dir_static.d_name) == 0)
2341 /* This was the last entry returned by readdir. */
2342 wfd = dir_find_data;
2344 else
2346 fh = FindFirstFile (name, &wfd);
2347 if (fh == INVALID_HANDLE_VALUE)
2349 errno = ENOENT;
2350 return -1;
2352 FindClose (fh);
2356 if (!NILP (Vw32_get_true_file_attributes)
2357 /* No access rights required to get info. */
2358 && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2359 FILE_FLAG_BACKUP_SEMANTICS, NULL))
2360 != INVALID_HANDLE_VALUE)
2362 /* This is more accurate in terms of gettting the correct number
2363 of links, but is quite slow (it is noticable when Emacs is
2364 making a list of file name completions). */
2365 BY_HANDLE_FILE_INFORMATION info;
2367 if (GetFileInformationByHandle (fh, &info))
2369 buf->st_nlink = info.nNumberOfLinks;
2370 /* Might as well use file index to fake inode values, but this
2371 is not guaranteed to be unique unless we keep a handle open
2372 all the time (even then there are situations where it is
2373 not unique). Reputedly, there are at most 48 bits of info
2374 (on NTFS, presumably less on FAT). */
2375 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2377 else
2379 buf->st_nlink = 1;
2380 fake_inode = 0;
2383 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2385 buf->st_mode = _S_IFDIR;
2387 else
2389 switch (GetFileType (fh))
2391 case FILE_TYPE_DISK:
2392 buf->st_mode = _S_IFREG;
2393 break;
2394 case FILE_TYPE_PIPE:
2395 buf->st_mode = _S_IFIFO;
2396 break;
2397 case FILE_TYPE_CHAR:
2398 case FILE_TYPE_UNKNOWN:
2399 default:
2400 buf->st_mode = _S_IFCHR;
2403 CloseHandle (fh);
2405 else
2407 /* Don't bother to make this information more accurate. */
2408 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2409 _S_IFDIR : _S_IFREG;
2410 buf->st_nlink = 1;
2411 fake_inode = 0;
2414 #if 0
2415 /* Not sure if there is any point in this. */
2416 if (!NILP (Vw32_generate_fake_inodes))
2417 fake_inode = generate_inode_val (name);
2418 else if (fake_inode == 0)
2420 /* For want of something better, try to make everything unique. */
2421 static DWORD gen_num = 0;
2422 fake_inode = ++gen_num;
2424 #endif
2426 /* MSVC defines _ino_t to be short; other libc's might not. */
2427 if (sizeof (buf->st_ino) == 2)
2428 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2429 else
2430 buf->st_ino = fake_inode;
2432 /* consider files to belong to current user */
2433 buf->st_uid = the_passwd.pw_uid;
2434 buf->st_gid = the_passwd.pw_gid;
2436 /* volume_info is set indirectly by map_w32_filename */
2437 buf->st_dev = volume_info.serialnum;
2438 buf->st_rdev = volume_info.serialnum;
2441 buf->st_size = wfd.nFileSizeLow;
2443 /* Convert timestamps to Unix format. */
2444 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2445 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2446 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2447 buf->st_ctime = convert_time (wfd.ftCreationTime);
2448 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2450 /* determine rwx permissions */
2451 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2452 permission = _S_IREAD;
2453 else
2454 permission = _S_IREAD | _S_IWRITE;
2456 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2457 permission |= _S_IEXEC;
2458 else if (is_exec (name))
2459 permission |= _S_IEXEC;
2461 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2463 return 0;
2466 /* Provide fstat and utime as well as stat for consistent handling of
2467 file timestamps. */
2469 fstat (int desc, struct stat * buf)
2471 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2472 BY_HANDLE_FILE_INFORMATION info;
2473 DWORD fake_inode;
2474 int permission;
2476 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2478 case FILE_TYPE_DISK:
2479 buf->st_mode = _S_IFREG;
2480 if (!GetFileInformationByHandle (fh, &info))
2482 errno = EACCES;
2483 return -1;
2485 break;
2486 case FILE_TYPE_PIPE:
2487 buf->st_mode = _S_IFIFO;
2488 goto non_disk;
2489 case FILE_TYPE_CHAR:
2490 case FILE_TYPE_UNKNOWN:
2491 default:
2492 buf->st_mode = _S_IFCHR;
2493 non_disk:
2494 memset (&info, 0, sizeof (info));
2495 info.dwFileAttributes = 0;
2496 info.ftCreationTime = utc_base_ft;
2497 info.ftLastAccessTime = utc_base_ft;
2498 info.ftLastWriteTime = utc_base_ft;
2501 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2502 buf->st_mode = _S_IFDIR;
2504 buf->st_nlink = info.nNumberOfLinks;
2505 /* Might as well use file index to fake inode values, but this
2506 is not guaranteed to be unique unless we keep a handle open
2507 all the time (even then there are situations where it is
2508 not unique). Reputedly, there are at most 48 bits of info
2509 (on NTFS, presumably less on FAT). */
2510 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2512 /* MSVC defines _ino_t to be short; other libc's might not. */
2513 if (sizeof (buf->st_ino) == 2)
2514 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2515 else
2516 buf->st_ino = fake_inode;
2518 /* consider files to belong to current user */
2519 buf->st_uid = 0;
2520 buf->st_gid = 0;
2522 buf->st_dev = info.dwVolumeSerialNumber;
2523 buf->st_rdev = info.dwVolumeSerialNumber;
2525 buf->st_size = info.nFileSizeLow;
2527 /* Convert timestamps to Unix format. */
2528 buf->st_mtime = convert_time (info.ftLastWriteTime);
2529 buf->st_atime = convert_time (info.ftLastAccessTime);
2530 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2531 buf->st_ctime = convert_time (info.ftCreationTime);
2532 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2534 /* determine rwx permissions */
2535 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2536 permission = _S_IREAD;
2537 else
2538 permission = _S_IREAD | _S_IWRITE;
2540 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2541 permission |= _S_IEXEC;
2542 else
2544 #if 0 /* no way of knowing the filename */
2545 char * p = strrchr (name, '.');
2546 if (p != NULL &&
2547 (stricmp (p, ".exe") == 0 ||
2548 stricmp (p, ".com") == 0 ||
2549 stricmp (p, ".bat") == 0 ||
2550 stricmp (p, ".cmd") == 0))
2551 permission |= _S_IEXEC;
2552 #endif
2555 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2557 return 0;
2561 utime (const char *name, struct utimbuf *times)
2563 struct utimbuf deftime;
2564 HANDLE fh;
2565 FILETIME mtime;
2566 FILETIME atime;
2568 if (times == NULL)
2570 deftime.modtime = deftime.actime = time (NULL);
2571 times = &deftime;
2574 /* Need write access to set times. */
2575 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2576 0, OPEN_EXISTING, 0, NULL);
2577 if (fh)
2579 convert_from_time_t (times->actime, &atime);
2580 convert_from_time_t (times->modtime, &mtime);
2581 if (!SetFileTime (fh, NULL, &atime, &mtime))
2583 CloseHandle (fh);
2584 errno = EACCES;
2585 return -1;
2587 CloseHandle (fh);
2589 else
2591 errno = EINVAL;
2592 return -1;
2594 return 0;
2597 #ifdef HAVE_SOCKETS
2599 /* Wrappers for winsock functions to map between our file descriptors
2600 and winsock's handles; also set h_errno for convenience.
2602 To allow Emacs to run on systems which don't have winsock support
2603 installed, we dynamically link to winsock on startup if present, and
2604 otherwise provide the minimum necessary functionality
2605 (eg. gethostname). */
2607 /* function pointers for relevant socket functions */
2608 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2609 void (PASCAL *pfn_WSASetLastError) (int iError);
2610 int (PASCAL *pfn_WSAGetLastError) (void);
2611 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2612 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2613 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2614 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2615 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2616 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2617 int (PASCAL *pfn_closesocket) (SOCKET s);
2618 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2619 int (PASCAL *pfn_WSACleanup) (void);
2621 u_short (PASCAL *pfn_htons) (u_short hostshort);
2622 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2623 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2624 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2625 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2626 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2627 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2628 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2629 const char * optval, int optlen);
2630 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2631 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2632 int * namelen);
2633 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2634 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2635 struct sockaddr * from, int * fromlen);
2636 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2637 const struct sockaddr * to, int tolen);
2639 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2640 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2641 #ifndef HANDLE_FLAG_INHERIT
2642 #define HANDLE_FLAG_INHERIT 1
2643 #endif
2645 HANDLE winsock_lib;
2646 static int winsock_inuse;
2648 BOOL
2649 term_winsock (void)
2651 if (winsock_lib != NULL && winsock_inuse == 0)
2653 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2654 after WSAStartup returns successfully, but it seems reasonable
2655 to allow unloading winsock anyway in that case. */
2656 if (pfn_WSACleanup () == 0 ||
2657 pfn_WSAGetLastError () == WSAENETDOWN)
2659 if (FreeLibrary (winsock_lib))
2660 winsock_lib = NULL;
2661 return TRUE;
2664 return FALSE;
2667 BOOL
2668 init_winsock (int load_now)
2670 WSADATA winsockData;
2672 if (winsock_lib != NULL)
2673 return TRUE;
2675 pfn_SetHandleInformation = NULL;
2676 pfn_SetHandleInformation
2677 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2678 "SetHandleInformation");
2680 winsock_lib = LoadLibrary ("wsock32.dll");
2682 if (winsock_lib != NULL)
2684 /* dynamically link to socket functions */
2686 #define LOAD_PROC(fn) \
2687 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2688 goto fail;
2690 LOAD_PROC( WSAStartup );
2691 LOAD_PROC( WSASetLastError );
2692 LOAD_PROC( WSAGetLastError );
2693 LOAD_PROC( socket );
2694 LOAD_PROC( bind );
2695 LOAD_PROC( connect );
2696 LOAD_PROC( ioctlsocket );
2697 LOAD_PROC( recv );
2698 LOAD_PROC( send );
2699 LOAD_PROC( closesocket );
2700 LOAD_PROC( shutdown );
2701 LOAD_PROC( htons );
2702 LOAD_PROC( ntohs );
2703 LOAD_PROC( inet_addr );
2704 LOAD_PROC( gethostname );
2705 LOAD_PROC( gethostbyname );
2706 LOAD_PROC( getservbyname );
2707 LOAD_PROC( getpeername );
2708 LOAD_PROC( WSACleanup );
2709 LOAD_PROC( setsockopt );
2710 LOAD_PROC( listen );
2711 LOAD_PROC( getsockname );
2712 LOAD_PROC( accept );
2713 LOAD_PROC( recvfrom );
2714 LOAD_PROC( sendto );
2715 #undef LOAD_PROC
2717 /* specify version 1.1 of winsock */
2718 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2720 if (winsockData.wVersion != 0x101)
2721 goto fail;
2723 if (!load_now)
2725 /* Report that winsock exists and is usable, but leave
2726 socket functions disabled. I am assuming that calling
2727 WSAStartup does not require any network interaction,
2728 and in particular does not cause or require a dial-up
2729 connection to be established. */
2731 pfn_WSACleanup ();
2732 FreeLibrary (winsock_lib);
2733 winsock_lib = NULL;
2735 winsock_inuse = 0;
2736 return TRUE;
2739 fail:
2740 FreeLibrary (winsock_lib);
2741 winsock_lib = NULL;
2744 return FALSE;
2748 int h_errno = 0;
2750 /* function to set h_errno for compatability; map winsock error codes to
2751 normal system codes where they overlap (non-overlapping definitions
2752 are already in <sys/socket.h> */
2753 static void set_errno ()
2755 if (winsock_lib == NULL)
2756 h_errno = EINVAL;
2757 else
2758 h_errno = pfn_WSAGetLastError ();
2760 switch (h_errno)
2762 case WSAEACCES: h_errno = EACCES; break;
2763 case WSAEBADF: h_errno = EBADF; break;
2764 case WSAEFAULT: h_errno = EFAULT; break;
2765 case WSAEINTR: h_errno = EINTR; break;
2766 case WSAEINVAL: h_errno = EINVAL; break;
2767 case WSAEMFILE: h_errno = EMFILE; break;
2768 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2769 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2771 errno = h_errno;
2774 static void check_errno ()
2776 if (h_errno == 0 && winsock_lib != NULL)
2777 pfn_WSASetLastError (0);
2780 /* Extend strerror to handle the winsock-specific error codes. */
2781 struct {
2782 int errnum;
2783 char * msg;
2784 } _wsa_errlist[] = {
2785 WSAEINTR , "Interrupted function call",
2786 WSAEBADF , "Bad file descriptor",
2787 WSAEACCES , "Permission denied",
2788 WSAEFAULT , "Bad address",
2789 WSAEINVAL , "Invalid argument",
2790 WSAEMFILE , "Too many open files",
2792 WSAEWOULDBLOCK , "Resource temporarily unavailable",
2793 WSAEINPROGRESS , "Operation now in progress",
2794 WSAEALREADY , "Operation already in progress",
2795 WSAENOTSOCK , "Socket operation on non-socket",
2796 WSAEDESTADDRREQ , "Destination address required",
2797 WSAEMSGSIZE , "Message too long",
2798 WSAEPROTOTYPE , "Protocol wrong type for socket",
2799 WSAENOPROTOOPT , "Bad protocol option",
2800 WSAEPROTONOSUPPORT , "Protocol not supported",
2801 WSAESOCKTNOSUPPORT , "Socket type not supported",
2802 WSAEOPNOTSUPP , "Operation not supported",
2803 WSAEPFNOSUPPORT , "Protocol family not supported",
2804 WSAEAFNOSUPPORT , "Address family not supported by protocol family",
2805 WSAEADDRINUSE , "Address already in use",
2806 WSAEADDRNOTAVAIL , "Cannot assign requested address",
2807 WSAENETDOWN , "Network is down",
2808 WSAENETUNREACH , "Network is unreachable",
2809 WSAENETRESET , "Network dropped connection on reset",
2810 WSAECONNABORTED , "Software caused connection abort",
2811 WSAECONNRESET , "Connection reset by peer",
2812 WSAENOBUFS , "No buffer space available",
2813 WSAEISCONN , "Socket is already connected",
2814 WSAENOTCONN , "Socket is not connected",
2815 WSAESHUTDOWN , "Cannot send after socket shutdown",
2816 WSAETOOMANYREFS , "Too many references", /* not sure */
2817 WSAETIMEDOUT , "Connection timed out",
2818 WSAECONNREFUSED , "Connection refused",
2819 WSAELOOP , "Network loop", /* not sure */
2820 WSAENAMETOOLONG , "Name is too long",
2821 WSAEHOSTDOWN , "Host is down",
2822 WSAEHOSTUNREACH , "No route to host",
2823 WSAENOTEMPTY , "Buffer not empty", /* not sure */
2824 WSAEPROCLIM , "Too many processes",
2825 WSAEUSERS , "Too many users", /* not sure */
2826 WSAEDQUOT , "Double quote in host name", /* really not sure */
2827 WSAESTALE , "Data is stale", /* not sure */
2828 WSAEREMOTE , "Remote error", /* not sure */
2830 WSASYSNOTREADY , "Network subsystem is unavailable",
2831 WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
2832 WSANOTINITIALISED , "Winsock not initialized successfully",
2833 WSAEDISCON , "Graceful shutdown in progress",
2834 #ifdef WSAENOMORE
2835 WSAENOMORE , "No more operations allowed", /* not sure */
2836 WSAECANCELLED , "Operation cancelled", /* not sure */
2837 WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
2838 WSAEINVALIDPROVIDER , "Invalid service provider version number",
2839 WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
2840 WSASYSCALLFAILURE , "System call failured",
2841 WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
2842 WSATYPE_NOT_FOUND , "Class type not found",
2843 WSA_E_NO_MORE , "No more resources available", /* really not sure */
2844 WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
2845 WSAEREFUSED , "Operation refused", /* not sure */
2846 #endif
2848 WSAHOST_NOT_FOUND , "Host not found",
2849 WSATRY_AGAIN , "Authoritative host not found during name lookup",
2850 WSANO_RECOVERY , "Non-recoverable error during name lookup",
2851 WSANO_DATA , "Valid name, no data record of requested type",
2853 -1, NULL
2856 char *
2857 sys_strerror(int error_no)
2859 int i;
2860 static char unknown_msg[40];
2862 if (error_no >= 0 && error_no < sys_nerr)
2863 return sys_errlist[error_no];
2865 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
2866 if (_wsa_errlist[i].errnum == error_no)
2867 return _wsa_errlist[i].msg;
2869 sprintf(unknown_msg, "Unidentified error: %d", error_no);
2870 return unknown_msg;
2873 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2874 but I believe the method of keeping the socket handle separate (and
2875 insuring it is not inheritable) is the correct one. */
2877 //#define SOCK_REPLACE_HANDLE
2879 #ifdef SOCK_REPLACE_HANDLE
2880 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2881 #else
2882 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2883 #endif
2885 int socket_to_fd (SOCKET s);
2888 sys_socket(int af, int type, int protocol)
2890 SOCKET s;
2892 if (winsock_lib == NULL)
2894 h_errno = ENETDOWN;
2895 return INVALID_SOCKET;
2898 check_errno ();
2900 /* call the real socket function */
2901 s = pfn_socket (af, type, protocol);
2903 if (s != INVALID_SOCKET)
2904 return socket_to_fd (s);
2906 set_errno ();
2907 return -1;
2910 /* Convert a SOCKET to a file descriptor. */
2912 socket_to_fd (SOCKET s)
2914 int fd;
2915 child_process * cp;
2917 /* Although under NT 3.5 _open_osfhandle will accept a socket
2918 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2919 that does not work under NT 3.1. However, we can get the same
2920 effect by using a backdoor function to replace an existing
2921 descriptor handle with the one we want. */
2923 /* allocate a file descriptor (with appropriate flags) */
2924 fd = _open ("NUL:", _O_RDWR);
2925 if (fd >= 0)
2927 #ifdef SOCK_REPLACE_HANDLE
2928 /* now replace handle to NUL with our socket handle */
2929 CloseHandle ((HANDLE) _get_osfhandle (fd));
2930 _free_osfhnd (fd);
2931 _set_osfhnd (fd, s);
2932 /* setmode (fd, _O_BINARY); */
2933 #else
2934 /* Make a non-inheritable copy of the socket handle. Note
2935 that it is possible that sockets aren't actually kernel
2936 handles, which appears to be the case on Windows 9x when
2937 the MS Proxy winsock client is installed. */
2939 /* Apparently there is a bug in NT 3.51 with some service
2940 packs, which prevents using DuplicateHandle to make a
2941 socket handle non-inheritable (causes WSACleanup to
2942 hang). The work-around is to use SetHandleInformation
2943 instead if it is available and implemented. */
2944 if (pfn_SetHandleInformation)
2946 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
2948 else
2950 HANDLE parent = GetCurrentProcess ();
2951 HANDLE new_s = INVALID_HANDLE_VALUE;
2953 if (DuplicateHandle (parent,
2954 (HANDLE) s,
2955 parent,
2956 &new_s,
2958 FALSE,
2959 DUPLICATE_SAME_ACCESS))
2961 /* It is possible that DuplicateHandle succeeds even
2962 though the socket wasn't really a kernel handle,
2963 because a real handle has the same value. So
2964 test whether the new handle really is a socket. */
2965 long nonblocking = 0;
2966 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
2968 pfn_closesocket (s);
2969 s = (SOCKET) new_s;
2971 else
2973 CloseHandle (new_s);
2978 fd_info[fd].hnd = (HANDLE) s;
2979 #endif
2981 /* set our own internal flags */
2982 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2984 cp = new_child ();
2985 if (cp)
2987 cp->fd = fd;
2988 cp->status = STATUS_READ_ACKNOWLEDGED;
2990 /* attach child_process to fd_info */
2991 if (fd_info[ fd ].cp != NULL)
2993 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2994 abort ();
2997 fd_info[ fd ].cp = cp;
2999 /* success! */
3000 winsock_inuse++; /* count open sockets */
3001 return fd;
3004 /* clean up */
3005 _close (fd);
3007 pfn_closesocket (s);
3008 h_errno = EMFILE;
3009 return -1;
3014 sys_bind (int s, const struct sockaddr * addr, int namelen)
3016 if (winsock_lib == NULL)
3018 h_errno = ENOTSOCK;
3019 return SOCKET_ERROR;
3022 check_errno ();
3023 if (fd_info[s].flags & FILE_SOCKET)
3025 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3026 if (rc == SOCKET_ERROR)
3027 set_errno ();
3028 return rc;
3030 h_errno = ENOTSOCK;
3031 return SOCKET_ERROR;
3036 sys_connect (int s, const struct sockaddr * name, int namelen)
3038 if (winsock_lib == NULL)
3040 h_errno = ENOTSOCK;
3041 return SOCKET_ERROR;
3044 check_errno ();
3045 if (fd_info[s].flags & FILE_SOCKET)
3047 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3048 if (rc == SOCKET_ERROR)
3049 set_errno ();
3050 return rc;
3052 h_errno = ENOTSOCK;
3053 return SOCKET_ERROR;
3056 u_short
3057 sys_htons (u_short hostshort)
3059 return (winsock_lib != NULL) ?
3060 pfn_htons (hostshort) : hostshort;
3063 u_short
3064 sys_ntohs (u_short netshort)
3066 return (winsock_lib != NULL) ?
3067 pfn_ntohs (netshort) : netshort;
3070 unsigned long
3071 sys_inet_addr (const char * cp)
3073 return (winsock_lib != NULL) ?
3074 pfn_inet_addr (cp) : INADDR_NONE;
3078 sys_gethostname (char * name, int namelen)
3080 if (winsock_lib != NULL)
3081 return pfn_gethostname (name, namelen);
3083 if (namelen > MAX_COMPUTERNAME_LENGTH)
3084 return !GetComputerName (name, (DWORD *)&namelen);
3086 h_errno = EFAULT;
3087 return SOCKET_ERROR;
3090 struct hostent *
3091 sys_gethostbyname(const char * name)
3093 struct hostent * host;
3095 if (winsock_lib == NULL)
3097 h_errno = ENETDOWN;
3098 return NULL;
3101 check_errno ();
3102 host = pfn_gethostbyname (name);
3103 if (!host)
3104 set_errno ();
3105 return host;
3108 struct servent *
3109 sys_getservbyname(const char * name, const char * proto)
3111 struct servent * serv;
3113 if (winsock_lib == NULL)
3115 h_errno = ENETDOWN;
3116 return NULL;
3119 check_errno ();
3120 serv = pfn_getservbyname (name, proto);
3121 if (!serv)
3122 set_errno ();
3123 return serv;
3127 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3129 if (winsock_lib == NULL)
3131 h_errno = ENETDOWN;
3132 return SOCKET_ERROR;
3135 check_errno ();
3136 if (fd_info[s].flags & FILE_SOCKET)
3138 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3139 if (rc == SOCKET_ERROR)
3140 set_errno ();
3141 return rc;
3143 h_errno = ENOTSOCK;
3144 return SOCKET_ERROR;
3149 sys_shutdown (int s, int how)
3151 if (winsock_lib == NULL)
3153 h_errno = ENETDOWN;
3154 return SOCKET_ERROR;
3157 check_errno ();
3158 if (fd_info[s].flags & FILE_SOCKET)
3160 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3161 if (rc == SOCKET_ERROR)
3162 set_errno ();
3163 return rc;
3165 h_errno = ENOTSOCK;
3166 return SOCKET_ERROR;
3170 sys_setsockopt (int s, int level, int optname, const char * optval, int optlen)
3172 if (winsock_lib == NULL)
3174 h_errno = ENETDOWN;
3175 return SOCKET_ERROR;
3178 check_errno ();
3179 if (fd_info[s].flags & FILE_SOCKET)
3181 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3182 optval, optlen);
3183 if (rc == SOCKET_ERROR)
3184 set_errno ();
3185 return rc;
3187 h_errno = ENOTSOCK;
3188 return SOCKET_ERROR;
3192 sys_listen (int s, int backlog)
3194 if (winsock_lib == NULL)
3196 h_errno = ENETDOWN;
3197 return SOCKET_ERROR;
3200 check_errno ();
3201 if (fd_info[s].flags & FILE_SOCKET)
3203 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3204 if (rc == SOCKET_ERROR)
3205 set_errno ();
3206 return rc;
3208 h_errno = ENOTSOCK;
3209 return SOCKET_ERROR;
3213 sys_getsockname (int s, struct sockaddr * name, int * namelen)
3215 if (winsock_lib == NULL)
3217 h_errno = ENETDOWN;
3218 return SOCKET_ERROR;
3221 check_errno ();
3222 if (fd_info[s].flags & FILE_SOCKET)
3224 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3225 if (rc == SOCKET_ERROR)
3226 set_errno ();
3227 return rc;
3229 h_errno = ENOTSOCK;
3230 return SOCKET_ERROR;
3234 sys_accept (int s, struct sockaddr * addr, int * addrlen)
3236 if (winsock_lib == NULL)
3238 h_errno = ENETDOWN;
3239 return -1;
3242 check_errno ();
3243 if (fd_info[s].flags & FILE_SOCKET)
3245 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3246 if (t != INVALID_SOCKET)
3247 return socket_to_fd (t);
3249 set_errno ();
3250 return -1;
3252 h_errno = ENOTSOCK;
3253 return -1;
3257 sys_recvfrom (int s, char * buf, int len, int flags,
3258 struct sockaddr * from, int * fromlen)
3260 if (winsock_lib == NULL)
3262 h_errno = ENETDOWN;
3263 return SOCKET_ERROR;
3266 check_errno ();
3267 if (fd_info[s].flags & FILE_SOCKET)
3269 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3270 if (rc == SOCKET_ERROR)
3271 set_errno ();
3272 return rc;
3274 h_errno = ENOTSOCK;
3275 return SOCKET_ERROR;
3279 sys_sendto (int s, const char * buf, int len, int flags,
3280 const struct sockaddr * to, int tolen)
3282 if (winsock_lib == NULL)
3284 h_errno = ENETDOWN;
3285 return SOCKET_ERROR;
3288 check_errno ();
3289 if (fd_info[s].flags & FILE_SOCKET)
3291 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3292 if (rc == SOCKET_ERROR)
3293 set_errno ();
3294 return rc;
3296 h_errno = ENOTSOCK;
3297 return SOCKET_ERROR;
3300 /* Windows does not have an fcntl function. Provide an implementation
3301 solely for making sockets non-blocking. */
3303 fcntl (int s, int cmd, int options)
3305 if (winsock_lib == NULL)
3307 h_errno = ENETDOWN;
3308 return -1;
3311 check_errno ();
3312 if (fd_info[s].flags & FILE_SOCKET)
3314 if (cmd == F_SETFL && options == O_NDELAY)
3316 unsigned long nblock = 1;
3317 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3318 if (rc == SOCKET_ERROR)
3319 set_errno();
3320 /* Keep track of the fact that we set this to non-blocking. */
3321 fd_info[s].flags |= FILE_NDELAY;
3322 return rc;
3324 else
3326 h_errno = EINVAL;
3327 return SOCKET_ERROR;
3330 h_errno = ENOTSOCK;
3331 return SOCKET_ERROR;
3334 #endif /* HAVE_SOCKETS */
3337 /* Shadow main io functions: we need to handle pipes and sockets more
3338 intelligently, and implement non-blocking mode as well. */
3341 sys_close (int fd)
3343 int rc;
3345 if (fd < 0 || fd >= MAXDESC)
3347 errno = EBADF;
3348 return -1;
3351 if (fd_info[fd].cp)
3353 child_process * cp = fd_info[fd].cp;
3355 fd_info[fd].cp = NULL;
3357 if (CHILD_ACTIVE (cp))
3359 /* if last descriptor to active child_process then cleanup */
3360 int i;
3361 for (i = 0; i < MAXDESC; i++)
3363 if (i == fd)
3364 continue;
3365 if (fd_info[i].cp == cp)
3366 break;
3368 if (i == MAXDESC)
3370 #ifdef HAVE_SOCKETS
3371 if (fd_info[fd].flags & FILE_SOCKET)
3373 #ifndef SOCK_REPLACE_HANDLE
3374 if (winsock_lib == NULL) abort ();
3376 pfn_shutdown (SOCK_HANDLE (fd), 2);
3377 rc = pfn_closesocket (SOCK_HANDLE (fd));
3378 #endif
3379 winsock_inuse--; /* count open sockets */
3381 #endif
3382 delete_child (cp);
3387 /* Note that sockets do not need special treatment here (at least on
3388 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3389 closesocket is equivalent to CloseHandle, which is to be expected
3390 because socket handles are fully fledged kernel handles. */
3391 rc = _close (fd);
3393 if (rc == 0)
3394 fd_info[fd].flags = 0;
3396 return rc;
3400 sys_dup (int fd)
3402 int new_fd;
3404 new_fd = _dup (fd);
3405 if (new_fd >= 0)
3407 /* duplicate our internal info as well */
3408 fd_info[new_fd] = fd_info[fd];
3410 return new_fd;
3415 sys_dup2 (int src, int dst)
3417 int rc;
3419 if (dst < 0 || dst >= MAXDESC)
3421 errno = EBADF;
3422 return -1;
3425 /* make sure we close the destination first if it's a pipe or socket */
3426 if (src != dst && fd_info[dst].flags != 0)
3427 sys_close (dst);
3429 rc = _dup2 (src, dst);
3430 if (rc == 0)
3432 /* duplicate our internal info as well */
3433 fd_info[dst] = fd_info[src];
3435 return rc;
3438 /* Unix pipe() has only one arg */
3440 sys_pipe (int * phandles)
3442 int rc;
3443 unsigned flags;
3445 /* make pipe handles non-inheritable; when we spawn a child, we
3446 replace the relevant handle with an inheritable one. Also put
3447 pipes into binary mode; we will do text mode translation ourselves
3448 if required. */
3449 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3451 if (rc == 0)
3453 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3454 fd_info[phandles[0]].flags = flags;
3456 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3457 fd_info[phandles[1]].flags = flags;
3460 return rc;
3463 /* From ntproc.c */
3464 extern Lisp_Object Vw32_pipe_read_delay;
3466 /* Function to do blocking read of one byte, needed to implement
3467 select. It is only allowed on sockets and pipes. */
3469 _sys_read_ahead (int fd)
3471 child_process * cp;
3472 int rc;
3474 if (fd < 0 || fd >= MAXDESC)
3475 return STATUS_READ_ERROR;
3477 cp = fd_info[fd].cp;
3479 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3480 return STATUS_READ_ERROR;
3482 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3483 || (fd_info[fd].flags & FILE_READ) == 0)
3485 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3486 abort ();
3489 cp->status = STATUS_READ_IN_PROGRESS;
3491 if (fd_info[fd].flags & FILE_PIPE)
3493 rc = _read (fd, &cp->chr, sizeof (char));
3495 /* Give subprocess time to buffer some more output for us before
3496 reporting that input is available; we need this because Windows 95
3497 connects DOS programs to pipes by making the pipe appear to be
3498 the normal console stdout - as a result most DOS programs will
3499 write to stdout without buffering, ie. one character at a
3500 time. Even some W32 programs do this - "dir" in a command
3501 shell on NT is very slow if we don't do this. */
3502 if (rc > 0)
3504 int wait = XINT (Vw32_pipe_read_delay);
3506 if (wait > 0)
3507 Sleep (wait);
3508 else if (wait < 0)
3509 while (++wait <= 0)
3510 /* Yield remainder of our time slice, effectively giving a
3511 temporary priority boost to the child process. */
3512 Sleep (0);
3515 #ifdef HAVE_SOCKETS
3516 else if (fd_info[fd].flags & FILE_SOCKET)
3518 unsigned long nblock = 0;
3519 /* We always want this to block, so temporarily disable NDELAY. */
3520 if (fd_info[fd].flags & FILE_NDELAY)
3521 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3523 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3525 if (fd_info[fd].flags & FILE_NDELAY)
3527 nblock = 1;
3528 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3531 #endif
3533 if (rc == sizeof (char))
3534 cp->status = STATUS_READ_SUCCEEDED;
3535 else
3536 cp->status = STATUS_READ_FAILED;
3538 return cp->status;
3542 sys_read (int fd, char * buffer, unsigned int count)
3544 int nchars;
3545 int to_read;
3546 DWORD waiting;
3547 char * orig_buffer = buffer;
3549 if (fd < 0 || fd >= MAXDESC)
3551 errno = EBADF;
3552 return -1;
3555 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3557 child_process *cp = fd_info[fd].cp;
3559 if ((fd_info[fd].flags & FILE_READ) == 0)
3561 errno = EBADF;
3562 return -1;
3565 nchars = 0;
3567 /* re-read CR carried over from last read */
3568 if (fd_info[fd].flags & FILE_LAST_CR)
3570 if (fd_info[fd].flags & FILE_BINARY) abort ();
3571 *buffer++ = 0x0d;
3572 count--;
3573 nchars++;
3574 fd_info[fd].flags &= ~FILE_LAST_CR;
3577 /* presence of a child_process structure means we are operating in
3578 non-blocking mode - otherwise we just call _read directly.
3579 Note that the child_process structure might be missing because
3580 reap_subprocess has been called; in this case the pipe is
3581 already broken, so calling _read on it is okay. */
3582 if (cp)
3584 int current_status = cp->status;
3586 switch (current_status)
3588 case STATUS_READ_FAILED:
3589 case STATUS_READ_ERROR:
3590 /* report normal EOF if nothing in buffer */
3591 if (nchars <= 0)
3592 fd_info[fd].flags |= FILE_AT_EOF;
3593 return nchars;
3595 case STATUS_READ_READY:
3596 case STATUS_READ_IN_PROGRESS:
3597 DebPrint (("sys_read called when read is in progress\n"));
3598 errno = EWOULDBLOCK;
3599 return -1;
3601 case STATUS_READ_SUCCEEDED:
3602 /* consume read-ahead char */
3603 *buffer++ = cp->chr;
3604 count--;
3605 nchars++;
3606 cp->status = STATUS_READ_ACKNOWLEDGED;
3607 ResetEvent (cp->char_avail);
3609 case STATUS_READ_ACKNOWLEDGED:
3610 break;
3612 default:
3613 DebPrint (("sys_read: bad status %d\n", current_status));
3614 errno = EBADF;
3615 return -1;
3618 if (fd_info[fd].flags & FILE_PIPE)
3620 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3621 to_read = min (waiting, (DWORD) count);
3623 if (to_read > 0)
3624 nchars += _read (fd, buffer, to_read);
3626 #ifdef HAVE_SOCKETS
3627 else /* FILE_SOCKET */
3629 if (winsock_lib == NULL) abort ();
3631 /* do the equivalent of a non-blocking read */
3632 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3633 if (waiting == 0 && nchars == 0)
3635 h_errno = errno = EWOULDBLOCK;
3636 return -1;
3639 if (waiting)
3641 /* always use binary mode for sockets */
3642 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3643 if (res == SOCKET_ERROR)
3645 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3646 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3647 set_errno ();
3648 return -1;
3650 nchars += res;
3653 #endif
3655 else
3657 int nread = _read (fd, buffer, count);
3658 if (nread >= 0)
3659 nchars += nread;
3660 else if (nchars == 0)
3661 nchars = nread;
3664 if (nchars <= 0)
3665 fd_info[fd].flags |= FILE_AT_EOF;
3666 /* Perform text mode translation if required. */
3667 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3669 nchars = crlf_to_lf (nchars, orig_buffer);
3670 /* If buffer contains only CR, return that. To be absolutely
3671 sure we should attempt to read the next char, but in
3672 practice a CR to be followed by LF would not appear by
3673 itself in the buffer. */
3674 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3676 fd_info[fd].flags |= FILE_LAST_CR;
3677 nchars--;
3681 else
3682 nchars = _read (fd, buffer, count);
3684 return nchars;
3687 /* For now, don't bother with a non-blocking mode */
3689 sys_write (int fd, const void * buffer, unsigned int count)
3691 int nchars;
3693 if (fd < 0 || fd >= MAXDESC)
3695 errno = EBADF;
3696 return -1;
3699 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3701 if ((fd_info[fd].flags & FILE_WRITE) == 0)
3703 errno = EBADF;
3704 return -1;
3707 /* Perform text mode translation if required. */
3708 if ((fd_info[fd].flags & FILE_BINARY) == 0)
3710 char * tmpbuf = alloca (count * 2);
3711 unsigned char * src = (void *)buffer;
3712 unsigned char * dst = tmpbuf;
3713 int nbytes = count;
3715 while (1)
3717 unsigned char *next;
3718 /* copy next line or remaining bytes */
3719 next = _memccpy (dst, src, '\n', nbytes);
3720 if (next)
3722 /* copied one line ending with '\n' */
3723 int copied = next - dst;
3724 nbytes -= copied;
3725 src += copied;
3726 /* insert '\r' before '\n' */
3727 next[-1] = '\r';
3728 next[0] = '\n';
3729 dst = next + 1;
3730 count++;
3732 else
3733 /* copied remaining partial line -> now finished */
3734 break;
3736 buffer = tmpbuf;
3740 #ifdef HAVE_SOCKETS
3741 if (fd_info[fd].flags & FILE_SOCKET)
3743 unsigned long nblock = 0;
3744 if (winsock_lib == NULL) abort ();
3746 /* TODO: implement select() properly so non-blocking I/O works. */
3747 /* For now, make sure the write blocks. */
3748 if (fd_info[fd].flags & FILE_NDELAY)
3749 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3751 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3753 /* Set the socket back to non-blocking if it was before,
3754 for other operations that support it. */
3755 if (fd_info[fd].flags & FILE_NDELAY)
3757 nblock = 1;
3758 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3761 if (nchars == SOCKET_ERROR)
3763 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3764 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3765 set_errno ();
3768 else
3769 #endif
3770 nchars = _write (fd, buffer, count);
3772 return nchars;
3775 static void
3776 check_windows_init_file ()
3778 extern int noninteractive, inhibit_window_system;
3780 /* A common indication that Emacs is not installed properly is when
3781 it cannot find the Windows installation file. If this file does
3782 not exist in the expected place, tell the user. */
3784 if (!noninteractive && !inhibit_window_system)
3786 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3787 Lisp_Object objs[2];
3788 Lisp_Object full_load_path;
3789 Lisp_Object init_file;
3790 int fd;
3792 objs[0] = Vload_path;
3793 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3794 full_load_path = Fappend (2, objs);
3795 init_file = build_string ("term/w32-win");
3796 fd = openp (full_load_path, init_file, Vload_suffixes, NULL, Qnil);
3797 if (fd < 0)
3799 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3800 char *init_file_name = SDATA (init_file);
3801 char *load_path = SDATA (load_path_print);
3802 char *buffer = alloca (1024);
3804 sprintf (buffer,
3805 "The Emacs Windows initialization file \"%s.el\" "
3806 "could not be found in your Emacs installation. "
3807 "Emacs checked the following directories for this file:\n"
3808 "\n%s\n\n"
3809 "When Emacs cannot find this file, it usually means that it "
3810 "was not installed properly, or its distribution file was "
3811 "not unpacked properly.\nSee the README.W32 file in the "
3812 "top-level Emacs directory for more information.",
3813 init_file_name, load_path);
3814 MessageBox (NULL,
3815 buffer,
3816 "Emacs Abort Dialog",
3817 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3818 /* Use the low-level Emacs abort. */
3819 #undef abort
3820 abort ();
3822 else
3824 _close (fd);
3829 void
3830 term_ntproc ()
3832 #ifdef HAVE_SOCKETS
3833 /* shutdown the socket interface if necessary */
3834 term_winsock ();
3835 #endif
3838 void
3839 init_ntproc ()
3841 #ifdef HAVE_SOCKETS
3842 /* Initialise the socket interface now if available and requested by
3843 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3844 delayed until open-network-stream is called (w32-has-winsock can
3845 also be used to dynamically load or reload winsock).
3847 Conveniently, init_environment is called before us, so
3848 PRELOAD_WINSOCK can be set in the registry. */
3850 /* Always initialize this correctly. */
3851 winsock_lib = NULL;
3853 if (getenv ("PRELOAD_WINSOCK") != NULL)
3854 init_winsock (TRUE);
3855 #endif
3857 /* Initial preparation for subprocess support: replace our standard
3858 handles with non-inheritable versions. */
3860 HANDLE parent;
3861 HANDLE stdin_save = INVALID_HANDLE_VALUE;
3862 HANDLE stdout_save = INVALID_HANDLE_VALUE;
3863 HANDLE stderr_save = INVALID_HANDLE_VALUE;
3865 parent = GetCurrentProcess ();
3867 /* ignore errors when duplicating and closing; typically the
3868 handles will be invalid when running as a gui program. */
3869 DuplicateHandle (parent,
3870 GetStdHandle (STD_INPUT_HANDLE),
3871 parent,
3872 &stdin_save,
3874 FALSE,
3875 DUPLICATE_SAME_ACCESS);
3877 DuplicateHandle (parent,
3878 GetStdHandle (STD_OUTPUT_HANDLE),
3879 parent,
3880 &stdout_save,
3882 FALSE,
3883 DUPLICATE_SAME_ACCESS);
3885 DuplicateHandle (parent,
3886 GetStdHandle (STD_ERROR_HANDLE),
3887 parent,
3888 &stderr_save,
3890 FALSE,
3891 DUPLICATE_SAME_ACCESS);
3893 fclose (stdin);
3894 fclose (stdout);
3895 fclose (stderr);
3897 if (stdin_save != INVALID_HANDLE_VALUE)
3898 _open_osfhandle ((long) stdin_save, O_TEXT);
3899 else
3900 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3901 _fdopen (0, "r");
3903 if (stdout_save != INVALID_HANDLE_VALUE)
3904 _open_osfhandle ((long) stdout_save, O_TEXT);
3905 else
3906 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3907 _fdopen (1, "w");
3909 if (stderr_save != INVALID_HANDLE_VALUE)
3910 _open_osfhandle ((long) stderr_save, O_TEXT);
3911 else
3912 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3913 _fdopen (2, "w");
3916 /* unfortunately, atexit depends on implementation of malloc */
3917 /* atexit (term_ntproc); */
3918 signal (SIGABRT, term_ntproc);
3920 /* determine which drives are fixed, for GetCachedVolumeInformation */
3922 /* GetDriveType must have trailing backslash. */
3923 char drive[] = "A:\\";
3925 /* Loop over all possible drive letters */
3926 while (*drive <= 'Z')
3928 /* Record if this drive letter refers to a fixed drive. */
3929 fixed_drives[DRIVE_INDEX (*drive)] =
3930 (GetDriveType (drive) == DRIVE_FIXED);
3932 (*drive)++;
3935 /* Reset the volume info cache. */
3936 volume_cache = NULL;
3939 /* Check to see if Emacs has been installed correctly. */
3940 check_windows_init_file ();
3944 globals_of_w32 is used to initialize those global variables that
3945 must always be initialized on startup even when the global variable
3946 initialized is non zero (see the function main in emacs.c).
3948 void globals_of_w32 ()
3950 g_b_init_is_windows_9x = 0;
3951 g_b_init_open_process_token = 0;
3952 g_b_init_get_token_information = 0;
3953 g_b_init_lookup_account_sid = 0;
3954 g_b_init_get_sid_identifier_authority = 0;
3957 /* end of nt.c */