int _win_close(int fd) { THandleType theType; int ret; theType = __win_GetHandleType((DWORD) fd); switch(theType) { case SOCKET_HANDLE: ret = closesocket(fd); if (ret == SOCKET_ERROR) SetErrnoFromWinsockError(WSAGetLastError()); break; case PIPE_HANDLE: if (!CloseHandle((HANDLE) fd)) { SetErrnoFromWinError(GetLastError()); ret = -1; } else ret = 0; break; case FD_HANDLE: ret = close(fd); break; case UNKNOWN_HANDLE: ret = -1; errno = EBADF; SetLastError(ERROR_INVALID_HANDLE); __plibc_panic(5, "Cannot close() unknown handle\n"); break; } if (theType != UNKNOWN_HANDLE) { __win_DiscardHandleBlockingMode(fd); __win_DiscardHandleType(fd); } return ret; }
/** * @brief Convert a POSIX-sytle path to a Windows-style path * @param pszUnix POSIX path * @param pszWindows Windows path * @param derefLinks 1 to dereference links * @return Error code from winerror.h, ERROR_SUCCESS on success */ int plibc_conv_to_win_path_ex(const char *pszUnix, char *pszWindows, int derefLinks) { char *pSrc, *pDest; long iSpaceUsed; int iUnixLen; if (!pszUnix || !pszWindows) return ERROR_INVALID_PARAMETER; iUnixLen = strlen(pszUnix); /* Check if we already have a windows path */ if((strchr(pszUnix, '\\') != NULL) || (strchr(pszUnix, ':') != NULL)) { if(iUnixLen > MAX_PATH) return ERROR_BUFFER_OVERFLOW; strcpy(pszWindows, pszUnix); } /* Temp. dir? */ if(strncmp(pszUnix, "/tmp", 4) == 0) { iSpaceUsed = GetTempPath(_MAX_PATH, pszWindows); if (iSpaceUsed > _MAX_PATH) return ERROR_BUFFER_OVERFLOW; pDest = pszWindows + iSpaceUsed; pSrc = (char *) pszUnix + 4; } /* Bit bucket? */ else if (strncmp(pszUnix, "/dev/null", 9) == 0) { strcpy(pszWindows, "nul"); iSpaceUsed = 3; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 9; } /* Data directories */ else if (strncmp(pszUnix, "/etc", 4) == 0 || strncmp(pszUnix, "/com", 4) == 0 || strncmp(pszUnix, "/var", 4) == 0) { strcpy(pszWindows, szDataDir); iSpaceUsed = lDataDirLen; pDest = pszWindows + lDataDirLen; pSrc = (char *) pszUnix + 1; } /* Is the unix path a full path? */ else if(pszUnix[0] == '/') { strcpy(pszWindows, szRootDir); iSpaceUsed = lRootDirLen; pDest = pszWindows + lRootDirLen; pSrc = (char *) pszUnix + 1; } /* Home dir? */ else if (pszUnix[0] == '~') { strcpy(pszWindows, szHomeDir); iSpaceUsed = lHomeDirLen; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 1; } /* Home dir (env var)? */ else if (strncmp(pszUnix, "$HOME", 5) == 0) { strcpy(pszWindows, szHomeDir); iSpaceUsed = lHomeDirLen; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 5; } else { pDest = pszWindows; iSpaceUsed = 0; pSrc = (char *) pszUnix; } iSpaceUsed += strlen(pSrc); if(iSpaceUsed + 1 > _MAX_PATH) return ERROR_BUFFER_OVERFLOW; /* substitute all slashes */ while(*pSrc) { if(*pSrc == '/') *pDest = '\\'; else *pDest = *pSrc; pDest++; pSrc++; } *pDest = 0; if (derefLinks) __win_deref(pszWindows); else { /* The filename possibly refers to a symlink, but the .lnk extension may be missing. 1. Check if the requested file seems to be a normal file 2. Check if the file exists 2.1. Yes: Finished 2.2. No: Check if "filename.lnk" exists 2.2.1 Yes: Append ".lnk" */ if (strnicmp(pDest - 4, ".lnk", 4) != 0) { HANDLE h = CreateFile(pszWindows, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { /* File doesn't exist, try shortcut */ char *pLnk; int mal; if (iSpaceUsed + 5 > _MAX_PATH) { pLnk = malloc(iSpaceUsed + 5); strcpy(pLnk, pszWindows); mal = 1; } else { pLnk = pszWindows; mal = 0; } strcat(pLnk, ".lnk"); h = CreateFile(pLnk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { /* Shortcut exists */ CloseHandle(h); if (mal) /* Need to copy */ if (iSpaceUsed + 5 <= _MAX_PATH) strcpy(pszWindows, pLnk); else { free(pLnk); return ERROR_BUFFER_OVERFLOW; } } else pLnk[iSpaceUsed] = 0; if (mal) free(pLnk); } else CloseHandle(h); } } #if DEBUG_WINPROC { char szInfo[1001]; _win_snprintf(szInfo, 1000, "Posix path %s resolved to %s\n", pszUnix, pszWindows); szInfo[1000] = 0; __plibc_panic(INT_MAX, szInfo); } #endif return ERROR_SUCCESS; }
/** * @brief Get the errno corresponding to the Winsock error * @param lWinError Error code defined in winsock.h */ int GetErrnoFromWinsockError(long lWinError) { switch(lWinError) { case 0: return 0; case WSAEINTR: return EINTR; case WSAEWOULDBLOCK: return EWOULDBLOCK; case WSAEINPROGRESS: return EINPROGRESS; case WSAEALREADY: return EALREADY; case WSAENOTSOCK: return ENOTSOCK; case WSAEDESTADDRREQ: return EDESTADDRREQ; case WSAEMSGSIZE: return EMSGSIZE; case WSAEPROTOTYPE: return EPROTOTYPE; case WSAENOPROTOOPT: return ENOPROTOOPT; case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT; case WSAESOCKTNOSUPPORT: return ESOCKTNOSUPPORT; case WSAEOPNOTSUPP: return EOPNOTSUPP; case WSAEPFNOSUPPORT: return EPFNOSUPPORT; case WSAEAFNOSUPPORT: return EAFNOSUPPORT; case WSAEADDRINUSE: return EADDRINUSE; case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL; case WSAENETDOWN: return ENETDOWN; case WSAENETUNREACH: return ENETUNREACH; case WSAENETRESET: return ENETRESET; case WSAECONNABORTED: return ECONNABORTED; case WSAECONNRESET: return ECONNRESET; case WSAENOBUFS: return ENOBUFS; case WSAEISCONN: return EISCONN; case WSAENOTCONN: return ENOTCONN; case WSAESHUTDOWN: return ESHUTDOWN; case WSAETOOMANYREFS: return ETOOMANYREFS; case WSAETIMEDOUT: return ETIMEDOUT; case WSAECONNREFUSED: return ECONNREFUSED; case WSAELOOP: return ELOOP; case WSAENAMETOOLONG: return ENAMETOOLONG; case WSAEHOSTDOWN: return EHOSTDOWN; case WSAEHOSTUNREACH: return EHOSTUNREACH; case WSAENOTEMPTY: return ENOTEMPTY; case WSAEPROCLIM: return EPROCLIM; case WSAEUSERS: return EUSERS; case WSAEDQUOT: return EDQUOT; case WSAESTALE: return ESTALE; case WSAEREMOTE: return EREMOTE; case WSAEINVAL: return EINVAL; case WSAEFAULT: return EFAULT; case WSANO_DATA: return ENODATA; default: { char szPanic[1001]; _win_snprintf(szPanic, 1000, "Unknown error %i in " \ "SetErrnoFromWinsockError()\n", lWinError); szPanic[1000] = 0; __plibc_panic(4, szPanic); return ESTALE; } } }
/** * @brief Set errno according to a Windows error * @param lWinError Error code defined in winerror.h */ void _SetErrnoFromWinError(long lWinError, char *pszCaller, int iLine) { switch(lWinError) { case ERROR_SUCCESS: errno = 0; break; case ERROR_INVALID_FUNCTION: errno = EBADRQC; break; case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break; case ERROR_ACCESS_DENIED: errno = EACCES; break; case ERROR_INVALID_HANDLE: errno = EBADF; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_INVALID_DATA: errno = EINVAL; break; case ERROR_OUTOFMEMORY: errno = ENOMEM; break; case ERROR_INVALID_DRIVE: errno = ENODEV; break; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break; case ERROR_NO_MORE_FILES: errno = ENMFILE; break; case ERROR_WRITE_PROTECT: errno = EROFS; break; case ERROR_BAD_UNIT: errno = ENODEV; break; case ERROR_SHARING_VIOLATION: errno = EACCES; break; case ERROR_LOCK_VIOLATION: errno = EACCES; break; case ERROR_SHARING_BUFFER_EXCEEDED: errno = ENOLCK; break; case ERROR_HANDLE_EOF: errno = ENODATA; break; case ERROR_HANDLE_DISK_FULL: errno = ENOSPC; break; case ERROR_NOT_SUPPORTED: errno = ENOSYS; break; case ERROR_REM_NOT_LIST: errno = ENONET; break; case ERROR_DUP_NAME: errno = ENOTUNIQ; break; case ERROR_BAD_NETPATH: errno = ENOSHARE; break; case ERROR_BAD_NET_NAME: errno = ENOSHARE; break; case ERROR_FILE_EXISTS: errno = EEXIST; break; case ERROR_CANNOT_MAKE: errno = EPERM; break; case ERROR_INVALID_PARAMETER: errno = EINVAL; break; case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break; case ERROR_BROKEN_PIPE: errno = EPIPE; break; case ERROR_OPEN_FAILED: errno = EIO; break; case ERROR_NO_MORE_SEARCH_HANDLES: errno = ENFILE; break; case ERROR_CALL_NOT_IMPLEMENTED: errno = ENOSYS; break; case ERROR_INVALID_NAME: errno = ENOENT; break; case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break; case ERROR_CHILD_NOT_COMPLETE: errno = EBUSY; break; case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break; case ERROR_SIGNAL_REFUSED: errno = EIO; break; case ERROR_BAD_PATHNAME: errno = ENOENT; break; case ERROR_SIGNAL_PENDING: errno = EBUSY; break; case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break; case ERROR_BUSY: errno = EBUSY; break; case ERROR_ALREADY_EXISTS: errno = EEXIST; break; case ERROR_NO_SIGNAL_SENT: errno = EIO; break; case ERROR_FILENAME_EXCED_RANGE: errno = EINVAL; break; case ERROR_META_EXPANSION_TOO_LONG: errno = EINVAL; break; case ERROR_INVALID_SIGNAL_NUMBER: errno = EINVAL; break; case ERROR_THREAD_1_INACTIVE: errno = EINVAL; break; case ERROR_BAD_PIPE: errno = EINVAL; break; case ERROR_PIPE_BUSY: errno = EBUSY; break; case ERROR_NO_DATA: errno = EPIPE; break; case ERROR_PIPE_NOT_CONNECTED: errno = ECOMM; break; case ERROR_MORE_DATA: errno = EAGAIN; break; case ERROR_DIRECTORY: errno = ENOTDIR; break; case ERROR_PIPE_CONNECTED: errno = EBUSY; break; case ERROR_PIPE_LISTENING: errno = ECOMM; break; case ERROR_NO_TOKEN: errno = EINVAL; break; case ERROR_PROCESS_ABORTED: errno = EFAULT; break; case ERROR_BAD_DEVICE: errno = ENODEV; break; case ERROR_BAD_USERNAME: errno = EINVAL; break; case ERROR_NOT_CONNECTED: errno = ENOLINK; break; case ERROR_OPEN_FILES: errno = EAGAIN; break; case ERROR_ACTIVE_CONNECTIONS: errno = EAGAIN; break; case ERROR_DEVICE_IN_USE: errno = EAGAIN; break; case ERROR_INVALID_AT_INTERRUPT_TIME: errno = EINTR; break; case ERROR_IO_DEVICE: errno = EIO; break; case ERROR_NOT_OWNER: errno = EPERM; break; case ERROR_END_OF_MEDIA: errno = ENOSPC; break; case ERROR_EOM_OVERFLOW: errno = ENOSPC; break; case ERROR_BEGINNING_OF_MEDIA: errno = ESPIPE; break; case ERROR_SETMARK_DETECTED: errno = ESPIPE; break; case ERROR_NO_DATA_DETECTED: errno = ENOSPC; break; case ERROR_POSSIBLE_DEADLOCK: errno = EDEADLOCK; break; case ERROR_CRC: errno = EIO; break; case ERROR_NEGATIVE_SEEK: errno = EINVAL; break; case ERROR_NOT_READY: errno = ENOMEDIUM; break; case ERROR_DISK_FULL: errno = ENOSPC; break; case ERROR_NOACCESS: errno = EFAULT; break; case ERROR_FILE_INVALID: errno = ENXIO; break; case ERROR_INVALID_ADDRESS: errno = EFAULT; break; case ERROR_BUFFER_OVERFLOW: errno = ENOMEM; break; case ERROR_SERVICE_DOES_NOT_EXIST: errno = ESRCH; break; case ERROR_SERVICE_EXISTS: errno = EEXIST; break; default: { char szPanic[1001]; errno = ESTALE; _win_snprintf(szPanic, 1000, "Unknown error %i in PlibC "\ "SetErrnoFromWinError(). Source: %s:%i\n", lWinError, pszCaller, iLine); szPanic[1000] = 0; __plibc_panic(3, szPanic); break; } } }