(message_dolog): GCPRO the oldpoint, oldbegv and oldzv
[bpt/emacs.git] / src / w32.c
1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
22 */
23
24
25 #include <stddef.h> /* for offsetof */
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <io.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <signal.h>
33 #include <sys/file.h>
34 #include <sys/time.h>
35 #include <sys/utime.h>
36
37 /* must include CRT headers *before* config.h */
38 #include "config.h"
39 #undef access
40 #undef chdir
41 #undef chmod
42 #undef creat
43 #undef ctime
44 #undef fopen
45 #undef link
46 #undef mkdir
47 #undef mktemp
48 #undef open
49 #undef rename
50 #undef rmdir
51 #undef unlink
52
53 #undef close
54 #undef dup
55 #undef dup2
56 #undef pipe
57 #undef read
58 #undef write
59
60 #include "lisp.h"
61
62 #include <pwd.h>
63
64 #include <windows.h>
65
66 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
67 #include <sys/socket.h>
68 #undef socket
69 #undef bind
70 #undef connect
71 #undef htons
72 #undef ntohs
73 #undef inet_addr
74 #undef gethostname
75 #undef gethostbyname
76 #undef getservbyname
77 #undef shutdown
78 #endif
79
80 #include "w32.h"
81 #include "ndir.h"
82 #include "w32heap.h"
83
84 #undef min
85 #undef max
86 #define min(x, y) (((x) < (y)) ? (x) : (y))
87 #define max(x, y) (((x) > (y)) ? (x) : (y))
88
89 extern Lisp_Object Vw32_downcase_file_names;
90 extern Lisp_Object Vw32_generate_fake_inodes;
91 extern Lisp_Object Vw32_get_true_file_attributes;
92
93 static char startup_dir[MAXPATHLEN];
94
95 /* Get the current working directory. */
96 char *
97 getwd (char *dir)
98 {
99 #if 0
100 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
101 return dir;
102 return NULL;
103 #else
104 /* Emacs doesn't actually change directory itself, and we want to
105 force our real wd to be where emacs.exe is to avoid unnecessary
106 conflicts when trying to rename or delete directories. */
107 strcpy (dir, startup_dir);
108 return dir;
109 #endif
110 }
111
112 #ifndef HAVE_SOCKETS
113 /* Emulate gethostname. */
114 int
115 gethostname (char *buffer, int size)
116 {
117 /* NT only allows small host names, so the buffer is
118 certainly large enough. */
119 return !GetComputerName (buffer, &size);
120 }
121 #endif /* HAVE_SOCKETS */
122
123 /* Emulate getloadavg. */
124 int
125 getloadavg (double loadavg[], int nelem)
126 {
127 int i;
128
129 /* A faithful emulation is going to have to be saved for a rainy day. */
130 for (i = 0; i < nelem; i++)
131 {
132 loadavg[i] = 0.0;
133 }
134 return i;
135 }
136
137 /* Emulate getpwuid, getpwnam and others. */
138
139 #define PASSWD_FIELD_SIZE 256
140
141 static char the_passwd_name[PASSWD_FIELD_SIZE];
142 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
143 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
144 static char the_passwd_dir[PASSWD_FIELD_SIZE];
145 static char the_passwd_shell[PASSWD_FIELD_SIZE];
146
147 static struct passwd the_passwd =
148 {
149 the_passwd_name,
150 the_passwd_passwd,
151 0,
152 0,
153 0,
154 the_passwd_gecos,
155 the_passwd_dir,
156 the_passwd_shell,
157 };
158
159 int
160 getuid ()
161 {
162 return the_passwd.pw_uid;
163 }
164
165 int
166 geteuid ()
167 {
168 /* I could imagine arguing for checking to see whether the user is
169 in the Administrators group and returning a UID of 0 for that
170 case, but I don't know how wise that would be in the long run. */
171 return getuid ();
172 }
173
174 int
175 getgid ()
176 {
177 return the_passwd.pw_gid;
178 }
179
180 int
181 getegid ()
182 {
183 return getgid ();
184 }
185
186 struct passwd *
187 getpwuid (int uid)
188 {
189 if (uid == the_passwd.pw_uid)
190 return &the_passwd;
191 return NULL;
192 }
193
194 struct passwd *
195 getpwnam (char *name)
196 {
197 struct passwd *pw;
198
199 pw = getpwuid (getuid ());
200 if (!pw)
201 return pw;
202
203 if (stricmp (name, pw->pw_name))
204 return NULL;
205
206 return pw;
207 }
208
209 void
210 init_user_info ()
211 {
212 /* Find the user's real name by opening the process token and
213 looking up the name associated with the user-sid in that token.
214
215 Use the relative portion of the identifier authority value from
216 the user-sid as the user id value (same for group id using the
217 primary group sid from the process token). */
218
219 char user_sid[256], name[256], domain[256];
220 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
221 HANDLE token = NULL;
222 SID_NAME_USE user_type;
223
224 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
225 && GetTokenInformation (token, TokenUser,
226 (PVOID) user_sid, sizeof (user_sid), &trash)
227 && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
228 domain, &dlength, &user_type))
229 {
230 strcpy (the_passwd.pw_name, name);
231 /* Determine a reasonable uid value. */
232 if (stricmp ("administrator", name) == 0)
233 {
234 the_passwd.pw_uid = 0;
235 the_passwd.pw_gid = 0;
236 }
237 else
238 {
239 SID_IDENTIFIER_AUTHORITY * pSIA;
240
241 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
242 /* I believe the relative portion is the last 4 bytes (of 6)
243 with msb first. */
244 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
245 (pSIA->Value[3] << 16) +
246 (pSIA->Value[4] << 8) +
247 (pSIA->Value[5] << 0));
248 /* restrict to conventional uid range for normal users */
249 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
250
251 /* Get group id */
252 if (GetTokenInformation (token, TokenPrimaryGroup,
253 (PVOID) user_sid, sizeof (user_sid), &trash))
254 {
255 SID_IDENTIFIER_AUTHORITY * pSIA;
256
257 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
258 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
259 (pSIA->Value[3] << 16) +
260 (pSIA->Value[4] << 8) +
261 (pSIA->Value[5] << 0));
262 /* I don't know if this is necessary, but for safety... */
263 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
264 }
265 else
266 the_passwd.pw_gid = the_passwd.pw_uid;
267 }
268 }
269 /* If security calls are not supported (presumably because we
270 are running under Windows 95), fallback to this. */
271 else if (GetUserName (name, &length))
272 {
273 strcpy (the_passwd.pw_name, name);
274 if (stricmp ("administrator", name) == 0)
275 the_passwd.pw_uid = 0;
276 else
277 the_passwd.pw_uid = 123;
278 the_passwd.pw_gid = the_passwd.pw_uid;
279 }
280 else
281 {
282 strcpy (the_passwd.pw_name, "unknown");
283 the_passwd.pw_uid = 123;
284 the_passwd.pw_gid = 123;
285 }
286
287 /* Ensure HOME and SHELL are defined. */
288 if (getenv ("HOME") == NULL)
289 putenv ("HOME=c:/");
290 if (getenv ("SHELL") == NULL)
291 putenv (os_subtype == OS_WIN95 ? "SHELL=command" : "SHELL=cmd");
292
293 /* Set dir and shell from environment variables. */
294 strcpy (the_passwd.pw_dir, getenv ("HOME"));
295 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
296
297 if (token)
298 CloseHandle (token);
299 }
300
301 int
302 random ()
303 {
304 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
305 return ((rand () << 15) | rand ());
306 }
307
308 void
309 srandom (int seed)
310 {
311 srand (seed);
312 }
313
314
315 /* Normalize filename by converting all path separators to
316 the specified separator. Also conditionally convert upper
317 case path name components to lower case. */
318
319 static void
320 normalize_filename (fp, path_sep)
321 register char *fp;
322 char path_sep;
323 {
324 char sep;
325 char *elem;
326
327 /* Always lower-case drive letters a-z, even if the filesystem
328 preserves case in filenames.
329 This is so filenames can be compared by string comparison
330 functions that are case-sensitive. Even case-preserving filesystems
331 do not distinguish case in drive letters. */
332 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
333 {
334 *fp += 'a' - 'A';
335 fp += 2;
336 }
337
338 if (NILP (Vw32_downcase_file_names))
339 {
340 while (*fp)
341 {
342 if (*fp == '/' || *fp == '\\')
343 *fp = path_sep;
344 fp++;
345 }
346 return;
347 }
348
349 sep = path_sep; /* convert to this path separator */
350 elem = fp; /* start of current path element */
351
352 do {
353 if (*fp >= 'a' && *fp <= 'z')
354 elem = 0; /* don't convert this element */
355
356 if (*fp == 0 || *fp == ':')
357 {
358 sep = *fp; /* restore current separator (or 0) */
359 *fp = '/'; /* after conversion of this element */
360 }
361
362 if (*fp == '/' || *fp == '\\')
363 {
364 if (elem && elem != fp)
365 {
366 *fp = 0; /* temporary end of string */
367 _strlwr (elem); /* while we convert to lower case */
368 }
369 *fp = sep; /* convert (or restore) path separator */
370 elem = fp + 1; /* next element starts after separator */
371 sep = path_sep;
372 }
373 } while (*fp++);
374 }
375
376 /* Destructively turn backslashes into slashes. */
377 void
378 dostounix_filename (p)
379 register char *p;
380 {
381 normalize_filename (p, '/');
382 }
383
384 /* Destructively turn slashes into backslashes. */
385 void
386 unixtodos_filename (p)
387 register char *p;
388 {
389 normalize_filename (p, '\\');
390 }
391
392 /* Remove all CR's that are followed by a LF.
393 (From msdos.c...probably should figure out a way to share it,
394 although this code isn't going to ever change.) */
395 int
396 crlf_to_lf (n, buf)
397 register int n;
398 register unsigned char *buf;
399 {
400 unsigned char *np = buf;
401 unsigned char *startp = buf;
402 unsigned char *endp = buf + n;
403
404 if (n == 0)
405 return n;
406 while (buf < endp - 1)
407 {
408 if (*buf == 0x0d)
409 {
410 if (*(++buf) != 0x0a)
411 *np++ = 0x0d;
412 }
413 else
414 *np++ = *buf++;
415 }
416 if (buf < endp)
417 *np++ = *buf++;
418 return np - startp;
419 }
420
421 /* Parse the root part of file name, if present. Return length and
422 optionally store pointer to char after root. */
423 static int
424 parse_root (char * name, char ** pPath)
425 {
426 char * start = name;
427
428 if (name == NULL)
429 return 0;
430
431 /* find the root name of the volume if given */
432 if (isalpha (name[0]) && name[1] == ':')
433 {
434 /* skip past drive specifier */
435 name += 2;
436 if (IS_DIRECTORY_SEP (name[0]))
437 name++;
438 }
439 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
440 {
441 int slashes = 2;
442 name += 2;
443 do
444 {
445 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
446 break;
447 name++;
448 }
449 while ( *name );
450 if (IS_DIRECTORY_SEP (name[0]))
451 name++;
452 }
453
454 if (pPath)
455 *pPath = name;
456
457 return name - start;
458 }
459
460 /* Get long base name for name; name is assumed to be absolute. */
461 static int
462 get_long_basename (char * name, char * buf, int size)
463 {
464 WIN32_FIND_DATA find_data;
465 HANDLE dir_handle;
466 int len = 0;
467
468 /* must be valid filename, no wild cards or other illegal characters */
469 if (strpbrk (name, "*?|<>\""))
470 return 0;
471
472 dir_handle = FindFirstFile (name, &find_data);
473 if (dir_handle != INVALID_HANDLE_VALUE)
474 {
475 if ((len = strlen (find_data.cFileName)) < size)
476 memcpy (buf, find_data.cFileName, len + 1);
477 else
478 len = 0;
479 FindClose (dir_handle);
480 }
481 return len;
482 }
483
484 /* Get long name for file, if possible (assumed to be absolute). */
485 BOOL
486 w32_get_long_filename (char * name, char * buf, int size)
487 {
488 char * o = buf;
489 char * p;
490 char * q;
491 char full[ MAX_PATH ];
492 int len;
493
494 len = strlen (name);
495 if (len >= MAX_PATH)
496 return FALSE;
497
498 /* Use local copy for destructive modification. */
499 memcpy (full, name, len+1);
500 unixtodos_filename (full);
501
502 /* Copy root part verbatim. */
503 len = parse_root (full, &p);
504 memcpy (o, full, len);
505 o += len;
506 size -= len;
507
508 do
509 {
510 q = p;
511 p = strchr (q, '\\');
512 if (p) *p = '\0';
513 len = get_long_basename (full, o, size);
514 if (len > 0)
515 {
516 o += len;
517 size -= len;
518 if (p != NULL)
519 {
520 *p++ = '\\';
521 if (size < 2)
522 return FALSE;
523 *o++ = '\\';
524 size--;
525 *o = '\0';
526 }
527 }
528 else
529 return FALSE;
530 }
531 while (p != NULL && *p);
532
533 return TRUE;
534 }
535
536
537 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
538
539 int
540 sigsetmask (int signal_mask)
541 {
542 return 0;
543 }
544
545 int
546 sigblock (int sig)
547 {
548 return 0;
549 }
550
551 int
552 setpgrp (int pid, int gid)
553 {
554 return 0;
555 }
556
557 int
558 alarm (int seconds)
559 {
560 return 0;
561 }
562
563 void
564 unrequest_sigio (void)
565 {
566 return;
567 }
568
569 void
570 request_sigio (void)
571 {
572 return;
573 }
574
575 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
576
577 LPBYTE
578 w32_get_resource (key, lpdwtype)
579 char *key;
580 LPDWORD lpdwtype;
581 {
582 LPBYTE lpvalue;
583 HKEY hrootkey = NULL;
584 DWORD cbData;
585 BOOL ok = FALSE;
586
587 /* Check both the current user and the local machine to see if
588 we have any resources. */
589
590 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
591 {
592 lpvalue = NULL;
593
594 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
595 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
596 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
597 {
598 return (lpvalue);
599 }
600
601 if (lpvalue) xfree (lpvalue);
602
603 RegCloseKey (hrootkey);
604 }
605
606 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
607 {
608 lpvalue = NULL;
609
610 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
611 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
612 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
613 {
614 return (lpvalue);
615 }
616
617 if (lpvalue) xfree (lpvalue);
618
619 RegCloseKey (hrootkey);
620 }
621
622 return (NULL);
623 }
624
625 char *get_emacs_configuration (void);
626 extern Lisp_Object Vsystem_configuration;
627
628 void
629 init_environment ()
630 {
631 int len;
632 static const char * const tempdirs[] = {
633 "$TMPDIR", "$TEMP", "$TMP", "c:/"
634 };
635 int i;
636 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
637
638 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
639 temporary files and assume "/tmp" if $TMPDIR is unset, which
640 will break on DOS/Windows. Refuse to work if we cannot find
641 a directory, not even "c:/", usable for that purpose. */
642 for (i = 0; i < imax ; i++)
643 {
644 const char *tmp = tempdirs[i];
645
646 if (*tmp == '$')
647 tmp = getenv (tmp + 1);
648 /* Note that `access' can lie to us if the directory resides on a
649 read-only filesystem, like CD-ROM or a write-protected floppy.
650 The only way to be really sure is to actually create a file and
651 see if it succeeds. But I think that's too much to ask. */
652 if (tmp && access (tmp, D_OK) == 0)
653 {
654 char * var = alloca (strlen (tmp) + 8);
655 sprintf (var, "TMPDIR=%s", tmp);
656 putenv (var);
657 break;
658 }
659 }
660 if (i >= imax)
661 cmd_error_internal
662 (Fcons (Qerror,
663 Fcons (build_string ("no usable temporary directories found!!"),
664 Qnil)),
665 "While setting TMPDIR: ");
666
667 /* Check for environment variables and use registry if they don't exist */
668 {
669 int i;
670 LPBYTE lpval;
671 DWORD dwType;
672
673 static char * env_vars[] =
674 {
675 "HOME",
676 "PRELOAD_WINSOCK",
677 "emacs_dir",
678 "EMACSLOADPATH",
679 "SHELL",
680 "CMDPROXY",
681 "EMACSDATA",
682 "EMACSPATH",
683 "EMACSLOCKDIR",
684 /* We no longer set INFOPATH because Info-default-directory-list
685 is then ignored. We use a hook in winnt.el instead. */
686 /* "INFOPATH", */
687 "EMACSDOC",
688 "TERM",
689 };
690
691 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
692 {
693 if (!getenv (env_vars[i])
694 && (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL)
695 {
696 if (dwType == REG_EXPAND_SZ)
697 {
698 char buf1[500], buf2[500];
699
700 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
701 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
702 putenv (strdup (buf2));
703 }
704 else if (dwType == REG_SZ)
705 {
706 char buf[500];
707
708 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
709 putenv (strdup (buf));
710 }
711
712 xfree (lpval);
713 }
714 }
715 }
716
717 /* Rebuild system configuration to reflect invoking system. */
718 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
719
720 /* Another special case: on NT, the PATH variable is actually named
721 "Path" although cmd.exe (perhaps NT itself) arranges for
722 environment variable lookup and setting to be case insensitive.
723 However, Emacs assumes a fully case sensitive environment, so we
724 need to change "Path" to "PATH" to match the expectations of
725 various elisp packages. We do this by the sneaky method of
726 modifying the string in the C runtime environ entry.
727
728 The same applies to COMSPEC. */
729 {
730 char ** envp;
731
732 for (envp = environ; *envp; envp++)
733 if (_strnicmp (*envp, "PATH=", 5) == 0)
734 memcpy (*envp, "PATH=", 5);
735 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
736 memcpy (*envp, "COMSPEC=", 8);
737 }
738
739 /* Remember the initial working directory for getwd, then make the
740 real wd be the location of emacs.exe to avoid conflicts when
741 renaming or deleting directories. (We also don't call chdir when
742 running subprocesses for the same reason.) */
743 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
744 abort ();
745
746 {
747 char *p;
748 char modname[MAX_PATH];
749
750 if (!GetModuleFileName (NULL, modname, MAX_PATH))
751 abort ();
752 if ((p = strrchr (modname, '\\')) == NULL)
753 abort ();
754 *p = 0;
755
756 SetCurrentDirectory (modname);
757 }
758
759 init_user_info ();
760 }
761
762 /* We don't have scripts to automatically determine the system configuration
763 for Emacs before it's compiled, and we don't want to have to make the
764 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
765 routine. */
766
767 static char configuration_buffer[32];
768
769 char *
770 get_emacs_configuration (void)
771 {
772 char *arch, *oem, *os;
773
774 /* Determine the processor type. */
775 switch (get_processor_type ())
776 {
777
778 #ifdef PROCESSOR_INTEL_386
779 case PROCESSOR_INTEL_386:
780 case PROCESSOR_INTEL_486:
781 case PROCESSOR_INTEL_PENTIUM:
782 arch = "i386";
783 break;
784 #endif
785
786 #ifdef PROCESSOR_INTEL_860
787 case PROCESSOR_INTEL_860:
788 arch = "i860";
789 break;
790 #endif
791
792 #ifdef PROCESSOR_MIPS_R2000
793 case PROCESSOR_MIPS_R2000:
794 case PROCESSOR_MIPS_R3000:
795 case PROCESSOR_MIPS_R4000:
796 arch = "mips";
797 break;
798 #endif
799
800 #ifdef PROCESSOR_ALPHA_21064
801 case PROCESSOR_ALPHA_21064:
802 arch = "alpha";
803 break;
804 #endif
805
806 default:
807 arch = "unknown";
808 break;
809 }
810
811 /* Let oem be "*" until we figure out how to decode the OEM field. */
812 oem = "*";
813
814 os = (GetVersion () & OS_WIN95) ? "windows95" : "nt";
815
816 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
817 get_w32_major_version (), get_w32_minor_version ());
818 return configuration_buffer;
819 }
820
821 #include <sys/timeb.h>
822
823 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
824 void
825 gettimeofday (struct timeval *tv, struct timezone *tz)
826 {
827 struct _timeb tb;
828 _ftime (&tb);
829
830 tv->tv_sec = tb.time;
831 tv->tv_usec = tb.millitm * 1000L;
832 if (tz)
833 {
834 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
835 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
836 }
837 }
838
839 /* ------------------------------------------------------------------------- */
840 /* IO support and wrapper functions for W32 API. */
841 /* ------------------------------------------------------------------------- */
842
843 /* Place a wrapper around the MSVC version of ctime. It returns NULL
844 on network directories, so we handle that case here.
845 (Ulrich Leodolter, 1/11/95). */
846 char *
847 sys_ctime (const time_t *t)
848 {
849 char *str = (char *) ctime (t);
850 return (str ? str : "Sun Jan 01 00:00:00 1970");
851 }
852
853 /* Emulate sleep...we could have done this with a define, but that
854 would necessitate including windows.h in the files that used it.
855 This is much easier. */
856 void
857 sys_sleep (int seconds)
858 {
859 Sleep (seconds * 1000);
860 }
861
862 /* Internal MSVC functions for low-level descriptor munging */
863 extern int __cdecl _set_osfhnd (int fd, long h);
864 extern int __cdecl _free_osfhnd (int fd);
865
866 /* parallel array of private info on file handles */
867 filedesc fd_info [ MAXDESC ];
868
869 typedef struct volume_info_data {
870 struct volume_info_data * next;
871
872 /* time when info was obtained */
873 DWORD timestamp;
874
875 /* actual volume info */
876 char * root_dir;
877 DWORD serialnum;
878 DWORD maxcomp;
879 DWORD flags;
880 char * name;
881 char * type;
882 } volume_info_data;
883
884 /* Global referenced by various functions. */
885 static volume_info_data volume_info;
886
887 /* Vector to indicate which drives are local and fixed (for which cached
888 data never expires). */
889 static BOOL fixed_drives[26];
890
891 /* Consider cached volume information to be stale if older than 10s,
892 at least for non-local drives. Info for fixed drives is never stale. */
893 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
894 #define VOLINFO_STILL_VALID( root_dir, info ) \
895 ( ( isalpha (root_dir[0]) && \
896 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
897 || GetTickCount () - info->timestamp < 10000 )
898
899 /* Cache support functions. */
900
901 /* Simple linked list with linear search is sufficient. */
902 static volume_info_data *volume_cache = NULL;
903
904 static volume_info_data *
905 lookup_volume_info (char * root_dir)
906 {
907 volume_info_data * info;
908
909 for (info = volume_cache; info; info = info->next)
910 if (stricmp (info->root_dir, root_dir) == 0)
911 break;
912 return info;
913 }
914
915 static void
916 add_volume_info (char * root_dir, volume_info_data * info)
917 {
918 info->root_dir = strdup (root_dir);
919 info->next = volume_cache;
920 volume_cache = info;
921 }
922
923
924 /* Wrapper for GetVolumeInformation, which uses caching to avoid
925 performance penalty (~2ms on 486 for local drives, 7.5ms for local
926 cdrom drive, ~5-10ms or more for remote drives on LAN). */
927 volume_info_data *
928 GetCachedVolumeInformation (char * root_dir)
929 {
930 volume_info_data * info;
931 char default_root[ MAX_PATH ];
932
933 /* NULL for root_dir means use root from current directory. */
934 if (root_dir == NULL)
935 {
936 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
937 return NULL;
938 parse_root (default_root, &root_dir);
939 *root_dir = 0;
940 root_dir = default_root;
941 }
942
943 /* Local fixed drives can be cached permanently. Removable drives
944 cannot be cached permanently, since the volume name and serial
945 number (if nothing else) can change. Remote drives should be
946 treated as if they are removable, since there is no sure way to
947 tell whether they are or not. Also, the UNC association of drive
948 letters mapped to remote volumes can be changed at any time (even
949 by other processes) without notice.
950
951 As a compromise, so we can benefit from caching info for remote
952 volumes, we use a simple expiry mechanism to invalidate cache
953 entries that are more than ten seconds old. */
954
955 #if 0
956 /* No point doing this, because WNetGetConnection is even slower than
957 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
958 GetDriveType is about the only call of this type which does not
959 involve network access, and so is extremely quick). */
960
961 /* Map drive letter to UNC if remote. */
962 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
963 {
964 char remote_name[ 256 ];
965 char drive[3] = { root_dir[0], ':' };
966
967 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
968 == NO_ERROR)
969 /* do something */ ;
970 }
971 #endif
972
973 info = lookup_volume_info (root_dir);
974
975 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
976 {
977 char name[ 256 ];
978 DWORD serialnum;
979 DWORD maxcomp;
980 DWORD flags;
981 char type[ 256 ];
982
983 /* Info is not cached, or is stale. */
984 if (!GetVolumeInformation (root_dir,
985 name, sizeof (name),
986 &serialnum,
987 &maxcomp,
988 &flags,
989 type, sizeof (type)))
990 return NULL;
991
992 /* Cache the volume information for future use, overwriting existing
993 entry if present. */
994 if (info == NULL)
995 {
996 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
997 add_volume_info (root_dir, info);
998 }
999 else
1000 {
1001 free (info->name);
1002 free (info->type);
1003 }
1004
1005 info->name = strdup (name);
1006 info->serialnum = serialnum;
1007 info->maxcomp = maxcomp;
1008 info->flags = flags;
1009 info->type = strdup (type);
1010 info->timestamp = GetTickCount ();
1011 }
1012
1013 return info;
1014 }
1015
1016 /* Get information on the volume where name is held; set path pointer to
1017 start of pathname in name (past UNC header\volume header if present). */
1018 int
1019 get_volume_info (const char * name, const char ** pPath)
1020 {
1021 char temp[MAX_PATH];
1022 char *rootname = NULL; /* default to current volume */
1023 volume_info_data * info;
1024
1025 if (name == NULL)
1026 return FALSE;
1027
1028 /* find the root name of the volume if given */
1029 if (isalpha (name[0]) && name[1] == ':')
1030 {
1031 rootname = temp;
1032 temp[0] = *name++;
1033 temp[1] = *name++;
1034 temp[2] = '\\';
1035 temp[3] = 0;
1036 }
1037 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1038 {
1039 char *str = temp;
1040 int slashes = 4;
1041 rootname = temp;
1042 do
1043 {
1044 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1045 break;
1046 *str++ = *name++;
1047 }
1048 while ( *name );
1049
1050 *str++ = '\\';
1051 *str = 0;
1052 }
1053
1054 if (pPath)
1055 *pPath = name;
1056
1057 info = GetCachedVolumeInformation (rootname);
1058 if (info != NULL)
1059 {
1060 /* Set global referenced by other functions. */
1061 volume_info = *info;
1062 return TRUE;
1063 }
1064 return FALSE;
1065 }
1066
1067 /* Determine if volume is FAT format (ie. only supports short 8.3
1068 names); also set path pointer to start of pathname in name. */
1069 int
1070 is_fat_volume (const char * name, const char ** pPath)
1071 {
1072 if (get_volume_info (name, pPath))
1073 return (volume_info.maxcomp == 12);
1074 return FALSE;
1075 }
1076
1077 /* Map filename to a legal 8.3 name if necessary. */
1078 const char *
1079 map_w32_filename (const char * name, const char ** pPath)
1080 {
1081 static char shortname[MAX_PATH];
1082 char * str = shortname;
1083 char c;
1084 char * path;
1085 const char * save_name = name;
1086
1087 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
1088 {
1089 register int left = 8; /* maximum number of chars in part */
1090 register int extn = 0; /* extension added? */
1091 register int dots = 2; /* maximum number of dots allowed */
1092
1093 while (name < path)
1094 *str++ = *name++; /* skip past UNC header */
1095
1096 while ((c = *name++))
1097 {
1098 switch ( c )
1099 {
1100 case '\\':
1101 case '/':
1102 *str++ = '\\';
1103 extn = 0; /* reset extension flags */
1104 dots = 2; /* max 2 dots */
1105 left = 8; /* max length 8 for main part */
1106 break;
1107 case ':':
1108 *str++ = ':';
1109 extn = 0; /* reset extension flags */
1110 dots = 2; /* max 2 dots */
1111 left = 8; /* max length 8 for main part */
1112 break;
1113 case '.':
1114 if ( dots )
1115 {
1116 /* Convert path components of the form .xxx to _xxx,
1117 but leave . and .. as they are. This allows .emacs
1118 to be read as _emacs, for example. */
1119
1120 if (! *name ||
1121 *name == '.' ||
1122 IS_DIRECTORY_SEP (*name))
1123 {
1124 *str++ = '.';
1125 dots--;
1126 }
1127 else
1128 {
1129 *str++ = '_';
1130 left--;
1131 dots = 0;
1132 }
1133 }
1134 else if ( !extn )
1135 {
1136 *str++ = '.';
1137 extn = 1; /* we've got an extension */
1138 left = 3; /* 3 chars in extension */
1139 }
1140 else
1141 {
1142 /* any embedded dots after the first are converted to _ */
1143 *str++ = '_';
1144 }
1145 break;
1146 case '~':
1147 case '#': /* don't lose these, they're important */
1148 if ( ! left )
1149 str[-1] = c; /* replace last character of part */
1150 /* FALLTHRU */
1151 default:
1152 if ( left )
1153 {
1154 *str++ = tolower (c); /* map to lower case (looks nicer) */
1155 left--;
1156 dots = 0; /* started a path component */
1157 }
1158 break;
1159 }
1160 }
1161 *str = '\0';
1162 }
1163 else
1164 {
1165 strcpy (shortname, name);
1166 unixtodos_filename (shortname);
1167 }
1168
1169 if (pPath)
1170 *pPath = shortname + (path - save_name);
1171
1172 return shortname;
1173 }
1174
1175 static int
1176 is_exec (const char * name)
1177 {
1178 char * p = strrchr (name, '.');
1179 return
1180 (p != NULL
1181 && (stricmp (p, ".exe") == 0 ||
1182 stricmp (p, ".com") == 0 ||
1183 stricmp (p, ".bat") == 0 ||
1184 stricmp (p, ".cmd") == 0));
1185 }
1186
1187 /* Emulate the Unix directory procedures opendir, closedir,
1188 and readdir. We can't use the procedures supplied in sysdep.c,
1189 so we provide them here. */
1190
1191 struct direct dir_static; /* simulated directory contents */
1192 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1193 static int dir_is_fat;
1194 static char dir_pathname[MAXPATHLEN+1];
1195 static WIN32_FIND_DATA dir_find_data;
1196
1197 DIR *
1198 opendir (char *filename)
1199 {
1200 DIR *dirp;
1201
1202 /* Opening is done by FindFirstFile. However, a read is inherent to
1203 this operation, so we defer the open until read time. */
1204
1205 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1206 return NULL;
1207 if (dir_find_handle != INVALID_HANDLE_VALUE)
1208 return NULL;
1209
1210 dirp->dd_fd = 0;
1211 dirp->dd_loc = 0;
1212 dirp->dd_size = 0;
1213
1214 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1215 dir_pathname[MAXPATHLEN] = '\0';
1216 dir_is_fat = is_fat_volume (filename, NULL);
1217
1218 return dirp;
1219 }
1220
1221 void
1222 closedir (DIR *dirp)
1223 {
1224 /* If we have a find-handle open, close it. */
1225 if (dir_find_handle != INVALID_HANDLE_VALUE)
1226 {
1227 FindClose (dir_find_handle);
1228 dir_find_handle = INVALID_HANDLE_VALUE;
1229 }
1230 xfree ((char *) dirp);
1231 }
1232
1233 struct direct *
1234 readdir (DIR *dirp)
1235 {
1236 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1237 if (dir_find_handle == INVALID_HANDLE_VALUE)
1238 {
1239 char filename[MAXNAMLEN + 3];
1240 int ln;
1241
1242 strcpy (filename, dir_pathname);
1243 ln = strlen (filename) - 1;
1244 if (!IS_DIRECTORY_SEP (filename[ln]))
1245 strcat (filename, "\\");
1246 strcat (filename, "*");
1247
1248 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1249
1250 if (dir_find_handle == INVALID_HANDLE_VALUE)
1251 return NULL;
1252 }
1253 else
1254 {
1255 if (!FindNextFile (dir_find_handle, &dir_find_data))
1256 return NULL;
1257 }
1258
1259 /* Emacs never uses this value, so don't bother making it match
1260 value returned by stat(). */
1261 dir_static.d_ino = 1;
1262
1263 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1264 dir_static.d_namlen - dir_static.d_namlen % 4;
1265
1266 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1267 strcpy (dir_static.d_name, dir_find_data.cFileName);
1268 if (dir_is_fat)
1269 _strlwr (dir_static.d_name);
1270 else if (!NILP (Vw32_downcase_file_names))
1271 {
1272 register char *p;
1273 for (p = dir_static.d_name; *p; p++)
1274 if (*p >= 'a' && *p <= 'z')
1275 break;
1276 if (!*p)
1277 _strlwr (dir_static.d_name);
1278 }
1279
1280 return &dir_static;
1281 }
1282
1283
1284 /* Shadow some MSVC runtime functions to map requests for long filenames
1285 to reasonable short names if necessary. This was originally added to
1286 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1287 long file names. */
1288
1289 int
1290 sys_access (const char * path, int mode)
1291 {
1292 DWORD attributes;
1293
1294 /* MSVC implementation doesn't recognize D_OK. */
1295 path = map_w32_filename (path, NULL);
1296 if ((attributes = GetFileAttributes (path)) == -1)
1297 {
1298 /* Should try mapping GetLastError to errno; for now just indicate
1299 that path doesn't exist. */
1300 errno = EACCES;
1301 return -1;
1302 }
1303 if ((mode & X_OK) != 0 && !is_exec (path))
1304 {
1305 errno = EACCES;
1306 return -1;
1307 }
1308 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1309 {
1310 errno = EACCES;
1311 return -1;
1312 }
1313 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1314 {
1315 errno = EACCES;
1316 return -1;
1317 }
1318 return 0;
1319 }
1320
1321 int
1322 sys_chdir (const char * path)
1323 {
1324 return _chdir (map_w32_filename (path, NULL));
1325 }
1326
1327 int
1328 sys_chmod (const char * path, int mode)
1329 {
1330 return _chmod (map_w32_filename (path, NULL), mode);
1331 }
1332
1333 int
1334 sys_creat (const char * path, int mode)
1335 {
1336 return _creat (map_w32_filename (path, NULL), mode);
1337 }
1338
1339 FILE *
1340 sys_fopen(const char * path, const char * mode)
1341 {
1342 int fd;
1343 int oflag;
1344 const char * mode_save = mode;
1345
1346 /* Force all file handles to be non-inheritable. This is necessary to
1347 ensure child processes don't unwittingly inherit handles that might
1348 prevent future file access. */
1349
1350 if (mode[0] == 'r')
1351 oflag = O_RDONLY;
1352 else if (mode[0] == 'w' || mode[0] == 'a')
1353 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1354 else
1355 return NULL;
1356
1357 /* Only do simplistic option parsing. */
1358 while (*++mode)
1359 if (mode[0] == '+')
1360 {
1361 oflag &= ~(O_RDONLY | O_WRONLY);
1362 oflag |= O_RDWR;
1363 }
1364 else if (mode[0] == 'b')
1365 {
1366 oflag &= ~O_TEXT;
1367 oflag |= O_BINARY;
1368 }
1369 else if (mode[0] == 't')
1370 {
1371 oflag &= ~O_BINARY;
1372 oflag |= O_TEXT;
1373 }
1374 else break;
1375
1376 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
1377 if (fd < 0)
1378 return NULL;
1379
1380 return _fdopen (fd, mode_save);
1381 }
1382
1383 /* This only works on NTFS volumes, but is useful to have. */
1384 int
1385 sys_link (const char * old, const char * new)
1386 {
1387 HANDLE fileh;
1388 int result = -1;
1389 char oldname[MAX_PATH], newname[MAX_PATH];
1390
1391 if (old == NULL || new == NULL)
1392 {
1393 errno = ENOENT;
1394 return -1;
1395 }
1396
1397 strcpy (oldname, map_w32_filename (old, NULL));
1398 strcpy (newname, map_w32_filename (new, NULL));
1399
1400 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1401 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1402 if (fileh != INVALID_HANDLE_VALUE)
1403 {
1404 int wlen;
1405
1406 /* Confusingly, the "alternate" stream name field does not apply
1407 when restoring a hard link, and instead contains the actual
1408 stream data for the link (ie. the name of the link to create).
1409 The WIN32_STREAM_ID structure before the cStreamName field is
1410 the stream header, which is then immediately followed by the
1411 stream data. */
1412
1413 struct {
1414 WIN32_STREAM_ID wid;
1415 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1416 } data;
1417
1418 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1419 data.wid.cStreamName, MAX_PATH);
1420 if (wlen > 0)
1421 {
1422 LPVOID context = NULL;
1423 DWORD wbytes = 0;
1424
1425 data.wid.dwStreamId = BACKUP_LINK;
1426 data.wid.dwStreamAttributes = 0;
1427 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
1428 data.wid.Size.HighPart = 0;
1429 data.wid.dwStreamNameSize = 0;
1430
1431 if (BackupWrite (fileh, (LPBYTE)&data,
1432 offsetof (WIN32_STREAM_ID, cStreamName)
1433 + data.wid.Size.LowPart,
1434 &wbytes, FALSE, FALSE, &context)
1435 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
1436 {
1437 /* succeeded */
1438 result = 0;
1439 }
1440 else
1441 {
1442 /* Should try mapping GetLastError to errno; for now just
1443 indicate a general error (eg. links not supported). */
1444 errno = EINVAL; // perhaps EMLINK?
1445 }
1446 }
1447
1448 CloseHandle (fileh);
1449 }
1450 else
1451 errno = ENOENT;
1452
1453 return result;
1454 }
1455
1456 int
1457 sys_mkdir (const char * path)
1458 {
1459 return _mkdir (map_w32_filename (path, NULL));
1460 }
1461
1462 /* Because of long name mapping issues, we need to implement this
1463 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1464 a unique name, instead of setting the input template to an empty
1465 string.
1466
1467 Standard algorithm seems to be use pid or tid with a letter on the
1468 front (in place of the 6 X's) and cycle through the letters to find a
1469 unique name. We extend that to allow any reasonable character as the
1470 first of the 6 X's. */
1471 char *
1472 sys_mktemp (char * template)
1473 {
1474 char * p;
1475 int i;
1476 unsigned uid = GetCurrentThreadId ();
1477 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1478
1479 if (template == NULL)
1480 return NULL;
1481 p = template + strlen (template);
1482 i = 5;
1483 /* replace up to the last 5 X's with uid in decimal */
1484 while (--p >= template && p[0] == 'X' && --i >= 0)
1485 {
1486 p[0] = '0' + uid % 10;
1487 uid /= 10;
1488 }
1489
1490 if (i < 0 && p[0] == 'X')
1491 {
1492 i = 0;
1493 do
1494 {
1495 int save_errno = errno;
1496 p[0] = first_char[i];
1497 if (sys_access (template, 0) < 0)
1498 {
1499 errno = save_errno;
1500 return template;
1501 }
1502 }
1503 while (++i < sizeof (first_char));
1504 }
1505
1506 /* Template is badly formed or else we can't generate a unique name,
1507 so return empty string */
1508 template[0] = 0;
1509 return template;
1510 }
1511
1512 int
1513 sys_open (const char * path, int oflag, int mode)
1514 {
1515 /* Force all file handles to be non-inheritable. */
1516 return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
1517 }
1518
1519 int
1520 sys_rename (const char * oldname, const char * newname)
1521 {
1522 int result;
1523 char temp[MAX_PATH];
1524
1525 /* MoveFile on Windows 95 doesn't correctly change the short file name
1526 alias in a number of circumstances (it is not easy to predict when
1527 just by looking at oldname and newname, unfortunately). In these
1528 cases, renaming through a temporary name avoids the problem.
1529
1530 A second problem on Windows 95 is that renaming through a temp name when
1531 newname is uppercase fails (the final long name ends up in
1532 lowercase, although the short alias might be uppercase) UNLESS the
1533 long temp name is not 8.3.
1534
1535 So, on Windows 95 we always rename through a temp name, and we make sure
1536 the temp name has a long extension to ensure correct renaming. */
1537
1538 strcpy (temp, map_w32_filename (oldname, NULL));
1539
1540 if (os_subtype == OS_WIN95)
1541 {
1542 char * o;
1543 char * p;
1544 int i = 0;
1545
1546 oldname = map_w32_filename (oldname, NULL);
1547 if (o = strrchr (oldname, '\\'))
1548 o++;
1549 else
1550 o = (char *) oldname;
1551
1552 if (p = strrchr (temp, '\\'))
1553 p++;
1554 else
1555 p = temp;
1556
1557 do
1558 {
1559 /* Force temp name to require a manufactured 8.3 alias - this
1560 seems to make the second rename work properly. */
1561 sprintf (p, ".%s.%u", o, i);
1562 i++;
1563 result = rename (oldname, temp);
1564 }
1565 /* This loop must surely terminate! */
1566 while (result < 0 && errno == EEXIST);
1567 if (result < 0)
1568 return -1;
1569 }
1570
1571 /* Emulate Unix behaviour - newname is deleted if it already exists
1572 (at least if it is a file; don't do this for directories).
1573
1574 Since we mustn't do this if we are just changing the case of the
1575 file name (we would end up deleting the file we are trying to
1576 rename!), we let rename detect if the destination file already
1577 exists - that way we avoid the possible pitfalls of trying to
1578 determine ourselves whether two names really refer to the same
1579 file, which is not always possible in the general case. (Consider
1580 all the permutations of shared or subst'd drives, etc.) */
1581
1582 newname = map_w32_filename (newname, NULL);
1583 result = rename (temp, newname);
1584
1585 if (result < 0
1586 && errno == EEXIST
1587 && _chmod (newname, 0666) == 0
1588 && _unlink (newname) == 0)
1589 result = rename (temp, newname);
1590
1591 return result;
1592 }
1593
1594 int
1595 sys_rmdir (const char * path)
1596 {
1597 return _rmdir (map_w32_filename (path, NULL));
1598 }
1599
1600 int
1601 sys_unlink (const char * path)
1602 {
1603 path = map_w32_filename (path, NULL);
1604
1605 /* On Unix, unlink works without write permission. */
1606 _chmod (path, 0666);
1607 return _unlink (path);
1608 }
1609
1610 static FILETIME utc_base_ft;
1611 static long double utc_base;
1612 static int init = 0;
1613
1614 static time_t
1615 convert_time (FILETIME ft)
1616 {
1617 long double ret;
1618
1619 if (!init)
1620 {
1621 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1622 SYSTEMTIME st;
1623
1624 st.wYear = 1970;
1625 st.wMonth = 1;
1626 st.wDay = 1;
1627 st.wHour = 0;
1628 st.wMinute = 0;
1629 st.wSecond = 0;
1630 st.wMilliseconds = 0;
1631
1632 SystemTimeToFileTime (&st, &utc_base_ft);
1633 utc_base = (long double) utc_base_ft.dwHighDateTime
1634 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1635 init = 1;
1636 }
1637
1638 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1639 return 0;
1640
1641 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1642 ret -= utc_base;
1643 return (time_t) (ret * 1e-7);
1644 }
1645
1646 void
1647 convert_from_time_t (time_t time, FILETIME * pft)
1648 {
1649 long double tmp;
1650
1651 if (!init)
1652 {
1653 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1654 SYSTEMTIME st;
1655
1656 st.wYear = 1970;
1657 st.wMonth = 1;
1658 st.wDay = 1;
1659 st.wHour = 0;
1660 st.wMinute = 0;
1661 st.wSecond = 0;
1662 st.wMilliseconds = 0;
1663
1664 SystemTimeToFileTime (&st, &utc_base_ft);
1665 utc_base = (long double) utc_base_ft.dwHighDateTime
1666 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1667 init = 1;
1668 }
1669
1670 /* time in 100ns units since 1-Jan-1601 */
1671 tmp = (long double) time * 1e7 + utc_base;
1672 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1673 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
1674 }
1675
1676 #if 0
1677 /* No reason to keep this; faking inode values either by hashing or even
1678 using the file index from GetInformationByHandle, is not perfect and
1679 so by default Emacs doesn't use the inode values on Windows.
1680 Instead, we now determine file-truename correctly (except for
1681 possible drive aliasing etc). */
1682
1683 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
1684 static unsigned
1685 hashval (const unsigned char * str)
1686 {
1687 unsigned h = 0;
1688 while (*str)
1689 {
1690 h = (h << 4) + *str++;
1691 h ^= (h >> 28);
1692 }
1693 return h;
1694 }
1695
1696 /* Return the hash value of the canonical pathname, excluding the
1697 drive/UNC header, to get a hopefully unique inode number. */
1698 static DWORD
1699 generate_inode_val (const char * name)
1700 {
1701 char fullname[ MAX_PATH ];
1702 char * p;
1703 unsigned hash;
1704
1705 /* Get the truly canonical filename, if it exists. (Note: this
1706 doesn't resolve aliasing due to subst commands, or recognise hard
1707 links. */
1708 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
1709 abort ();
1710
1711 parse_root (fullname, &p);
1712 /* Normal W32 filesystems are still case insensitive. */
1713 _strlwr (p);
1714 return hashval (p);
1715 }
1716
1717 #endif
1718
1719 /* MSVC stat function can't cope with UNC names and has other bugs, so
1720 replace it with our own. This also allows us to calculate consistent
1721 inode values without hacks in the main Emacs code. */
1722 int
1723 stat (const char * path, struct stat * buf)
1724 {
1725 char *name, *r;
1726 WIN32_FIND_DATA wfd;
1727 HANDLE fh;
1728 DWORD fake_inode;
1729 int permission;
1730 int len;
1731 int rootdir = FALSE;
1732
1733 if (path == NULL || buf == NULL)
1734 {
1735 errno = EFAULT;
1736 return -1;
1737 }
1738
1739 name = (char *) map_w32_filename (path, &path);
1740 /* must be valid filename, no wild cards or other illegal characters */
1741 if (strpbrk (name, "*?|<>\""))
1742 {
1743 errno = ENOENT;
1744 return -1;
1745 }
1746
1747 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
1748 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
1749 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
1750 {
1751 r[1] = r[2] = '\0';
1752 }
1753
1754 /* Remove trailing directory separator, unless name is the root
1755 directory of a drive or UNC volume in which case ensure there
1756 is a trailing separator. */
1757 len = strlen (name);
1758 rootdir = (path >= name + len - 1
1759 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1760 name = strcpy (alloca (len + 2), name);
1761
1762 if (rootdir)
1763 {
1764 if (!IS_DIRECTORY_SEP (name[len-1]))
1765 strcat (name, "\\");
1766 if (GetDriveType (name) < 2)
1767 {
1768 errno = ENOENT;
1769 return -1;
1770 }
1771 memset (&wfd, 0, sizeof (wfd));
1772 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1773 wfd.ftCreationTime = utc_base_ft;
1774 wfd.ftLastAccessTime = utc_base_ft;
1775 wfd.ftLastWriteTime = utc_base_ft;
1776 strcpy (wfd.cFileName, name);
1777 }
1778 else
1779 {
1780 if (IS_DIRECTORY_SEP (name[len-1]))
1781 name[len - 1] = 0;
1782
1783 /* (This is hacky, but helps when doing file completions on
1784 network drives.) Optimize by using information available from
1785 active readdir if possible. */
1786 if (dir_find_handle != INVALID_HANDLE_VALUE
1787 && (len = strlen (dir_pathname)),
1788 strnicmp (name, dir_pathname, len) == 0
1789 && IS_DIRECTORY_SEP (name[len])
1790 && stricmp (name + len + 1, dir_static.d_name) == 0)
1791 {
1792 /* This was the last entry returned by readdir. */
1793 wfd = dir_find_data;
1794 }
1795 else
1796 {
1797 fh = FindFirstFile (name, &wfd);
1798 if (fh == INVALID_HANDLE_VALUE)
1799 {
1800 errno = ENOENT;
1801 return -1;
1802 }
1803 FindClose (fh);
1804 }
1805 }
1806
1807 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1808 {
1809 buf->st_mode = _S_IFDIR;
1810 buf->st_nlink = 2; /* doesn't really matter */
1811 fake_inode = 0; /* this doesn't either I think */
1812 }
1813 else if (!NILP (Vw32_get_true_file_attributes))
1814 {
1815 /* This is more accurate in terms of gettting the correct number
1816 of links, but is quite slow (it is noticable when Emacs is
1817 making a list of file name completions). */
1818 BY_HANDLE_FILE_INFORMATION info;
1819
1820 /* No access rights required to get info. */
1821 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1822
1823 if (GetFileInformationByHandle (fh, &info))
1824 {
1825 switch (GetFileType (fh))
1826 {
1827 case FILE_TYPE_DISK:
1828 buf->st_mode = _S_IFREG;
1829 break;
1830 case FILE_TYPE_PIPE:
1831 buf->st_mode = _S_IFIFO;
1832 break;
1833 case FILE_TYPE_CHAR:
1834 case FILE_TYPE_UNKNOWN:
1835 default:
1836 buf->st_mode = _S_IFCHR;
1837 }
1838 buf->st_nlink = info.nNumberOfLinks;
1839 /* Might as well use file index to fake inode values, but this
1840 is not guaranteed to be unique unless we keep a handle open
1841 all the time (even then there are situations where it is
1842 not unique). Reputedly, there are at most 48 bits of info
1843 (on NTFS, presumably less on FAT). */
1844 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1845 CloseHandle (fh);
1846 }
1847 else
1848 {
1849 errno = EACCES;
1850 return -1;
1851 }
1852 }
1853 else
1854 {
1855 /* Don't bother to make this information more accurate. */
1856 buf->st_mode = _S_IFREG;
1857 buf->st_nlink = 1;
1858 fake_inode = 0;
1859 }
1860
1861 #if 0
1862 /* Not sure if there is any point in this. */
1863 if (!NILP (Vw32_generate_fake_inodes))
1864 fake_inode = generate_inode_val (name);
1865 else if (fake_inode == 0)
1866 {
1867 /* For want of something better, try to make everything unique. */
1868 static DWORD gen_num = 0;
1869 fake_inode = ++gen_num;
1870 }
1871 #endif
1872
1873 /* MSVC defines _ino_t to be short; other libc's might not. */
1874 if (sizeof (buf->st_ino) == 2)
1875 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1876 else
1877 buf->st_ino = fake_inode;
1878
1879 /* consider files to belong to current user */
1880 buf->st_uid = the_passwd.pw_uid;
1881 buf->st_gid = the_passwd.pw_gid;
1882
1883 /* volume_info is set indirectly by map_w32_filename */
1884 buf->st_dev = volume_info.serialnum;
1885 buf->st_rdev = volume_info.serialnum;
1886
1887
1888 buf->st_size = wfd.nFileSizeLow;
1889
1890 /* Convert timestamps to Unix format. */
1891 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1892 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1893 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1894 buf->st_ctime = convert_time (wfd.ftCreationTime);
1895 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1896
1897 /* determine rwx permissions */
1898 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1899 permission = _S_IREAD;
1900 else
1901 permission = _S_IREAD | _S_IWRITE;
1902
1903 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1904 permission |= _S_IEXEC;
1905 else if (is_exec (name))
1906 permission |= _S_IEXEC;
1907
1908 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1909
1910 return 0;
1911 }
1912
1913 /* Provide fstat and utime as well as stat for consistent handling of
1914 file timestamps. */
1915 int
1916 fstat (int desc, struct stat * buf)
1917 {
1918 HANDLE fh = (HANDLE) _get_osfhandle (desc);
1919 BY_HANDLE_FILE_INFORMATION info;
1920 DWORD fake_inode;
1921 int permission;
1922
1923 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
1924 {
1925 case FILE_TYPE_DISK:
1926 buf->st_mode = _S_IFREG;
1927 if (!GetFileInformationByHandle (fh, &info))
1928 {
1929 errno = EACCES;
1930 return -1;
1931 }
1932 break;
1933 case FILE_TYPE_PIPE:
1934 buf->st_mode = _S_IFIFO;
1935 goto non_disk;
1936 case FILE_TYPE_CHAR:
1937 case FILE_TYPE_UNKNOWN:
1938 default:
1939 buf->st_mode = _S_IFCHR;
1940 non_disk:
1941 memset (&info, 0, sizeof (info));
1942 info.dwFileAttributes = 0;
1943 info.ftCreationTime = utc_base_ft;
1944 info.ftLastAccessTime = utc_base_ft;
1945 info.ftLastWriteTime = utc_base_ft;
1946 }
1947
1948 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1949 {
1950 buf->st_mode = _S_IFDIR;
1951 buf->st_nlink = 2; /* doesn't really matter */
1952 fake_inode = 0; /* this doesn't either I think */
1953 }
1954 else
1955 {
1956 buf->st_nlink = info.nNumberOfLinks;
1957 /* Might as well use file index to fake inode values, but this
1958 is not guaranteed to be unique unless we keep a handle open
1959 all the time (even then there are situations where it is
1960 not unique). Reputedly, there are at most 48 bits of info
1961 (on NTFS, presumably less on FAT). */
1962 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1963 }
1964
1965 /* MSVC defines _ino_t to be short; other libc's might not. */
1966 if (sizeof (buf->st_ino) == 2)
1967 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1968 else
1969 buf->st_ino = fake_inode;
1970
1971 /* consider files to belong to current user */
1972 buf->st_uid = 0;
1973 buf->st_gid = 0;
1974
1975 buf->st_dev = info.dwVolumeSerialNumber;
1976 buf->st_rdev = info.dwVolumeSerialNumber;
1977
1978 buf->st_size = info.nFileSizeLow;
1979
1980 /* Convert timestamps to Unix format. */
1981 buf->st_mtime = convert_time (info.ftLastWriteTime);
1982 buf->st_atime = convert_time (info.ftLastAccessTime);
1983 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1984 buf->st_ctime = convert_time (info.ftCreationTime);
1985 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1986
1987 /* determine rwx permissions */
1988 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1989 permission = _S_IREAD;
1990 else
1991 permission = _S_IREAD | _S_IWRITE;
1992
1993 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1994 permission |= _S_IEXEC;
1995 else
1996 {
1997 #if 0 /* no way of knowing the filename */
1998 char * p = strrchr (name, '.');
1999 if (p != NULL &&
2000 (stricmp (p, ".exe") == 0 ||
2001 stricmp (p, ".com") == 0 ||
2002 stricmp (p, ".bat") == 0 ||
2003 stricmp (p, ".cmd") == 0))
2004 permission |= _S_IEXEC;
2005 #endif
2006 }
2007
2008 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2009
2010 return 0;
2011 }
2012
2013 int
2014 utime (const char *name, struct utimbuf *times)
2015 {
2016 struct utimbuf deftime;
2017 HANDLE fh;
2018 FILETIME mtime;
2019 FILETIME atime;
2020
2021 if (times == NULL)
2022 {
2023 deftime.modtime = deftime.actime = time (NULL);
2024 times = &deftime;
2025 }
2026
2027 /* Need write access to set times. */
2028 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2029 0, OPEN_EXISTING, 0, NULL);
2030 if (fh)
2031 {
2032 convert_from_time_t (times->actime, &atime);
2033 convert_from_time_t (times->modtime, &mtime);
2034 if (!SetFileTime (fh, NULL, &atime, &mtime))
2035 {
2036 CloseHandle (fh);
2037 errno = EACCES;
2038 return -1;
2039 }
2040 CloseHandle (fh);
2041 }
2042 else
2043 {
2044 errno = EINVAL;
2045 return -1;
2046 }
2047 return 0;
2048 }
2049
2050 #ifdef HAVE_SOCKETS
2051
2052 /* Wrappers for winsock functions to map between our file descriptors
2053 and winsock's handles; also set h_errno for convenience.
2054
2055 To allow Emacs to run on systems which don't have winsock support
2056 installed, we dynamically link to winsock on startup if present, and
2057 otherwise provide the minimum necessary functionality
2058 (eg. gethostname). */
2059
2060 /* function pointers for relevant socket functions */
2061 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2062 void (PASCAL *pfn_WSASetLastError) (int iError);
2063 int (PASCAL *pfn_WSAGetLastError) (void);
2064 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2065 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2066 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2067 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2068 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2069 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2070 int (PASCAL *pfn_closesocket) (SOCKET s);
2071 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2072 int (PASCAL *pfn_WSACleanup) (void);
2073
2074 u_short (PASCAL *pfn_htons) (u_short hostshort);
2075 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2076 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2077 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2078 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2079 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2080
2081 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2082 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2083 #ifndef HANDLE_FLAG_INHERIT
2084 #define HANDLE_FLAG_INHERIT 1
2085 #endif
2086
2087 HANDLE winsock_lib;
2088 static int winsock_inuse;
2089
2090 BOOL
2091 term_winsock (void)
2092 {
2093 if (winsock_lib != NULL && winsock_inuse == 0)
2094 {
2095 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2096 after WSAStartup returns successfully, but it seems reasonable
2097 to allow unloading winsock anyway in that case. */
2098 if (pfn_WSACleanup () == 0 ||
2099 pfn_WSAGetLastError () == WSAENETDOWN)
2100 {
2101 if (FreeLibrary (winsock_lib))
2102 winsock_lib = NULL;
2103 return TRUE;
2104 }
2105 }
2106 return FALSE;
2107 }
2108
2109 BOOL
2110 init_winsock (int load_now)
2111 {
2112 WSADATA winsockData;
2113
2114 if (winsock_lib != NULL)
2115 return TRUE;
2116
2117 pfn_SetHandleInformation = NULL;
2118 pfn_SetHandleInformation
2119 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2120 "SetHandleInformation");
2121
2122 winsock_lib = LoadLibrary ("wsock32.dll");
2123
2124 if (winsock_lib != NULL)
2125 {
2126 /* dynamically link to socket functions */
2127
2128 #define LOAD_PROC(fn) \
2129 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2130 goto fail;
2131
2132 LOAD_PROC( WSAStartup );
2133 LOAD_PROC( WSASetLastError );
2134 LOAD_PROC( WSAGetLastError );
2135 LOAD_PROC( socket );
2136 LOAD_PROC( bind );
2137 LOAD_PROC( connect );
2138 LOAD_PROC( ioctlsocket );
2139 LOAD_PROC( recv );
2140 LOAD_PROC( send );
2141 LOAD_PROC( closesocket );
2142 LOAD_PROC( shutdown );
2143 LOAD_PROC( htons );
2144 LOAD_PROC( ntohs );
2145 LOAD_PROC( inet_addr );
2146 LOAD_PROC( gethostname );
2147 LOAD_PROC( gethostbyname );
2148 LOAD_PROC( getservbyname );
2149 LOAD_PROC( WSACleanup );
2150
2151 #undef LOAD_PROC
2152
2153 /* specify version 1.1 of winsock */
2154 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2155 {
2156 if (winsockData.wVersion != 0x101)
2157 goto fail;
2158
2159 if (!load_now)
2160 {
2161 /* Report that winsock exists and is usable, but leave
2162 socket functions disabled. I am assuming that calling
2163 WSAStartup does not require any network interaction,
2164 and in particular does not cause or require a dial-up
2165 connection to be established. */
2166
2167 pfn_WSACleanup ();
2168 FreeLibrary (winsock_lib);
2169 winsock_lib = NULL;
2170 }
2171 winsock_inuse = 0;
2172 return TRUE;
2173 }
2174
2175 fail:
2176 FreeLibrary (winsock_lib);
2177 winsock_lib = NULL;
2178 }
2179
2180 return FALSE;
2181 }
2182
2183
2184 int h_errno = 0;
2185
2186 /* function to set h_errno for compatability; map winsock error codes to
2187 normal system codes where they overlap (non-overlapping definitions
2188 are already in <sys/socket.h> */
2189 static void set_errno ()
2190 {
2191 if (winsock_lib == NULL)
2192 h_errno = EINVAL;
2193 else
2194 h_errno = pfn_WSAGetLastError ();
2195
2196 switch (h_errno)
2197 {
2198 case WSAEACCES: h_errno = EACCES; break;
2199 case WSAEBADF: h_errno = EBADF; break;
2200 case WSAEFAULT: h_errno = EFAULT; break;
2201 case WSAEINTR: h_errno = EINTR; break;
2202 case WSAEINVAL: h_errno = EINVAL; break;
2203 case WSAEMFILE: h_errno = EMFILE; break;
2204 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2205 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2206 }
2207 errno = h_errno;
2208 }
2209
2210 static void check_errno ()
2211 {
2212 if (h_errno == 0 && winsock_lib != NULL)
2213 pfn_WSASetLastError (0);
2214 }
2215
2216 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2217 but I believe the method of keeping the socket handle separate (and
2218 insuring it is not inheritable) is the correct one. */
2219
2220 //#define SOCK_REPLACE_HANDLE
2221
2222 #ifdef SOCK_REPLACE_HANDLE
2223 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2224 #else
2225 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2226 #endif
2227
2228 int
2229 sys_socket(int af, int type, int protocol)
2230 {
2231 int fd;
2232 long s;
2233 child_process * cp;
2234
2235 if (winsock_lib == NULL)
2236 {
2237 h_errno = ENETDOWN;
2238 return INVALID_SOCKET;
2239 }
2240
2241 check_errno ();
2242
2243 /* call the real socket function */
2244 s = (long) pfn_socket (af, type, protocol);
2245
2246 if (s != INVALID_SOCKET)
2247 {
2248 /* Although under NT 3.5 _open_osfhandle will accept a socket
2249 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2250 that does not work under NT 3.1. However, we can get the same
2251 effect by using a backdoor function to replace an existing
2252 descriptor handle with the one we want. */
2253
2254 /* allocate a file descriptor (with appropriate flags) */
2255 fd = _open ("NUL:", _O_RDWR);
2256 if (fd >= 0)
2257 {
2258 #ifdef SOCK_REPLACE_HANDLE
2259 /* now replace handle to NUL with our socket handle */
2260 CloseHandle ((HANDLE) _get_osfhandle (fd));
2261 _free_osfhnd (fd);
2262 _set_osfhnd (fd, s);
2263 /* setmode (fd, _O_BINARY); */
2264 #else
2265 /* Make a non-inheritable copy of the socket handle. */
2266 {
2267 HANDLE parent;
2268 HANDLE new_s = INVALID_HANDLE_VALUE;
2269
2270 parent = GetCurrentProcess ();
2271
2272 /* Apparently there is a bug in NT 3.51 with some service
2273 packs, which prevents using DuplicateHandle to make a
2274 socket handle non-inheritable (causes WSACleanup to
2275 hang). The work-around is to use SetHandleInformation
2276 instead if it is available and implemented. */
2277 if (!pfn_SetHandleInformation
2278 || !pfn_SetHandleInformation ((HANDLE) s,
2279 HANDLE_FLAG_INHERIT,
2280 0))
2281 {
2282 DuplicateHandle (parent,
2283 (HANDLE) s,
2284 parent,
2285 &new_s,
2286 0,
2287 FALSE,
2288 DUPLICATE_SAME_ACCESS);
2289 pfn_closesocket (s);
2290 s = (SOCKET) new_s;
2291 }
2292 fd_info[fd].hnd = (HANDLE) s;
2293 }
2294 #endif
2295
2296 /* set our own internal flags */
2297 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2298
2299 cp = new_child ();
2300 if (cp)
2301 {
2302 cp->fd = fd;
2303 cp->status = STATUS_READ_ACKNOWLEDGED;
2304
2305 /* attach child_process to fd_info */
2306 if (fd_info[ fd ].cp != NULL)
2307 {
2308 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2309 abort ();
2310 }
2311
2312 fd_info[ fd ].cp = cp;
2313
2314 /* success! */
2315 winsock_inuse++; /* count open sockets */
2316 return fd;
2317 }
2318
2319 /* clean up */
2320 _close (fd);
2321 }
2322 pfn_closesocket (s);
2323 h_errno = EMFILE;
2324 }
2325 set_errno ();
2326
2327 return -1;
2328 }
2329
2330
2331 int
2332 sys_bind (int s, const struct sockaddr * addr, int namelen)
2333 {
2334 if (winsock_lib == NULL)
2335 {
2336 h_errno = ENOTSOCK;
2337 return SOCKET_ERROR;
2338 }
2339
2340 check_errno ();
2341 if (fd_info[s].flags & FILE_SOCKET)
2342 {
2343 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
2344 if (rc == SOCKET_ERROR)
2345 set_errno ();
2346 return rc;
2347 }
2348 h_errno = ENOTSOCK;
2349 return SOCKET_ERROR;
2350 }
2351
2352
2353 int
2354 sys_connect (int s, const struct sockaddr * name, int namelen)
2355 {
2356 if (winsock_lib == NULL)
2357 {
2358 h_errno = ENOTSOCK;
2359 return SOCKET_ERROR;
2360 }
2361
2362 check_errno ();
2363 if (fd_info[s].flags & FILE_SOCKET)
2364 {
2365 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
2366 if (rc == SOCKET_ERROR)
2367 set_errno ();
2368 return rc;
2369 }
2370 h_errno = ENOTSOCK;
2371 return SOCKET_ERROR;
2372 }
2373
2374 u_short
2375 sys_htons (u_short hostshort)
2376 {
2377 return (winsock_lib != NULL) ?
2378 pfn_htons (hostshort) : hostshort;
2379 }
2380
2381 u_short
2382 sys_ntohs (u_short netshort)
2383 {
2384 return (winsock_lib != NULL) ?
2385 pfn_ntohs (netshort) : netshort;
2386 }
2387
2388 unsigned long
2389 sys_inet_addr (const char * cp)
2390 {
2391 return (winsock_lib != NULL) ?
2392 pfn_inet_addr (cp) : INADDR_NONE;
2393 }
2394
2395 int
2396 sys_gethostname (char * name, int namelen)
2397 {
2398 if (winsock_lib != NULL)
2399 return pfn_gethostname (name, namelen);
2400
2401 if (namelen > MAX_COMPUTERNAME_LENGTH)
2402 return !GetComputerName (name, &namelen);
2403
2404 h_errno = EFAULT;
2405 return SOCKET_ERROR;
2406 }
2407
2408 struct hostent *
2409 sys_gethostbyname(const char * name)
2410 {
2411 struct hostent * host;
2412
2413 if (winsock_lib == NULL)
2414 {
2415 h_errno = ENETDOWN;
2416 return NULL;
2417 }
2418
2419 check_errno ();
2420 host = pfn_gethostbyname (name);
2421 if (!host)
2422 set_errno ();
2423 return host;
2424 }
2425
2426 struct servent *
2427 sys_getservbyname(const char * name, const char * proto)
2428 {
2429 struct servent * serv;
2430
2431 if (winsock_lib == NULL)
2432 {
2433 h_errno = ENETDOWN;
2434 return NULL;
2435 }
2436
2437 check_errno ();
2438 serv = pfn_getservbyname (name, proto);
2439 if (!serv)
2440 set_errno ();
2441 return serv;
2442 }
2443
2444 int
2445 sys_shutdown (int s, int how)
2446 {
2447 int rc;
2448
2449 if (winsock_lib == NULL)
2450 {
2451 h_errno = ENETDOWN;
2452 return SOCKET_ERROR;
2453 }
2454
2455 check_errno ();
2456 if (fd_info[s].flags & FILE_SOCKET)
2457 {
2458 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
2459 if (rc == SOCKET_ERROR)
2460 set_errno ();
2461 return rc;
2462 }
2463 h_errno = ENOTSOCK;
2464 return SOCKET_ERROR;
2465 }
2466
2467 #endif /* HAVE_SOCKETS */
2468
2469
2470 /* Shadow main io functions: we need to handle pipes and sockets more
2471 intelligently, and implement non-blocking mode as well. */
2472
2473 int
2474 sys_close (int fd)
2475 {
2476 int rc;
2477
2478 if (fd < 0 || fd >= MAXDESC)
2479 {
2480 errno = EBADF;
2481 return -1;
2482 }
2483
2484 if (fd_info[fd].cp)
2485 {
2486 child_process * cp = fd_info[fd].cp;
2487
2488 fd_info[fd].cp = NULL;
2489
2490 if (CHILD_ACTIVE (cp))
2491 {
2492 /* if last descriptor to active child_process then cleanup */
2493 int i;
2494 for (i = 0; i < MAXDESC; i++)
2495 {
2496 if (i == fd)
2497 continue;
2498 if (fd_info[i].cp == cp)
2499 break;
2500 }
2501 if (i == MAXDESC)
2502 {
2503 #ifdef HAVE_SOCKETS
2504 if (fd_info[fd].flags & FILE_SOCKET)
2505 {
2506 #ifndef SOCK_REPLACE_HANDLE
2507 if (winsock_lib == NULL) abort ();
2508
2509 pfn_shutdown (SOCK_HANDLE (fd), 2);
2510 rc = pfn_closesocket (SOCK_HANDLE (fd));
2511 #endif
2512 winsock_inuse--; /* count open sockets */
2513 }
2514 #endif
2515 delete_child (cp);
2516 }
2517 }
2518 }
2519
2520 /* Note that sockets do not need special treatment here (at least on
2521 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
2522 closesocket is equivalent to CloseHandle, which is to be expected
2523 because socket handles are fully fledged kernel handles. */
2524 rc = _close (fd);
2525
2526 if (rc == 0)
2527 fd_info[fd].flags = 0;
2528
2529 return rc;
2530 }
2531
2532 int
2533 sys_dup (int fd)
2534 {
2535 int new_fd;
2536
2537 new_fd = _dup (fd);
2538 if (new_fd >= 0)
2539 {
2540 /* duplicate our internal info as well */
2541 fd_info[new_fd] = fd_info[fd];
2542 }
2543 return new_fd;
2544 }
2545
2546
2547 int
2548 sys_dup2 (int src, int dst)
2549 {
2550 int rc;
2551
2552 if (dst < 0 || dst >= MAXDESC)
2553 {
2554 errno = EBADF;
2555 return -1;
2556 }
2557
2558 /* make sure we close the destination first if it's a pipe or socket */
2559 if (src != dst && fd_info[dst].flags != 0)
2560 sys_close (dst);
2561
2562 rc = _dup2 (src, dst);
2563 if (rc == 0)
2564 {
2565 /* duplicate our internal info as well */
2566 fd_info[dst] = fd_info[src];
2567 }
2568 return rc;
2569 }
2570
2571 /* Unix pipe() has only one arg */
2572 int
2573 sys_pipe (int * phandles)
2574 {
2575 int rc;
2576 unsigned flags;
2577 child_process * cp;
2578
2579 /* make pipe handles non-inheritable; when we spawn a child, we
2580 replace the relevant handle with an inheritable one. Also put
2581 pipes into binary mode; we will do text mode translation ourselves
2582 if required. */
2583 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
2584
2585 if (rc == 0)
2586 {
2587 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
2588 fd_info[phandles[0]].flags = flags;
2589
2590 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
2591 fd_info[phandles[1]].flags = flags;
2592 }
2593
2594 return rc;
2595 }
2596
2597 /* From ntproc.c */
2598 extern Lisp_Object Vw32_pipe_read_delay;
2599
2600 /* Function to do blocking read of one byte, needed to implement
2601 select. It is only allowed on sockets and pipes. */
2602 int
2603 _sys_read_ahead (int fd)
2604 {
2605 child_process * cp;
2606 int rc;
2607
2608 if (fd < 0 || fd >= MAXDESC)
2609 return STATUS_READ_ERROR;
2610
2611 cp = fd_info[fd].cp;
2612
2613 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
2614 return STATUS_READ_ERROR;
2615
2616 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
2617 || (fd_info[fd].flags & FILE_READ) == 0)
2618 {
2619 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
2620 abort ();
2621 }
2622
2623 cp->status = STATUS_READ_IN_PROGRESS;
2624
2625 if (fd_info[fd].flags & FILE_PIPE)
2626 {
2627 rc = _read (fd, &cp->chr, sizeof (char));
2628
2629 /* Give subprocess time to buffer some more output for us before
2630 reporting that input is available; we need this because Windows 95
2631 connects DOS programs to pipes by making the pipe appear to be
2632 the normal console stdout - as a result most DOS programs will
2633 write to stdout without buffering, ie. one character at a
2634 time. Even some W32 programs do this - "dir" in a command
2635 shell on NT is very slow if we don't do this. */
2636 if (rc > 0)
2637 {
2638 int wait = XINT (Vw32_pipe_read_delay);
2639
2640 if (wait > 0)
2641 Sleep (wait);
2642 else if (wait < 0)
2643 while (++wait <= 0)
2644 /* Yield remainder of our time slice, effectively giving a
2645 temporary priority boost to the child process. */
2646 Sleep (0);
2647 }
2648 }
2649 #ifdef HAVE_SOCKETS
2650 else if (fd_info[fd].flags & FILE_SOCKET)
2651 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
2652 #endif
2653
2654 if (rc == sizeof (char))
2655 cp->status = STATUS_READ_SUCCEEDED;
2656 else
2657 cp->status = STATUS_READ_FAILED;
2658
2659 return cp->status;
2660 }
2661
2662 int
2663 sys_read (int fd, char * buffer, unsigned int count)
2664 {
2665 int nchars;
2666 int to_read;
2667 DWORD waiting;
2668 char * orig_buffer = buffer;
2669
2670 if (fd < 0 || fd >= MAXDESC)
2671 {
2672 errno = EBADF;
2673 return -1;
2674 }
2675
2676 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2677 {
2678 child_process *cp = fd_info[fd].cp;
2679
2680 if ((fd_info[fd].flags & FILE_READ) == 0)
2681 {
2682 errno = EBADF;
2683 return -1;
2684 }
2685
2686 nchars = 0;
2687
2688 /* re-read CR carried over from last read */
2689 if (fd_info[fd].flags & FILE_LAST_CR)
2690 {
2691 if (fd_info[fd].flags & FILE_BINARY) abort ();
2692 *buffer++ = 0x0d;
2693 count--;
2694 nchars++;
2695 fd_info[fd].flags &= ~FILE_LAST_CR;
2696 }
2697
2698 /* presence of a child_process structure means we are operating in
2699 non-blocking mode - otherwise we just call _read directly.
2700 Note that the child_process structure might be missing because
2701 reap_subprocess has been called; in this case the pipe is
2702 already broken, so calling _read on it is okay. */
2703 if (cp)
2704 {
2705 int current_status = cp->status;
2706
2707 switch (current_status)
2708 {
2709 case STATUS_READ_FAILED:
2710 case STATUS_READ_ERROR:
2711 /* report normal EOF if nothing in buffer */
2712 if (nchars <= 0)
2713 fd_info[fd].flags |= FILE_AT_EOF;
2714 return nchars;
2715
2716 case STATUS_READ_READY:
2717 case STATUS_READ_IN_PROGRESS:
2718 DebPrint (("sys_read called when read is in progress\n"));
2719 errno = EWOULDBLOCK;
2720 return -1;
2721
2722 case STATUS_READ_SUCCEEDED:
2723 /* consume read-ahead char */
2724 *buffer++ = cp->chr;
2725 count--;
2726 nchars++;
2727 cp->status = STATUS_READ_ACKNOWLEDGED;
2728 ResetEvent (cp->char_avail);
2729
2730 case STATUS_READ_ACKNOWLEDGED:
2731 break;
2732
2733 default:
2734 DebPrint (("sys_read: bad status %d\n", current_status));
2735 errno = EBADF;
2736 return -1;
2737 }
2738
2739 if (fd_info[fd].flags & FILE_PIPE)
2740 {
2741 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2742 to_read = min (waiting, (DWORD) count);
2743
2744 if (to_read > 0)
2745 nchars += _read (fd, buffer, to_read);
2746 }
2747 #ifdef HAVE_SOCKETS
2748 else /* FILE_SOCKET */
2749 {
2750 if (winsock_lib == NULL) abort ();
2751
2752 /* do the equivalent of a non-blocking read */
2753 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2754 if (waiting == 0 && nchars == 0)
2755 {
2756 h_errno = errno = EWOULDBLOCK;
2757 return -1;
2758 }
2759
2760 if (waiting)
2761 {
2762 /* always use binary mode for sockets */
2763 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2764 if (res == SOCKET_ERROR)
2765 {
2766 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2767 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2768 set_errno ();
2769 return -1;
2770 }
2771 nchars += res;
2772 }
2773 }
2774 #endif
2775 }
2776 else
2777 {
2778 int nread = _read (fd, buffer, count);
2779 if (nread >= 0)
2780 nchars += nread;
2781 else if (nchars == 0)
2782 nchars = nread;
2783 }
2784
2785 if (nchars <= 0)
2786 fd_info[fd].flags |= FILE_AT_EOF;
2787 /* Perform text mode translation if required. */
2788 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
2789 {
2790 nchars = crlf_to_lf (nchars, orig_buffer);
2791 /* If buffer contains only CR, return that. To be absolutely
2792 sure we should attempt to read the next char, but in
2793 practice a CR to be followed by LF would not appear by
2794 itself in the buffer. */
2795 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2796 {
2797 fd_info[fd].flags |= FILE_LAST_CR;
2798 nchars--;
2799 }
2800 }
2801 }
2802 else
2803 nchars = _read (fd, buffer, count);
2804
2805 return nchars;
2806 }
2807
2808 /* For now, don't bother with a non-blocking mode */
2809 int
2810 sys_write (int fd, const void * buffer, unsigned int count)
2811 {
2812 int nchars;
2813
2814 if (fd < 0 || fd >= MAXDESC)
2815 {
2816 errno = EBADF;
2817 return -1;
2818 }
2819
2820 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2821 {
2822 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2823 {
2824 errno = EBADF;
2825 return -1;
2826 }
2827
2828 /* Perform text mode translation if required. */
2829 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2830 {
2831 char * tmpbuf = alloca (count * 2);
2832 unsigned char * src = (void *)buffer;
2833 unsigned char * dst = tmpbuf;
2834 int nbytes = count;
2835
2836 while (1)
2837 {
2838 unsigned char *next;
2839 /* copy next line or remaining bytes */
2840 next = _memccpy (dst, src, '\n', nbytes);
2841 if (next)
2842 {
2843 /* copied one line ending with '\n' */
2844 int copied = next - dst;
2845 nbytes -= copied;
2846 src += copied;
2847 /* insert '\r' before '\n' */
2848 next[-1] = '\r';
2849 next[0] = '\n';
2850 dst = next + 1;
2851 count++;
2852 }
2853 else
2854 /* copied remaining partial line -> now finished */
2855 break;
2856 }
2857 buffer = tmpbuf;
2858 }
2859 }
2860
2861 #ifdef HAVE_SOCKETS
2862 if (fd_info[fd].flags & FILE_SOCKET)
2863 {
2864 if (winsock_lib == NULL) abort ();
2865 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2866 if (nchars == SOCKET_ERROR)
2867 {
2868 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2869 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2870 set_errno ();
2871 }
2872 }
2873 else
2874 #endif
2875 nchars = _write (fd, buffer, count);
2876
2877 return nchars;
2878 }
2879
2880 static void
2881 check_windows_init_file ()
2882 {
2883 extern int noninteractive, inhibit_window_system;
2884
2885 /* A common indication that Emacs is not installed properly is when
2886 it cannot find the Windows installation file. If this file does
2887 not exist in the expected place, tell the user. */
2888
2889 if (!noninteractive && !inhibit_window_system) {
2890 extern Lisp_Object Vwindow_system, Vload_path;
2891 Lisp_Object init_file;
2892 int fd;
2893
2894 init_file = build_string ("term/w32-win");
2895 fd = openp (Vload_path, init_file, ".el:.elc", NULL, 0);
2896 if (fd < 0) {
2897 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
2898 char *init_file_name = XSTRING (init_file)->data;
2899 char *load_path = XSTRING (load_path_print)->data;
2900 char *buffer = alloca (1024);
2901
2902 sprintf (buffer,
2903 "The Emacs Windows initialization file \"%s.el\" "
2904 "could not be found in your Emacs installation. "
2905 "Emacs checked the following directories for this file:\n"
2906 "\n%s\n\n"
2907 "When Emacs cannot find this file, it usually means that it "
2908 "was not installed properly, or its distribution file was "
2909 "not unpacked properly.\nSee the README.W32 file in the "
2910 "top-level Emacs directory for more information.",
2911 init_file_name, load_path);
2912 MessageBox (NULL,
2913 buffer,
2914 "Emacs Abort Dialog",
2915 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
2916 close (fd);
2917
2918 /* Use the low-level Emacs abort. */
2919 #undef abort
2920 abort ();
2921 }
2922 }
2923 }
2924
2925 void
2926 term_ntproc ()
2927 {
2928 #ifdef HAVE_SOCKETS
2929 /* shutdown the socket interface if necessary */
2930 term_winsock ();
2931 #endif
2932
2933 /* Check whether we are shutting down because we cannot find the
2934 Windows initialization file. Do this during shutdown so that
2935 Emacs is initialized as possible, and so that it is out of the
2936 critical startup path. */
2937 check_windows_init_file ();
2938 }
2939
2940 void
2941 init_ntproc ()
2942 {
2943 #ifdef HAVE_SOCKETS
2944 /* Initialise the socket interface now if available and requested by
2945 the user by defining PRELOAD_WINSOCK; otherwise loading will be
2946 delayed until open-network-stream is called (w32-has-winsock can
2947 also be used to dynamically load or reload winsock).
2948
2949 Conveniently, init_environment is called before us, so
2950 PRELOAD_WINSOCK can be set in the registry. */
2951
2952 /* Always initialize this correctly. */
2953 winsock_lib = NULL;
2954
2955 if (getenv ("PRELOAD_WINSOCK") != NULL)
2956 init_winsock (TRUE);
2957 #endif
2958
2959 /* Initial preparation for subprocess support: replace our standard
2960 handles with non-inheritable versions. */
2961 {
2962 HANDLE parent;
2963 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2964 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2965 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2966
2967 parent = GetCurrentProcess ();
2968
2969 /* ignore errors when duplicating and closing; typically the
2970 handles will be invalid when running as a gui program. */
2971 DuplicateHandle (parent,
2972 GetStdHandle (STD_INPUT_HANDLE),
2973 parent,
2974 &stdin_save,
2975 0,
2976 FALSE,
2977 DUPLICATE_SAME_ACCESS);
2978
2979 DuplicateHandle (parent,
2980 GetStdHandle (STD_OUTPUT_HANDLE),
2981 parent,
2982 &stdout_save,
2983 0,
2984 FALSE,
2985 DUPLICATE_SAME_ACCESS);
2986
2987 DuplicateHandle (parent,
2988 GetStdHandle (STD_ERROR_HANDLE),
2989 parent,
2990 &stderr_save,
2991 0,
2992 FALSE,
2993 DUPLICATE_SAME_ACCESS);
2994
2995 fclose (stdin);
2996 fclose (stdout);
2997 fclose (stderr);
2998
2999 if (stdin_save != INVALID_HANDLE_VALUE)
3000 _open_osfhandle ((long) stdin_save, O_TEXT);
3001 else
3002 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3003 _fdopen (0, "r");
3004
3005 if (stdout_save != INVALID_HANDLE_VALUE)
3006 _open_osfhandle ((long) stdout_save, O_TEXT);
3007 else
3008 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3009 _fdopen (1, "w");
3010
3011 if (stderr_save != INVALID_HANDLE_VALUE)
3012 _open_osfhandle ((long) stderr_save, O_TEXT);
3013 else
3014 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3015 _fdopen (2, "w");
3016 }
3017
3018 /* unfortunately, atexit depends on implementation of malloc */
3019 /* atexit (term_ntproc); */
3020 signal (SIGABRT, term_ntproc);
3021
3022 /* determine which drives are fixed, for GetCachedVolumeInformation */
3023 {
3024 /* GetDriveType must have trailing backslash. */
3025 char drive[] = "A:\\";
3026
3027 /* Loop over all possible drive letters */
3028 while (*drive <= 'Z')
3029 {
3030 /* Record if this drive letter refers to a fixed drive. */
3031 fixed_drives[DRIVE_INDEX (*drive)] =
3032 (GetDriveType (drive) == DRIVE_FIXED);
3033
3034 (*drive)++;
3035 }
3036 }
3037 }
3038
3039 /* end of nt.c */