const char * vp_file_write(char *args) { vp_stack_t stack; int fd; char *buf; size_t size; int timeout; size_t nleft; int n; struct pollfd pfd = {0, POLLOUT, 0}; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd)); VP_RETURN_IF_FAIL(vp_stack_pop_bin(&stack, &buf, &size)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout)); pfd.fd = fd; nleft = 0; while (nleft < size) { n = poll(&pfd, 1, timeout); if (n == -1) { return vp_stack_return_error(&_result, "poll() error: %s", strerror(errno)); } else if (n == 0) { /* timeout */ break; } if (pfd.revents & POLLOUT) { n = write(fd, buf + nleft, size - nleft); if (n == -1) { return vp_stack_return_error(&_result, "write() error: %s", strerror(errno)); } nleft += n; /* try write more bytes without waiting */ timeout = 0; continue; } else if (pfd.revents & (POLLERR | POLLHUP)) { /* eof or error */ break; } else if (pfd.revents & POLLNVAL) { return vp_stack_return_error(&_result, "poll() POLLNVAL: %d", pfd.revents); } /* DO NOT REACH HERE */ return vp_stack_return_error(&_result, "poll() unknown status: %s", pfd.revents); } vp_stack_push_num(&_result, "%zu", nleft); return vp_stack_return(&_result); }
const char * vp_socket_write(char *args) { vp_stack_t stack; int sock; char *buf; size_t size; int timeout; struct timeval tv; size_t nleft; int n; fd_set fdset; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &sock)); VP_RETURN_IF_FAIL(vp_stack_pop_bin(&stack, &buf, &size)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout)); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; FD_ZERO(&fdset); FD_SET((unsigned)sock, &fdset); nleft = 0; while (nleft < size) { n = select(0, NULL, &fdset, NULL, (timeout == -1) ? NULL : &tv); if (n == SOCKET_ERROR) { return vp_stack_return_error(&_result, "select() error: %d", WSAGetLastError()); } else if (n == 0) { /* timeout */ break; } n = send(sock, buf + nleft, (int)(size - nleft), 0); if (n == -1) return vp_stack_return_error(&_result, "send() error: %s", strerror(errno)); nleft += n; /* try write more bytes without waiting */ timeout = 0; } vp_stack_push_num(&_result, "%u", nleft); return vp_stack_return(&_result); }
const char * vp_file_write(char *args) { vp_stack_t stack; int fd; char *buf; size_t size; int timeout; size_t nleft; DWORD ret; int n; VP_RETURN_IF_FAIL(vp_stack_from_args(&stack, args)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &fd)); VP_RETURN_IF_FAIL(vp_stack_pop_bin(&stack, &buf, &size)); VP_RETURN_IF_FAIL(vp_stack_pop_num(&stack, "%d", &timeout)); nleft = 0; while (nleft < size) { ret = WaitForSingleObject((HANDLE)_get_osfhandle(fd), timeout); if (ret == WAIT_FAILED) { return vp_stack_return_error(&_result, "WaitForSingleObject() error: %s", lasterror()); } else if (ret == WAIT_TIMEOUT) { /* timeout */ break; } n = write(fd, buf + nleft, (unsigned int)(size - nleft)); if (n == -1) { return vp_stack_return_error(&_result, "write() error: %s", strerror(errno)); } nleft += n; /* try write more bytes without waiting */ timeout = 0; } vp_stack_push_num(&_result, "%u", nleft); return vp_stack_return(&_result); }