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 */
68 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
69 #include <sys/socket.h>
88 #define min(x, y) (((x) < (y)) ? (x) : (y))
89 #define max(x, y) (((x) > (y)) ? (x) : (y))
91 extern Lisp_Object Vw32_downcase_file_names
;
92 extern Lisp_Object Vw32_generate_fake_inodes
;
93 extern Lisp_Object Vw32_get_true_file_attributes
;
94 extern Lisp_Object Vw32_num_mouse_buttons
;
96 static char startup_dir
[MAXPATHLEN
];
98 /* Get the current working directory. */
103 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
107 /* Emacs doesn't actually change directory itself, and we want to
108 force our real wd to be where emacs.exe is to avoid unnecessary
109 conflicts when trying to rename or delete directories. */
110 strcpy (dir
, startup_dir
);
116 /* Emulate gethostname. */
118 gethostname (char *buffer
, int size
)
120 /* NT only allows small host names, so the buffer is
121 certainly large enough. */
122 return !GetComputerName (buffer
, &size
);
124 #endif /* HAVE_SOCKETS */
126 /* Emulate getloadavg. */
128 getloadavg (double loadavg
[], int nelem
)
132 /* A faithful emulation is going to have to be saved for a rainy day. */
133 for (i
= 0; i
< nelem
; i
++)
140 /* Emulate getpwuid, getpwnam and others. */
142 #define PASSWD_FIELD_SIZE 256
144 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
145 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
146 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
147 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
148 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
150 static struct passwd the_passwd
=
165 return the_passwd
.pw_uid
;
171 /* I could imagine arguing for checking to see whether the user is
172 in the Administrators group and returning a UID of 0 for that
173 case, but I don't know how wise that would be in the long run. */
180 return the_passwd
.pw_gid
;
192 if (uid
== the_passwd
.pw_uid
)
198 getpwnam (char *name
)
202 pw
= getpwuid (getuid ());
206 if (stricmp (name
, pw
->pw_name
))
215 /* Find the user's real name by opening the process token and
216 looking up the name associated with the user-sid in that token.
218 Use the relative portion of the identifier authority value from
219 the user-sid as the user id value (same for group id using the
220 primary group sid from the process token). */
222 char user_sid
[256], name
[256], domain
[256];
223 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
225 SID_NAME_USE user_type
;
227 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
)
228 && GetTokenInformation (token
, TokenUser
,
229 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
230 && LookupAccountSid (NULL
, *((PSID
*) user_sid
), name
, &length
,
231 domain
, &dlength
, &user_type
))
233 strcpy (the_passwd
.pw_name
, name
);
234 /* Determine a reasonable uid value. */
235 if (stricmp ("administrator", name
) == 0)
237 the_passwd
.pw_uid
= 0;
238 the_passwd
.pw_gid
= 0;
242 SID_IDENTIFIER_AUTHORITY
* pSIA
;
244 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
245 /* I believe the relative portion is the last 4 bytes (of 6)
247 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
248 (pSIA
->Value
[3] << 16) +
249 (pSIA
->Value
[4] << 8) +
250 (pSIA
->Value
[5] << 0));
251 /* restrict to conventional uid range for normal users */
252 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
255 if (GetTokenInformation (token
, TokenPrimaryGroup
,
256 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
258 SID_IDENTIFIER_AUTHORITY
* pSIA
;
260 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
261 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
262 (pSIA
->Value
[3] << 16) +
263 (pSIA
->Value
[4] << 8) +
264 (pSIA
->Value
[5] << 0));
265 /* I don't know if this is necessary, but for safety... */
266 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
269 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
272 /* If security calls are not supported (presumably because we
273 are running under Windows 95), fallback to this. */
274 else if (GetUserName (name
, &length
))
276 strcpy (the_passwd
.pw_name
, name
);
277 if (stricmp ("administrator", name
) == 0)
278 the_passwd
.pw_uid
= 0;
280 the_passwd
.pw_uid
= 123;
281 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
285 strcpy (the_passwd
.pw_name
, "unknown");
286 the_passwd
.pw_uid
= 123;
287 the_passwd
.pw_gid
= 123;
290 /* Ensure HOME and SHELL are defined. */
291 if (getenv ("HOME") == NULL
)
293 if (getenv ("SHELL") == NULL
)
294 putenv (os_subtype
== OS_WIN95
? "SHELL=command" : "SHELL=cmd");
296 /* Set dir and shell from environment variables. */
297 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
298 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
307 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
308 return ((rand () << 15) | rand ());
318 /* Normalize filename by converting all path separators to
319 the specified separator. Also conditionally convert upper
320 case path name components to lower case. */
323 normalize_filename (fp
, path_sep
)
330 /* Always lower-case drive letters a-z, even if the filesystem
331 preserves case in filenames.
332 This is so filenames can be compared by string comparison
333 functions that are case-sensitive. Even case-preserving filesystems
334 do not distinguish case in drive letters. */
335 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
341 if (NILP (Vw32_downcase_file_names
))
345 if (*fp
== '/' || *fp
== '\\')
352 sep
= path_sep
; /* convert to this path separator */
353 elem
= fp
; /* start of current path element */
356 if (*fp
>= 'a' && *fp
<= 'z')
357 elem
= 0; /* don't convert this element */
359 if (*fp
== 0 || *fp
== ':')
361 sep
= *fp
; /* restore current separator (or 0) */
362 *fp
= '/'; /* after conversion of this element */
365 if (*fp
== '/' || *fp
== '\\')
367 if (elem
&& elem
!= fp
)
369 *fp
= 0; /* temporary end of string */
370 _strlwr (elem
); /* while we convert to lower case */
372 *fp
= sep
; /* convert (or restore) path separator */
373 elem
= fp
+ 1; /* next element starts after separator */
379 /* Destructively turn backslashes into slashes. */
381 dostounix_filename (p
)
384 normalize_filename (p
, '/');
387 /* Destructively turn slashes into backslashes. */
389 unixtodos_filename (p
)
392 normalize_filename (p
, '\\');
395 /* Remove all CR's that are followed by a LF.
396 (From msdos.c...probably should figure out a way to share it,
397 although this code isn't going to ever change.) */
401 register unsigned char *buf
;
403 unsigned char *np
= buf
;
404 unsigned char *startp
= buf
;
405 unsigned char *endp
= buf
+ n
;
409 while (buf
< endp
- 1)
413 if (*(++buf
) != 0x0a)
424 /* Parse the root part of file name, if present. Return length and
425 optionally store pointer to char after root. */
427 parse_root (char * name
, char ** pPath
)
434 /* find the root name of the volume if given */
435 if (isalpha (name
[0]) && name
[1] == ':')
437 /* skip past drive specifier */
439 if (IS_DIRECTORY_SEP (name
[0]))
442 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
448 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
453 if (IS_DIRECTORY_SEP (name
[0]))
463 /* Get long base name for name; name is assumed to be absolute. */
465 get_long_basename (char * name
, char * buf
, int size
)
467 WIN32_FIND_DATA find_data
;
471 /* must be valid filename, no wild cards or other invalid characters */
472 if (strpbrk (name
, "*?|<>\""))
475 dir_handle
= FindFirstFile (name
, &find_data
);
476 if (dir_handle
!= INVALID_HANDLE_VALUE
)
478 if ((len
= strlen (find_data
.cFileName
)) < size
)
479 memcpy (buf
, find_data
.cFileName
, len
+ 1);
482 FindClose (dir_handle
);
487 /* Get long name for file, if possible (assumed to be absolute). */
489 w32_get_long_filename (char * name
, char * buf
, int size
)
494 char full
[ MAX_PATH
];
501 /* Use local copy for destructive modification. */
502 memcpy (full
, name
, len
+1);
503 unixtodos_filename (full
);
505 /* Copy root part verbatim. */
506 len
= parse_root (full
, &p
);
507 memcpy (o
, full
, len
);
512 while (p
!= NULL
&& *p
)
515 p
= strchr (q
, '\\');
517 len
= get_long_basename (full
, o
, size
);
540 is_unc_volume (const char *filename
)
542 const char *ptr
= filename
;
544 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
547 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
553 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
556 sigsetmask (int signal_mask
)
580 setpgrp (int pid
, int gid
)
592 unrequest_sigio (void)
603 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
606 w32_get_resource (key
, lpdwtype
)
611 HKEY hrootkey
= NULL
;
615 /* Check both the current user and the local machine to see if
616 we have any resources. */
618 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
622 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
623 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
624 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
629 if (lpvalue
) xfree (lpvalue
);
631 RegCloseKey (hrootkey
);
634 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
638 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
639 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
640 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
645 if (lpvalue
) xfree (lpvalue
);
647 RegCloseKey (hrootkey
);
653 char *get_emacs_configuration (void);
654 extern Lisp_Object Vsystem_configuration
;
657 init_environment (char ** argv
)
660 static const char * const tempdirs
[] = {
661 "$TMPDIR", "$TEMP", "$TMP", "c:/"
664 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
666 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
667 temporary files and assume "/tmp" if $TMPDIR is unset, which
668 will break on DOS/Windows. Refuse to work if we cannot find
669 a directory, not even "c:/", usable for that purpose. */
670 for (i
= 0; i
< imax
; i
++)
672 const char *tmp
= tempdirs
[i
];
675 tmp
= getenv (tmp
+ 1);
676 /* Note that `access' can lie to us if the directory resides on a
677 read-only filesystem, like CD-ROM or a write-protected floppy.
678 The only way to be really sure is to actually create a file and
679 see if it succeeds. But I think that's too much to ask. */
680 if (tmp
&& access (tmp
, D_OK
) == 0)
682 char * var
= alloca (strlen (tmp
) + 8);
683 sprintf (var
, "TMPDIR=%s", tmp
);
691 Fcons (build_string ("no usable temporary directories found!!"),
693 "While setting TMPDIR: ");
695 /* Check for environment variables and use registry if they don't exist */
701 static char * env_vars
[] =
712 /* We no longer set INFOPATH because Info-default-directory-list
713 is then ignored. We use a hook in winnt.el instead. */
719 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
721 if (!getenv (env_vars
[i
])
722 && (lpval
= w32_get_resource (env_vars
[i
], &dwType
)) != NULL
)
724 if (dwType
== REG_EXPAND_SZ
)
726 char buf1
[500], buf2
[500];
728 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, 500);
729 _snprintf (buf2
, 499, "%s=%s", env_vars
[i
], buf1
);
730 putenv (strdup (buf2
));
732 else if (dwType
== REG_SZ
)
736 _snprintf (buf
, 499, "%s=%s", env_vars
[i
], lpval
);
737 putenv (strdup (buf
));
745 /* Rebuild system configuration to reflect invoking system. */
746 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
748 /* Another special case: on NT, the PATH variable is actually named
749 "Path" although cmd.exe (perhaps NT itself) arranges for
750 environment variable lookup and setting to be case insensitive.
751 However, Emacs assumes a fully case sensitive environment, so we
752 need to change "Path" to "PATH" to match the expectations of
753 various elisp packages. We do this by the sneaky method of
754 modifying the string in the C runtime environ entry.
756 The same applies to COMSPEC. */
760 for (envp
= environ
; *envp
; envp
++)
761 if (_strnicmp (*envp
, "PATH=", 5) == 0)
762 memcpy (*envp
, "PATH=", 5);
763 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
764 memcpy (*envp
, "COMSPEC=", 8);
767 /* Remember the initial working directory for getwd, then make the
768 real wd be the location of emacs.exe to avoid conflicts when
769 renaming or deleting directories. (We also don't call chdir when
770 running subprocesses for the same reason.) */
771 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
776 static char modname
[MAX_PATH
];
778 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
780 if ((p
= strrchr (modname
, '\\')) == NULL
)
784 SetCurrentDirectory (modname
);
786 /* Ensure argv[0] has the full path to Emacs. */
791 /* Determine if there is a middle mouse button, to allow parse_button
792 to decide whether right mouse events should be mouse-2 or
794 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
799 /* We don't have scripts to automatically determine the system configuration
800 for Emacs before it's compiled, and we don't want to have to make the
801 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
804 static char configuration_buffer
[32];
807 get_emacs_configuration (void)
809 char *arch
, *oem
, *os
;
812 /* Determine the processor type. */
813 switch (get_processor_type ())
816 #ifdef PROCESSOR_INTEL_386
817 case PROCESSOR_INTEL_386
:
818 case PROCESSOR_INTEL_486
:
819 case PROCESSOR_INTEL_PENTIUM
:
824 #ifdef PROCESSOR_INTEL_860
825 case PROCESSOR_INTEL_860
:
830 #ifdef PROCESSOR_MIPS_R2000
831 case PROCESSOR_MIPS_R2000
:
832 case PROCESSOR_MIPS_R3000
:
833 case PROCESSOR_MIPS_R4000
:
838 #ifdef PROCESSOR_ALPHA_21064
839 case PROCESSOR_ALPHA_21064
:
849 /* Let oem be "*" until we figure out how to decode the OEM field. */
852 switch (osinfo_cache
.dwPlatformId
) {
853 case VER_PLATFORM_WIN32_NT
:
855 build_num
= osinfo_cache
.dwBuildNumber
;
857 case VER_PLATFORM_WIN32_WINDOWS
:
858 if (osinfo_cache
.dwMinorVersion
== 0) {
863 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
865 case VER_PLATFORM_WIN32s
:
866 /* Not supported, should not happen. */
868 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
876 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
877 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
878 get_w32_major_version (), get_w32_minor_version (), build_num
);
880 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
883 return configuration_buffer
;
886 #include <sys/timeb.h>
888 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
890 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
895 tv
->tv_sec
= tb
.time
;
896 tv
->tv_usec
= tb
.millitm
* 1000L;
899 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
900 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
904 /* ------------------------------------------------------------------------- */
905 /* IO support and wrapper functions for W32 API. */
906 /* ------------------------------------------------------------------------- */
908 /* Place a wrapper around the MSVC version of ctime. It returns NULL
909 on network directories, so we handle that case here.
910 (Ulrich Leodolter, 1/11/95). */
912 sys_ctime (const time_t *t
)
914 char *str
= (char *) ctime (t
);
915 return (str
? str
: "Sun Jan 01 00:00:00 1970");
918 /* Emulate sleep...we could have done this with a define, but that
919 would necessitate including windows.h in the files that used it.
920 This is much easier. */
922 sys_sleep (int seconds
)
924 Sleep (seconds
* 1000);
927 /* Internal MSVC functions for low-level descriptor munging */
928 extern int __cdecl
_set_osfhnd (int fd
, long h
);
929 extern int __cdecl
_free_osfhnd (int fd
);
931 /* parallel array of private info on file handles */
932 filedesc fd_info
[ MAXDESC
];
934 typedef struct volume_info_data
{
935 struct volume_info_data
* next
;
937 /* time when info was obtained */
940 /* actual volume info */
949 /* Global referenced by various functions. */
950 static volume_info_data volume_info
;
952 /* Vector to indicate which drives are local and fixed (for which cached
953 data never expires). */
954 static BOOL fixed_drives
[26];
956 /* Consider cached volume information to be stale if older than 10s,
957 at least for non-local drives. Info for fixed drives is never stale. */
958 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
959 #define VOLINFO_STILL_VALID( root_dir, info ) \
960 ( ( isalpha (root_dir[0]) && \
961 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
962 || GetTickCount () - info->timestamp < 10000 )
964 /* Cache support functions. */
966 /* Simple linked list with linear search is sufficient. */
967 static volume_info_data
*volume_cache
= NULL
;
969 static volume_info_data
*
970 lookup_volume_info (char * root_dir
)
972 volume_info_data
* info
;
974 for (info
= volume_cache
; info
; info
= info
->next
)
975 if (stricmp (info
->root_dir
, root_dir
) == 0)
981 add_volume_info (char * root_dir
, volume_info_data
* info
)
983 info
->root_dir
= strdup (root_dir
);
984 info
->next
= volume_cache
;
989 /* Wrapper for GetVolumeInformation, which uses caching to avoid
990 performance penalty (~2ms on 486 for local drives, 7.5ms for local
991 cdrom drive, ~5-10ms or more for remote drives on LAN). */
993 GetCachedVolumeInformation (char * root_dir
)
995 volume_info_data
* info
;
996 char default_root
[ MAX_PATH
];
998 /* NULL for root_dir means use root from current directory. */
999 if (root_dir
== NULL
)
1001 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1003 parse_root (default_root
, &root_dir
);
1005 root_dir
= default_root
;
1008 /* Local fixed drives can be cached permanently. Removable drives
1009 cannot be cached permanently, since the volume name and serial
1010 number (if nothing else) can change. Remote drives should be
1011 treated as if they are removable, since there is no sure way to
1012 tell whether they are or not. Also, the UNC association of drive
1013 letters mapped to remote volumes can be changed at any time (even
1014 by other processes) without notice.
1016 As a compromise, so we can benefit from caching info for remote
1017 volumes, we use a simple expiry mechanism to invalidate cache
1018 entries that are more than ten seconds old. */
1021 /* No point doing this, because WNetGetConnection is even slower than
1022 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1023 GetDriveType is about the only call of this type which does not
1024 involve network access, and so is extremely quick). */
1026 /* Map drive letter to UNC if remote. */
1027 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1029 char remote_name
[ 256 ];
1030 char drive
[3] = { root_dir
[0], ':' };
1032 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1034 /* do something */ ;
1038 info
= lookup_volume_info (root_dir
);
1040 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1048 /* Info is not cached, or is stale. */
1049 if (!GetVolumeInformation (root_dir
,
1050 name
, sizeof (name
),
1054 type
, sizeof (type
)))
1057 /* Cache the volume information for future use, overwriting existing
1058 entry if present. */
1061 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1062 add_volume_info (root_dir
, info
);
1070 info
->name
= strdup (name
);
1071 info
->serialnum
= serialnum
;
1072 info
->maxcomp
= maxcomp
;
1073 info
->flags
= flags
;
1074 info
->type
= strdup (type
);
1075 info
->timestamp
= GetTickCount ();
1081 /* Get information on the volume where name is held; set path pointer to
1082 start of pathname in name (past UNC header\volume header if present). */
1084 get_volume_info (const char * name
, const char ** pPath
)
1086 char temp
[MAX_PATH
];
1087 char *rootname
= NULL
; /* default to current volume */
1088 volume_info_data
* info
;
1093 /* find the root name of the volume if given */
1094 if (isalpha (name
[0]) && name
[1] == ':')
1102 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1109 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1122 info
= GetCachedVolumeInformation (rootname
);
1125 /* Set global referenced by other functions. */
1126 volume_info
= *info
;
1132 /* Determine if volume is FAT format (ie. only supports short 8.3
1133 names); also set path pointer to start of pathname in name. */
1135 is_fat_volume (const char * name
, const char ** pPath
)
1137 if (get_volume_info (name
, pPath
))
1138 return (volume_info
.maxcomp
== 12);
1142 /* Map filename to a legal 8.3 name if necessary. */
1144 map_w32_filename (const char * name
, const char ** pPath
)
1146 static char shortname
[MAX_PATH
];
1147 char * str
= shortname
;
1150 const char * save_name
= name
;
1152 if (is_fat_volume (name
, &path
)) /* truncate to 8.3 */
1154 register int left
= 8; /* maximum number of chars in part */
1155 register int extn
= 0; /* extension added? */
1156 register int dots
= 2; /* maximum number of dots allowed */
1159 *str
++ = *name
++; /* skip past UNC header */
1161 while ((c
= *name
++))
1168 extn
= 0; /* reset extension flags */
1169 dots
= 2; /* max 2 dots */
1170 left
= 8; /* max length 8 for main part */
1174 extn
= 0; /* reset extension flags */
1175 dots
= 2; /* max 2 dots */
1176 left
= 8; /* max length 8 for main part */
1181 /* Convert path components of the form .xxx to _xxx,
1182 but leave . and .. as they are. This allows .emacs
1183 to be read as _emacs, for example. */
1187 IS_DIRECTORY_SEP (*name
))
1202 extn
= 1; /* we've got an extension */
1203 left
= 3; /* 3 chars in extension */
1207 /* any embedded dots after the first are converted to _ */
1212 case '#': /* don't lose these, they're important */
1214 str
[-1] = c
; /* replace last character of part */
1219 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1221 dots
= 0; /* started a path component */
1230 strcpy (shortname
, name
);
1231 unixtodos_filename (shortname
);
1235 *pPath
= shortname
+ (path
- save_name
);
1241 is_exec (const char * name
)
1243 char * p
= strrchr (name
, '.');
1246 && (stricmp (p
, ".exe") == 0 ||
1247 stricmp (p
, ".com") == 0 ||
1248 stricmp (p
, ".bat") == 0 ||
1249 stricmp (p
, ".cmd") == 0));
1252 /* Emulate the Unix directory procedures opendir, closedir,
1253 and readdir. We can't use the procedures supplied in sysdep.c,
1254 so we provide them here. */
1256 struct direct dir_static
; /* simulated directory contents */
1257 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1258 static int dir_is_fat
;
1259 static char dir_pathname
[MAXPATHLEN
+1];
1260 static WIN32_FIND_DATA dir_find_data
;
1262 /* Support shares on a network resource as subdirectories of a read-only
1264 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1265 HANDLE
open_unc_volume (char *);
1266 char *read_unc_volume (HANDLE
, char *, int);
1267 void close_unc_volume (HANDLE
);
1270 opendir (char *filename
)
1274 /* Opening is done by FindFirstFile. However, a read is inherent to
1275 this operation, so we defer the open until read time. */
1277 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1279 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1282 if (is_unc_volume (filename
))
1284 wnet_enum_handle
= open_unc_volume (filename
);
1285 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1289 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1296 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1297 dir_pathname
[MAXPATHLEN
] = '\0';
1298 dir_is_fat
= is_fat_volume (filename
, NULL
);
1304 closedir (DIR *dirp
)
1306 /* If we have a find-handle open, close it. */
1307 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1309 FindClose (dir_find_handle
);
1310 dir_find_handle
= INVALID_HANDLE_VALUE
;
1312 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1314 close_unc_volume (wnet_enum_handle
);
1315 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1317 xfree ((char *) dirp
);
1323 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1325 if (!read_unc_volume (wnet_enum_handle
,
1326 dir_find_data
.cFileName
,
1330 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1331 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1333 char filename
[MAXNAMLEN
+ 3];
1336 strcpy (filename
, dir_pathname
);
1337 ln
= strlen (filename
) - 1;
1338 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1339 strcat (filename
, "\\");
1340 strcat (filename
, "*");
1342 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1344 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1349 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1353 /* Emacs never uses this value, so don't bother making it match
1354 value returned by stat(). */
1355 dir_static
.d_ino
= 1;
1357 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1358 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1360 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1361 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1363 _strlwr (dir_static
.d_name
);
1364 else if (!NILP (Vw32_downcase_file_names
))
1367 for (p
= dir_static
.d_name
; *p
; p
++)
1368 if (*p
>= 'a' && *p
<= 'z')
1371 _strlwr (dir_static
.d_name
);
1378 open_unc_volume (char *path
)
1384 nr
.dwScope
= RESOURCE_GLOBALNET
;
1385 nr
.dwType
= RESOURCETYPE_DISK
;
1386 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1387 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1388 nr
.lpLocalName
= NULL
;
1389 nr
.lpRemoteName
= map_w32_filename (path
, NULL
);
1390 nr
.lpComment
= NULL
;
1391 nr
.lpProvider
= NULL
;
1393 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1394 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1396 if (result
== NO_ERROR
)
1399 return INVALID_HANDLE_VALUE
;
1403 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1412 buffer
= alloca (bufsize
);
1413 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1414 if (result
!= NO_ERROR
)
1417 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1418 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1420 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1423 strncpy (readbuf
, ptr
, size
);
1428 close_unc_volume (HANDLE henum
)
1430 if (henum
!= INVALID_HANDLE_VALUE
)
1431 WNetCloseEnum (henum
);
1435 unc_volume_file_attributes (char *path
)
1440 henum
= open_unc_volume (path
);
1441 if (henum
== INVALID_HANDLE_VALUE
)
1444 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1446 close_unc_volume (henum
);
1452 /* Shadow some MSVC runtime functions to map requests for long filenames
1453 to reasonable short names if necessary. This was originally added to
1454 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1458 sys_access (const char * path
, int mode
)
1462 /* MSVC implementation doesn't recognize D_OK. */
1463 path
= map_w32_filename (path
, NULL
);
1464 if (is_unc_volume (path
))
1466 attributes
= unc_volume_file_attributes (path
);
1467 if (attributes
== -1) {
1472 else if ((attributes
= GetFileAttributes (path
)) == -1)
1474 /* Should try mapping GetLastError to errno; for now just indicate
1475 that path doesn't exist. */
1479 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1484 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1489 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1498 sys_chdir (const char * path
)
1500 return _chdir (map_w32_filename (path
, NULL
));
1504 sys_chmod (const char * path
, int mode
)
1506 return _chmod (map_w32_filename (path
, NULL
), mode
);
1510 sys_creat (const char * path
, int mode
)
1512 return _creat (map_w32_filename (path
, NULL
), mode
);
1516 sys_fopen(const char * path
, const char * mode
)
1520 const char * mode_save
= mode
;
1522 /* Force all file handles to be non-inheritable. This is necessary to
1523 ensure child processes don't unwittingly inherit handles that might
1524 prevent future file access. */
1528 else if (mode
[0] == 'w' || mode
[0] == 'a')
1529 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1533 /* Only do simplistic option parsing. */
1537 oflag
&= ~(O_RDONLY
| O_WRONLY
);
1540 else if (mode
[0] == 'b')
1545 else if (mode
[0] == 't')
1552 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
1556 return _fdopen (fd
, mode_save
);
1559 /* This only works on NTFS volumes, but is useful to have. */
1561 sys_link (const char * old
, const char * new)
1565 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
1567 if (old
== NULL
|| new == NULL
)
1573 strcpy (oldname
, map_w32_filename (old
, NULL
));
1574 strcpy (newname
, map_w32_filename (new, NULL
));
1576 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
1577 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
1578 if (fileh
!= INVALID_HANDLE_VALUE
)
1582 /* Confusingly, the "alternate" stream name field does not apply
1583 when restoring a hard link, and instead contains the actual
1584 stream data for the link (ie. the name of the link to create).
1585 The WIN32_STREAM_ID structure before the cStreamName field is
1586 the stream header, which is then immediately followed by the
1590 WIN32_STREAM_ID wid
;
1591 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
1594 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
1595 data
.wid
.cStreamName
, MAX_PATH
);
1598 LPVOID context
= NULL
;
1601 data
.wid
.dwStreamId
= BACKUP_LINK
;
1602 data
.wid
.dwStreamAttributes
= 0;
1603 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
1604 data
.wid
.Size
.HighPart
= 0;
1605 data
.wid
.dwStreamNameSize
= 0;
1607 if (BackupWrite (fileh
, (LPBYTE
)&data
,
1608 offsetof (WIN32_STREAM_ID
, cStreamName
)
1609 + data
.wid
.Size
.LowPart
,
1610 &wbytes
, FALSE
, FALSE
, &context
)
1611 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
1618 /* Should try mapping GetLastError to errno; for now just
1619 indicate a general error (eg. links not supported). */
1620 errno
= EINVAL
; // perhaps EMLINK?
1624 CloseHandle (fileh
);
1633 sys_mkdir (const char * path
)
1635 return _mkdir (map_w32_filename (path
, NULL
));
1638 /* Because of long name mapping issues, we need to implement this
1639 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1640 a unique name, instead of setting the input template to an empty
1643 Standard algorithm seems to be use pid or tid with a letter on the
1644 front (in place of the 6 X's) and cycle through the letters to find a
1645 unique name. We extend that to allow any reasonable character as the
1646 first of the 6 X's. */
1648 sys_mktemp (char * template)
1652 unsigned uid
= GetCurrentThreadId ();
1653 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1655 if (template == NULL
)
1657 p
= template + strlen (template);
1659 /* replace up to the last 5 X's with uid in decimal */
1660 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
1662 p
[0] = '0' + uid
% 10;
1666 if (i
< 0 && p
[0] == 'X')
1671 int save_errno
= errno
;
1672 p
[0] = first_char
[i
];
1673 if (sys_access (template, 0) < 0)
1679 while (++i
< sizeof (first_char
));
1682 /* Template is badly formed or else we can't generate a unique name,
1683 so return empty string */
1689 sys_open (const char * path
, int oflag
, int mode
)
1691 /* Force all file handles to be non-inheritable. */
1692 return _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, mode
);
1696 sys_rename (const char * oldname
, const char * newname
)
1699 char temp
[MAX_PATH
];
1701 /* MoveFile on Windows 95 doesn't correctly change the short file name
1702 alias in a number of circumstances (it is not easy to predict when
1703 just by looking at oldname and newname, unfortunately). In these
1704 cases, renaming through a temporary name avoids the problem.
1706 A second problem on Windows 95 is that renaming through a temp name when
1707 newname is uppercase fails (the final long name ends up in
1708 lowercase, although the short alias might be uppercase) UNLESS the
1709 long temp name is not 8.3.
1711 So, on Windows 95 we always rename through a temp name, and we make sure
1712 the temp name has a long extension to ensure correct renaming. */
1714 strcpy (temp
, map_w32_filename (oldname
, NULL
));
1716 if (os_subtype
== OS_WIN95
)
1722 oldname
= map_w32_filename (oldname
, NULL
);
1723 if (o
= strrchr (oldname
, '\\'))
1726 o
= (char *) oldname
;
1728 if (p
= strrchr (temp
, '\\'))
1735 /* Force temp name to require a manufactured 8.3 alias - this
1736 seems to make the second rename work properly. */
1737 sprintf (p
, "_.%s.%u", o
, i
);
1739 result
= rename (oldname
, temp
);
1741 /* This loop must surely terminate! */
1742 while (result
< 0 && (errno
== EEXIST
|| errno
== EACCES
));
1747 /* Emulate Unix behaviour - newname is deleted if it already exists
1748 (at least if it is a file; don't do this for directories).
1750 Since we mustn't do this if we are just changing the case of the
1751 file name (we would end up deleting the file we are trying to
1752 rename!), we let rename detect if the destination file already
1753 exists - that way we avoid the possible pitfalls of trying to
1754 determine ourselves whether two names really refer to the same
1755 file, which is not always possible in the general case. (Consider
1756 all the permutations of shared or subst'd drives, etc.) */
1758 newname
= map_w32_filename (newname
, NULL
);
1759 result
= rename (temp
, newname
);
1762 && (errno
== EEXIST
|| errno
== EACCES
)
1763 && _chmod (newname
, 0666) == 0
1764 && _unlink (newname
) == 0)
1765 result
= rename (temp
, newname
);
1771 sys_rmdir (const char * path
)
1773 return _rmdir (map_w32_filename (path
, NULL
));
1777 sys_unlink (const char * path
)
1779 path
= map_w32_filename (path
, NULL
);
1781 /* On Unix, unlink works without write permission. */
1782 _chmod (path
, 0666);
1783 return _unlink (path
);
1786 static FILETIME utc_base_ft
;
1787 static long double utc_base
;
1788 static int init
= 0;
1791 convert_time (FILETIME ft
)
1797 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1806 st
.wMilliseconds
= 0;
1808 SystemTimeToFileTime (&st
, &utc_base_ft
);
1809 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1810 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1814 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
1817 ret
= (long double) ft
.dwHighDateTime
* 4096 * 1024 * 1024 + ft
.dwLowDateTime
;
1819 return (time_t) (ret
* 1e-7);
1823 convert_from_time_t (time_t time
, FILETIME
* pft
)
1829 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1838 st
.wMilliseconds
= 0;
1840 SystemTimeToFileTime (&st
, &utc_base_ft
);
1841 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1842 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1846 /* time in 100ns units since 1-Jan-1601 */
1847 tmp
= (long double) time
* 1e7
+ utc_base
;
1848 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
1849 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
1853 /* No reason to keep this; faking inode values either by hashing or even
1854 using the file index from GetInformationByHandle, is not perfect and
1855 so by default Emacs doesn't use the inode values on Windows.
1856 Instead, we now determine file-truename correctly (except for
1857 possible drive aliasing etc). */
1859 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
1861 hashval (const unsigned char * str
)
1866 h
= (h
<< 4) + *str
++;
1872 /* Return the hash value of the canonical pathname, excluding the
1873 drive/UNC header, to get a hopefully unique inode number. */
1875 generate_inode_val (const char * name
)
1877 char fullname
[ MAX_PATH
];
1881 /* Get the truly canonical filename, if it exists. (Note: this
1882 doesn't resolve aliasing due to subst commands, or recognise hard
1884 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
1887 parse_root (fullname
, &p
);
1888 /* Normal W32 filesystems are still case insensitive. */
1895 /* MSVC stat function can't cope with UNC names and has other bugs, so
1896 replace it with our own. This also allows us to calculate consistent
1897 inode values without hacks in the main Emacs code. */
1899 stat (const char * path
, struct stat
* buf
)
1902 WIN32_FIND_DATA wfd
;
1907 int rootdir
= FALSE
;
1909 if (path
== NULL
|| buf
== NULL
)
1915 name
= (char *) map_w32_filename (path
, &path
);
1916 /* must be valid filename, no wild cards or other invalid characters */
1917 if (strpbrk (name
, "*?|<>\""))
1923 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
1924 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
1925 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
1930 /* Remove trailing directory separator, unless name is the root
1931 directory of a drive or UNC volume in which case ensure there
1932 is a trailing separator. */
1933 len
= strlen (name
);
1934 rootdir
= (path
>= name
+ len
- 1
1935 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
1936 name
= strcpy (alloca (len
+ 2), name
);
1938 if (is_unc_volume (name
))
1940 DWORD attrs
= unc_volume_file_attributes (name
);
1945 memset (&wfd
, 0, sizeof (wfd
));
1946 wfd
.dwFileAttributes
= attrs
;
1947 wfd
.ftCreationTime
= utc_base_ft
;
1948 wfd
.ftLastAccessTime
= utc_base_ft
;
1949 wfd
.ftLastWriteTime
= utc_base_ft
;
1950 strcpy (wfd
.cFileName
, name
);
1954 if (!IS_DIRECTORY_SEP (name
[len
-1]))
1955 strcat (name
, "\\");
1956 if (GetDriveType (name
) < 2)
1961 memset (&wfd
, 0, sizeof (wfd
));
1962 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
1963 wfd
.ftCreationTime
= utc_base_ft
;
1964 wfd
.ftLastAccessTime
= utc_base_ft
;
1965 wfd
.ftLastWriteTime
= utc_base_ft
;
1966 strcpy (wfd
.cFileName
, name
);
1970 if (IS_DIRECTORY_SEP (name
[len
-1]))
1973 /* (This is hacky, but helps when doing file completions on
1974 network drives.) Optimize by using information available from
1975 active readdir if possible. */
1976 len
= strlen (dir_pathname
);
1977 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
1979 if (dir_find_handle
!= INVALID_HANDLE_VALUE
1980 && strnicmp (name
, dir_pathname
, len
) == 0
1981 && IS_DIRECTORY_SEP (name
[len
])
1982 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
1984 /* This was the last entry returned by readdir. */
1985 wfd
= dir_find_data
;
1989 fh
= FindFirstFile (name
, &wfd
);
1990 if (fh
== INVALID_HANDLE_VALUE
)
1999 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2001 buf
->st_mode
= _S_IFDIR
;
2002 buf
->st_nlink
= 2; /* doesn't really matter */
2003 fake_inode
= 0; /* this doesn't either I think */
2005 else if (!NILP (Vw32_get_true_file_attributes
)
2006 /* No access rights required to get info. */
2007 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
))
2008 != INVALID_HANDLE_VALUE
)
2010 /* This is more accurate in terms of gettting the correct number
2011 of links, but is quite slow (it is noticable when Emacs is
2012 making a list of file name completions). */
2013 BY_HANDLE_FILE_INFORMATION info
;
2015 if (GetFileInformationByHandle (fh
, &info
))
2017 buf
->st_nlink
= info
.nNumberOfLinks
;
2018 /* Might as well use file index to fake inode values, but this
2019 is not guaranteed to be unique unless we keep a handle open
2020 all the time (even then there are situations where it is
2021 not unique). Reputedly, there are at most 48 bits of info
2022 (on NTFS, presumably less on FAT). */
2023 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2031 switch (GetFileType (fh
))
2033 case FILE_TYPE_DISK
:
2034 buf
->st_mode
= _S_IFREG
;
2036 case FILE_TYPE_PIPE
:
2037 buf
->st_mode
= _S_IFIFO
;
2039 case FILE_TYPE_CHAR
:
2040 case FILE_TYPE_UNKNOWN
:
2042 buf
->st_mode
= _S_IFCHR
;
2048 /* Don't bother to make this information more accurate. */
2049 buf
->st_mode
= _S_IFREG
;
2055 /* Not sure if there is any point in this. */
2056 if (!NILP (Vw32_generate_fake_inodes
))
2057 fake_inode
= generate_inode_val (name
);
2058 else if (fake_inode
== 0)
2060 /* For want of something better, try to make everything unique. */
2061 static DWORD gen_num
= 0;
2062 fake_inode
= ++gen_num
;
2066 /* MSVC defines _ino_t to be short; other libc's might not. */
2067 if (sizeof (buf
->st_ino
) == 2)
2068 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2070 buf
->st_ino
= fake_inode
;
2072 /* consider files to belong to current user */
2073 buf
->st_uid
= the_passwd
.pw_uid
;
2074 buf
->st_gid
= the_passwd
.pw_gid
;
2076 /* volume_info is set indirectly by map_w32_filename */
2077 buf
->st_dev
= volume_info
.serialnum
;
2078 buf
->st_rdev
= volume_info
.serialnum
;
2081 buf
->st_size
= wfd
.nFileSizeLow
;
2083 /* Convert timestamps to Unix format. */
2084 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2085 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2086 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2087 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2088 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2090 /* determine rwx permissions */
2091 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2092 permission
= _S_IREAD
;
2094 permission
= _S_IREAD
| _S_IWRITE
;
2096 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2097 permission
|= _S_IEXEC
;
2098 else if (is_exec (name
))
2099 permission
|= _S_IEXEC
;
2101 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2106 /* Provide fstat and utime as well as stat for consistent handling of
2109 fstat (int desc
, struct stat
* buf
)
2111 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2112 BY_HANDLE_FILE_INFORMATION info
;
2116 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2118 case FILE_TYPE_DISK
:
2119 buf
->st_mode
= _S_IFREG
;
2120 if (!GetFileInformationByHandle (fh
, &info
))
2126 case FILE_TYPE_PIPE
:
2127 buf
->st_mode
= _S_IFIFO
;
2129 case FILE_TYPE_CHAR
:
2130 case FILE_TYPE_UNKNOWN
:
2132 buf
->st_mode
= _S_IFCHR
;
2134 memset (&info
, 0, sizeof (info
));
2135 info
.dwFileAttributes
= 0;
2136 info
.ftCreationTime
= utc_base_ft
;
2137 info
.ftLastAccessTime
= utc_base_ft
;
2138 info
.ftLastWriteTime
= utc_base_ft
;
2141 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2143 buf
->st_mode
= _S_IFDIR
;
2144 buf
->st_nlink
= 2; /* doesn't really matter */
2145 fake_inode
= 0; /* this doesn't either I think */
2149 buf
->st_nlink
= info
.nNumberOfLinks
;
2150 /* Might as well use file index to fake inode values, but this
2151 is not guaranteed to be unique unless we keep a handle open
2152 all the time (even then there are situations where it is
2153 not unique). Reputedly, there are at most 48 bits of info
2154 (on NTFS, presumably less on FAT). */
2155 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2158 /* MSVC defines _ino_t to be short; other libc's might not. */
2159 if (sizeof (buf
->st_ino
) == 2)
2160 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2162 buf
->st_ino
= fake_inode
;
2164 /* consider files to belong to current user */
2168 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2169 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2171 buf
->st_size
= info
.nFileSizeLow
;
2173 /* Convert timestamps to Unix format. */
2174 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2175 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2176 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2177 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2178 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2180 /* determine rwx permissions */
2181 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2182 permission
= _S_IREAD
;
2184 permission
= _S_IREAD
| _S_IWRITE
;
2186 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2187 permission
|= _S_IEXEC
;
2190 #if 0 /* no way of knowing the filename */
2191 char * p
= strrchr (name
, '.');
2193 (stricmp (p
, ".exe") == 0 ||
2194 stricmp (p
, ".com") == 0 ||
2195 stricmp (p
, ".bat") == 0 ||
2196 stricmp (p
, ".cmd") == 0))
2197 permission
|= _S_IEXEC
;
2201 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2207 utime (const char *name
, struct utimbuf
*times
)
2209 struct utimbuf deftime
;
2216 deftime
.modtime
= deftime
.actime
= time (NULL
);
2220 /* Need write access to set times. */
2221 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2222 0, OPEN_EXISTING
, 0, NULL
);
2225 convert_from_time_t (times
->actime
, &atime
);
2226 convert_from_time_t (times
->modtime
, &mtime
);
2227 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2245 /* Wrappers for winsock functions to map between our file descriptors
2246 and winsock's handles; also set h_errno for convenience.
2248 To allow Emacs to run on systems which don't have winsock support
2249 installed, we dynamically link to winsock on startup if present, and
2250 otherwise provide the minimum necessary functionality
2251 (eg. gethostname). */
2253 /* function pointers for relevant socket functions */
2254 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2255 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2256 int (PASCAL
*pfn_WSAGetLastError
) (void);
2257 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2258 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2259 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2260 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2261 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2262 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2263 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2264 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2265 int (PASCAL
*pfn_WSACleanup
) (void);
2267 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2268 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2269 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2270 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2271 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2272 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2274 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2275 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2276 #ifndef HANDLE_FLAG_INHERIT
2277 #define HANDLE_FLAG_INHERIT 1
2281 static int winsock_inuse
;
2286 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2288 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2289 after WSAStartup returns successfully, but it seems reasonable
2290 to allow unloading winsock anyway in that case. */
2291 if (pfn_WSACleanup () == 0 ||
2292 pfn_WSAGetLastError () == WSAENETDOWN
)
2294 if (FreeLibrary (winsock_lib
))
2303 init_winsock (int load_now
)
2305 WSADATA winsockData
;
2307 if (winsock_lib
!= NULL
)
2310 pfn_SetHandleInformation
= NULL
;
2311 pfn_SetHandleInformation
2312 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2313 "SetHandleInformation");
2315 winsock_lib
= LoadLibrary ("wsock32.dll");
2317 if (winsock_lib
!= NULL
)
2319 /* dynamically link to socket functions */
2321 #define LOAD_PROC(fn) \
2322 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2325 LOAD_PROC( WSAStartup
);
2326 LOAD_PROC( WSASetLastError
);
2327 LOAD_PROC( WSAGetLastError
);
2328 LOAD_PROC( socket
);
2330 LOAD_PROC( connect
);
2331 LOAD_PROC( ioctlsocket
);
2334 LOAD_PROC( closesocket
);
2335 LOAD_PROC( shutdown
);
2338 LOAD_PROC( inet_addr
);
2339 LOAD_PROC( gethostname
);
2340 LOAD_PROC( gethostbyname
);
2341 LOAD_PROC( getservbyname
);
2342 LOAD_PROC( WSACleanup
);
2346 /* specify version 1.1 of winsock */
2347 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2349 if (winsockData
.wVersion
!= 0x101)
2354 /* Report that winsock exists and is usable, but leave
2355 socket functions disabled. I am assuming that calling
2356 WSAStartup does not require any network interaction,
2357 and in particular does not cause or require a dial-up
2358 connection to be established. */
2361 FreeLibrary (winsock_lib
);
2369 FreeLibrary (winsock_lib
);
2379 /* function to set h_errno for compatability; map winsock error codes to
2380 normal system codes where they overlap (non-overlapping definitions
2381 are already in <sys/socket.h> */
2382 static void set_errno ()
2384 if (winsock_lib
== NULL
)
2387 h_errno
= pfn_WSAGetLastError ();
2391 case WSAEACCES
: h_errno
= EACCES
; break;
2392 case WSAEBADF
: h_errno
= EBADF
; break;
2393 case WSAEFAULT
: h_errno
= EFAULT
; break;
2394 case WSAEINTR
: h_errno
= EINTR
; break;
2395 case WSAEINVAL
: h_errno
= EINVAL
; break;
2396 case WSAEMFILE
: h_errno
= EMFILE
; break;
2397 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2398 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2403 static void check_errno ()
2405 if (h_errno
== 0 && winsock_lib
!= NULL
)
2406 pfn_WSASetLastError (0);
2409 /* Extend strerror to handle the winsock-specific error codes. */
2413 } _wsa_errlist
[] = {
2414 WSAEINTR
, "Interrupted function call",
2415 WSAEBADF
, "Bad file descriptor",
2416 WSAEACCES
, "Permission denied",
2417 WSAEFAULT
, "Bad address",
2418 WSAEINVAL
, "Invalid argument",
2419 WSAEMFILE
, "Too many open files",
2421 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2422 WSAEINPROGRESS
, "Operation now in progress",
2423 WSAEALREADY
, "Operation already in progress",
2424 WSAENOTSOCK
, "Socket operation on non-socket",
2425 WSAEDESTADDRREQ
, "Destination address required",
2426 WSAEMSGSIZE
, "Message too long",
2427 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2428 WSAENOPROTOOPT
, "Bad protocol option",
2429 WSAEPROTONOSUPPORT
, "Protocol not supported",
2430 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2431 WSAEOPNOTSUPP
, "Operation not supported",
2432 WSAEPFNOSUPPORT
, "Protocol family not supported",
2433 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2434 WSAEADDRINUSE
, "Address already in use",
2435 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2436 WSAENETDOWN
, "Network is down",
2437 WSAENETUNREACH
, "Network is unreachable",
2438 WSAENETRESET
, "Network dropped connection on reset",
2439 WSAECONNABORTED
, "Software caused connection abort",
2440 WSAECONNRESET
, "Connection reset by peer",
2441 WSAENOBUFS
, "No buffer space available",
2442 WSAEISCONN
, "Socket is already connected",
2443 WSAENOTCONN
, "Socket is not connected",
2444 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2445 WSAETOOMANYREFS
, "Too many references", /* not sure */
2446 WSAETIMEDOUT
, "Connection timed out",
2447 WSAECONNREFUSED
, "Connection refused",
2448 WSAELOOP
, "Network loop", /* not sure */
2449 WSAENAMETOOLONG
, "Name is too long",
2450 WSAEHOSTDOWN
, "Host is down",
2451 WSAEHOSTUNREACH
, "No route to host",
2452 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2453 WSAEPROCLIM
, "Too many processes",
2454 WSAEUSERS
, "Too many users", /* not sure */
2455 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2456 WSAESTALE
, "Data is stale", /* not sure */
2457 WSAEREMOTE
, "Remote error", /* not sure */
2459 WSASYSNOTREADY
, "Network subsystem is unavailable",
2460 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2461 WSANOTINITIALISED
, "Winsock not initialized successfully",
2462 WSAEDISCON
, "Graceful shutdown in progress",
2464 WSAENOMORE
, "No more operations allowed", /* not sure */
2465 WSAECANCELLED
, "Operation cancelled", /* not sure */
2466 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2467 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2468 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2469 WSASYSCALLFAILURE
, "System call failured",
2470 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2471 WSATYPE_NOT_FOUND
, "Class type not found",
2472 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2473 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2474 WSAEREFUSED
, "Operation refused", /* not sure */
2477 WSAHOST_NOT_FOUND
, "Host not found",
2478 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2479 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2480 WSANO_DATA
, "Valid name, no data record of requested type",
2486 sys_strerror(int error_no
)
2489 static char unknown_msg
[40];
2491 if (error_no
>= 0 && error_no
< _sys_nerr
)
2492 return _sys_errlist
[error_no
];
2494 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2495 if (_wsa_errlist
[i
].errnum
== error_no
)
2496 return _wsa_errlist
[i
].msg
;
2498 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2502 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2503 but I believe the method of keeping the socket handle separate (and
2504 insuring it is not inheritable) is the correct one. */
2506 //#define SOCK_REPLACE_HANDLE
2508 #ifdef SOCK_REPLACE_HANDLE
2509 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2511 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2515 sys_socket(int af
, int type
, int protocol
)
2521 if (winsock_lib
== NULL
)
2524 return INVALID_SOCKET
;
2529 /* call the real socket function */
2530 s
= (long) pfn_socket (af
, type
, protocol
);
2532 if (s
!= INVALID_SOCKET
)
2534 /* Although under NT 3.5 _open_osfhandle will accept a socket
2535 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2536 that does not work under NT 3.1. However, we can get the same
2537 effect by using a backdoor function to replace an existing
2538 descriptor handle with the one we want. */
2540 /* allocate a file descriptor (with appropriate flags) */
2541 fd
= _open ("NUL:", _O_RDWR
);
2544 #ifdef SOCK_REPLACE_HANDLE
2545 /* now replace handle to NUL with our socket handle */
2546 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
2548 _set_osfhnd (fd
, s
);
2549 /* setmode (fd, _O_BINARY); */
2551 /* Make a non-inheritable copy of the socket handle. */
2554 HANDLE new_s
= INVALID_HANDLE_VALUE
;
2556 parent
= GetCurrentProcess ();
2558 /* Apparently there is a bug in NT 3.51 with some service
2559 packs, which prevents using DuplicateHandle to make a
2560 socket handle non-inheritable (causes WSACleanup to
2561 hang). The work-around is to use SetHandleInformation
2562 instead if it is available and implemented. */
2563 if (!pfn_SetHandleInformation
2564 || !pfn_SetHandleInformation ((HANDLE
) s
,
2565 HANDLE_FLAG_INHERIT
,
2568 DuplicateHandle (parent
,
2574 DUPLICATE_SAME_ACCESS
);
2575 pfn_closesocket (s
);
2578 fd_info
[fd
].hnd
= (HANDLE
) s
;
2582 /* set our own internal flags */
2583 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
2589 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
2591 /* attach child_process to fd_info */
2592 if (fd_info
[ fd
].cp
!= NULL
)
2594 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
2598 fd_info
[ fd
].cp
= cp
;
2601 winsock_inuse
++; /* count open sockets */
2608 pfn_closesocket (s
);
2618 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
2620 if (winsock_lib
== NULL
)
2623 return SOCKET_ERROR
;
2627 if (fd_info
[s
].flags
& FILE_SOCKET
)
2629 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
2630 if (rc
== SOCKET_ERROR
)
2635 return SOCKET_ERROR
;
2640 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
2642 if (winsock_lib
== NULL
)
2645 return SOCKET_ERROR
;
2649 if (fd_info
[s
].flags
& FILE_SOCKET
)
2651 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
2652 if (rc
== SOCKET_ERROR
)
2657 return SOCKET_ERROR
;
2661 sys_htons (u_short hostshort
)
2663 return (winsock_lib
!= NULL
) ?
2664 pfn_htons (hostshort
) : hostshort
;
2668 sys_ntohs (u_short netshort
)
2670 return (winsock_lib
!= NULL
) ?
2671 pfn_ntohs (netshort
) : netshort
;
2675 sys_inet_addr (const char * cp
)
2677 return (winsock_lib
!= NULL
) ?
2678 pfn_inet_addr (cp
) : INADDR_NONE
;
2682 sys_gethostname (char * name
, int namelen
)
2684 if (winsock_lib
!= NULL
)
2685 return pfn_gethostname (name
, namelen
);
2687 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
2688 return !GetComputerName (name
, &namelen
);
2691 return SOCKET_ERROR
;
2695 sys_gethostbyname(const char * name
)
2697 struct hostent
* host
;
2699 if (winsock_lib
== NULL
)
2706 host
= pfn_gethostbyname (name
);
2713 sys_getservbyname(const char * name
, const char * proto
)
2715 struct servent
* serv
;
2717 if (winsock_lib
== NULL
)
2724 serv
= pfn_getservbyname (name
, proto
);
2731 sys_shutdown (int s
, int how
)
2735 if (winsock_lib
== NULL
)
2738 return SOCKET_ERROR
;
2742 if (fd_info
[s
].flags
& FILE_SOCKET
)
2744 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
2745 if (rc
== SOCKET_ERROR
)
2750 return SOCKET_ERROR
;
2753 #endif /* HAVE_SOCKETS */
2756 /* Shadow main io functions: we need to handle pipes and sockets more
2757 intelligently, and implement non-blocking mode as well. */
2764 if (fd
< 0 || fd
>= MAXDESC
)
2772 child_process
* cp
= fd_info
[fd
].cp
;
2774 fd_info
[fd
].cp
= NULL
;
2776 if (CHILD_ACTIVE (cp
))
2778 /* if last descriptor to active child_process then cleanup */
2780 for (i
= 0; i
< MAXDESC
; i
++)
2784 if (fd_info
[i
].cp
== cp
)
2790 if (fd_info
[fd
].flags
& FILE_SOCKET
)
2792 #ifndef SOCK_REPLACE_HANDLE
2793 if (winsock_lib
== NULL
) abort ();
2795 pfn_shutdown (SOCK_HANDLE (fd
), 2);
2796 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
2798 winsock_inuse
--; /* count open sockets */
2806 /* Note that sockets do not need special treatment here (at least on
2807 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
2808 closesocket is equivalent to CloseHandle, which is to be expected
2809 because socket handles are fully fledged kernel handles. */
2813 fd_info
[fd
].flags
= 0;
2826 /* duplicate our internal info as well */
2827 fd_info
[new_fd
] = fd_info
[fd
];
2834 sys_dup2 (int src
, int dst
)
2838 if (dst
< 0 || dst
>= MAXDESC
)
2844 /* make sure we close the destination first if it's a pipe or socket */
2845 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
2848 rc
= _dup2 (src
, dst
);
2851 /* duplicate our internal info as well */
2852 fd_info
[dst
] = fd_info
[src
];
2857 /* Unix pipe() has only one arg */
2859 sys_pipe (int * phandles
)
2865 /* make pipe handles non-inheritable; when we spawn a child, we
2866 replace the relevant handle with an inheritable one. Also put
2867 pipes into binary mode; we will do text mode translation ourselves
2869 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
2873 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
2874 fd_info
[phandles
[0]].flags
= flags
;
2876 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
2877 fd_info
[phandles
[1]].flags
= flags
;
2884 extern Lisp_Object Vw32_pipe_read_delay
;
2886 /* Function to do blocking read of one byte, needed to implement
2887 select. It is only allowed on sockets and pipes. */
2889 _sys_read_ahead (int fd
)
2894 if (fd
< 0 || fd
>= MAXDESC
)
2895 return STATUS_READ_ERROR
;
2897 cp
= fd_info
[fd
].cp
;
2899 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
2900 return STATUS_READ_ERROR
;
2902 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
2903 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
2905 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
2909 cp
->status
= STATUS_READ_IN_PROGRESS
;
2911 if (fd_info
[fd
].flags
& FILE_PIPE
)
2913 rc
= _read (fd
, &cp
->chr
, sizeof (char));
2915 /* Give subprocess time to buffer some more output for us before
2916 reporting that input is available; we need this because Windows 95
2917 connects DOS programs to pipes by making the pipe appear to be
2918 the normal console stdout - as a result most DOS programs will
2919 write to stdout without buffering, ie. one character at a
2920 time. Even some W32 programs do this - "dir" in a command
2921 shell on NT is very slow if we don't do this. */
2924 int wait
= XINT (Vw32_pipe_read_delay
);
2930 /* Yield remainder of our time slice, effectively giving a
2931 temporary priority boost to the child process. */
2936 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
2937 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
2940 if (rc
== sizeof (char))
2941 cp
->status
= STATUS_READ_SUCCEEDED
;
2943 cp
->status
= STATUS_READ_FAILED
;
2949 sys_read (int fd
, char * buffer
, unsigned int count
)
2954 char * orig_buffer
= buffer
;
2956 if (fd
< 0 || fd
>= MAXDESC
)
2962 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
2964 child_process
*cp
= fd_info
[fd
].cp
;
2966 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
2974 /* re-read CR carried over from last read */
2975 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
2977 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
2981 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
2984 /* presence of a child_process structure means we are operating in
2985 non-blocking mode - otherwise we just call _read directly.
2986 Note that the child_process structure might be missing because
2987 reap_subprocess has been called; in this case the pipe is
2988 already broken, so calling _read on it is okay. */
2991 int current_status
= cp
->status
;
2993 switch (current_status
)
2995 case STATUS_READ_FAILED
:
2996 case STATUS_READ_ERROR
:
2997 /* report normal EOF if nothing in buffer */
2999 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3002 case STATUS_READ_READY
:
3003 case STATUS_READ_IN_PROGRESS
:
3004 DebPrint (("sys_read called when read is in progress\n"));
3005 errno
= EWOULDBLOCK
;
3008 case STATUS_READ_SUCCEEDED
:
3009 /* consume read-ahead char */
3010 *buffer
++ = cp
->chr
;
3013 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3014 ResetEvent (cp
->char_avail
);
3016 case STATUS_READ_ACKNOWLEDGED
:
3020 DebPrint (("sys_read: bad status %d\n", current_status
));
3025 if (fd_info
[fd
].flags
& FILE_PIPE
)
3027 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3028 to_read
= min (waiting
, (DWORD
) count
);
3031 nchars
+= _read (fd
, buffer
, to_read
);
3034 else /* FILE_SOCKET */
3036 if (winsock_lib
== NULL
) abort ();
3038 /* do the equivalent of a non-blocking read */
3039 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3040 if (waiting
== 0 && nchars
== 0)
3042 h_errno
= errno
= EWOULDBLOCK
;
3048 /* always use binary mode for sockets */
3049 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3050 if (res
== SOCKET_ERROR
)
3052 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3053 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3064 int nread
= _read (fd
, buffer
, count
);
3067 else if (nchars
== 0)
3072 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3073 /* Perform text mode translation if required. */
3074 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3076 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3077 /* If buffer contains only CR, return that. To be absolutely
3078 sure we should attempt to read the next char, but in
3079 practice a CR to be followed by LF would not appear by
3080 itself in the buffer. */
3081 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3083 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3089 nchars
= _read (fd
, buffer
, count
);
3094 /* For now, don't bother with a non-blocking mode */
3096 sys_write (int fd
, const void * buffer
, unsigned int count
)
3100 if (fd
< 0 || fd
>= MAXDESC
)
3106 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3108 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3114 /* Perform text mode translation if required. */
3115 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3117 char * tmpbuf
= alloca (count
* 2);
3118 unsigned char * src
= (void *)buffer
;
3119 unsigned char * dst
= tmpbuf
;
3124 unsigned char *next
;
3125 /* copy next line or remaining bytes */
3126 next
= _memccpy (dst
, src
, '\n', nbytes
);
3129 /* copied one line ending with '\n' */
3130 int copied
= next
- dst
;
3133 /* insert '\r' before '\n' */
3140 /* copied remaining partial line -> now finished */
3148 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3150 if (winsock_lib
== NULL
) abort ();
3151 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3152 if (nchars
== SOCKET_ERROR
)
3154 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
3155 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3161 nchars
= _write (fd
, buffer
, count
);
3167 check_windows_init_file ()
3169 extern int noninteractive
, inhibit_window_system
;
3171 /* A common indication that Emacs is not installed properly is when
3172 it cannot find the Windows installation file. If this file does
3173 not exist in the expected place, tell the user. */
3175 if (!noninteractive
&& !inhibit_window_system
)
3177 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3178 Lisp_Object objs
[2];
3179 Lisp_Object full_load_path
;
3180 Lisp_Object init_file
;
3183 objs
[0] = Vload_path
;
3184 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3185 full_load_path
= Fappend (2, objs
);
3186 init_file
= build_string ("term/w32-win");
3187 fd
= openp (full_load_path
, init_file
, ".el:.elc", NULL
, 0);
3190 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3191 char *init_file_name
= XSTRING (init_file
)->data
;
3192 char *load_path
= XSTRING (load_path_print
)->data
;
3193 char *buffer
= alloca (1024);
3196 "The Emacs Windows initialization file \"%s.el\" "
3197 "could not be found in your Emacs installation. "
3198 "Emacs checked the following directories for this file:\n"
3200 "When Emacs cannot find this file, it usually means that it "
3201 "was not installed properly, or its distribution file was "
3202 "not unpacked properly.\nSee the README.W32 file in the "
3203 "top-level Emacs directory for more information.",
3204 init_file_name
, load_path
);
3207 "Emacs Abort Dialog",
3208 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3209 /* Use the low-level Emacs abort. */
3224 /* shutdown the socket interface if necessary */
3233 /* Initialise the socket interface now if available and requested by
3234 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3235 delayed until open-network-stream is called (w32-has-winsock can
3236 also be used to dynamically load or reload winsock).
3238 Conveniently, init_environment is called before us, so
3239 PRELOAD_WINSOCK can be set in the registry. */
3241 /* Always initialize this correctly. */
3244 if (getenv ("PRELOAD_WINSOCK") != NULL
)
3245 init_winsock (TRUE
);
3248 /* Initial preparation for subprocess support: replace our standard
3249 handles with non-inheritable versions. */
3252 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
3253 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
3254 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
3256 parent
= GetCurrentProcess ();
3258 /* ignore errors when duplicating and closing; typically the
3259 handles will be invalid when running as a gui program. */
3260 DuplicateHandle (parent
,
3261 GetStdHandle (STD_INPUT_HANDLE
),
3266 DUPLICATE_SAME_ACCESS
);
3268 DuplicateHandle (parent
,
3269 GetStdHandle (STD_OUTPUT_HANDLE
),
3274 DUPLICATE_SAME_ACCESS
);
3276 DuplicateHandle (parent
,
3277 GetStdHandle (STD_ERROR_HANDLE
),
3282 DUPLICATE_SAME_ACCESS
);
3288 if (stdin_save
!= INVALID_HANDLE_VALUE
)
3289 _open_osfhandle ((long) stdin_save
, O_TEXT
);
3291 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
3294 if (stdout_save
!= INVALID_HANDLE_VALUE
)
3295 _open_osfhandle ((long) stdout_save
, O_TEXT
);
3297 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3300 if (stderr_save
!= INVALID_HANDLE_VALUE
)
3301 _open_osfhandle ((long) stderr_save
, O_TEXT
);
3303 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3307 /* unfortunately, atexit depends on implementation of malloc */
3308 /* atexit (term_ntproc); */
3309 signal (SIGABRT
, term_ntproc
);
3311 /* determine which drives are fixed, for GetCachedVolumeInformation */
3313 /* GetDriveType must have trailing backslash. */
3314 char drive
[] = "A:\\";
3316 /* Loop over all possible drive letters */
3317 while (*drive
<= 'Z')
3319 /* Record if this drive letter refers to a fixed drive. */
3320 fixed_drives
[DRIVE_INDEX (*drive
)] =
3321 (GetDriveType (drive
) == DRIVE_FIXED
);
3327 /* Check to see if Emacs has been installed correctly. */
3328 check_windows_init_file ();