diff options
Diffstat (limited to 'src/w32.c')
| -rw-r--r-- | src/w32.c | 140 |
1 files changed, 91 insertions, 49 deletions
| @@ -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. */ | ||
| 103 | PEXCEPTION_POINTERS excptr; | ||
| 104 | PEXCEPTION_RECORD excprec; | ||
| 105 | PCONTEXT 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); | |||
| 233 | extern int sys_access (const char *, int); | 247 | extern int sys_access (const char *, int); |
| 234 | extern void *e_malloc (size_t); | 248 | extern void *e_malloc (size_t); |
| 235 | extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, | 249 | extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, |
| 236 | EMACS_TIME *, void *); | 250 | struct timespec *, void *); |
| 237 | extern int sys_dup (int); | 251 | extern int sys_dup (int); |
| 238 | 252 | ||
| 239 | 253 | ||
| @@ -2489,8 +2503,6 @@ gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz) | |||
| 2489 | int | 2503 | int |
| 2490 | fdutimens (int fd, char const *file, struct timespec const timespec[2]) | 2504 | fdutimens (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 | 3445 | int |
| 3418 | ourselves. Also, MSVC's _mktemp returns NULL when it can't generate | 3446 | sys_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, |
| 3426 | char * | 3469 | so that the number of simultaneously used temporary files will be |
| 3427 | sys_mktemp (char * template) | 3470 | greater. */ |
| 3471 | |||
| 3472 | int | ||
| 3473 | mkostemp (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 | |||
| 3467 | int | ||
| 3468 | sys_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 | ||
| 3484 | int | 3517 | int |
| @@ -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 | |||
| 4485 | int | 4521 | int |
| 4486 | utime (const char *name, struct utimbuf *times) | 4522 | utime (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 | ||