summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-10-31 04:16:11 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-10-31 04:16:11 +0000
commitb2a1af15474219c75d2447b0213e20f1e60b3dc1 (patch)
tree765fb5f496cfe4ea2cdcdac6992a1f3e94b80c42 /win32
parent92a8bfacd9e22062bf30ca4cb996af8f5e25b7b5 (diff)
* win32/win32.c (setfl): extract from fcntl().
* win32/win32.c (dupfd): new function to support F_DUPFD. base on a patch written by akr. * win32/win32.c (fcntl): use above functions. * include/ruby/win32.h (F_DUPFD): define. [experimental] * include/ruby/win32.h (F_SETFL): change the value to correspond with other platforms. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33581 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32')
-rw-r--r--win32/win32.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 6b201764f1..5851377ff2 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -3766,28 +3766,13 @@ void setprotoent (int stayopen) {}
void setservent (int stayopen) {}
/* License: Ruby's */
-int
-fcntl(int fd, int cmd, ...)
+static int
+setfl(SOCKET sock, int arg)
{
- SOCKET sock = TO_SOCKET(fd);
- va_list va;
- int arg;
int ret;
int flag = 0;
u_long ioctlArg;
- if (!is_socket(sock)) {
- errno = EBADF;
- return -1;
- }
- if (cmd != F_SETFL) {
- errno = EINVAL;
- return -1;
- }
-
- va_start(va, cmd);
- arg = va_arg(va, int);
- va_end(va);
socklist_lookup(sock, &flag);
if (arg & O_NONBLOCK) {
flag |= O_NONBLOCK;
@@ -3808,6 +3793,82 @@ fcntl(int fd, int cmd, ...)
return ret;
}
+/* License: Ruby's */
+static int
+dupfd(HANDLE hDup, char flags, int minfd)
+{
+ int save_errno;
+ int ret;
+ int fds[32];
+ int filled = 0;
+
+ do {
+ ret = _open_osfhandle((intptr_t)hDup, flags | FOPEN);
+ if (ret == -1) {
+ goto close_fds_and_return;
+ }
+ if (ret >= minfd) {
+ goto close_fds_and_return;
+ }
+ fds[filled++] = ret;
+ } while (filled < (sizeof(fds)/sizeof(fds[0])));
+
+ ret = dupfd(hDup, flags, minfd);
+
+ close_fds_and_return:
+ save_errno = errno;
+ while (filled > 0) {
+ _osfhnd(fds[--filled]) = (intptr_t)INVALID_HANDLE_VALUE;
+ close(fds[filled]);
+ }
+ errno = save_errno;
+
+ return ret;
+}
+
+/* License: Ruby's */
+int
+fcntl(int fd, int cmd, ...)
+{
+ va_list va;
+ int arg;
+
+ if (cmd == F_SETFL) {
+ SOCKET sock = TO_SOCKET(fd);
+ if (!is_socket(sock)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ va_start(va, cmd);
+ arg = va_arg(va, int);
+ va_end(va);
+ return setfl(sock, arg);
+ }
+ else if (cmd == F_DUPFD) {
+ int ret;
+ HANDLE hDup;
+ if (!(DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
+ GetCurrentProcess(), &hDup, 0L, TRUE,
+ DUPLICATE_SAME_ACCESS))) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+
+ va_start(va, cmd);
+ arg = va_arg(va, int);
+ va_end(va);
+
+ if ((ret = dupfd(hDup, _osfile(fd), arg)) == -1)
+ CloseHandle(hDup);
+ return ret;
+ }
+ else {
+ errno = EINVAL;
+ return -1;
+ }
+}
+
#ifndef WNOHANG
#define WNOHANG -1
#endif