/* * nixio - Linux I/O library for lua * * Copyright (C) 2009 Steven Barth <steven@midlink.org> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "nixio.h" #include <string.h> #include <fcntl.h> #include <errno.h> #include <sys/locking.h> #include <sys/time.h> #include <sys/utime.h> void nixio_open__mingw(lua_State *L) { _fmode = _O_BINARY; WSADATA wsa; if (WSAStartup(MAKEWORD(2, 2), &wsa)) { luaL_error(L, "Unable to initialize Winsock"); } lua_newtable(L); NIXIO_WSA_CONSTANT(WSAEACCES); NIXIO_WSA_CONSTANT(WSAEINTR); NIXIO_WSA_CONSTANT(WSAEINVAL); NIXIO_WSA_CONSTANT(WSAEBADF); NIXIO_WSA_CONSTANT(WSAEFAULT); NIXIO_WSA_CONSTANT(WSAEMFILE); NIXIO_WSA_CONSTANT(WSAENAMETOOLONG); NIXIO_WSA_CONSTANT(WSAELOOP); NIXIO_WSA_CONSTANT(WSAEAFNOSUPPORT); NIXIO_WSA_CONSTANT(WSAENOBUFS); NIXIO_WSA_CONSTANT(WSAEPROTONOSUPPORT); NIXIO_WSA_CONSTANT(WSAENOPROTOOPT); NIXIO_WSA_CONSTANT(WSAEADDRINUSE); NIXIO_WSA_CONSTANT(WSAENETDOWN); NIXIO_WSA_CONSTANT(WSAENETUNREACH); NIXIO_WSA_CONSTANT(WSAECONNABORTED); NIXIO_WSA_CONSTANT(WSAECONNRESET); lua_setfield(L, -2, "const_sock"); } const char* nixio__mgw_inet_ntop (int af, const void *src, char *dst, socklen_t size) { struct sockaddr_storage saddr; memset(&saddr, 0, sizeof(saddr)); DWORD hostlen = size, sl; if (af == AF_INET) { struct sockaddr_in *saddr4 = (struct sockaddr_in *)&saddr; memcpy(&saddr4->sin_addr, src, sizeof(saddr4->sin_addr)); saddr4->sin_family = AF_INET; saddr4->sin_port = 0; sl = sizeof(struct sockaddr_in); } else if (af == AF_INET6) { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&saddr; memcpy(&saddr6->sin6_addr, src, sizeof(saddr6->sin6_addr)); saddr6->sin6_family = AF_INET6; saddr6->sin6_port = 0; sl = sizeof(struct sockaddr_in6); } else { return NULL; } if (WSAAddressToString((struct sockaddr*)&saddr, sl, NULL, dst, &hostlen)) { return NULL; } return dst; } int nixio__mgw_inet_pton (int af, const char *src, void *dst) { struct sockaddr_storage sa; int sl = sizeof(sa); if (!WSAStringToAddress((char*)src, af, NULL, (struct sockaddr*)&sa, &sl)) { if (af == AF_INET) { struct in_addr ina = ((struct sockaddr_in *)&sa)->sin_addr; memcpy(dst, &ina, sizeof(ina)); return 1; } else if (af == AF_INET6) { struct in_addr6 ina6 = ((struct sockaddr_in6 *)&sa)->sin6_addr; memcpy(dst, &ina6, sizeof(ina6)); return 1; } else { WSASetLastError(WSAEAFNOSUPPORT); return -1; } } else { return -1; } } int nixio__mgw_nanosleep(const struct timespec *req, struct timespec *rem) { if (rem) { rem->tv_sec = 0; rem->tv_nsec = 0; } Sleep(req->tv_sec * 1000 + req->tv_nsec * 1000000); return 0; } int nixio__mgw_poll(struct pollfd *fds, int nfds, int timeout) { if (!fds || !nfds) { Sleep(timeout); return 0; } struct timeval tv; int high = 0, rf = 0, wf = 0, ef = 0; fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; for (int i = 0; i < nfds; i++) { if (fds->events & POLLIN) { FD_SET(fds->fd, &rfds); rf++; } if (fds->events & POLLOUT) { FD_SET(fds->fd, &wfds); wf++; } if (fds->events & POLLERR) { FD_SET(fds->fd, &efds); ef++; } if (fds->fd > high) { high = fds->fd; } } int stat = select(high + 1, (rf) ? &rfds : NULL, (wf) ? &wfds : NULL, (ef) ? &efds : NULL, &tv); if (stat < 1) { errno = WSAGetLastError(); return stat; } high = 0; for (int i = 0; i < nfds; i++) { fds->revents = 0; if ((fds->events & POLLIN) && FD_ISSET(fds->fd, &rfds)) { fds->revents |= POLLIN; } if ((fds->events & POLLOUT) && FD_ISSET(fds->fd, &wfds)) { fds->revents |= POLLOUT; } if ((fds->events & POLLERR) && FD_ISSET(fds->fd, &efds)) { fds->revents |= POLLERR; } if (fds->revents) { high++; } } return high; } int nixio__mgw_lockf(int fd, int cmd, off_t len) { int stat; if (cmd == F_LOCK) { do { stat = _locking(fd, _LK_LOCK, len); } while (stat == -1 && errno == EDEADLOCK); } else if (cmd == F_TLOCK) { stat = _locking(fd, _LK_NBLCK, len); } else if (cmd == F_ULOCK) { stat = _locking(fd, _LK_UNLCK, len); } else { stat = -1; errno = EINVAL; } return stat; } char* nixio__mgw_realpath(const char *path, char *resolved) { if (GetFullPathName(path, PATH_MAX, resolved, NULL)) { return resolved; } else { errno = GetLastError(); return NULL; } } int nixio__mgw_link(const char *oldpath, const char *newpath) { if (!CreateHardLink(newpath, oldpath, NULL)) { errno = GetLastError(); return -1; } else { return 0; } } int nixio__mgw_utimes(const char *filename, const struct timeval times[2]) { struct _utimbuf timebuffer; timebuffer.actime = times[0].tv_sec; timebuffer.modtime = times[1].tv_sec; return _utime(filename, &timebuffer); }