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