Merge branch 'sp/emfile'
[gitweb.git] / compat / mingw.c
index 736d03fa0c3b61163325d9ef6933111e4ef2e656..fdbf093f6eb704ec0ca0e5abf6baf1f94350676b 100644 (file)
@@ -198,9 +198,10 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
  */
 static int do_lstat(int follow, const char *file_name, struct stat *buf)
 {
+       int err;
        WIN32_FILE_ATTRIBUTE_DATA fdata;
 
-       if (!(errno = get_file_attr(file_name, &fdata))) {
+       if (!(err = get_file_attr(file_name, &fdata))) {
                buf->st_ino = 0;
                buf->st_gid = 0;
                buf->st_uid = 0;
@@ -233,6 +234,7 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
                }
                return 0;
        }
+       errno = err;
        return -1;
 }
 
@@ -408,71 +410,6 @@ int pipe(int filedes[2])
        return 0;
 }
 
-int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
-{
-       int i, pending;
-
-       if (timeout >= 0) {
-               if (nfds == 0) {
-                       Sleep(timeout);
-                       return 0;
-               }
-               return errno = EINVAL, error("poll timeout not supported");
-       }
-
-       /* When there is only one fd to wait for, then we pretend that
-        * input is available and let the actual wait happen when the
-        * caller invokes read().
-        */
-       if (nfds == 1) {
-               if (!(ufds[0].events & POLLIN))
-                       return errno = EINVAL, error("POLLIN not set");
-               ufds[0].revents = POLLIN;
-               return 0;
-       }
-
-repeat:
-       pending = 0;
-       for (i = 0; i < nfds; i++) {
-               DWORD avail = 0;
-               HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
-               if (h == INVALID_HANDLE_VALUE)
-                       return -1;      /* errno was set */
-
-               if (!(ufds[i].events & POLLIN))
-                       return errno = EINVAL, error("POLLIN not set");
-
-               /* this emulation works only for pipes */
-               if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
-                       int err = GetLastError();
-                       if (err == ERROR_BROKEN_PIPE) {
-                               ufds[i].revents = POLLHUP;
-                               pending++;
-                       } else {
-                               errno = EINVAL;
-                               return error("PeekNamedPipe failed,"
-                                       " GetLastError: %u", err);
-                       }
-               } else if (avail) {
-                       ufds[i].revents = POLLIN;
-                       pending++;
-               } else
-                       ufds[i].revents = 0;
-       }
-       if (!pending) {
-               /* The only times that we spin here is when the process
-                * that is connected through the pipes is waiting for
-                * its own input data to become available. But since
-                * the process (pack-objects) is itself CPU intensive,
-                * it will happily pick up the time slice that we are
-                * relinquishing here.
-                */
-               Sleep(0);
-               goto repeat;
-       }
-       return 0;
-}
-
 struct tm *gmtime_r(const time_t *timep, struct tm *result)
 {
        /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
@@ -936,6 +873,25 @@ void mingw_execv(const char *cmd, char *const *argv)
        mingw_execve(cmd, argv, environ);
 }
 
+int mingw_kill(pid_t pid, int sig)
+{
+       if (pid > 0 && sig == SIGTERM) {
+               HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+
+               if (TerminateProcess(h, -1)) {
+                       CloseHandle(h);
+                       return 0;
+               }
+
+               errno = err_win_to_posix(GetLastError());
+               CloseHandle(h);
+               return -1;
+       }
+
+       errno = EINVAL;
+       return -1;
+}
+
 static char **copy_environ(void)
 {
        char **env;
@@ -1020,19 +976,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
                                   const struct addrinfo *hints,
                                   struct addrinfo **res)
 {
-       struct hostent *h = gethostbyname(node);
+       struct hostent *h = NULL;
        struct addrinfo *ai;
        struct sockaddr_in *sin;
 
-       if (!h)
-               return WSAGetLastError();
+       if (node) {
+               h = gethostbyname(node);
+               if (!h)
+                       return WSAGetLastError();
+       }
 
        ai = xmalloc(sizeof(struct addrinfo));
        *res = ai;
        ai->ai_flags = 0;
        ai->ai_family = AF_INET;
-       ai->ai_socktype = hints->ai_socktype;
-       switch (hints->ai_socktype) {
+       ai->ai_socktype = hints ? hints->ai_socktype : 0;
+       switch (ai->ai_socktype) {
        case SOCK_STREAM:
                ai->ai_protocol = IPPROTO_TCP;
                break;
@@ -1044,14 +1003,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
                break;
        }
        ai->ai_addrlen = sizeof(struct sockaddr_in);
-       ai->ai_canonname = strdup(h->h_name);
+       if (hints && (hints->ai_flags & AI_CANONNAME))
+               ai->ai_canonname = h ? strdup(h->h_name) : NULL;
+       else
+               ai->ai_canonname = NULL;
 
        sin = xmalloc(ai->ai_addrlen);
        memset(sin, 0, ai->ai_addrlen);
        sin->sin_family = AF_INET;
+       /* Note: getaddrinfo is supposed to allow service to be a string,
+        * which should be looked up using getservbyname. This is
+        * currently not implemented */
        if (service)
                sin->sin_port = htons(atoi(service));
-       sin->sin_addr = *(struct in_addr *)h->h_addr;
+       if (h)
+               sin->sin_addr = *(struct in_addr *)h->h_addr;
+       else if (hints && (hints->ai_flags & AI_PASSIVE))
+               sin->sin_addr.s_addr = INADDR_ANY;
+       else
+               sin->sin_addr.s_addr = INADDR_LOOPBACK;
        ai->ai_addr = (struct sockaddr *)sin;
        ai->ai_next = 0;
        return 0;
@@ -1554,6 +1524,14 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)
                return -1;
        }
 
+       if (pid > 0 && options & WNOHANG) {
+               if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {
+                       CloseHandle(h);
+                       return 0;
+               }
+               options &= ~WNOHANG;
+       }
+
        if (options == 0) {
                struct pinfo_t **ppinfo;
                if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {