X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/3f82a88a05e227145b0470991050698085d19fbe..f0398ec17f8a00d6c6d828c3d04522d94337d156:/src/w32.c diff --git a/src/w32.c b/src/w32.c index d0af53889e..fb2d7c7597 100644 --- a/src/w32.c +++ b/src/w32.c @@ -29,10 +29,10 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include /* must be before nt/inc/sys/time.h, for MinGW64 */ #include #include #include -#include /* must include CRT headers *before* config.h */ @@ -65,11 +65,13 @@ along with GNU Emacs. If not, see . */ #undef localtime #include "lisp.h" +#include "epaths.h" /* for SHELL */ #include #include -#ifdef __GNUC__ +/* MinGW64 (_W64) defines these in its _mingw.h. */ +#if defined(__GNUC__) && !defined(_W64) #define _ANONYMOUS_UNION #define _ANONYMOUS_STRUCT #endif @@ -96,6 +98,7 @@ typedef struct _MEMORY_STATUS_EX { #ifndef _MSC_VER #include #endif +#if _WIN32_WINNT < 0x0500 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15) /* This either is not in psapi.h or guarded by higher value of _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15 @@ -114,6 +117,7 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX { SIZE_T PrivateUsage; } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX; #endif +#endif #include #include @@ -127,11 +131,11 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX { #define SDDL_REVISION_1 1 #endif /* SDDL_REVISION_1 */ -#ifdef _MSC_VER -/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the - associated macros, except on ntifs.h, which cannot be included - because it triggers conflicts with other Windows API headers. So - we define it here by hand. */ +#if defined(_MSC_VER) || defined(_W64) +/* MSVC and MinGW64 don't provide the definition of + REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h, + which cannot be included because it triggers conflicts with other + Windows API headers. So we define it here by hand. */ typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; @@ -171,9 +175,12 @@ typedef struct _REPARSE_DATA_BUFFER { #ifndef CTL_CODE #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) #endif +/* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */ +#ifndef FSCTL_GET_REPARSE_POINT #define FSCTL_GET_REPARSE_POINT \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif +#endif /* TCP connection support. */ #include @@ -227,6 +234,8 @@ extern int sys_access (const char *, int); extern void *e_malloc (size_t); extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, EMACS_TIME *, void *); +extern int sys_dup (int); + @@ -1598,12 +1607,17 @@ max_filename_mbslen (void) case path name components to lower case. */ static void -normalize_filename (register char *fp, char path_sep) +normalize_filename (register char *fp, char path_sep, int multibyte) { char sep; char *elem, *p2; int dbcs_p = max_filename_mbslen () > 1; + /* Multibyte file names are in the Emacs internal representation, so + we can traverse them by bytes with no problems. */ + if (multibyte) + dbcs_p = 0; + /* Always lower-case drive letters a-z, even if the filesystem preserves case in filenames. This is so filenames can be compared by string comparison @@ -1620,7 +1634,7 @@ normalize_filename (register char *fp, char path_sep) fp += 2; } - if (NILP (Vw32_downcase_file_names)) + if (multibyte || NILP (Vw32_downcase_file_names)) { while (*fp) { @@ -1668,18 +1682,20 @@ normalize_filename (register char *fp, char path_sep) } while (*fp); } -/* Destructively turn backslashes into slashes. */ +/* Destructively turn backslashes into slashes. MULTIBYTE non-zero + means the file name is a multibyte string in Emacs's internal + representation. */ void -dostounix_filename (register char *p) +dostounix_filename (register char *p, int multibyte) { - normalize_filename (p, '/'); + normalize_filename (p, '/', multibyte); } /* Destructively turn slashes into backslashes. */ void unixtodos_filename (register char *p) { - normalize_filename (p, '\\'); + normalize_filename (p, '\\', 0); } /* Remove all CR's that are followed by a LF. @@ -2005,7 +2021,7 @@ init_environment (char ** argv) {"PRELOAD_WINSOCK", NULL}, {"emacs_dir", "C:/emacs"}, {"EMACSLOADPATH", NULL}, - {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"}, + {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */ {"EMACSDATA", NULL}, {"EMACSPATH", NULL}, {"INFOPATH", NULL}, @@ -2081,9 +2097,12 @@ init_environment (char ** argv) emacs_abort (); *p = 0; - if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) + if ((p = _mbsrchr (modname, '\\')) + /* From bin means installed Emacs, from src means uninstalled. */ + && (xstrcasecmp (p, "\\bin") == 0 || xstrcasecmp (p, "\\src") == 0)) { char buf[SET_ENV_BUF_SIZE]; + int within_build_tree = xstrcasecmp (p, "\\src") == 0; *p = 0; for (p = modname; *p; p = CharNext (p)) @@ -2091,6 +2110,15 @@ init_environment (char ** argv) _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); _putenv (strdup (buf)); + /* If we are running from the Posix-like build tree, define + SHELL to point to our own cmdproxy. The loop below will + then disregard PATH_EXEC and the default value. */ + if (within_build_tree) + { + _snprintf (buf, sizeof (buf) - 1, + "SHELL=%s/nt/cmdproxy.exe", modname); + _putenv (strdup (buf)); + } } /* Handle running emacs from the build directory: src/oo-spd/i386/ */ @@ -2126,16 +2154,60 @@ init_environment (char ** argv) if (!getenv (env_vars[i].name)) { int dont_free = 0; + char bufc[SET_ENV_BUF_SIZE]; if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL /* Also ignore empty environment variables. */ || *lpval == 0) { xfree (lpval); - lpval = env_vars[i].def_value; - dwType = REG_EXPAND_SZ; dont_free = 1; - if (!strcmp (env_vars[i].name, "HOME") && !appdata) + if (strcmp (env_vars[i].name, "SHELL") == 0) + { + /* Look for cmdproxy.exe in every directory in + PATH_EXEC. FIXME: This does not find cmdproxy + in nt/ when we run uninstalled. */ + char fname[MAX_PATH]; + const char *pstart = PATH_EXEC, *pend; + + do { + pend = _mbschr (pstart, ';'); + if (!pend) + pend = pstart + strlen (pstart); + /* Be defensive against series of ;;; characters. */ + if (pend > pstart) + { + strncpy (fname, pstart, pend - pstart); + fname[pend - pstart] = '/'; + strcpy (&fname[pend - pstart + 1], "cmdproxy.exe"); + ExpandEnvironmentStrings ((LPSTR) fname, bufc, + sizeof (bufc)); + if (check_existing (bufc)) + { + lpval = bufc; + dwType = REG_SZ; + break; + } + } + if (*pend) + pstart = pend + 1; + else + pstart = pend; + if (!*pstart) + { + /* If not found in any directory, use the + default as the last resort. */ + lpval = env_vars[i].def_value; + dwType = REG_EXPAND_SZ; + } + } while (*pstart); + } + else + { + lpval = env_vars[i].def_value; + dwType = REG_EXPAND_SZ; + } + if (strcmp (env_vars[i].name, "HOME") == 0 && !appdata) Vdelayed_warnings_list = Fcons (listn (CONSTYPE_HEAP, 2, intern ("initialization"), @@ -2222,7 +2294,7 @@ emacs_root_dir (void) emacs_abort (); strcpy (root_dir, p); root_dir[parse_root (root_dir, NULL)] = '\0'; - dostounix_filename (root_dir); + dostounix_filename (root_dir, 0); return root_dir; } @@ -2381,8 +2453,8 @@ get_emacs_configuration_options (void) #include /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ -void -gettimeofday (struct timeval *tv, struct timezone *tz) +int +gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz) { struct _timeb tb; _ftime (&tb); @@ -2400,6 +2472,7 @@ gettimeofday (struct timeval *tv, struct timezone *tz) tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ tz->tz_dsttime = tb.dstflag; /* type of dst correction */ } + return 0; } /* Emulate fdutimens. */ @@ -3212,14 +3285,6 @@ sys_chmod (const char * path, int mode) return _chmod (path, mode); } -int -sys_chown (const char *path, uid_t owner, gid_t group) -{ - if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */ - return -1; - return 0; -} - int sys_creat (const char * path, int mode) { @@ -3403,20 +3468,27 @@ int sys_open (const char * path, int oflag, int mode) { const char* mpath = map_w32_filename (path, NULL); - /* Try to open file without _O_CREAT, to be able to write to hidden - and system files. Force all file handles to be - non-inheritable. */ - int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); + int res = -1; + + /* If possible, try to open file without _O_CREAT, to be able to + write to existing hidden and system files. Force all file + handles to be non-inheritable. */ + if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL)) + res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); if (res < 0) res = _open (mpath, oflag | _O_NOINHERIT, mode); - if (res >= 0 && res < MAXDESC) - fd_info[res].flags = 0; return res; } int -sys_rename (const char * oldname, const char * newname) +fchmod (int fd, mode_t mode) +{ + return 0; +} + +int +sys_rename_replace (const char *oldname, const char *newname, BOOL force) { BOOL result; char temp[MAX_PATH]; @@ -3472,7 +3544,7 @@ sys_rename (const char * oldname, const char * newname) return -1; } - /* Emulate Unix behavior - newname is deleted if it already exists + /* If FORCE, emulate Unix behavior - newname is deleted if it already exists (at least if it is a file; don't do this for directories). Since we mustn't do this if we are just changing the case of the @@ -3490,7 +3562,7 @@ sys_rename (const char * oldname, const char * newname) result = rename (temp, newname); - if (result < 0) + if (result < 0 && force) { DWORD w32err = GetLastError (); @@ -3529,6 +3601,12 @@ sys_rename (const char * oldname, const char * newname) return result; } +int +sys_rename (char const *old, char const *new) +{ + return sys_rename_replace (old, new, TRUE); +} + int sys_rmdir (const char * path) { @@ -3709,12 +3787,6 @@ get_rid (PSID sid) /* Caching SID and account values for faster lokup. */ -#ifdef __GNUC__ -# define FLEXIBLE_ARRAY_MEMBER -#else -# define FLEXIBLE_ARRAY_MEMBER 1 -#endif - struct w32_id { unsigned rid; struct w32_id *next; @@ -4274,6 +4346,30 @@ lstat (const char * path, struct stat * buf) return stat_worker (path, buf, 0); } +int +fstatat (int fd, char const *name, struct stat *st, int flags) +{ + /* Rely on a hack: an open directory is modeled as file descriptor 0. + This is good enough for the current usage in Emacs, but is fragile. + + FIXME: Add proper support for fdopendir, fstatat, readlinkat. + Gnulib does this and can serve as a model. */ + char fullname[MAX_PATH]; + + if (fd != AT_FDCWD) + { + if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) + < 0) + { + errno = ENAMETOOLONG; + return -1; + } + name = fullname; + } + + return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW)); +} + /* Provide fstat and utime as well as stat for consistent handling of file timestamps. */ int @@ -4816,6 +4912,28 @@ readlink (const char *name, char *buf, size_t buf_size) return retval; } +ssize_t +readlinkat (int fd, char const *name, char *buffer, + size_t buffer_size) +{ + /* Rely on a hack: an open directory is modeled as file descriptor 0, + as in fstatat. FIXME: Add proper support for readlinkat. */ + char fullname[MAX_PATH]; + + if (fd != AT_FDCWD) + { + if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name) + < 0) + { + errno = ENAMETOOLONG; + return -1; + } + name = fullname; + } + + return readlink (name, buffer, buffer_size); +} + /* If FILE is a symlink, return its target (stored in a static buffer); otherwise return FILE. @@ -5168,12 +5286,6 @@ careadlinkat (int fd, char const *filename, char linkname[MAX_PATH]; ssize_t link_size; - if (fd != AT_FDCWD) - { - errno = EINVAL; - return NULL; - } - link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); if (link_size > 0) @@ -5191,14 +5303,6 @@ careadlinkat (int fd, char const *filename, return NULL; } -ssize_t -careadlinkatcwd (int fd, char const *filename, char *buffer, - size_t buffer_size) -{ - (void) fd; - return readlink (filename, buffer, buffer_size); -} - /* Support for browsing other processes and their attributes. See process.c for the Lisp bindings. */ @@ -5536,10 +5640,8 @@ ltime (ULONGLONG time_100ns) { ULONGLONG time_sec = time_100ns / 10000000; int subsec = time_100ns % 10000000; - return list4 (make_number (time_sec >> 16), - make_number (time_sec & 0xffff), - make_number (subsec / 10), - make_number (subsec % 10 * 100000)); + return list4i (time_sec >> 16, time_sec & 0xffff, + subsec / 10, subsec % 10 * 100000); } #define U64_TO_LISP_TIME(time) ltime (time) @@ -6053,35 +6155,39 @@ init_winsock (int load_now) int h_errno = 0; -/* function to set h_errno for compatibility; map winsock error codes to - normal system codes where they overlap (non-overlapping definitions - are already in */ +/* Function to map winsock error codes to errno codes for those errno + code defined in errno.h (errno values not defined by errno.h are + already in nt/inc/sys/socket.h). */ static void set_errno (void) { + int wsa_err; + + h_errno = 0; if (winsock_lib == NULL) - h_errno = EINVAL; + wsa_err = EINVAL; else - h_errno = pfn_WSAGetLastError (); + wsa_err = pfn_WSAGetLastError (); - switch (h_errno) + switch (wsa_err) { - case WSAEACCES: h_errno = EACCES; break; - case WSAEBADF: h_errno = EBADF; break; - case WSAEFAULT: h_errno = EFAULT; break; - case WSAEINTR: h_errno = EINTR; break; - case WSAEINVAL: h_errno = EINVAL; break; - case WSAEMFILE: h_errno = EMFILE; break; - case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break; - case WSAENOTEMPTY: h_errno = ENOTEMPTY; break; + case WSAEACCES: errno = EACCES; break; + case WSAEBADF: errno = EBADF; break; + case WSAEFAULT: errno = EFAULT; break; + case WSAEINTR: errno = EINTR; break; + case WSAEINVAL: errno = EINVAL; break; + case WSAEMFILE: errno = EMFILE; break; + case WSAENAMETOOLONG: errno = ENAMETOOLONG; break; + case WSAENOTEMPTY: errno = ENOTEMPTY; break; + default: errno = wsa_err; break; } - errno = h_errno; } static void check_errno (void) { - if (h_errno == 0 && winsock_lib != NULL) + h_errno = 0; + if (winsock_lib != NULL) pfn_WSASetLastError (0); } @@ -6193,7 +6299,7 @@ sys_socket (int af, int type, int protocol) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return INVALID_SOCKET; } @@ -6270,6 +6376,7 @@ socket_to_fd (SOCKET s) } } } + eassert (fd < MAXDESC); fd_info[fd].hnd = (HANDLE) s; /* set our own internal flags */ @@ -6298,8 +6405,9 @@ socket_to_fd (SOCKET s) /* clean up */ _close (fd); } + else pfn_closesocket (s); - h_errno = EMFILE; + errno = EMFILE; return -1; } @@ -6308,7 +6416,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6320,7 +6428,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6329,7 +6437,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6341,7 +6449,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6370,12 +6478,20 @@ int sys_gethostname (char * name, int namelen) { if (winsock_lib != NULL) - return pfn_gethostname (name, namelen); + { + int retval; + + check_errno (); + retval = pfn_gethostname (name, namelen); + if (retval == SOCKET_ERROR) + set_errno (); + return retval; + } if (namelen > MAX_COMPUTERNAME_LENGTH) return !GetComputerName (name, (DWORD *)&namelen); - h_errno = EFAULT; + errno = EFAULT; return SOCKET_ERROR; } @@ -6383,17 +6499,24 @@ struct hostent * sys_gethostbyname (const char * name) { struct hostent * host; + int h_err = h_errno; if (winsock_lib == NULL) { - h_errno = ENETDOWN; + h_errno = NO_RECOVERY; + errno = ENETDOWN; return NULL; } check_errno (); host = pfn_gethostbyname (name); if (!host) - set_errno (); + { + set_errno (); + h_errno = errno; + } + else + h_errno = h_err; return host; } @@ -6404,7 +6527,7 @@ sys_getservbyname (const char * name, const char * proto) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return NULL; } @@ -6420,7 +6543,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6432,7 +6555,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6441,7 +6564,7 @@ sys_shutdown (int s, int how) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6453,7 +6576,7 @@ sys_shutdown (int s, int how) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6462,7 +6585,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6475,7 +6598,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6484,7 +6607,7 @@ sys_listen (int s, int backlog) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6498,7 +6621,7 @@ sys_listen (int s, int backlog) fd_info[s].flags |= FILE_LISTEN; return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6507,7 +6630,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6519,7 +6642,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6528,7 +6651,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return -1; } @@ -6542,11 +6665,14 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) else fd = socket_to_fd (t); - fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; - ResetEvent (fd_info[s].cp->char_avail); + if (fd >= 0) + { + fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; + ResetEvent (fd_info[s].cp->char_avail); + } return fd; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return -1; } @@ -6556,7 +6682,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6568,7 +6694,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6578,7 +6704,7 @@ sys_sendto (int s, const char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return SOCKET_ERROR; } @@ -6590,18 +6716,24 @@ sys_sendto (int s, const char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } /* Windows does not have an fcntl function. Provide an implementation - solely for making sockets non-blocking. */ + good enough for Emacs. */ int fcntl (int s, int cmd, int options) { + /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always + invoked in a context where fd1 is closed and all descriptors less + than fd1 are open, so sys_dup is an adequate implementation. */ + if (cmd == F_DUPFD_CLOEXEC) + return sys_dup (s); + if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = ENETDOWN; return -1; } @@ -6620,11 +6752,11 @@ fcntl (int s, int cmd, int options) } else { - h_errno = EINVAL; + errno = EINVAL; return SOCKET_ERROR; } } - h_errno = ENOTSOCK; + errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6740,13 +6872,14 @@ sys_dup2 (int src, int dst) return rc; } -/* Unix pipe() has only one arg */ int -sys_pipe (int * phandles) +pipe2 (int * phandles, int pipe2_flags) { int rc; unsigned flags; + eassert (pipe2_flags == O_CLOEXEC); + /* make pipe handles non-inheritable; when we spawn a child, we replace the relevant handle with an inheritable one. Also put pipes into binary mode; we will do text mode translation ourselves @@ -6761,6 +6894,7 @@ sys_pipe (int * phandles) { _close (phandles[0]); _close (phandles[1]); + errno = EMFILE; rc = -1; } else @@ -6834,19 +6968,31 @@ _sys_read_ahead (int fd) /* Configure timeouts for blocking read. */ if (!GetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } ct.ReadIntervalTimeout = 0; ct.ReadTotalTimeoutMultiplier = 0; ct.ReadTotalTimeoutConstant = 0; if (!SetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl)) { if (GetLastError () != ERROR_IO_PENDING) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } } } else if (fd_info[fd].flags & FILE_SOCKET) @@ -7042,7 +7188,7 @@ sys_read (int fd, char * buffer, unsigned int count) pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); if (waiting == 0 && nchars == 0) { - h_errno = errno = EWOULDBLOCK; + errno = EWOULDBLOCK; return -1; } @@ -7561,8 +7707,9 @@ globals_of_w32 (void) /* For make-serial-process */ int -serial_open (char *port) +serial_open (Lisp_Object port_obj) { + char *port = SSDATA (port_obj); HANDLE hnd; child_process *cp; int fd = -1; @@ -7754,47 +7901,26 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) ssize_t emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) { - int n, sc, err; + int n, err; SELECT_TYPE fdset; EMACS_TIME timeout; struct Lisp_Process *process = (struct Lisp_Process *)p; int fd = process->infd; - for (;;) - { - n = sys_read (fd, (char*)buf, sz); + n = sys_read (fd, (char*)buf, sz); - if (n >= 0) - return n; + if (n >= 0) + return n; - err = errno; + err = errno; - if (err == EWOULDBLOCK) - { - /* Set a small timeout. */ - timeout = make_emacs_time (1, 0); - FD_ZERO (&fdset); - FD_SET ((int)fd, &fdset); - - /* Use select with the timeout to poll the selector. */ - sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0, - &timeout, NULL); - - if (sc > 0) - continue; /* Try again. */ - - /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. - Also accept select return 0 as an indicator to EAGAIN. */ - if (sc == 0 || errno == EWOULDBLOCK) - err = EAGAIN; - else - err = errno; /* Other errors are just passed on. */ - } + /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */ + if (err == EWOULDBLOCK) + err = EAGAIN; - emacs_gnutls_transport_set_errno (process->gnutls_state, err); + emacs_gnutls_transport_set_errno (process->gnutls_state, err); - return -1; - } + return -1; } ssize_t