aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/w32.c')
-rw-r--r--src/w32.c140
1 files changed, 91 insertions, 49 deletions
diff --git a/src/w32.c b/src/w32.c
index fb2d7c75972..1dcf46b5f4b 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -47,7 +47,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
47#undef fopen 47#undef fopen
48#undef link 48#undef link
49#undef mkdir 49#undef mkdir
50#undef mktemp
51#undef open 50#undef open
52#undef rename 51#undef rename
53#undef rmdir 52#undef rmdir
@@ -90,6 +89,21 @@ typedef struct _MEMORY_STATUS_EX {
90 DWORDLONG ullAvailExtendedVirtual; 89 DWORDLONG ullAvailExtendedVirtual;
91} MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX; 90} MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
92 91
92/* These are here so that GDB would know about these data types. This
93 allows to attach GDB to Emacs when a fatal exception is triggered
94 and Windows pops up the "application needs to be closed" dialog.
95 At that point, _gnu_exception_handler, the top-level exception
96 handler installed by the MinGW startup code, is somewhere on the
97 call-stack of the main thread, so going to that call frame and
98 looking at the argument to _gnu_exception_handler, which is a
99 PEXCEPTION_POINTERS pointer, can reveal the exception code
100 (excptr->ExceptionRecord->ExceptionCode) and the address where the
101 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
102 well as some additional information specific to the exception. */
103PEXCEPTION_POINTERS excptr;
104PEXCEPTION_RECORD excprec;
105PCONTEXT ctxrec;
106
93#include <lmcons.h> 107#include <lmcons.h>
94#include <shlobj.h> 108#include <shlobj.h>
95 109
@@ -233,7 +247,7 @@ static BOOL WINAPI revert_to_self (void);
233extern int sys_access (const char *, int); 247extern int sys_access (const char *, int);
234extern void *e_malloc (size_t); 248extern void *e_malloc (size_t);
235extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, 249extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
236 EMACS_TIME *, void *); 250 struct timespec *, void *);
237extern int sys_dup (int); 251extern int sys_dup (int);
238 252
239 253
@@ -2489,8 +2503,6 @@ gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2489int 2503int
2490fdutimens (int fd, char const *file, struct timespec const timespec[2]) 2504fdutimens (int fd, char const *file, struct timespec const timespec[2])
2491{ 2505{
2492 struct _utimbuf ut;
2493
2494 if (!timespec) 2506 if (!timespec)
2495 { 2507 {
2496 errno = ENOSYS; 2508 errno = ENOSYS;
@@ -2501,12 +2513,28 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
2501 errno = EBADF; 2513 errno = EBADF;
2502 return -1; 2514 return -1;
2503 } 2515 }
2504 ut.actime = timespec[0].tv_sec; 2516 /* _futime's prototype defines 2nd arg as having the type 'struct
2505 ut.modtime = timespec[1].tv_sec; 2517 _utimbuf', while utime needs to accept 'struct utimbuf' for
2518 compatibility with Posix. So we need to use 2 different (but
2519 equivalent) types to avoid compiler warnings, sigh. */
2506 if (fd >= 0) 2520 if (fd >= 0)
2507 return _futime (fd, &ut); 2521 {
2522 struct _utimbuf _ut;
2523
2524 _ut.actime = timespec[0].tv_sec;
2525 _ut.modtime = timespec[1].tv_sec;
2526 return _futime (fd, &_ut);
2527 }
2508 else 2528 else
2509 return _utime (file, &ut); 2529 {
2530 struct utimbuf ut;
2531
2532 ut.actime = timespec[0].tv_sec;
2533 ut.modtime = timespec[1].tv_sec;
2534 /* Call 'utime', which is implemented below, not the MS library
2535 function, which fails on directories. */
2536 return utime (file, &ut);
2537 }
2510} 2538}
2511 2539
2512 2540
@@ -3414,25 +3442,46 @@ sys_mkdir (const char * path)
3414 return _mkdir (map_w32_filename (path, NULL)); 3442 return _mkdir (map_w32_filename (path, NULL));
3415} 3443}
3416 3444
3417/* Because of long name mapping issues, we need to implement this 3445int
3418 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate 3446sys_open (const char * path, int oflag, int mode)
3419 a unique name, instead of setting the input template to an empty 3447{
3420 string. 3448 const char* mpath = map_w32_filename (path, NULL);
3449 int res = -1;
3450
3451 /* If possible, try to open file without _O_CREAT, to be able to
3452 write to existing hidden and system files. Force all file
3453 handles to be non-inheritable. */
3454 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
3455 res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
3456 if (res < 0)
3457 res = _open (mpath, oflag | _O_NOINHERIT, mode);
3458
3459 return res;
3460}
3461
3462/* Implementation of mkostemp for MS-Windows, to avoid race conditions
3463 when using mktemp.
3421 3464
3422 Standard algorithm seems to be use pid or tid with a letter on the 3465 Standard algorithm for generating a temporary file name seems to be
3423 front (in place of the 6 X's) and cycle through the letters to find a 3466 use pid or tid with a letter on the front (in place of the 6 X's)
3424 unique name. We extend that to allow any reasonable character as the 3467 and cycle through the letters to find a unique name. We extend
3425 first of the 6 X's. */ 3468 that to allow any reasonable character as the first of the 6 X's,
3426char * 3469 so that the number of simultaneously used temporary files will be
3427sys_mktemp (char * template) 3470 greater. */
3471
3472int
3473mkostemp (char * template, int flags)
3428{ 3474{
3429 char * p; 3475 char * p;
3430 int i; 3476 int i, fd = -1;
3431 unsigned uid = GetCurrentThreadId (); 3477 unsigned uid = GetCurrentThreadId ();
3478 int save_errno = errno;
3432 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#"; 3479 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
3433 3480
3481 errno = EINVAL;
3434 if (template == NULL) 3482 if (template == NULL)
3435 return NULL; 3483 return -1;
3484
3436 p = template + strlen (template); 3485 p = template + strlen (template);
3437 i = 5; 3486 i = 5;
3438 /* replace up to the last 5 X's with uid in decimal */ 3487 /* replace up to the last 5 X's with uid in decimal */
@@ -3447,38 +3496,22 @@ sys_mktemp (char * template)
3447 i = 0; 3496 i = 0;
3448 do 3497 do
3449 { 3498 {
3450 int save_errno = errno;
3451 p[0] = first_char[i]; 3499 p[0] = first_char[i];
3452 if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0) 3500 if ((fd = sys_open (template,
3501 flags | _O_CREAT | _O_EXCL | _O_RDWR,
3502 S_IRUSR | S_IWUSR)) >= 0
3503 || errno != EEXIST)
3453 { 3504 {
3454 errno = save_errno; 3505 if (fd >= 0)
3455 return template; 3506 errno = save_errno;
3507 return fd;
3456 } 3508 }
3457 } 3509 }
3458 while (++i < sizeof (first_char)); 3510 while (++i < sizeof (first_char));
3459 } 3511 }
3460 3512
3461 /* Template is badly formed or else we can't generate a unique name, 3513 /* Template is badly formed or else we can't generate a unique name. */
3462 so return empty string */ 3514 return -1;
3463 template[0] = 0;
3464 return template;
3465}
3466
3467int
3468sys_open (const char * path, int oflag, int mode)
3469{
3470 const char* mpath = map_w32_filename (path, NULL);
3471 int res = -1;
3472
3473 /* If possible, try to open file without _O_CREAT, to be able to
3474 write to existing hidden and system files. Force all file
3475 handles to be non-inheritable. */
3476 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
3477 res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
3478 if (res < 0)
3479 res = _open (mpath, oflag | _O_NOINHERIT, mode);
3480
3481 return res;
3482} 3515}
3483 3516
3484int 3517int
@@ -4482,6 +4515,9 @@ fstat (int desc, struct stat * buf)
4482 return 0; 4515 return 0;
4483} 4516}
4484 4517
4518/* A version of 'utime' which handles directories as well as
4519 files. */
4520
4485int 4521int
4486utime (const char *name, struct utimbuf *times) 4522utime (const char *name, struct utimbuf *times)
4487{ 4523{
@@ -5750,8 +5786,8 @@ system_process_attributes (Lisp_Object pid)
5750 { 5786 {
5751 /* Decode the command name from locale-specific 5787 /* Decode the command name from locale-specific
5752 encoding. */ 5788 encoding. */
5753 cmd_str = make_unibyte_string (pe.szExeFile, 5789 cmd_str = build_unibyte_string (pe.szExeFile);
5754 strlen (pe.szExeFile)); 5790
5755 decoded_cmd = 5791 decoded_cmd =
5756 code_convert_string_norecord (cmd_str, 5792 code_convert_string_norecord (cmd_str,
5757 Vlocale_coding_system, 0); 5793 Vlocale_coding_system, 0);
@@ -6056,6 +6092,7 @@ term_winsock (void)
6056{ 6092{
6057 if (winsock_lib != NULL && winsock_inuse == 0) 6093 if (winsock_lib != NULL && winsock_inuse == 0)
6058 { 6094 {
6095 release_listen_threads ();
6059 /* Not sure what would cause WSAENETDOWN, or even if it can happen 6096 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6060 after WSAStartup returns successfully, but it seems reasonable 6097 after WSAStartup returns successfully, but it seems reasonable
6061 to allow unloading winsock anyway in that case. */ 6098 to allow unloading winsock anyway in that case. */
@@ -7040,7 +7077,12 @@ _sys_wait_accept (int fd)
7040 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT); 7077 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
7041 if (rc != SOCKET_ERROR) 7078 if (rc != SOCKET_ERROR)
7042 { 7079 {
7043 rc = WaitForSingleObject (hEv, INFINITE); 7080 do {
7081 rc = WaitForSingleObject (hEv, 500);
7082 Sleep (5);
7083 } while (rc == WAIT_TIMEOUT
7084 && cp->status != STATUS_READ_ERROR
7085 && cp->char_avail);
7044 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0); 7086 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
7045 if (rc == WAIT_OBJECT_0) 7087 if (rc == WAIT_OBJECT_0)
7046 cp->status = STATUS_READ_SUCCEEDED; 7088 cp->status = STATUS_READ_SUCCEEDED;
@@ -7903,7 +7945,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
7903{ 7945{
7904 int n, err; 7946 int n, err;
7905 SELECT_TYPE fdset; 7947 SELECT_TYPE fdset;
7906 EMACS_TIME timeout; 7948 struct timespec timeout;
7907 struct Lisp_Process *process = (struct Lisp_Process *)p; 7949 struct Lisp_Process *process = (struct Lisp_Process *)p;
7908 int fd = process->infd; 7950 int fd = process->infd;
7909 7951