1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1994, 1995 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)
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 */
35 #include <sys/utime.h>
37 /* must include CRT headers *before* config.h */
67 #define _ANONYMOUS_UNION
68 #define _ANONYMOUS_STRUCT
72 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
73 #include <sys/socket.h>
92 #define min(x, y) (((x) < (y)) ? (x) : (y))
93 #define max(x, y) (((x) > (y)) ? (x) : (y))
95 extern Lisp_Object Vw32_downcase_file_names
;
96 extern Lisp_Object Vw32_generate_fake_inodes
;
97 extern Lisp_Object Vw32_get_true_file_attributes
;
98 extern Lisp_Object Vw32_num_mouse_buttons
;
100 static char startup_dir
[MAXPATHLEN
];
102 /* Get the current working directory. */
107 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
111 /* Emacs doesn't actually change directory itself, and we want to
112 force our real wd to be where emacs.exe is to avoid unnecessary
113 conflicts when trying to rename or delete directories. */
114 strcpy (dir
, startup_dir
);
120 /* Emulate gethostname. */
122 gethostname (char *buffer
, int size
)
124 /* NT only allows small host names, so the buffer is
125 certainly large enough. */
126 return !GetComputerName (buffer
, &size
);
128 #endif /* HAVE_SOCKETS */
130 /* Emulate getloadavg. */
132 getloadavg (double loadavg
[], int nelem
)
136 /* A faithful emulation is going to have to be saved for a rainy day. */
137 for (i
= 0; i
< nelem
; i
++)
144 /* Emulate getpwuid, getpwnam and others. */
146 #define PASSWD_FIELD_SIZE 256
148 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
149 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
150 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
151 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
152 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
154 static struct passwd the_passwd
=
169 return the_passwd
.pw_uid
;
175 /* I could imagine arguing for checking to see whether the user is
176 in the Administrators group and returning a UID of 0 for that
177 case, but I don't know how wise that would be in the long run. */
184 return the_passwd
.pw_gid
;
196 if (uid
== the_passwd
.pw_uid
)
202 getpwnam (char *name
)
206 pw
= getpwuid (getuid ());
210 if (stricmp (name
, pw
->pw_name
))
219 /* Find the user's real name by opening the process token and
220 looking up the name associated with the user-sid in that token.
222 Use the relative portion of the identifier authority value from
223 the user-sid as the user id value (same for group id using the
224 primary group sid from the process token). */
226 char user_sid
[256], name
[256], domain
[256];
227 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
229 SID_NAME_USE user_type
;
231 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
)
232 && GetTokenInformation (token
, TokenUser
,
233 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
234 && LookupAccountSid (NULL
, *((PSID
*) user_sid
), name
, &length
,
235 domain
, &dlength
, &user_type
))
237 strcpy (the_passwd
.pw_name
, name
);
238 /* Determine a reasonable uid value. */
239 if (stricmp ("administrator", name
) == 0)
241 the_passwd
.pw_uid
= 0;
242 the_passwd
.pw_gid
= 0;
246 SID_IDENTIFIER_AUTHORITY
* pSIA
;
248 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
249 /* I believe the relative portion is the last 4 bytes (of 6)
251 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
252 (pSIA
->Value
[3] << 16) +
253 (pSIA
->Value
[4] << 8) +
254 (pSIA
->Value
[5] << 0));
255 /* restrict to conventional uid range for normal users */
256 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
259 if (GetTokenInformation (token
, TokenPrimaryGroup
,
260 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
262 SID_IDENTIFIER_AUTHORITY
* pSIA
;
264 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
265 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
266 (pSIA
->Value
[3] << 16) +
267 (pSIA
->Value
[4] << 8) +
268 (pSIA
->Value
[5] << 0));
269 /* I don't know if this is necessary, but for safety... */
270 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
273 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
276 /* If security calls are not supported (presumably because we
277 are running under Windows 95), fallback to this. */
278 else if (GetUserName (name
, &length
))
280 strcpy (the_passwd
.pw_name
, name
);
281 if (stricmp ("administrator", name
) == 0)
282 the_passwd
.pw_uid
= 0;
284 the_passwd
.pw_uid
= 123;
285 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
289 strcpy (the_passwd
.pw_name
, "unknown");
290 the_passwd
.pw_uid
= 123;
291 the_passwd
.pw_gid
= 123;
294 /* Ensure HOME and SHELL are defined. */
295 if (getenv ("HOME") == NULL
)
297 if (getenv ("SHELL") == NULL
)
300 /* Set dir and shell from environment variables. */
301 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
302 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
311 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
312 return ((rand () << 15) | rand ());
322 /* Normalize filename by converting all path separators to
323 the specified separator. Also conditionally convert upper
324 case path name components to lower case. */
327 normalize_filename (fp
, path_sep
)
334 /* Always lower-case drive letters a-z, even if the filesystem
335 preserves case in filenames.
336 This is so filenames can be compared by string comparison
337 functions that are case-sensitive. Even case-preserving filesystems
338 do not distinguish case in drive letters. */
339 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
345 if (NILP (Vw32_downcase_file_names
))
349 if (*fp
== '/' || *fp
== '\\')
356 sep
= path_sep
; /* convert to this path separator */
357 elem
= fp
; /* start of current path element */
360 if (*fp
>= 'a' && *fp
<= 'z')
361 elem
= 0; /* don't convert this element */
363 if (*fp
== 0 || *fp
== ':')
365 sep
= *fp
; /* restore current separator (or 0) */
366 *fp
= '/'; /* after conversion of this element */
369 if (*fp
== '/' || *fp
== '\\')
371 if (elem
&& elem
!= fp
)
373 *fp
= 0; /* temporary end of string */
374 _strlwr (elem
); /* while we convert to lower case */
376 *fp
= sep
; /* convert (or restore) path separator */
377 elem
= fp
+ 1; /* next element starts after separator */
383 /* Destructively turn backslashes into slashes. */
385 dostounix_filename (p
)
388 normalize_filename (p
, '/');
391 /* Destructively turn slashes into backslashes. */
393 unixtodos_filename (p
)
396 normalize_filename (p
, '\\');
399 /* Remove all CR's that are followed by a LF.
400 (From msdos.c...probably should figure out a way to share it,
401 although this code isn't going to ever change.) */
405 register unsigned char *buf
;
407 unsigned char *np
= buf
;
408 unsigned char *startp
= buf
;
409 unsigned char *endp
= buf
+ n
;
413 while (buf
< endp
- 1)
417 if (*(++buf
) != 0x0a)
428 /* Parse the root part of file name, if present. Return length and
429 optionally store pointer to char after root. */
431 parse_root (char * name
, char ** pPath
)
438 /* find the root name of the volume if given */
439 if (isalpha (name
[0]) && name
[1] == ':')
441 /* skip past drive specifier */
443 if (IS_DIRECTORY_SEP (name
[0]))
446 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
452 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
457 if (IS_DIRECTORY_SEP (name
[0]))
467 /* Get long base name for name; name is assumed to be absolute. */
469 get_long_basename (char * name
, char * buf
, int size
)
471 WIN32_FIND_DATA find_data
;
475 /* must be valid filename, no wild cards or other invalid characters */
476 if (strpbrk (name
, "*?|<>\""))
479 dir_handle
= FindFirstFile (name
, &find_data
);
480 if (dir_handle
!= INVALID_HANDLE_VALUE
)
482 if ((len
= strlen (find_data
.cFileName
)) < size
)
483 memcpy (buf
, find_data
.cFileName
, len
+ 1);
486 FindClose (dir_handle
);
491 /* Get long name for file, if possible (assumed to be absolute). */
493 w32_get_long_filename (char * name
, char * buf
, int size
)
498 char full
[ MAX_PATH
];
505 /* Use local copy for destructive modification. */
506 memcpy (full
, name
, len
+1);
507 unixtodos_filename (full
);
509 /* Copy root part verbatim. */
510 len
= parse_root (full
, &p
);
511 memcpy (o
, full
, len
);
516 while (p
!= NULL
&& *p
)
519 p
= strchr (q
, '\\');
521 len
= get_long_basename (full
, o
, size
);
544 is_unc_volume (const char *filename
)
546 const char *ptr
= filename
;
548 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
551 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
557 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
560 sigsetmask (int signal_mask
)
584 setpgrp (int pid
, int gid
)
596 unrequest_sigio (void)
607 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
610 w32_get_resource (key
, lpdwtype
)
615 HKEY hrootkey
= NULL
;
619 /* Check both the current user and the local machine to see if
620 we have any resources. */
622 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
626 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
627 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
628 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
633 if (lpvalue
) xfree (lpvalue
);
635 RegCloseKey (hrootkey
);
638 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
642 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
643 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
644 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
649 if (lpvalue
) xfree (lpvalue
);
651 RegCloseKey (hrootkey
);
657 char *get_emacs_configuration (void);
658 extern Lisp_Object Vsystem_configuration
;
661 init_environment (char ** argv
)
664 static const char * const tempdirs
[] = {
665 "$TMPDIR", "$TEMP", "$TMP", "c:/"
668 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
670 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
671 temporary files and assume "/tmp" if $TMPDIR is unset, which
672 will break on DOS/Windows. Refuse to work if we cannot find
673 a directory, not even "c:/", usable for that purpose. */
674 for (i
= 0; i
< imax
; i
++)
676 const char *tmp
= tempdirs
[i
];
679 tmp
= getenv (tmp
+ 1);
680 /* Note that `access' can lie to us if the directory resides on a
681 read-only filesystem, like CD-ROM or a write-protected floppy.
682 The only way to be really sure is to actually create a file and
683 see if it succeeds. But I think that's too much to ask. */
684 if (tmp
&& _access (tmp
, D_OK
) == 0)
686 char * var
= alloca (strlen (tmp
) + 8);
687 sprintf (var
, "TMPDIR=%s", tmp
);
695 Fcons (build_string ("no usable temporary directories found!!"),
697 "While setting TMPDIR: ");
699 /* Check for environment variables and use registry settings if they
700 don't exist. Fallback on default values where applicable. */
705 char locale_name
[32];
707 static struct env_entry
714 {"PRELOAD_WINSOCK", NULL
},
715 {"emacs_dir", "C:/emacs"},
716 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
717 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
718 {"EMACSDATA", "%emacs_dir%/etc"},
719 {"EMACSPATH", "%emacs_dir%/bin"},
720 {"EMACSLOCKDIR", "%emacs_dir%/lock"},
721 /* We no longer set INFOPATH because Info-default-directory-list
723 /* {"INFOPATH", "%emacs_dir%/info"}, */
724 {"EMACSDOC", "%emacs_dir%/etc"},
729 /* Get default locale info and use it for LANG. */
730 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
731 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
732 locale_name
, sizeof (locale_name
)))
734 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
736 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
738 env_vars
[i
].def_value
= locale_name
;
744 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
746 /* Treat emacs_dir specially: set it unconditionally based on our
747 location, if it appears that we are running from the bin subdir
748 of a standard installation. */
751 char modname
[MAX_PATH
];
753 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
755 if ((p
= strrchr (modname
, '\\')) == NULL
)
759 if ((p
= strrchr (modname
, '\\')) && stricmp (p
, "\\bin") == 0)
761 char buf
[SET_ENV_BUF_SIZE
];
764 for (p
= modname
; *p
; p
++)
765 if (*p
== '\\') *p
= '/';
767 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
768 _putenv (strdup (buf
));
772 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
774 if (!getenv (env_vars
[i
].name
))
778 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
)
780 lpval
= env_vars
[i
].def_value
;
781 dwType
= REG_EXPAND_SZ
;
787 if (dwType
== REG_EXPAND_SZ
)
789 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
791 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof(buf1
));
792 _snprintf (buf2
, sizeof(buf2
)-1, "%s=%s", env_vars
[i
].name
, buf1
);
793 _putenv (strdup (buf2
));
795 else if (dwType
== REG_SZ
)
797 char buf
[SET_ENV_BUF_SIZE
];
799 _snprintf (buf
, sizeof(buf
)-1, "%s=%s", env_vars
[i
].name
, lpval
);
800 _putenv (strdup (buf
));
810 /* Rebuild system configuration to reflect invoking system. */
811 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
813 /* Another special case: on NT, the PATH variable is actually named
814 "Path" although cmd.exe (perhaps NT itself) arranges for
815 environment variable lookup and setting to be case insensitive.
816 However, Emacs assumes a fully case sensitive environment, so we
817 need to change "Path" to "PATH" to match the expectations of
818 various elisp packages. We do this by the sneaky method of
819 modifying the string in the C runtime environ entry.
821 The same applies to COMSPEC. */
825 for (envp
= environ
; *envp
; envp
++)
826 if (_strnicmp (*envp
, "PATH=", 5) == 0)
827 memcpy (*envp
, "PATH=", 5);
828 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
829 memcpy (*envp
, "COMSPEC=", 8);
832 /* Remember the initial working directory for getwd, then make the
833 real wd be the location of emacs.exe to avoid conflicts when
834 renaming or deleting directories. (We also don't call chdir when
835 running subprocesses for the same reason.) */
836 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
841 static char modname
[MAX_PATH
];
843 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
845 if ((p
= strrchr (modname
, '\\')) == NULL
)
849 SetCurrentDirectory (modname
);
851 /* Ensure argv[0] has the full path to Emacs. */
856 /* Determine if there is a middle mouse button, to allow parse_button
857 to decide whether right mouse events should be mouse-2 or
859 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
864 /* We don't have scripts to automatically determine the system configuration
865 for Emacs before it's compiled, and we don't want to have to make the
866 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
870 get_emacs_configuration (void)
872 char *arch
, *oem
, *os
;
874 static char configuration_buffer
[32];
876 /* Determine the processor type. */
877 switch (get_processor_type ())
880 #ifdef PROCESSOR_INTEL_386
881 case PROCESSOR_INTEL_386
:
882 case PROCESSOR_INTEL_486
:
883 case PROCESSOR_INTEL_PENTIUM
:
888 #ifdef PROCESSOR_INTEL_860
889 case PROCESSOR_INTEL_860
:
894 #ifdef PROCESSOR_MIPS_R2000
895 case PROCESSOR_MIPS_R2000
:
896 case PROCESSOR_MIPS_R3000
:
897 case PROCESSOR_MIPS_R4000
:
902 #ifdef PROCESSOR_ALPHA_21064
903 case PROCESSOR_ALPHA_21064
:
913 /* Use the OEM field to reflect the compiler/library combination. */
915 #define COMPILER_NAME "msvc"
918 #define COMPILER_NAME "mingw"
920 #define COMPILER_NAME "unknown"
925 switch (osinfo_cache
.dwPlatformId
) {
926 case VER_PLATFORM_WIN32_NT
:
928 build_num
= osinfo_cache
.dwBuildNumber
;
930 case VER_PLATFORM_WIN32_WINDOWS
:
931 if (osinfo_cache
.dwMinorVersion
== 0) {
936 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
938 case VER_PLATFORM_WIN32s
:
939 /* Not supported, should not happen. */
941 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
949 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
950 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
951 get_w32_major_version (), get_w32_minor_version (), build_num
);
953 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
956 return configuration_buffer
;
960 get_emacs_configuration_options (void)
962 static char options_buffer
[256];
964 /* Work out the effective configure options for this build. */
966 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
969 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
971 #define COMPILER_VERSION ""
975 sprintf (options_buffer
, COMPILER_VERSION
);
977 strcat (options_buffer
, " --no-opt");
980 strcat (options_buffer
, " --cflags");
981 strcat (options_buffer
, USER_CFLAGS
);
984 strcat (options_buffer
, " --ldflags");
985 strcat (options_buffer
, USER_LDFLAGS
);
987 return options_buffer
;
991 #include <sys/timeb.h>
993 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
995 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
1000 tv
->tv_sec
= tb
.time
;
1001 tv
->tv_usec
= tb
.millitm
* 1000L;
1004 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
1005 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
1009 /* ------------------------------------------------------------------------- */
1010 /* IO support and wrapper functions for W32 API. */
1011 /* ------------------------------------------------------------------------- */
1013 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1014 on network directories, so we handle that case here.
1015 (Ulrich Leodolter, 1/11/95). */
1017 sys_ctime (const time_t *t
)
1019 char *str
= (char *) ctime (t
);
1020 return (str
? str
: "Sun Jan 01 00:00:00 1970");
1023 /* Emulate sleep...we could have done this with a define, but that
1024 would necessitate including windows.h in the files that used it.
1025 This is much easier. */
1027 sys_sleep (int seconds
)
1029 Sleep (seconds
* 1000);
1032 /* Internal MSVC functions for low-level descriptor munging */
1033 extern int __cdecl
_set_osfhnd (int fd
, long h
);
1034 extern int __cdecl
_free_osfhnd (int fd
);
1036 /* parallel array of private info on file handles */
1037 filedesc fd_info
[ MAXDESC
];
1039 typedef struct volume_info_data
{
1040 struct volume_info_data
* next
;
1042 /* time when info was obtained */
1045 /* actual volume info */
1054 /* Global referenced by various functions. */
1055 static volume_info_data volume_info
;
1057 /* Vector to indicate which drives are local and fixed (for which cached
1058 data never expires). */
1059 static BOOL fixed_drives
[26];
1061 /* Consider cached volume information to be stale if older than 10s,
1062 at least for non-local drives. Info for fixed drives is never stale. */
1063 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1064 #define VOLINFO_STILL_VALID( root_dir, info ) \
1065 ( ( isalpha (root_dir[0]) && \
1066 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1067 || GetTickCount () - info->timestamp < 10000 )
1069 /* Cache support functions. */
1071 /* Simple linked list with linear search is sufficient. */
1072 static volume_info_data
*volume_cache
= NULL
;
1074 static volume_info_data
*
1075 lookup_volume_info (char * root_dir
)
1077 volume_info_data
* info
;
1079 for (info
= volume_cache
; info
; info
= info
->next
)
1080 if (stricmp (info
->root_dir
, root_dir
) == 0)
1086 add_volume_info (char * root_dir
, volume_info_data
* info
)
1088 info
->root_dir
= xstrdup (root_dir
);
1089 info
->next
= volume_cache
;
1090 volume_cache
= info
;
1094 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1095 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1096 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1098 GetCachedVolumeInformation (char * root_dir
)
1100 volume_info_data
* info
;
1101 char default_root
[ MAX_PATH
];
1103 /* NULL for root_dir means use root from current directory. */
1104 if (root_dir
== NULL
)
1106 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1108 parse_root (default_root
, &root_dir
);
1110 root_dir
= default_root
;
1113 /* Local fixed drives can be cached permanently. Removable drives
1114 cannot be cached permanently, since the volume name and serial
1115 number (if nothing else) can change. Remote drives should be
1116 treated as if they are removable, since there is no sure way to
1117 tell whether they are or not. Also, the UNC association of drive
1118 letters mapped to remote volumes can be changed at any time (even
1119 by other processes) without notice.
1121 As a compromise, so we can benefit from caching info for remote
1122 volumes, we use a simple expiry mechanism to invalidate cache
1123 entries that are more than ten seconds old. */
1126 /* No point doing this, because WNetGetConnection is even slower than
1127 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1128 GetDriveType is about the only call of this type which does not
1129 involve network access, and so is extremely quick). */
1131 /* Map drive letter to UNC if remote. */
1132 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1134 char remote_name
[ 256 ];
1135 char drive
[3] = { root_dir
[0], ':' };
1137 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1139 /* do something */ ;
1143 info
= lookup_volume_info (root_dir
);
1145 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1153 /* Info is not cached, or is stale. */
1154 if (!GetVolumeInformation (root_dir
,
1155 name
, sizeof (name
),
1159 type
, sizeof (type
)))
1162 /* Cache the volume information for future use, overwriting existing
1163 entry if present. */
1166 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1167 add_volume_info (root_dir
, info
);
1175 info
->name
= xstrdup (name
);
1176 info
->serialnum
= serialnum
;
1177 info
->maxcomp
= maxcomp
;
1178 info
->flags
= flags
;
1179 info
->type
= xstrdup (type
);
1180 info
->timestamp
= GetTickCount ();
1186 /* Get information on the volume where name is held; set path pointer to
1187 start of pathname in name (past UNC header\volume header if present). */
1189 get_volume_info (const char * name
, const char ** pPath
)
1191 char temp
[MAX_PATH
];
1192 char *rootname
= NULL
; /* default to current volume */
1193 volume_info_data
* info
;
1198 /* find the root name of the volume if given */
1199 if (isalpha (name
[0]) && name
[1] == ':')
1207 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1214 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1227 info
= GetCachedVolumeInformation (rootname
);
1230 /* Set global referenced by other functions. */
1231 volume_info
= *info
;
1237 /* Determine if volume is FAT format (ie. only supports short 8.3
1238 names); also set path pointer to start of pathname in name. */
1240 is_fat_volume (const char * name
, const char ** pPath
)
1242 if (get_volume_info (name
, pPath
))
1243 return (volume_info
.maxcomp
== 12);
1247 /* Map filename to a legal 8.3 name if necessary. */
1249 map_w32_filename (const char * name
, const char ** pPath
)
1251 static char shortname
[MAX_PATH
];
1252 char * str
= shortname
;
1255 const char * save_name
= name
;
1257 if (strlen (name
) >= MAX_PATH
)
1259 /* Return a filename which will cause callers to fail. */
1260 strcpy (shortname
, "?");
1264 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
1266 register int left
= 8; /* maximum number of chars in part */
1267 register int extn
= 0; /* extension added? */
1268 register int dots
= 2; /* maximum number of dots allowed */
1271 *str
++ = *name
++; /* skip past UNC header */
1273 while ((c
= *name
++))
1280 extn
= 0; /* reset extension flags */
1281 dots
= 2; /* max 2 dots */
1282 left
= 8; /* max length 8 for main part */
1286 extn
= 0; /* reset extension flags */
1287 dots
= 2; /* max 2 dots */
1288 left
= 8; /* max length 8 for main part */
1293 /* Convert path components of the form .xxx to _xxx,
1294 but leave . and .. as they are. This allows .emacs
1295 to be read as _emacs, for example. */
1299 IS_DIRECTORY_SEP (*name
))
1314 extn
= 1; /* we've got an extension */
1315 left
= 3; /* 3 chars in extension */
1319 /* any embedded dots after the first are converted to _ */
1324 case '#': /* don't lose these, they're important */
1326 str
[-1] = c
; /* replace last character of part */
1331 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1333 dots
= 0; /* started a path component */
1342 strcpy (shortname
, name
);
1343 unixtodos_filename (shortname
);
1347 *pPath
= shortname
+ (path
- save_name
);
1353 is_exec (const char * name
)
1355 char * p
= strrchr (name
, '.');
1358 && (stricmp (p
, ".exe") == 0 ||
1359 stricmp (p
, ".com") == 0 ||
1360 stricmp (p
, ".bat") == 0 ||
1361 stricmp (p
, ".cmd") == 0));
1364 /* Emulate the Unix directory procedures opendir, closedir,
1365 and readdir. We can't use the procedures supplied in sysdep.c,
1366 so we provide them here. */
1368 struct direct dir_static
; /* simulated directory contents */
1369 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1370 static int dir_is_fat
;
1371 static char dir_pathname
[MAXPATHLEN
+1];
1372 static WIN32_FIND_DATA dir_find_data
;
1374 /* Support shares on a network resource as subdirectories of a read-only
1376 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1377 HANDLE
open_unc_volume (char *);
1378 char *read_unc_volume (HANDLE
, char *, int);
1379 void close_unc_volume (HANDLE
);
1382 opendir (char *filename
)
1386 /* Opening is done by FindFirstFile. However, a read is inherent to
1387 this operation, so we defer the open until read time. */
1389 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1391 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1394 if (is_unc_volume (filename
))
1396 wnet_enum_handle
= open_unc_volume (filename
);
1397 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1401 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1408 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1409 dir_pathname
[MAXPATHLEN
] = '\0';
1410 dir_is_fat
= is_fat_volume (filename
, NULL
);
1416 closedir (DIR *dirp
)
1418 /* If we have a find-handle open, close it. */
1419 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1421 FindClose (dir_find_handle
);
1422 dir_find_handle
= INVALID_HANDLE_VALUE
;
1424 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1426 close_unc_volume (wnet_enum_handle
);
1427 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1429 xfree ((char *) dirp
);
1435 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1437 if (!read_unc_volume (wnet_enum_handle
,
1438 dir_find_data
.cFileName
,
1442 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1443 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1445 char filename
[MAXNAMLEN
+ 3];
1448 strcpy (filename
, dir_pathname
);
1449 ln
= strlen (filename
) - 1;
1450 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1451 strcat (filename
, "\\");
1452 strcat (filename
, "*");
1454 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1456 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1461 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1465 /* Emacs never uses this value, so don't bother making it match
1466 value returned by stat(). */
1467 dir_static
.d_ino
= 1;
1469 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1470 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1472 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1473 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1475 _strlwr (dir_static
.d_name
);
1476 else if (!NILP (Vw32_downcase_file_names
))
1479 for (p
= dir_static
.d_name
; *p
; p
++)
1480 if (*p
>= 'a' && *p
<= 'z')
1483 _strlwr (dir_static
.d_name
);
1490 open_unc_volume (char *path
)
1496 nr
.dwScope
= RESOURCE_GLOBALNET
;
1497 nr
.dwType
= RESOURCETYPE_DISK
;
1498 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1499 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1500 nr
.lpLocalName
= NULL
;
1501 nr
.lpRemoteName
= map_w32_filename (path
, NULL
);
1502 nr
.lpComment
= NULL
;
1503 nr
.lpProvider
= NULL
;
1505 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1506 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1508 if (result
== NO_ERROR
)
1511 return INVALID_HANDLE_VALUE
;
1515 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1519 DWORD bufsize
= 512;
1524 buffer
= alloca (bufsize
);
1525 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1526 if (result
!= NO_ERROR
)
1529 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1530 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1532 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1535 strncpy (readbuf
, ptr
, size
);
1540 close_unc_volume (HANDLE henum
)
1542 if (henum
!= INVALID_HANDLE_VALUE
)
1543 WNetCloseEnum (henum
);
1547 unc_volume_file_attributes (char *path
)
1552 henum
= open_unc_volume (path
);
1553 if (henum
== INVALID_HANDLE_VALUE
)
1556 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1558 close_unc_volume (henum
);
1564 /* Shadow some MSVC runtime functions to map requests for long filenames
1565 to reasonable short names if necessary. This was originally added to
1566 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1570 sys_access (const char * path
, int mode
)
1574 /* MSVC implementation doesn't recognize D_OK. */
1575 path
= map_w32_filename (path
, NULL
);
1576 if (is_unc_volume (path
))
1578 attributes
= unc_volume_file_attributes (path
);
1579 if (attributes
== -1) {
1584 else if ((attributes
= GetFileAttributes (path
)) == -1)
1586 /* Should try mapping GetLastError to errno; for now just indicate
1587 that path doesn't exist. */
1591 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1596 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1601 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1610 sys_chdir (const char * path
)
1612 return _chdir (map_w32_filename (path
, NULL
));
1616 sys_chmod (const char * path
, int mode
)
1618 return _chmod (map_w32_filename (path
, NULL
), mode
);
1622 sys_creat (const char * path
, int mode
)
1624 return _creat (map_w32_filename (path
, NULL
), mode
);
1628 sys_fopen(const char * path
, const char * mode
)
1632 const char * mode_save
= mode
;
1634 /* Force all file handles to be non-inheritable. This is necessary to
1635 ensure child processes don't unwittingly inherit handles that might
1636 prevent future file access. */
1640 else if (mode
[0] == 'w' || mode
[0] == 'a')
1641 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1645 /* Only do simplistic option parsing. */
1649 oflag
&= ~(O_RDONLY
| O_WRONLY
);
1652 else if (mode
[0] == 'b')
1657 else if (mode
[0] == 't')
1664 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
1668 return _fdopen (fd
, mode_save
);
1671 /* This only works on NTFS volumes, but is useful to have. */
1673 sys_link (const char * old
, const char * new)
1677 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
1679 if (old
== NULL
|| new == NULL
)
1685 strcpy (oldname
, map_w32_filename (old
, NULL
));
1686 strcpy (newname
, map_w32_filename (new, NULL
));
1688 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
1689 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
1690 if (fileh
!= INVALID_HANDLE_VALUE
)
1694 /* Confusingly, the "alternate" stream name field does not apply
1695 when restoring a hard link, and instead contains the actual
1696 stream data for the link (ie. the name of the link to create).
1697 The WIN32_STREAM_ID structure before the cStreamName field is
1698 the stream header, which is then immediately followed by the
1702 WIN32_STREAM_ID wid
;
1703 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
1706 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
1707 data
.wid
.cStreamName
, MAX_PATH
);
1710 LPVOID context
= NULL
;
1713 data
.wid
.dwStreamId
= BACKUP_LINK
;
1714 data
.wid
.dwStreamAttributes
= 0;
1715 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
1716 data
.wid
.Size
.HighPart
= 0;
1717 data
.wid
.dwStreamNameSize
= 0;
1719 if (BackupWrite (fileh
, (LPBYTE
)&data
,
1720 offsetof (WIN32_STREAM_ID
, cStreamName
)
1721 + data
.wid
.Size
.LowPart
,
1722 &wbytes
, FALSE
, FALSE
, &context
)
1723 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
1730 /* Should try mapping GetLastError to errno; for now just
1731 indicate a general error (eg. links not supported). */
1732 errno
= EINVAL
; // perhaps EMLINK?
1736 CloseHandle (fileh
);
1745 sys_mkdir (const char * path
)
1747 return _mkdir (map_w32_filename (path
, NULL
));
1750 /* Because of long name mapping issues, we need to implement this
1751 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1752 a unique name, instead of setting the input template to an empty
1755 Standard algorithm seems to be use pid or tid with a letter on the
1756 front (in place of the 6 X's) and cycle through the letters to find a
1757 unique name. We extend that to allow any reasonable character as the
1758 first of the 6 X's. */
1760 sys_mktemp (char * template)
1764 unsigned uid
= GetCurrentThreadId ();
1765 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1767 if (template == NULL
)
1769 p
= template + strlen (template);
1771 /* replace up to the last 5 X's with uid in decimal */
1772 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
1774 p
[0] = '0' + uid
% 10;
1778 if (i
< 0 && p
[0] == 'X')
1783 int save_errno
= errno
;
1784 p
[0] = first_char
[i
];
1785 if (sys_access (template, 0) < 0)
1791 while (++i
< sizeof (first_char
));
1794 /* Template is badly formed or else we can't generate a unique name,
1795 so return empty string */
1801 sys_open (const char * path
, int oflag
, int mode
)
1803 /* Force all file handles to be non-inheritable. */
1804 return _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, mode
);
1808 sys_rename (const char * oldname
, const char * newname
)
1811 char temp
[MAX_PATH
];
1813 /* MoveFile on Windows 95 doesn't correctly change the short file name
1814 alias in a number of circumstances (it is not easy to predict when
1815 just by looking at oldname and newname, unfortunately). In these
1816 cases, renaming through a temporary name avoids the problem.
1818 A second problem on Windows 95 is that renaming through a temp name when
1819 newname is uppercase fails (the final long name ends up in
1820 lowercase, although the short alias might be uppercase) UNLESS the
1821 long temp name is not 8.3.
1823 So, on Windows 95 we always rename through a temp name, and we make sure
1824 the temp name has a long extension to ensure correct renaming. */
1826 strcpy (temp
, map_w32_filename (oldname
, NULL
));
1828 if (os_subtype
== OS_WIN95
)
1834 oldname
= map_w32_filename (oldname
, NULL
);
1835 if (o
= strrchr (oldname
, '\\'))
1838 o
= (char *) oldname
;
1840 if (p
= strrchr (temp
, '\\'))
1847 /* Force temp name to require a manufactured 8.3 alias - this
1848 seems to make the second rename work properly. */
1849 sprintf (p
, "_.%s.%u", o
, i
);
1851 result
= rename (oldname
, temp
);
1853 /* This loop must surely terminate! */
1854 while (result
< 0 && errno
== EEXIST
);
1859 /* Emulate Unix behaviour - newname is deleted if it already exists
1860 (at least if it is a file; don't do this for directories).
1862 Since we mustn't do this if we are just changing the case of the
1863 file name (we would end up deleting the file we are trying to
1864 rename!), we let rename detect if the destination file already
1865 exists - that way we avoid the possible pitfalls of trying to
1866 determine ourselves whether two names really refer to the same
1867 file, which is not always possible in the general case. (Consider
1868 all the permutations of shared or subst'd drives, etc.) */
1870 newname
= map_w32_filename (newname
, NULL
);
1871 result
= rename (temp
, newname
);
1875 && _chmod (newname
, 0666) == 0
1876 && _unlink (newname
) == 0)
1877 result
= rename (temp
, newname
);
1883 sys_rmdir (const char * path
)
1885 return _rmdir (map_w32_filename (path
, NULL
));
1889 sys_unlink (const char * path
)
1891 path
= map_w32_filename (path
, NULL
);
1893 /* On Unix, unlink works without write permission. */
1894 _chmod (path
, 0666);
1895 return _unlink (path
);
1898 static FILETIME utc_base_ft
;
1899 static long double utc_base
;
1900 static int init
= 0;
1903 convert_time (FILETIME ft
)
1909 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1918 st
.wMilliseconds
= 0;
1920 SystemTimeToFileTime (&st
, &utc_base_ft
);
1921 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1922 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1926 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
1929 ret
= (long double) ft
.dwHighDateTime
* 4096 * 1024 * 1024 + ft
.dwLowDateTime
;
1931 return (time_t) (ret
* 1e-7);
1935 convert_from_time_t (time_t time
, FILETIME
* pft
)
1941 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1950 st
.wMilliseconds
= 0;
1952 SystemTimeToFileTime (&st
, &utc_base_ft
);
1953 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1954 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1958 /* time in 100ns units since 1-Jan-1601 */
1959 tmp
= (long double) time
* 1e7
+ utc_base
;
1960 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
1961 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
1965 /* No reason to keep this; faking inode values either by hashing or even
1966 using the file index from GetInformationByHandle, is not perfect and
1967 so by default Emacs doesn't use the inode values on Windows.
1968 Instead, we now determine file-truename correctly (except for
1969 possible drive aliasing etc). */
1971 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
1973 hashval (const unsigned char * str
)
1978 h
= (h
<< 4) + *str
++;
1984 /* Return the hash value of the canonical pathname, excluding the
1985 drive/UNC header, to get a hopefully unique inode number. */
1987 generate_inode_val (const char * name
)
1989 char fullname
[ MAX_PATH
];
1993 /* Get the truly canonical filename, if it exists. (Note: this
1994 doesn't resolve aliasing due to subst commands, or recognise hard
1996 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
1999 parse_root (fullname
, &p
);
2000 /* Normal W32 filesystems are still case insensitive. */
2007 /* MSVC stat function can't cope with UNC names and has other bugs, so
2008 replace it with our own. This also allows us to calculate consistent
2009 inode values without hacks in the main Emacs code. */
2011 stat (const char * path
, struct stat
* buf
)
2014 WIN32_FIND_DATA wfd
;
2019 int rootdir
= FALSE
;
2021 if (path
== NULL
|| buf
== NULL
)
2027 name
= (char *) map_w32_filename (path
, &path
);
2028 /* must be valid filename, no wild cards or other invalid characters */
2029 if (strpbrk (name
, "*?|<>\""))
2035 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2036 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
2037 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
2042 /* Remove trailing directory separator, unless name is the root
2043 directory of a drive or UNC volume in which case ensure there
2044 is a trailing separator. */
2045 len
= strlen (name
);
2046 rootdir
= (path
>= name
+ len
- 1
2047 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
2048 name
= strcpy (alloca (len
+ 2), name
);
2050 if (is_unc_volume (name
))
2052 DWORD attrs
= unc_volume_file_attributes (name
);
2057 memset (&wfd
, 0, sizeof (wfd
));
2058 wfd
.dwFileAttributes
= attrs
;
2059 wfd
.ftCreationTime
= utc_base_ft
;
2060 wfd
.ftLastAccessTime
= utc_base_ft
;
2061 wfd
.ftLastWriteTime
= utc_base_ft
;
2062 strcpy (wfd
.cFileName
, name
);
2066 if (!IS_DIRECTORY_SEP (name
[len
-1]))
2067 strcat (name
, "\\");
2068 if (GetDriveType (name
) < 2)
2073 memset (&wfd
, 0, sizeof (wfd
));
2074 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
2075 wfd
.ftCreationTime
= utc_base_ft
;
2076 wfd
.ftLastAccessTime
= utc_base_ft
;
2077 wfd
.ftLastWriteTime
= utc_base_ft
;
2078 strcpy (wfd
.cFileName
, name
);
2082 if (IS_DIRECTORY_SEP (name
[len
-1]))
2085 /* (This is hacky, but helps when doing file completions on
2086 network drives.) Optimize by using information available from
2087 active readdir if possible. */
2088 len
= strlen (dir_pathname
);
2089 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
2091 if (dir_find_handle
!= INVALID_HANDLE_VALUE
2092 && strnicmp (name
, dir_pathname
, len
) == 0
2093 && IS_DIRECTORY_SEP (name
[len
])
2094 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
2096 /* This was the last entry returned by readdir. */
2097 wfd
= dir_find_data
;
2101 fh
= FindFirstFile (name
, &wfd
);
2102 if (fh
== INVALID_HANDLE_VALUE
)
2111 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2113 buf
->st_mode
= _S_IFDIR
;
2114 buf
->st_nlink
= 2; /* doesn't really matter */
2115 fake_inode
= 0; /* this doesn't either I think */
2117 else if (!NILP (Vw32_get_true_file_attributes
)
2118 /* No access rights required to get info. */
2119 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
))
2120 != INVALID_HANDLE_VALUE
)
2122 /* This is more accurate in terms of gettting the correct number
2123 of links, but is quite slow (it is noticable when Emacs is
2124 making a list of file name completions). */
2125 BY_HANDLE_FILE_INFORMATION info
;
2127 if (GetFileInformationByHandle (fh
, &info
))
2129 buf
->st_nlink
= info
.nNumberOfLinks
;
2130 /* Might as well use file index to fake inode values, but this
2131 is not guaranteed to be unique unless we keep a handle open
2132 all the time (even then there are situations where it is
2133 not unique). Reputedly, there are at most 48 bits of info
2134 (on NTFS, presumably less on FAT). */
2135 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2143 switch (GetFileType (fh
))
2145 case FILE_TYPE_DISK
:
2146 buf
->st_mode
= _S_IFREG
;
2148 case FILE_TYPE_PIPE
:
2149 buf
->st_mode
= _S_IFIFO
;
2151 case FILE_TYPE_CHAR
:
2152 case FILE_TYPE_UNKNOWN
:
2154 buf
->st_mode
= _S_IFCHR
;
2160 /* Don't bother to make this information more accurate. */
2161 buf
->st_mode
= _S_IFREG
;
2167 /* Not sure if there is any point in this. */
2168 if (!NILP (Vw32_generate_fake_inodes
))
2169 fake_inode
= generate_inode_val (name
);
2170 else if (fake_inode
== 0)
2172 /* For want of something better, try to make everything unique. */
2173 static DWORD gen_num
= 0;
2174 fake_inode
= ++gen_num
;
2178 /* MSVC defines _ino_t to be short; other libc's might not. */
2179 if (sizeof (buf
->st_ino
) == 2)
2180 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2182 buf
->st_ino
= fake_inode
;
2184 /* consider files to belong to current user */
2185 buf
->st_uid
= the_passwd
.pw_uid
;
2186 buf
->st_gid
= the_passwd
.pw_gid
;
2188 /* volume_info is set indirectly by map_w32_filename */
2189 buf
->st_dev
= volume_info
.serialnum
;
2190 buf
->st_rdev
= volume_info
.serialnum
;
2193 buf
->st_size
= wfd
.nFileSizeLow
;
2195 /* Convert timestamps to Unix format. */
2196 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2197 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2198 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2199 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2200 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2202 /* determine rwx permissions */
2203 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2204 permission
= _S_IREAD
;
2206 permission
= _S_IREAD
| _S_IWRITE
;
2208 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2209 permission
|= _S_IEXEC
;
2210 else if (is_exec (name
))
2211 permission
|= _S_IEXEC
;
2213 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2218 /* Provide fstat and utime as well as stat for consistent handling of
2221 fstat (int desc
, struct stat
* buf
)
2223 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2224 BY_HANDLE_FILE_INFORMATION info
;
2228 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2230 case FILE_TYPE_DISK
:
2231 buf
->st_mode
= _S_IFREG
;
2232 if (!GetFileInformationByHandle (fh
, &info
))
2238 case FILE_TYPE_PIPE
:
2239 buf
->st_mode
= _S_IFIFO
;
2241 case FILE_TYPE_CHAR
:
2242 case FILE_TYPE_UNKNOWN
:
2244 buf
->st_mode
= _S_IFCHR
;
2246 memset (&info
, 0, sizeof (info
));
2247 info
.dwFileAttributes
= 0;
2248 info
.ftCreationTime
= utc_base_ft
;
2249 info
.ftLastAccessTime
= utc_base_ft
;
2250 info
.ftLastWriteTime
= utc_base_ft
;
2253 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2255 buf
->st_mode
= _S_IFDIR
;
2256 buf
->st_nlink
= 2; /* doesn't really matter */
2257 fake_inode
= 0; /* this doesn't either I think */
2261 buf
->st_nlink
= info
.nNumberOfLinks
;
2262 /* Might as well use file index to fake inode values, but this
2263 is not guaranteed to be unique unless we keep a handle open
2264 all the time (even then there are situations where it is
2265 not unique). Reputedly, there are at most 48 bits of info
2266 (on NTFS, presumably less on FAT). */
2267 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2270 /* MSVC defines _ino_t to be short; other libc's might not. */
2271 if (sizeof (buf
->st_ino
) == 2)
2272 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2274 buf
->st_ino
= fake_inode
;
2276 /* consider files to belong to current user */
2280 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2281 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2283 buf
->st_size
= info
.nFileSizeLow
;
2285 /* Convert timestamps to Unix format. */
2286 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2287 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2288 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2289 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2290 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2292 /* determine rwx permissions */
2293 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2294 permission
= _S_IREAD
;
2296 permission
= _S_IREAD
| _S_IWRITE
;
2298 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2299 permission
|= _S_IEXEC
;
2302 #if 0 /* no way of knowing the filename */
2303 char * p
= strrchr (name
, '.');
2305 (stricmp (p
, ".exe") == 0 ||
2306 stricmp (p
, ".com") == 0 ||
2307 stricmp (p
, ".bat") == 0 ||
2308 stricmp (p
, ".cmd") == 0))
2309 permission
|= _S_IEXEC
;
2313 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2319 utime (const char *name
, struct utimbuf
*times
)
2321 struct utimbuf deftime
;
2328 deftime
.modtime
= deftime
.actime
= time (NULL
);
2332 /* Need write access to set times. */
2333 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2334 0, OPEN_EXISTING
, 0, NULL
);
2337 convert_from_time_t (times
->actime
, &atime
);
2338 convert_from_time_t (times
->modtime
, &mtime
);
2339 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2357 /* Wrappers for winsock functions to map between our file descriptors
2358 and winsock's handles; also set h_errno for convenience.
2360 To allow Emacs to run on systems which don't have winsock support
2361 installed, we dynamically link to winsock on startup if present, and
2362 otherwise provide the minimum necessary functionality
2363 (eg. gethostname). */
2365 /* function pointers for relevant socket functions */
2366 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2367 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2368 int (PASCAL
*pfn_WSAGetLastError
) (void);
2369 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2370 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2371 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2372 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2373 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2374 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2375 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2376 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2377 int (PASCAL
*pfn_WSACleanup
) (void);
2379 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2380 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2381 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2382 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2383 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2384 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2386 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2387 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2388 #ifndef HANDLE_FLAG_INHERIT
2389 #define HANDLE_FLAG_INHERIT 1
2393 static int winsock_inuse
;
2398 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2400 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2401 after WSAStartup returns successfully, but it seems reasonable
2402 to allow unloading winsock anyway in that case. */
2403 if (pfn_WSACleanup () == 0 ||
2404 pfn_WSAGetLastError () == WSAENETDOWN
)
2406 if (FreeLibrary (winsock_lib
))
2415 init_winsock (int load_now
)
2417 WSADATA winsockData
;
2419 if (winsock_lib
!= NULL
)
2422 pfn_SetHandleInformation
= NULL
;
2423 pfn_SetHandleInformation
2424 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2425 "SetHandleInformation");
2427 winsock_lib
= LoadLibrary ("wsock32.dll");
2429 if (winsock_lib
!= NULL
)
2431 /* dynamically link to socket functions */
2433 #define LOAD_PROC(fn) \
2434 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2437 LOAD_PROC( WSAStartup
);
2438 LOAD_PROC( WSASetLastError
);
2439 LOAD_PROC( WSAGetLastError
);
2440 LOAD_PROC( socket
);
2442 LOAD_PROC( connect
);
2443 LOAD_PROC( ioctlsocket
);
2446 LOAD_PROC( closesocket
);
2447 LOAD_PROC( shutdown
);
2450 LOAD_PROC( inet_addr
);
2451 LOAD_PROC( gethostname
);
2452 LOAD_PROC( gethostbyname
);
2453 LOAD_PROC( getservbyname
);
2454 LOAD_PROC( WSACleanup
);
2458 /* specify version 1.1 of winsock */
2459 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2461 if (winsockData
.wVersion
!= 0x101)
2466 /* Report that winsock exists and is usable, but leave
2467 socket functions disabled. I am assuming that calling
2468 WSAStartup does not require any network interaction,
2469 and in particular does not cause or require a dial-up
2470 connection to be established. */
2473 FreeLibrary (winsock_lib
);
2481 FreeLibrary (winsock_lib
);
2491 /* function to set h_errno for compatability; map winsock error codes to
2492 normal system codes where they overlap (non-overlapping definitions
2493 are already in <sys/socket.h> */
2494 static void set_errno ()
2496 if (winsock_lib
== NULL
)
2499 h_errno
= pfn_WSAGetLastError ();
2503 case WSAEACCES
: h_errno
= EACCES
; break;
2504 case WSAEBADF
: h_errno
= EBADF
; break;
2505 case WSAEFAULT
: h_errno
= EFAULT
; break;
2506 case WSAEINTR
: h_errno
= EINTR
; break;
2507 case WSAEINVAL
: h_errno
= EINVAL
; break;
2508 case WSAEMFILE
: h_errno
= EMFILE
; break;
2509 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2510 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2515 static void check_errno ()
2517 if (h_errno
== 0 && winsock_lib
!= NULL
)
2518 pfn_WSASetLastError (0);
2521 /* Extend strerror to handle the winsock-specific error codes. */
2525 } _wsa_errlist
[] = {
2526 WSAEINTR
, "Interrupted function call",
2527 WSAEBADF
, "Bad file descriptor",
2528 WSAEACCES
, "Permission denied",
2529 WSAEFAULT
, "Bad address",
2530 WSAEINVAL
, "Invalid argument",
2531 WSAEMFILE
, "Too many open files",
2533 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2534 WSAEINPROGRESS
, "Operation now in progress",
2535 WSAEALREADY
, "Operation already in progress",
2536 WSAENOTSOCK
, "Socket operation on non-socket",
2537 WSAEDESTADDRREQ
, "Destination address required",
2538 WSAEMSGSIZE
, "Message too long",
2539 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2540 WSAENOPROTOOPT
, "Bad protocol option",
2541 WSAEPROTONOSUPPORT
, "Protocol not supported",
2542 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2543 WSAEOPNOTSUPP
, "Operation not supported",
2544 WSAEPFNOSUPPORT
, "Protocol family not supported",
2545 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2546 WSAEADDRINUSE
, "Address already in use",
2547 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2548 WSAENETDOWN
, "Network is down",
2549 WSAENETUNREACH
, "Network is unreachable",
2550 WSAENETRESET
, "Network dropped connection on reset",
2551 WSAECONNABORTED
, "Software caused connection abort",
2552 WSAECONNRESET
, "Connection reset by peer",
2553 WSAENOBUFS
, "No buffer space available",
2554 WSAEISCONN
, "Socket is already connected",
2555 WSAENOTCONN
, "Socket is not connected",
2556 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2557 WSAETOOMANYREFS
, "Too many references", /* not sure */
2558 WSAETIMEDOUT
, "Connection timed out",
2559 WSAECONNREFUSED
, "Connection refused",
2560 WSAELOOP
, "Network loop", /* not sure */
2561 WSAENAMETOOLONG
, "Name is too long",
2562 WSAEHOSTDOWN
, "Host is down",
2563 WSAEHOSTUNREACH
, "No route to host",
2564 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2565 WSAEPROCLIM
, "Too many processes",
2566 WSAEUSERS
, "Too many users", /* not sure */
2567 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2568 WSAESTALE
, "Data is stale", /* not sure */
2569 WSAEREMOTE
, "Remote error", /* not sure */
2571 WSASYSNOTREADY
, "Network subsystem is unavailable",
2572 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2573 WSANOTINITIALISED
, "Winsock not initialized successfully",
2574 WSAEDISCON
, "Graceful shutdown in progress",
2576 WSAENOMORE
, "No more operations allowed", /* not sure */
2577 WSAECANCELLED
, "Operation cancelled", /* not sure */
2578 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2579 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2580 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2581 WSASYSCALLFAILURE
, "System call failured",
2582 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2583 WSATYPE_NOT_FOUND
, "Class type not found",
2584 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2585 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2586 WSAEREFUSED
, "Operation refused", /* not sure */
2589 WSAHOST_NOT_FOUND
, "Host not found",
2590 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2591 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2592 WSANO_DATA
, "Valid name, no data record of requested type",
2598 sys_strerror(int error_no
)
2601 static char unknown_msg
[40];
2603 if (error_no
>= 0 && error_no
< sys_nerr
)
2604 return sys_errlist
[error_no
];
2606 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2607 if (_wsa_errlist
[i
].errnum
== error_no
)
2608 return _wsa_errlist
[i
].msg
;
2610 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2614 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2615 but I believe the method of keeping the socket handle separate (and
2616 insuring it is not inheritable) is the correct one. */
2618 //#define SOCK_REPLACE_HANDLE
2620 #ifdef SOCK_REPLACE_HANDLE
2621 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2623 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2627 sys_socket(int af
, int type
, int protocol
)
2633 if (winsock_lib
== NULL
)
2636 return INVALID_SOCKET
;
2641 /* call the real socket function */
2642 s
= (long) pfn_socket (af
, type
, protocol
);
2644 if (s
!= INVALID_SOCKET
)
2646 /* Although under NT 3.5 _open_osfhandle will accept a socket
2647 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2648 that does not work under NT 3.1. However, we can get the same
2649 effect by using a backdoor function to replace an existing
2650 descriptor handle with the one we want. */
2652 /* allocate a file descriptor (with appropriate flags) */
2653 fd
= _open ("NUL:", _O_RDWR
);
2656 #ifdef SOCK_REPLACE_HANDLE
2657 /* now replace handle to NUL with our socket handle */
2658 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
2660 _set_osfhnd (fd
, s
);
2661 /* setmode (fd, _O_BINARY); */
2663 /* Make a non-inheritable copy of the socket handle. Note
2664 that it is possible that sockets aren't actually kernel
2665 handles, which appears to be the case on Windows 9x when
2666 the MS Proxy winsock client is installed. */
2668 /* Apparently there is a bug in NT 3.51 with some service
2669 packs, which prevents using DuplicateHandle to make a
2670 socket handle non-inheritable (causes WSACleanup to
2671 hang). The work-around is to use SetHandleInformation
2672 instead if it is available and implemented. */
2673 if (pfn_SetHandleInformation
)
2675 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
2679 HANDLE parent
= GetCurrentProcess ();
2680 HANDLE new_s
= INVALID_HANDLE_VALUE
;
2682 if (DuplicateHandle (parent
,
2688 DUPLICATE_SAME_ACCESS
))
2690 /* It is possible that DuplicateHandle succeeds even
2691 though the socket wasn't really a kernel handle,
2692 because a real handle has the same value. So
2693 test whether the new handle really is a socket. */
2694 long nonblocking
= 0;
2695 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
2697 pfn_closesocket (s
);
2702 CloseHandle (new_s
);
2707 fd_info
[fd
].hnd
= (HANDLE
) s
;
2710 /* set our own internal flags */
2711 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
2717 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
2719 /* attach child_process to fd_info */
2720 if (fd_info
[ fd
].cp
!= NULL
)
2722 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
2726 fd_info
[ fd
].cp
= cp
;
2729 winsock_inuse
++; /* count open sockets */
2736 pfn_closesocket (s
);
2746 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
2748 if (winsock_lib
== NULL
)
2751 return SOCKET_ERROR
;
2755 if (fd_info
[s
].flags
& FILE_SOCKET
)
2757 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
2758 if (rc
== SOCKET_ERROR
)
2763 return SOCKET_ERROR
;
2768 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
2770 if (winsock_lib
== NULL
)
2773 return SOCKET_ERROR
;
2777 if (fd_info
[s
].flags
& FILE_SOCKET
)
2779 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
2780 if (rc
== SOCKET_ERROR
)
2785 return SOCKET_ERROR
;
2789 sys_htons (u_short hostshort
)
2791 return (winsock_lib
!= NULL
) ?
2792 pfn_htons (hostshort
) : hostshort
;
2796 sys_ntohs (u_short netshort
)
2798 return (winsock_lib
!= NULL
) ?
2799 pfn_ntohs (netshort
) : netshort
;
2803 sys_inet_addr (const char * cp
)
2805 return (winsock_lib
!= NULL
) ?
2806 pfn_inet_addr (cp
) : INADDR_NONE
;
2810 sys_gethostname (char * name
, int namelen
)
2812 if (winsock_lib
!= NULL
)
2813 return pfn_gethostname (name
, namelen
);
2815 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
2816 return !GetComputerName (name
, (DWORD
*)&namelen
);
2819 return SOCKET_ERROR
;
2823 sys_gethostbyname(const char * name
)
2825 struct hostent
* host
;
2827 if (winsock_lib
== NULL
)
2834 host
= pfn_gethostbyname (name
);
2841 sys_getservbyname(const char * name
, const char * proto
)
2843 struct servent
* serv
;
2845 if (winsock_lib
== NULL
)
2852 serv
= pfn_getservbyname (name
, proto
);
2859 sys_shutdown (int s
, int how
)
2863 if (winsock_lib
== NULL
)
2866 return SOCKET_ERROR
;
2870 if (fd_info
[s
].flags
& FILE_SOCKET
)
2872 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
2873 if (rc
== SOCKET_ERROR
)
2878 return SOCKET_ERROR
;
2881 #endif /* HAVE_SOCKETS */
2884 /* Shadow main io functions: we need to handle pipes and sockets more
2885 intelligently, and implement non-blocking mode as well. */
2892 if (fd
< 0 || fd
>= MAXDESC
)
2900 child_process
* cp
= fd_info
[fd
].cp
;
2902 fd_info
[fd
].cp
= NULL
;
2904 if (CHILD_ACTIVE (cp
))
2906 /* if last descriptor to active child_process then cleanup */
2908 for (i
= 0; i
< MAXDESC
; i
++)
2912 if (fd_info
[i
].cp
== cp
)
2918 if (fd_info
[fd
].flags
& FILE_SOCKET
)
2920 #ifndef SOCK_REPLACE_HANDLE
2921 if (winsock_lib
== NULL
) abort ();
2923 pfn_shutdown (SOCK_HANDLE (fd
), 2);
2924 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
2926 winsock_inuse
--; /* count open sockets */
2934 /* Note that sockets do not need special treatment here (at least on
2935 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
2936 closesocket is equivalent to CloseHandle, which is to be expected
2937 because socket handles are fully fledged kernel handles. */
2941 fd_info
[fd
].flags
= 0;
2954 /* duplicate our internal info as well */
2955 fd_info
[new_fd
] = fd_info
[fd
];
2962 sys_dup2 (int src
, int dst
)
2966 if (dst
< 0 || dst
>= MAXDESC
)
2972 /* make sure we close the destination first if it's a pipe or socket */
2973 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
2976 rc
= _dup2 (src
, dst
);
2979 /* duplicate our internal info as well */
2980 fd_info
[dst
] = fd_info
[src
];
2985 /* Unix pipe() has only one arg */
2987 sys_pipe (int * phandles
)
2993 /* make pipe handles non-inheritable; when we spawn a child, we
2994 replace the relevant handle with an inheritable one. Also put
2995 pipes into binary mode; we will do text mode translation ourselves
2997 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
3001 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
3002 fd_info
[phandles
[0]].flags
= flags
;
3004 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
3005 fd_info
[phandles
[1]].flags
= flags
;
3012 extern Lisp_Object Vw32_pipe_read_delay
;
3014 /* Function to do blocking read of one byte, needed to implement
3015 select. It is only allowed on sockets and pipes. */
3017 _sys_read_ahead (int fd
)
3022 if (fd
< 0 || fd
>= MAXDESC
)
3023 return STATUS_READ_ERROR
;
3025 cp
= fd_info
[fd
].cp
;
3027 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3028 return STATUS_READ_ERROR
;
3030 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
3031 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
3033 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
3037 cp
->status
= STATUS_READ_IN_PROGRESS
;
3039 if (fd_info
[fd
].flags
& FILE_PIPE
)
3041 rc
= _read (fd
, &cp
->chr
, sizeof (char));
3043 /* Give subprocess time to buffer some more output for us before
3044 reporting that input is available; we need this because Windows 95
3045 connects DOS programs to pipes by making the pipe appear to be
3046 the normal console stdout - as a result most DOS programs will
3047 write to stdout without buffering, ie. one character at a
3048 time. Even some W32 programs do this - "dir" in a command
3049 shell on NT is very slow if we don't do this. */
3052 int wait
= XINT (Vw32_pipe_read_delay
);
3058 /* Yield remainder of our time slice, effectively giving a
3059 temporary priority boost to the child process. */
3064 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
3065 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
3068 if (rc
== sizeof (char))
3069 cp
->status
= STATUS_READ_SUCCEEDED
;
3071 cp
->status
= STATUS_READ_FAILED
;
3077 sys_read (int fd
, char * buffer
, unsigned int count
)
3082 char * orig_buffer
= buffer
;
3084 if (fd
< 0 || fd
>= MAXDESC
)
3090 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3092 child_process
*cp
= fd_info
[fd
].cp
;
3094 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
3102 /* re-read CR carried over from last read */
3103 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
3105 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
3109 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
3112 /* presence of a child_process structure means we are operating in
3113 non-blocking mode - otherwise we just call _read directly.
3114 Note that the child_process structure might be missing because
3115 reap_subprocess has been called; in this case the pipe is
3116 already broken, so calling _read on it is okay. */
3119 int current_status
= cp
->status
;
3121 switch (current_status
)
3123 case STATUS_READ_FAILED
:
3124 case STATUS_READ_ERROR
:
3125 /* report normal EOF if nothing in buffer */
3127 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3130 case STATUS_READ_READY
:
3131 case STATUS_READ_IN_PROGRESS
:
3132 DebPrint (("sys_read called when read is in progress\n"));
3133 errno
= EWOULDBLOCK
;
3136 case STATUS_READ_SUCCEEDED
:
3137 /* consume read-ahead char */
3138 *buffer
++ = cp
->chr
;
3141 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3142 ResetEvent (cp
->char_avail
);
3144 case STATUS_READ_ACKNOWLEDGED
:
3148 DebPrint (("sys_read: bad status %d\n", current_status
));
3153 if (fd_info
[fd
].flags
& FILE_PIPE
)
3155 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3156 to_read
= min (waiting
, (DWORD
) count
);
3159 nchars
+= _read (fd
, buffer
, to_read
);
3162 else /* FILE_SOCKET */
3164 if (winsock_lib
== NULL
) abort ();
3166 /* do the equivalent of a non-blocking read */
3167 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3168 if (waiting
== 0 && nchars
== 0)
3170 h_errno
= errno
= EWOULDBLOCK
;
3176 /* always use binary mode for sockets */
3177 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3178 if (res
== SOCKET_ERROR
)
3180 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3181 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3192 int nread
= _read (fd
, buffer
, count
);
3195 else if (nchars
== 0)
3200 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3201 /* Perform text mode translation if required. */
3202 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3204 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3205 /* If buffer contains only CR, return that. To be absolutely
3206 sure we should attempt to read the next char, but in
3207 practice a CR to be followed by LF would not appear by
3208 itself in the buffer. */
3209 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3211 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3217 nchars
= _read (fd
, buffer
, count
);
3222 /* For now, don't bother with a non-blocking mode */
3224 sys_write (int fd
, const void * buffer
, unsigned int count
)
3228 if (fd
< 0 || fd
>= MAXDESC
)
3234 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3236 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3242 /* Perform text mode translation if required. */
3243 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3245 char * tmpbuf
= alloca (count
* 2);
3246 unsigned char * src
= (void *)buffer
;
3247 unsigned char * dst
= tmpbuf
;
3252 unsigned char *next
;
3253 /* copy next line or remaining bytes */
3254 next
= _memccpy (dst
, src
, '\n', nbytes
);
3257 /* copied one line ending with '\n' */
3258 int copied
= next
- dst
;
3261 /* insert '\r' before '\n' */
3268 /* copied remaining partial line -> now finished */
3276 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3278 if (winsock_lib
== NULL
) abort ();
3279 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3280 if (nchars
== SOCKET_ERROR
)
3282 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
3283 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3289 nchars
= _write (fd
, buffer
, count
);
3295 check_windows_init_file ()
3297 extern int noninteractive
, inhibit_window_system
;
3299 /* A common indication that Emacs is not installed properly is when
3300 it cannot find the Windows installation file. If this file does
3301 not exist in the expected place, tell the user. */
3303 if (!noninteractive
&& !inhibit_window_system
)
3305 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3306 Lisp_Object objs
[2];
3307 Lisp_Object full_load_path
;
3308 Lisp_Object init_file
;
3311 objs
[0] = Vload_path
;
3312 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3313 full_load_path
= Fappend (2, objs
);
3314 init_file
= build_string ("term/w32-win");
3315 fd
= openp (full_load_path
, init_file
, ".el:.elc", NULL
, 0);
3318 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3319 char *init_file_name
= XSTRING (init_file
)->data
;
3320 char *load_path
= XSTRING (load_path_print
)->data
;
3321 char *buffer
= alloca (1024);
3324 "The Emacs Windows initialization file \"%s.el\" "
3325 "could not be found in your Emacs installation. "
3326 "Emacs checked the following directories for this file:\n"
3328 "When Emacs cannot find this file, it usually means that it "
3329 "was not installed properly, or its distribution file was "
3330 "not unpacked properly.\nSee the README.W32 file in the "
3331 "top-level Emacs directory for more information.",
3332 init_file_name
, load_path
);
3335 "Emacs Abort Dialog",
3336 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3337 /* Use the low-level Emacs abort. */
3352 /* shutdown the socket interface if necessary */
3361 /* Initialise the socket interface now if available and requested by
3362 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3363 delayed until open-network-stream is called (w32-has-winsock can
3364 also be used to dynamically load or reload winsock).
3366 Conveniently, init_environment is called before us, so
3367 PRELOAD_WINSOCK can be set in the registry. */
3369 /* Always initialize this correctly. */
3372 if (getenv ("PRELOAD_WINSOCK") != NULL
)
3373 init_winsock (TRUE
);
3376 /* Initial preparation for subprocess support: replace our standard
3377 handles with non-inheritable versions. */
3380 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
3381 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
3382 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
3384 parent
= GetCurrentProcess ();
3386 /* ignore errors when duplicating and closing; typically the
3387 handles will be invalid when running as a gui program. */
3388 DuplicateHandle (parent
,
3389 GetStdHandle (STD_INPUT_HANDLE
),
3394 DUPLICATE_SAME_ACCESS
);
3396 DuplicateHandle (parent
,
3397 GetStdHandle (STD_OUTPUT_HANDLE
),
3402 DUPLICATE_SAME_ACCESS
);
3404 DuplicateHandle (parent
,
3405 GetStdHandle (STD_ERROR_HANDLE
),
3410 DUPLICATE_SAME_ACCESS
);
3416 if (stdin_save
!= INVALID_HANDLE_VALUE
)
3417 _open_osfhandle ((long) stdin_save
, O_TEXT
);
3419 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
3422 if (stdout_save
!= INVALID_HANDLE_VALUE
)
3423 _open_osfhandle ((long) stdout_save
, O_TEXT
);
3425 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3428 if (stderr_save
!= INVALID_HANDLE_VALUE
)
3429 _open_osfhandle ((long) stderr_save
, O_TEXT
);
3431 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3435 /* unfortunately, atexit depends on implementation of malloc */
3436 /* atexit (term_ntproc); */
3437 signal (SIGABRT
, term_ntproc
);
3439 /* determine which drives are fixed, for GetCachedVolumeInformation */
3441 /* GetDriveType must have trailing backslash. */
3442 char drive
[] = "A:\\";
3444 /* Loop over all possible drive letters */
3445 while (*drive
<= 'Z')
3447 /* Record if this drive letter refers to a fixed drive. */
3448 fixed_drives
[DRIVE_INDEX (*drive
)] =
3449 (GetDriveType (drive
) == DRIVE_FIXED
);
3454 /* Reset the volume info cache. */
3455 volume_cache
= NULL
;
3458 /* Check to see if Emacs has been installed correctly. */
3459 check_windows_init_file ();