#include sys/file.h
[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 }
1564 /* This loop must surely terminate! */
1565 while (rename (oldname, temp) < 0 && errno == EEXIST);
1566 if (errno != EEXIST)
1567 return -1;
1568 }
1569
1570 /* Emulate Unix behaviour - newname is deleted if it already exists
1571 (at least if it is a file; don't do this for directories).
1572
1573 Since we mustn't do this if we are just changing the case of the
1574 file name (we would end up deleting the file we are trying to
1575 rename!), we let rename detect if the destination file already
1576 exists - that way we avoid the possible pitfalls of trying to
1577 determine ourselves whether two names really refer to the same
1578 file, which is not always possible in the general case. (Consider
1579 all the permutations of shared or subst'd drives, etc.) */
1580
1581 newname = map_w32_filename (newname, NULL);
1582 result = rename (temp, newname);
1583
1584 if (result < 0
1585 && errno == EEXIST
1586 && _chmod (newname, 0666) == 0
1587 && _unlink (newname) == 0)
1588 result = rename (temp, newname);
1589
1590 return result;
1591 }
1592
1593 int
1594 sys_rmdir (const char * path)
1595 {
1596 return _rmdir (map_w32_filename (path, NULL));
1597 }
1598
1599 int
1600 sys_unlink (const char * path)
1601 {
1602 path = map_w32_filename (path, NULL);
1603
1604 /* On Unix, unlink works without write permission. */
1605 _chmod (path, 0666);
1606 return _unlink (path);
1607 }
1608
1609 static FILETIME utc_base_ft;
1610 static long double utc_base;
1611 static int init = 0;
1612
1613 static time_t
1614 convert_time (FILETIME ft)
1615 {
1616 long double ret;
1617
1618 if (!init)
1619 {
1620 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1621 SYSTEMTIME st;
1622
1623 st.wYear = 1970;
1624 st.wMonth = 1;
1625 st.wDay = 1;
1626 st.wHour = 0;
1627 st.wMinute = 0;
1628 st.wSecond = 0;
1629 st.wMilliseconds = 0;
1630
1631 SystemTimeToFileTime (&st, &utc_base_ft);
1632 utc_base = (long double) utc_base_ft.dwHighDateTime
1633 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1634 init = 1;
1635 }
1636
1637 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1638 return 0;
1639
1640 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1641 ret -= utc_base;
1642 return (time_t) (ret * 1e-7);
1643 }
1644
1645 void
1646 convert_from_time_t (time_t time, FILETIME * pft)
1647 {
1648 long double tmp;
1649
1650 if (!init)
1651 {
1652 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1653 SYSTEMTIME st;
1654
1655 st.wYear = 1970;
1656 st.wMonth = 1;
1657 st.wDay = 1;
1658 st.wHour = 0;
1659 st.wMinute = 0;
1660 st.wSecond = 0;
1661 st.wMilliseconds = 0;
1662
1663 SystemTimeToFileTime (&st, &utc_base_ft);
1664 utc_base = (long double) utc_base_ft.dwHighDateTime
1665 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1666 init = 1;
1667 }
1668
1669 /* time in 100ns units since 1-Jan-1601 */
1670 tmp = (long double) time * 1e7 + utc_base;
1671 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1672 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
1673 }
1674
1675 #if 0
1676 /* No reason to keep this; faking inode values either by hashing or even
1677 using the file index from GetInformationByHandle, is not perfect and
1678 so by default Emacs doesn't use the inode values on Windows.
1679 Instead, we now determine file-truename correctly (except for
1680 possible drive aliasing etc). */
1681
1682 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
1683 static unsigned
1684 hashval (const unsigned char * str)
1685 {
1686 unsigned h = 0;
1687 while (*str)
1688 {
1689 h = (h << 4) + *str++;
1690 h ^= (h >> 28);
1691 }
1692 return h;
1693 }
1694
1695 /* Return the hash value of the canonical pathname, excluding the
1696 drive/UNC header, to get a hopefully unique inode number. */
1697 static DWORD
1698 generate_inode_val (const char * name)
1699 {
1700 char fullname[ MAX_PATH ];
1701 char * p;
1702 unsigned hash;
1703
1704 /* Get the truly canonical filename, if it exists. (Note: this
1705 doesn't resolve aliasing due to subst commands, or recognise hard
1706 links. */
1707 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
1708 abort ();
1709
1710 parse_root (fullname, &p);
1711 /* Normal W32 filesystems are still case insensitive. */
1712 _strlwr (p);
1713 return hashval (p);
1714 }
1715
1716 #endif
1717
1718 /* MSVC stat function can't cope with UNC names and has other bugs, so
1719 replace it with our own. This also allows us to calculate consistent
1720 inode values without hacks in the main Emacs code. */
1721 int
1722 stat (const char * path, struct stat * buf)
1723 {
1724 char *name, *r;
1725 WIN32_FIND_DATA wfd;
1726 HANDLE fh;
1727 DWORD fake_inode;
1728 int permission;
1729 int len;
1730 int rootdir = FALSE;
1731
1732 if (path == NULL || buf == NULL)
1733 {
1734 errno = EFAULT;
1735 return -1;
1736 }
1737
1738 name = (char *) map_w32_filename (path, &path);
1739 /* must be valid filename, no wild cards or other illegal characters */
1740 if (strpbrk (name, "*?|<>\""))
1741 {
1742 errno = ENOENT;
1743 return -1;
1744 }
1745
1746 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
1747 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
1748 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
1749 {
1750 r[1] = r[2] = '\0';
1751 }
1752
1753 /* Remove trailing directory separator, unless name is the root
1754 directory of a drive or UNC volume in which case ensure there
1755 is a trailing separator. */
1756 len = strlen (name);
1757 rootdir = (path >= name + len - 1
1758 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1759 name = strcpy (alloca (len + 2), name);
1760
1761 if (rootdir)
1762 {
1763 if (!IS_DIRECTORY_SEP (name[len-1]))
1764 strcat (name, "\\");
1765 if (GetDriveType (name) < 2)
1766 {
1767 errno = ENOENT;
1768 return -1;
1769 }
1770 memset (&wfd, 0, sizeof (wfd));
1771 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1772 wfd.ftCreationTime = utc_base_ft;
1773 wfd.ftLastAccessTime = utc_base_ft;
1774 wfd.ftLastWriteTime = utc_base_ft;
1775 strcpy (wfd.cFileName, name);
1776 }
1777 else
1778 {
1779 if (IS_DIRECTORY_SEP (name[len-1]))
1780 name[len - 1] = 0;
1781
1782 /* (This is hacky, but helps when doing file completions on
1783 network drives.) Optimize by using information available from
1784 active readdir if possible. */
1785 if (dir_find_handle != INVALID_HANDLE_VALUE
1786 && (len = strlen (dir_pathname)),
1787 strnicmp (name, dir_pathname, len) == 0
1788 && IS_DIRECTORY_SEP (name[len])
1789 && stricmp (name + len + 1, dir_static.d_name) == 0)
1790 {
1791 /* This was the last entry returned by readdir. */
1792 wfd = dir_find_data;
1793 }
1794 else
1795 {
1796 fh = FindFirstFile (name, &wfd);
1797 if (fh == INVALID_HANDLE_VALUE)
1798 {
1799 errno = ENOENT;
1800 return -1;
1801 }
1802 FindClose (fh);
1803 }
1804 }
1805
1806 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1807 {
1808 buf->st_mode = _S_IFDIR;
1809 buf->st_nlink = 2; /* doesn't really matter */
1810 fake_inode = 0; /* this doesn't either I think */
1811 }
1812 else if (!NILP (Vw32_get_true_file_attributes))
1813 {
1814 /* This is more accurate in terms of gettting the correct number
1815 of links, but is quite slow (it is noticable when Emacs is
1816 making a list of file name completions). */
1817 BY_HANDLE_FILE_INFORMATION info;
1818
1819 /* No access rights required to get info. */
1820 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1821
1822 if (GetFileInformationByHandle (fh, &info))
1823 {
1824 switch (GetFileType (fh))
1825 {
1826 case FILE_TYPE_DISK:
1827 buf->st_mode = _S_IFREG;
1828 break;
1829 case FILE_TYPE_PIPE:
1830 buf->st_mode = _S_IFIFO;
1831 break;
1832 case FILE_TYPE_CHAR:
1833 case FILE_TYPE_UNKNOWN:
1834 default:
1835 buf->st_mode = _S_IFCHR;
1836 }
1837 buf->st_nlink = info.nNumberOfLinks;
1838 /* Might as well use file index to fake inode values, but this
1839 is not guaranteed to be unique unless we keep a handle open
1840 all the time (even then there are situations where it is
1841 not unique). Reputedly, there are at most 48 bits of info
1842 (on NTFS, presumably less on FAT). */
1843 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1844 CloseHandle (fh);
1845 }
1846 else
1847 {
1848 errno = EACCES;
1849 return -1;
1850 }
1851 }
1852 else
1853 {
1854 /* Don't bother to make this information more accurate. */
1855 buf->st_mode = _S_IFREG;
1856 buf->st_nlink = 1;
1857 fake_inode = 0;
1858 }
1859
1860 #if 0
1861 /* Not sure if there is any point in this. */
1862 if (!NILP (Vw32_generate_fake_inodes))
1863 fake_inode = generate_inode_val (name);
1864 else if (fake_inode == 0)
1865 {
1866 /* For want of something better, try to make everything unique. */
1867 static DWORD gen_num = 0;
1868 fake_inode = ++gen_num;
1869 }
1870 #endif
1871
1872 /* MSVC defines _ino_t to be short; other libc's might not. */
1873 if (sizeof (buf->st_ino) == 2)
1874 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1875 else
1876 buf->st_ino = fake_inode;
1877
1878 /* consider files to belong to current user */
1879 buf->st_uid = the_passwd.pw_uid;
1880 buf->st_gid = the_passwd.pw_gid;
1881
1882 /* volume_info is set indirectly by map_w32_filename */
1883 buf->st_dev = volume_info.serialnum;
1884 buf->st_rdev = volume_info.serialnum;
1885
1886
1887 buf->st_size = wfd.nFileSizeLow;
1888
1889 /* Convert timestamps to Unix format. */
1890 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1891 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1892 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1893 buf->st_ctime = convert_time (wfd.ftCreationTime);
1894 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1895
1896 /* determine rwx permissions */
1897 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1898 permission = _S_IREAD;
1899 else
1900 permission = _S_IREAD | _S_IWRITE;
1901
1902 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1903 permission |= _S_IEXEC;
1904 else if (is_exec (name))
1905 permission |= _S_IEXEC;
1906
1907 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1908
1909 return 0;
1910 }
1911
1912 /* Provide fstat and utime as well as stat for consistent handling of
1913 file timestamps. */
1914 int
1915 fstat (int desc, struct stat * buf)
1916 {
1917 HANDLE fh = (HANDLE) _get_osfhandle (desc);
1918 BY_HANDLE_FILE_INFORMATION info;
1919 DWORD fake_inode;
1920 int permission;
1921
1922 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
1923 {
1924 case FILE_TYPE_DISK:
1925 buf->st_mode = _S_IFREG;
1926 if (!GetFileInformationByHandle (fh, &info))
1927 {
1928 errno = EACCES;
1929 return -1;
1930 }
1931 break;
1932 case FILE_TYPE_PIPE:
1933 buf->st_mode = _S_IFIFO;
1934 goto non_disk;
1935 case FILE_TYPE_CHAR:
1936 case FILE_TYPE_UNKNOWN:
1937 default:
1938 buf->st_mode = _S_IFCHR;
1939 non_disk:
1940 memset (&info, 0, sizeof (info));
1941 info.dwFileAttributes = 0;
1942 info.ftCreationTime = utc_base_ft;
1943 info.ftLastAccessTime = utc_base_ft;
1944 info.ftLastWriteTime = utc_base_ft;
1945 }
1946
1947 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1948 {
1949 buf->st_mode = _S_IFDIR;
1950 buf->st_nlink = 2; /* doesn't really matter */
1951 fake_inode = 0; /* this doesn't either I think */
1952 }
1953 else
1954 {
1955 buf->st_nlink = info.nNumberOfLinks;
1956 /* Might as well use file index to fake inode values, but this
1957 is not guaranteed to be unique unless we keep a handle open
1958 all the time (even then there are situations where it is
1959 not unique). Reputedly, there are at most 48 bits of info
1960 (on NTFS, presumably less on FAT). */
1961 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1962 }
1963
1964 /* MSVC defines _ino_t to be short; other libc's might not. */
1965 if (sizeof (buf->st_ino) == 2)
1966 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1967 else
1968 buf->st_ino = fake_inode;
1969
1970 /* consider files to belong to current user */
1971 buf->st_uid = 0;
1972 buf->st_gid = 0;
1973
1974 buf->st_dev = info.dwVolumeSerialNumber;
1975 buf->st_rdev = info.dwVolumeSerialNumber;
1976
1977 buf->st_size = info.nFileSizeLow;
1978
1979 /* Convert timestamps to Unix format. */
1980 buf->st_mtime = convert_time (info.ftLastWriteTime);
1981 buf->st_atime = convert_time (info.ftLastAccessTime);
1982 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1983 buf->st_ctime = convert_time (info.ftCreationTime);
1984 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1985
1986 /* determine rwx permissions */
1987 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1988 permission = _S_IREAD;
1989 else
1990 permission = _S_IREAD | _S_IWRITE;
1991
1992 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1993 permission |= _S_IEXEC;
1994 else
1995 {
1996 #if 0 /* no way of knowing the filename */
1997 char * p = strrchr (name, '.');
1998 if (p != NULL &&
1999 (stricmp (p, ".exe") == 0 ||
2000 stricmp (p, ".com") == 0 ||
2001 stricmp (p, ".bat") == 0 ||
2002 stricmp (p, ".cmd") == 0))
2003 permission |= _S_IEXEC;
2004 #endif
2005 }
2006
2007 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2008
2009 return 0;
2010 }
2011
2012 int
2013 utime (const char *name, struct utimbuf *times)
2014 {
2015 struct utimbuf deftime;
2016 HANDLE fh;
2017 FILETIME mtime;
2018 FILETIME atime;
2019
2020 if (times == NULL)
2021 {
2022 deftime.modtime = deftime.actime = time (NULL);
2023 times = &deftime;
2024 }
2025
2026 /* Need write access to set times. */
2027 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2028 0, OPEN_EXISTING, 0, NULL);
2029 if (fh)
2030 {
2031 convert_from_time_t (times->actime, &atime);
2032 convert_from_time_t (times->modtime, &mtime);
2033 if (!SetFileTime (fh, NULL, &atime, &mtime))
2034 {
2035 CloseHandle (fh);
2036 errno = EACCES;
2037 return -1;
2038 }
2039 CloseHandle (fh);
2040 }
2041 else
2042 {
2043 errno = EINVAL;
2044 return -1;
2045 }
2046 return 0;
2047 }
2048
2049 #ifdef HAVE_SOCKETS
2050
2051 /* Wrappers for winsock functions to map between our file descriptors
2052 and winsock's handles; also set h_errno for convenience.
2053
2054 To allow Emacs to run on systems which don't have winsock support
2055 installed, we dynamically link to winsock on startup if present, and
2056 otherwise provide the minimum necessary functionality
2057 (eg. gethostname). */
2058
2059 /* function pointers for relevant socket functions */
2060 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2061 void (PASCAL *pfn_WSASetLastError) (int iError);
2062 int (PASCAL *pfn_WSAGetLastError) (void);
2063 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2064 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2065 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2066 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2067 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2068 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2069 int (PASCAL *pfn_closesocket) (SOCKET s);
2070 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2071 int (PASCAL *pfn_WSACleanup) (void);
2072
2073 u_short (PASCAL *pfn_htons) (u_short hostshort);
2074 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2075 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2076 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2077 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2078 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2079
2080 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2081 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2082 #ifndef HANDLE_FLAG_INHERIT
2083 #define HANDLE_FLAG_INHERIT 1
2084 #endif
2085
2086 HANDLE winsock_lib;
2087 static int winsock_inuse;
2088
2089 BOOL
2090 term_winsock (void)
2091 {
2092 if (winsock_lib != NULL && winsock_inuse == 0)
2093 {
2094 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2095 after WSAStartup returns successfully, but it seems reasonable
2096 to allow unloading winsock anyway in that case. */
2097 if (pfn_WSACleanup () == 0 ||
2098 pfn_WSAGetLastError () == WSAENETDOWN)
2099 {
2100 if (FreeLibrary (winsock_lib))
2101 winsock_lib = NULL;
2102 return TRUE;
2103 }
2104 }
2105 return FALSE;
2106 }
2107
2108 BOOL
2109 init_winsock (int load_now)
2110 {
2111 WSADATA winsockData;
2112
2113 if (winsock_lib != NULL)
2114 return TRUE;
2115
2116 pfn_SetHandleInformation = NULL;
2117 pfn_SetHandleInformation
2118 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2119 "SetHandleInformation");
2120
2121 winsock_lib = LoadLibrary ("wsock32.dll");
2122
2123 if (winsock_lib != NULL)
2124 {
2125 /* dynamically link to socket functions */
2126
2127 #define LOAD_PROC(fn) \
2128 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2129 goto fail;
2130
2131 LOAD_PROC( WSAStartup );
2132 LOAD_PROC( WSASetLastError );
2133 LOAD_PROC( WSAGetLastError );
2134 LOAD_PROC( socket );
2135 LOAD_PROC( bind );
2136 LOAD_PROC( connect );
2137 LOAD_PROC( ioctlsocket );
2138 LOAD_PROC( recv );
2139 LOAD_PROC( send );
2140 LOAD_PROC( closesocket );
2141 LOAD_PROC( shutdown );
2142 LOAD_PROC( htons );
2143 LOAD_PROC( ntohs );
2144 LOAD_PROC( inet_addr );
2145 LOAD_PROC( gethostname );
2146 LOAD_PROC( gethostbyname );
2147 LOAD_PROC( getservbyname );
2148 LOAD_PROC( WSACleanup );
2149
2150 #undef LOAD_PROC
2151
2152 /* specify version 1.1 of winsock */
2153 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2154 {
2155 if (winsockData.wVersion != 0x101)
2156 goto fail;
2157
2158 if (!load_now)
2159 {
2160 /* Report that winsock exists and is usable, but leave
2161 socket functions disabled. I am assuming that calling
2162 WSAStartup does not require any network interaction,
2163 and in particular does not cause or require a dial-up
2164 connection to be established. */
2165
2166 pfn_WSACleanup ();
2167 FreeLibrary (winsock_lib);
2168 winsock_lib = NULL;
2169 }
2170 winsock_inuse = 0;
2171 return TRUE;
2172 }
2173
2174 fail:
2175 FreeLibrary (winsock_lib);
2176 winsock_lib = NULL;
2177 }
2178
2179 return FALSE;
2180 }
2181
2182
2183 int h_errno = 0;
2184
2185 /* function to set h_errno for compatability; map winsock error codes to
2186 normal system codes where they overlap (non-overlapping definitions
2187 are already in <sys/socket.h> */
2188 static void set_errno ()
2189 {
2190 if (winsock_lib == NULL)
2191 h_errno = EINVAL;
2192 else
2193 h_errno = pfn_WSAGetLastError ();
2194
2195 switch (h_errno)
2196 {
2197 case WSAEACCES: h_errno = EACCES; break;
2198 case WSAEBADF: h_errno = EBADF; break;
2199 case WSAEFAULT: h_errno = EFAULT; break;
2200 case WSAEINTR: h_errno = EINTR; break;
2201 case WSAEINVAL: h_errno = EINVAL; break;
2202 case WSAEMFILE: h_errno = EMFILE; break;
2203 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2204 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2205 }
2206 errno = h_errno;
2207 }
2208
2209 static void check_errno ()
2210 {
2211 if (h_errno == 0 && winsock_lib != NULL)
2212 pfn_WSASetLastError (0);
2213 }
2214
2215 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2216 but I believe the method of keeping the socket handle separate (and
2217 insuring it is not inheritable) is the correct one. */
2218
2219 //#define SOCK_REPLACE_HANDLE
2220
2221 #ifdef SOCK_REPLACE_HANDLE
2222 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2223 #else
2224 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2225 #endif
2226
2227 int
2228 sys_socket(int af, int type, int protocol)
2229 {
2230 int fd;
2231 long s;
2232 child_process * cp;
2233
2234 if (winsock_lib == NULL)
2235 {
2236 h_errno = ENETDOWN;
2237 return INVALID_SOCKET;
2238 }
2239
2240 check_errno ();
2241
2242 /* call the real socket function */
2243 s = (long) pfn_socket (af, type, protocol);
2244
2245 if (s != INVALID_SOCKET)
2246 {
2247 /* Although under NT 3.5 _open_osfhandle will accept a socket
2248 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2249 that does not work under NT 3.1. However, we can get the same
2250 effect by using a backdoor function to replace an existing
2251 descriptor handle with the one we want. */
2252
2253 /* allocate a file descriptor (with appropriate flags) */
2254 fd = _open ("NUL:", _O_RDWR);
2255 if (fd >= 0)
2256 {
2257 #ifdef SOCK_REPLACE_HANDLE
2258 /* now replace handle to NUL with our socket handle */
2259 CloseHandle ((HANDLE) _get_osfhandle (fd));
2260 _free_osfhnd (fd);
2261 _set_osfhnd (fd, s);
2262 /* setmode (fd, _O_BINARY); */
2263 #else
2264 /* Make a non-inheritable copy of the socket handle. */
2265 {
2266 HANDLE parent;
2267 HANDLE new_s = INVALID_HANDLE_VALUE;
2268
2269 parent = GetCurrentProcess ();
2270
2271 /* Apparently there is a bug in NT 3.51 with some service
2272 packs, which prevents using DuplicateHandle to make a
2273 socket handle non-inheritable (causes WSACleanup to
2274 hang). The work-around is to use SetHandleInformation
2275 instead if it is available and implemented. */
2276 if (!pfn_SetHandleInformation
2277 || !pfn_SetHandleInformation ((HANDLE) s,
2278 HANDLE_FLAG_INHERIT,
2279 0))
2280 {
2281 DuplicateHandle (parent,
2282 (HANDLE) s,
2283 parent,
2284 &new_s,
2285 0,
2286 FALSE,
2287 DUPLICATE_SAME_ACCESS);
2288 pfn_closesocket (s);
2289 s = (SOCKET) new_s;
2290 }
2291 fd_info[fd].hnd = (HANDLE) s;
2292 }
2293 #endif
2294
2295 /* set our own internal flags */
2296 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2297
2298 cp = new_child ();
2299 if (cp)
2300 {
2301 cp->fd = fd;
2302 cp->status = STATUS_READ_ACKNOWLEDGED;
2303
2304 /* attach child_process to fd_info */
2305 if (fd_info[ fd ].cp != NULL)
2306 {
2307 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2308 abort ();
2309 }
2310
2311 fd_info[ fd ].cp = cp;
2312
2313 /* success! */
2314 winsock_inuse++; /* count open sockets */
2315 return fd;
2316 }
2317
2318 /* clean up */
2319 _close (fd);
2320 }
2321 pfn_closesocket (s);
2322 h_errno = EMFILE;
2323 }
2324 set_errno ();
2325
2326 return -1;
2327 }
2328
2329
2330 int
2331 sys_bind (int s, const struct sockaddr * addr, int namelen)
2332 {
2333 if (winsock_lib == NULL)
2334 {
2335 h_errno = ENOTSOCK;
2336 return SOCKET_ERROR;
2337 }
2338
2339 check_errno ();
2340 if (fd_info[s].flags & FILE_SOCKET)
2341 {
2342 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
2343 if (rc == SOCKET_ERROR)
2344 set_errno ();
2345 return rc;
2346 }
2347 h_errno = ENOTSOCK;
2348 return SOCKET_ERROR;
2349 }
2350
2351
2352 int
2353 sys_connect (int s, const struct sockaddr * name, int namelen)
2354 {
2355 if (winsock_lib == NULL)
2356 {
2357 h_errno = ENOTSOCK;
2358 return SOCKET_ERROR;
2359 }
2360
2361 check_errno ();
2362 if (fd_info[s].flags & FILE_SOCKET)
2363 {
2364 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
2365 if (rc == SOCKET_ERROR)
2366 set_errno ();
2367 return rc;
2368 }
2369 h_errno = ENOTSOCK;
2370 return SOCKET_ERROR;
2371 }
2372
2373 u_short
2374 sys_htons (u_short hostshort)
2375 {
2376 return (winsock_lib != NULL) ?
2377 pfn_htons (hostshort) : hostshort;
2378 }
2379
2380 u_short
2381 sys_ntohs (u_short netshort)
2382 {
2383 return (winsock_lib != NULL) ?
2384 pfn_ntohs (netshort) : netshort;
2385 }
2386
2387 unsigned long
2388 sys_inet_addr (const char * cp)
2389 {
2390 return (winsock_lib != NULL) ?
2391 pfn_inet_addr (cp) : INADDR_NONE;
2392 }
2393
2394 int
2395 sys_gethostname (char * name, int namelen)
2396 {
2397 if (winsock_lib != NULL)
2398 return pfn_gethostname (name, namelen);
2399
2400 if (namelen > MAX_COMPUTERNAME_LENGTH)
2401 return !GetComputerName (name, &namelen);
2402
2403 h_errno = EFAULT;
2404 return SOCKET_ERROR;
2405 }
2406
2407 struct hostent *
2408 sys_gethostbyname(const char * name)
2409 {
2410 struct hostent * host;
2411
2412 if (winsock_lib == NULL)
2413 {
2414 h_errno = ENETDOWN;
2415 return NULL;
2416 }
2417
2418 check_errno ();
2419 host = pfn_gethostbyname (name);
2420 if (!host)
2421 set_errno ();
2422 return host;
2423 }
2424
2425 struct servent *
2426 sys_getservbyname(const char * name, const char * proto)
2427 {
2428 struct servent * serv;
2429
2430 if (winsock_lib == NULL)
2431 {
2432 h_errno = ENETDOWN;
2433 return NULL;
2434 }
2435
2436 check_errno ();
2437 serv = pfn_getservbyname (name, proto);
2438 if (!serv)
2439 set_errno ();
2440 return serv;
2441 }
2442
2443 int
2444 sys_shutdown (int s, int how)
2445 {
2446 int rc;
2447
2448 if (winsock_lib == NULL)
2449 {
2450 h_errno = ENETDOWN;
2451 return SOCKET_ERROR;
2452 }
2453
2454 check_errno ();
2455 if (fd_info[s].flags & FILE_SOCKET)
2456 {
2457 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
2458 if (rc == SOCKET_ERROR)
2459 set_errno ();
2460 return rc;
2461 }
2462 h_errno = ENOTSOCK;
2463 return SOCKET_ERROR;
2464 }
2465
2466 #endif /* HAVE_SOCKETS */
2467
2468
2469 /* Shadow main io functions: we need to handle pipes and sockets more
2470 intelligently, and implement non-blocking mode as well. */
2471
2472 int
2473 sys_close (int fd)
2474 {
2475 int rc;
2476
2477 if (fd < 0 || fd >= MAXDESC)
2478 {
2479 errno = EBADF;
2480 return -1;
2481 }
2482
2483 if (fd_info[fd].cp)
2484 {
2485 child_process * cp = fd_info[fd].cp;
2486
2487 fd_info[fd].cp = NULL;
2488
2489 if (CHILD_ACTIVE (cp))
2490 {
2491 /* if last descriptor to active child_process then cleanup */
2492 int i;
2493 for (i = 0; i < MAXDESC; i++)
2494 {
2495 if (i == fd)
2496 continue;
2497 if (fd_info[i].cp == cp)
2498 break;
2499 }
2500 if (i == MAXDESC)
2501 {
2502 #ifdef HAVE_SOCKETS
2503 if (fd_info[fd].flags & FILE_SOCKET)
2504 {
2505 #ifndef SOCK_REPLACE_HANDLE
2506 if (winsock_lib == NULL) abort ();
2507
2508 pfn_shutdown (SOCK_HANDLE (fd), 2);
2509 rc = pfn_closesocket (SOCK_HANDLE (fd));
2510 #endif
2511 winsock_inuse--; /* count open sockets */
2512 }
2513 #endif
2514 delete_child (cp);
2515 }
2516 }
2517 }
2518
2519 /* Note that sockets do not need special treatment here (at least on
2520 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
2521 closesocket is equivalent to CloseHandle, which is to be expected
2522 because socket handles are fully fledged kernel handles. */
2523 rc = _close (fd);
2524
2525 if (rc == 0)
2526 fd_info[fd].flags = 0;
2527
2528 return rc;
2529 }
2530
2531 int
2532 sys_dup (int fd)
2533 {
2534 int new_fd;
2535
2536 new_fd = _dup (fd);
2537 if (new_fd >= 0)
2538 {
2539 /* duplicate our internal info as well */
2540 fd_info[new_fd] = fd_info[fd];
2541 }
2542 return new_fd;
2543 }
2544
2545
2546 int
2547 sys_dup2 (int src, int dst)
2548 {
2549 int rc;
2550
2551 if (dst < 0 || dst >= MAXDESC)
2552 {
2553 errno = EBADF;
2554 return -1;
2555 }
2556
2557 /* make sure we close the destination first if it's a pipe or socket */
2558 if (src != dst && fd_info[dst].flags != 0)
2559 sys_close (dst);
2560
2561 rc = _dup2 (src, dst);
2562 if (rc == 0)
2563 {
2564 /* duplicate our internal info as well */
2565 fd_info[dst] = fd_info[src];
2566 }
2567 return rc;
2568 }
2569
2570 /* Unix pipe() has only one arg */
2571 int
2572 sys_pipe (int * phandles)
2573 {
2574 int rc;
2575 unsigned flags;
2576 child_process * cp;
2577
2578 /* make pipe handles non-inheritable; when we spawn a child, we
2579 replace the relevant handle with an inheritable one. Also put
2580 pipes into binary mode; we will do text mode translation ourselves
2581 if required. */
2582 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
2583
2584 if (rc == 0)
2585 {
2586 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
2587 fd_info[phandles[0]].flags = flags;
2588
2589 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
2590 fd_info[phandles[1]].flags = flags;
2591 }
2592
2593 return rc;
2594 }
2595
2596 /* From ntproc.c */
2597 extern Lisp_Object Vw32_pipe_read_delay;
2598
2599 /* Function to do blocking read of one byte, needed to implement
2600 select. It is only allowed on sockets and pipes. */
2601 int
2602 _sys_read_ahead (int fd)
2603 {
2604 child_process * cp;
2605 int rc;
2606
2607 if (fd < 0 || fd >= MAXDESC)
2608 return STATUS_READ_ERROR;
2609
2610 cp = fd_info[fd].cp;
2611
2612 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
2613 return STATUS_READ_ERROR;
2614
2615 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
2616 || (fd_info[fd].flags & FILE_READ) == 0)
2617 {
2618 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
2619 abort ();
2620 }
2621
2622 cp->status = STATUS_READ_IN_PROGRESS;
2623
2624 if (fd_info[fd].flags & FILE_PIPE)
2625 {
2626 rc = _read (fd, &cp->chr, sizeof (char));
2627
2628 /* Give subprocess time to buffer some more output for us before
2629 reporting that input is available; we need this because Windows 95
2630 connects DOS programs to pipes by making the pipe appear to be
2631 the normal console stdout - as a result most DOS programs will
2632 write to stdout without buffering, ie. one character at a
2633 time. Even some W32 programs do this - "dir" in a command
2634 shell on NT is very slow if we don't do this. */
2635 if (rc > 0)
2636 {
2637 int wait = XINT (Vw32_pipe_read_delay);
2638
2639 if (wait > 0)
2640 Sleep (wait);
2641 else if (wait < 0)
2642 while (++wait <= 0)
2643 /* Yield remainder of our time slice, effectively giving a
2644 temporary priority boost to the child process. */
2645 Sleep (0);
2646 }
2647 }
2648 #ifdef HAVE_SOCKETS
2649 else if (fd_info[fd].flags & FILE_SOCKET)
2650 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
2651 #endif
2652
2653 if (rc == sizeof (char))
2654 cp->status = STATUS_READ_SUCCEEDED;
2655 else
2656 cp->status = STATUS_READ_FAILED;
2657
2658 return cp->status;
2659 }
2660
2661 int
2662 sys_read (int fd, char * buffer, unsigned int count)
2663 {
2664 int nchars;
2665 int to_read;
2666 DWORD waiting;
2667 char * orig_buffer = buffer;
2668
2669 if (fd < 0 || fd >= MAXDESC)
2670 {
2671 errno = EBADF;
2672 return -1;
2673 }
2674
2675 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2676 {
2677 child_process *cp = fd_info[fd].cp;
2678
2679 if ((fd_info[fd].flags & FILE_READ) == 0)
2680 {
2681 errno = EBADF;
2682 return -1;
2683 }
2684
2685 nchars = 0;
2686
2687 /* re-read CR carried over from last read */
2688 if (fd_info[fd].flags & FILE_LAST_CR)
2689 {
2690 if (fd_info[fd].flags & FILE_BINARY) abort ();
2691 *buffer++ = 0x0d;
2692 count--;
2693 nchars++;
2694 fd_info[fd].flags &= ~FILE_LAST_CR;
2695 }
2696
2697 /* presence of a child_process structure means we are operating in
2698 non-blocking mode - otherwise we just call _read directly.
2699 Note that the child_process structure might be missing because
2700 reap_subprocess has been called; in this case the pipe is
2701 already broken, so calling _read on it is okay. */
2702 if (cp)
2703 {
2704 int current_status = cp->status;
2705
2706 switch (current_status)
2707 {
2708 case STATUS_READ_FAILED:
2709 case STATUS_READ_ERROR:
2710 /* report normal EOF if nothing in buffer */
2711 if (nchars <= 0)
2712 fd_info[fd].flags |= FILE_AT_EOF;
2713 return nchars;
2714
2715 case STATUS_READ_READY:
2716 case STATUS_READ_IN_PROGRESS:
2717 DebPrint (("sys_read called when read is in progress\n"));
2718 errno = EWOULDBLOCK;
2719 return -1;
2720
2721 case STATUS_READ_SUCCEEDED:
2722 /* consume read-ahead char */
2723 *buffer++ = cp->chr;
2724 count--;
2725 nchars++;
2726 cp->status = STATUS_READ_ACKNOWLEDGED;
2727 ResetEvent (cp->char_avail);
2728
2729 case STATUS_READ_ACKNOWLEDGED:
2730 break;
2731
2732 default:
2733 DebPrint (("sys_read: bad status %d\n", current_status));
2734 errno = EBADF;
2735 return -1;
2736 }
2737
2738 if (fd_info[fd].flags & FILE_PIPE)
2739 {
2740 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2741 to_read = min (waiting, (DWORD) count);
2742
2743 if (to_read > 0)
2744 nchars += _read (fd, buffer, to_read);
2745 }
2746 #ifdef HAVE_SOCKETS
2747 else /* FILE_SOCKET */
2748 {
2749 if (winsock_lib == NULL) abort ();
2750
2751 /* do the equivalent of a non-blocking read */
2752 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2753 if (waiting == 0 && nchars == 0)
2754 {
2755 h_errno = errno = EWOULDBLOCK;
2756 return -1;
2757 }
2758
2759 if (waiting)
2760 {
2761 /* always use binary mode for sockets */
2762 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2763 if (res == SOCKET_ERROR)
2764 {
2765 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2766 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2767 set_errno ();
2768 return -1;
2769 }
2770 nchars += res;
2771 }
2772 }
2773 #endif
2774 }
2775 else
2776 {
2777 int nread = _read (fd, buffer, count);
2778 if (nread >= 0)
2779 nchars += nread;
2780 else if (nchars == 0)
2781 nchars = nread;
2782 }
2783
2784 if (nchars <= 0)
2785 fd_info[fd].flags |= FILE_AT_EOF;
2786 /* Perform text mode translation if required. */
2787 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
2788 {
2789 nchars = crlf_to_lf (nchars, orig_buffer);
2790 /* If buffer contains only CR, return that. To be absolutely
2791 sure we should attempt to read the next char, but in
2792 practice a CR to be followed by LF would not appear by
2793 itself in the buffer. */
2794 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2795 {
2796 fd_info[fd].flags |= FILE_LAST_CR;
2797 nchars--;
2798 }
2799 }
2800 }
2801 else
2802 nchars = _read (fd, buffer, count);
2803
2804 return nchars;
2805 }
2806
2807 /* For now, don't bother with a non-blocking mode */
2808 int
2809 sys_write (int fd, const void * buffer, unsigned int count)
2810 {
2811 int nchars;
2812
2813 if (fd < 0 || fd >= MAXDESC)
2814 {
2815 errno = EBADF;
2816 return -1;
2817 }
2818
2819 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2820 {
2821 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2822 {
2823 errno = EBADF;
2824 return -1;
2825 }
2826
2827 /* Perform text mode translation if required. */
2828 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2829 {
2830 char * tmpbuf = alloca (count * 2);
2831 unsigned char * src = (void *)buffer;
2832 unsigned char * dst = tmpbuf;
2833 int nbytes = count;
2834
2835 while (1)
2836 {
2837 unsigned char *next;
2838 /* copy next line or remaining bytes */
2839 next = _memccpy (dst, src, '\n', nbytes);
2840 if (next)
2841 {
2842 /* copied one line ending with '\n' */
2843 int copied = next - dst;
2844 nbytes -= copied;
2845 src += copied;
2846 /* insert '\r' before '\n' */
2847 next[-1] = '\r';
2848 next[0] = '\n';
2849 dst = next + 1;
2850 count++;
2851 }
2852 else
2853 /* copied remaining partial line -> now finished */
2854 break;
2855 }
2856 buffer = tmpbuf;
2857 }
2858 }
2859
2860 #ifdef HAVE_SOCKETS
2861 if (fd_info[fd].flags & FILE_SOCKET)
2862 {
2863 if (winsock_lib == NULL) abort ();
2864 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2865 if (nchars == SOCKET_ERROR)
2866 {
2867 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2868 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2869 set_errno ();
2870 }
2871 }
2872 else
2873 #endif
2874 nchars = _write (fd, buffer, count);
2875
2876 return nchars;
2877 }
2878
2879 static void
2880 check_windows_init_file ()
2881 {
2882 extern int noninteractive, inhibit_window_system;
2883
2884 /* A common indication that Emacs is not installed properly is when
2885 it cannot find the Windows installation file. If this file does
2886 not exist in the expected place, tell the user. */
2887
2888 if (!noninteractive && !inhibit_window_system) {
2889 extern Lisp_Object Vwindow_system, Vload_path;
2890 Lisp_Object init_file;
2891 int fd;
2892
2893 init_file = build_string ("term/w32-win");
2894 fd = openp (Vload_path, init_file, ".el:.elc", NULL, 0);
2895 if (fd < 0) {
2896 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
2897 char *init_file_name = XSTRING (init_file)->data;
2898 char *load_path = XSTRING (load_path_print)->data;
2899 char *buffer = alloca (1024);
2900
2901 sprintf (buffer,
2902 "The Emacs Windows initialization file \"%s.el\" "
2903 "could not be found in your Emacs installation. "
2904 "Emacs checked the following directories for this file:\n"
2905 "\n%s\n\n"
2906 "When Emacs cannot find this file, it usually means that it "
2907 "was not installed properly, or its distribution file was "
2908 "not unpacked properly.\nSee the README.W32 file in the "
2909 "top-level Emacs directory for more information.",
2910 init_file_name, load_path);
2911 MessageBox (NULL,
2912 buffer,
2913 "Emacs Abort Dialog",
2914 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
2915 close (fd);
2916
2917 /* Use the low-level Emacs abort. */
2918 #undef abort
2919 abort ();
2920 }
2921 }
2922 }
2923
2924 void
2925 term_ntproc ()
2926 {
2927 #ifdef HAVE_SOCKETS
2928 /* shutdown the socket interface if necessary */
2929 term_winsock ();
2930 #endif
2931
2932 /* Check whether we are shutting down because we cannot find the
2933 Windows initialization file. Do this during shutdown so that
2934 Emacs is initialized as possible, and so that it is out of the
2935 critical startup path. */
2936 check_windows_init_file ();
2937 }
2938
2939 void
2940 init_ntproc ()
2941 {
2942 #ifdef HAVE_SOCKETS
2943 /* Initialise the socket interface now if available and requested by
2944 the user by defining PRELOAD_WINSOCK; otherwise loading will be
2945 delayed until open-network-stream is called (w32-has-winsock can
2946 also be used to dynamically load or reload winsock).
2947
2948 Conveniently, init_environment is called before us, so
2949 PRELOAD_WINSOCK can be set in the registry. */
2950
2951 /* Always initialize this correctly. */
2952 winsock_lib = NULL;
2953
2954 if (getenv ("PRELOAD_WINSOCK") != NULL)
2955 init_winsock (TRUE);
2956 #endif
2957
2958 /* Initial preparation for subprocess support: replace our standard
2959 handles with non-inheritable versions. */
2960 {
2961 HANDLE parent;
2962 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2963 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2964 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2965
2966 parent = GetCurrentProcess ();
2967
2968 /* ignore errors when duplicating and closing; typically the
2969 handles will be invalid when running as a gui program. */
2970 DuplicateHandle (parent,
2971 GetStdHandle (STD_INPUT_HANDLE),
2972 parent,
2973 &stdin_save,
2974 0,
2975 FALSE,
2976 DUPLICATE_SAME_ACCESS);
2977
2978 DuplicateHandle (parent,
2979 GetStdHandle (STD_OUTPUT_HANDLE),
2980 parent,
2981 &stdout_save,
2982 0,
2983 FALSE,
2984 DUPLICATE_SAME_ACCESS);
2985
2986 DuplicateHandle (parent,
2987 GetStdHandle (STD_ERROR_HANDLE),
2988 parent,
2989 &stderr_save,
2990 0,
2991 FALSE,
2992 DUPLICATE_SAME_ACCESS);
2993
2994 fclose (stdin);
2995 fclose (stdout);
2996 fclose (stderr);
2997
2998 if (stdin_save != INVALID_HANDLE_VALUE)
2999 _open_osfhandle ((long) stdin_save, O_TEXT);
3000 else
3001 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3002 _fdopen (0, "r");
3003
3004 if (stdout_save != INVALID_HANDLE_VALUE)
3005 _open_osfhandle ((long) stdout_save, O_TEXT);
3006 else
3007 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3008 _fdopen (1, "w");
3009
3010 if (stderr_save != INVALID_HANDLE_VALUE)
3011 _open_osfhandle ((long) stderr_save, O_TEXT);
3012 else
3013 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3014 _fdopen (2, "w");
3015 }
3016
3017 /* unfortunately, atexit depends on implementation of malloc */
3018 /* atexit (term_ntproc); */
3019 signal (SIGABRT, term_ntproc);
3020
3021 /* determine which drives are fixed, for GetCachedVolumeInformation */
3022 {
3023 /* GetDriveType must have trailing backslash. */
3024 char drive[] = "A:\\";
3025
3026 /* Loop over all possible drive letters */
3027 while (*drive <= 'Z')
3028 {
3029 /* Record if this drive letter refers to a fixed drive. */
3030 fixed_drives[DRIVE_INDEX (*drive)] =
3031 (GetDriveType (drive) == DRIVE_FIXED);
3032
3033 (*drive)++;
3034 }
3035 }
3036 }
3037
3038 /* end of nt.c */