]> Chaos Git - corbenik/ctrulib.git/commitdiff
First attempt at hooking sockets into a devoptab.
authormtheall <pigman46@gmail.com>
Fri, 23 Jan 2015 20:23:59 +0000 (14:23 -0600)
committermtheall <pigman46@gmail.com>
Fri, 23 Jan 2015 20:23:59 +0000 (14:23 -0600)
19 files changed:
libctru/source/services/soc/soc_accept.c
libctru/source/services/soc/soc_bind.c
libctru/source/services/soc/soc_closesocket.c
libctru/source/services/soc/soc_common.c
libctru/source/services/soc/soc_common.h
libctru/source/services/soc/soc_connect.c
libctru/source/services/soc/soc_fcntl.c
libctru/source/services/soc/soc_getpeername.c
libctru/source/services/soc/soc_getsockname.c
libctru/source/services/soc/soc_getsockopt.c
libctru/source/services/soc/soc_init.c
libctru/source/services/soc/soc_ioctl.c
libctru/source/services/soc/soc_listen.c
libctru/source/services/soc/soc_poll.c
libctru/source/services/soc/soc_recvfrom.c
libctru/source/services/soc/soc_sendto.c
libctru/source/services/soc/soc_shutdown.c
libctru/source/services/soc/soc_sockatmark.c
libctru/source/services/soc/soc_socket.c

index 355a744bd182cba2d935ce2530019a3ea60da9a8..cf6486374ed0056c9d24b8f247d72192d26e24a7 100644 (file)
@@ -3,12 +3,39 @@
 
 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
 {
-       int ret=0;
-       int tmp_addrlen=0x1c;
+       int ret = 0;
+       int tmp_addrlen = 0x1c;
+       int fd, dev;
+       __handle *handle;
        u32 *cmdbuf = getThreadCommandBuffer();
        u8 tmpaddr[0x1c];
        u32 saved_threadstorage[2];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
+       dev = FindDevice("soc:");
+       if(dev < 0)
+       {
+               SOCU_errno = -ENODEV;
+               return -1;
+       }
+
+       fd = __alloc_handle(sizeof(__handle) + sizeof(Handle));
+       if(fd < 0)
+       {
+               SOCU_errno = -ENOMEM;
+               return -1;
+       }
+
+       handle = __get_handle(fd);
+       handle->device = dev;
+       handle->fileStruct = ((void *)handle) + sizeof(__handle);
+
        memset(tmpaddr, 0, 0x1c);
 
        cmdbuf[0] = 0x00040082;
@@ -22,22 +49,37 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
        cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2;
        cmdbuf[0x104>>2] = (u32)tmpaddr;
 
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+       if((ret = svcSendSyncRequest(SOCU_handle)) != 0)
+       {
+               __release_handle(fd);
+               return ret;
+       }
 
        cmdbuf[0x100>>2] = saved_threadstorage[0];
        cmdbuf[0x104>>2] = saved_threadstorage[1];
 
        ret = (int)cmdbuf[1];
-       if(ret==0)ret = _net_convert_error(cmdbuf[2]);
-       if(ret<0)SOCU_errno = ret;
+       if(ret == 0)
+               ret = _net_convert_error(cmdbuf[2]);
 
-       if(ret>=0 && addr!=NULL)
+       if(ret < 0)
+               SOCU_errno = ret;
+
+       if(ret >= 0 && addr != NULL)
        {
                addr->sa_family = tmpaddr[1];
-               if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0];
+               if(*addrlen > tmpaddr[0])
+                       *addrlen = tmpaddr[0];
                memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);
        }
 
-       if(ret<0)return -1;
-       return ret;
+       if(ret < 0)
+       {
+               __release_handle(fd);
+               return -1;
+       }
+       else
+               *(Handle*)handle->fileStruct = ret;
+
+       return fd;
 }
index dba52e57b12243e5921a4ddedf8e06c1740cc8a3..dd37f7ed2307021924fc1a7c3668178636d84769 100644 (file)
@@ -9,6 +9,13 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
        u32 *cmdbuf = getThreadCommandBuffer();
        u8 tmpaddr[0x1c];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        memset(tmpaddr, 0, 0x1c);
 
        if(addr->sa_family == AF_INET)
index 85dcd52234fbc8c4cf34da81c9731f652eadaa9f..37e19230f6c171c44c1b44d630fe80c4b29d8081 100644 (file)
@@ -3,19 +3,12 @@
 
 int closesocket(int sockfd)
 {
-       int ret=0;
-       u32 *cmdbuf = getThreadCommandBuffer();
-
-       cmdbuf[0] = 0x000B0042;
-       cmdbuf[1] = (u32)sockfd;
-       cmdbuf[2] = 0x20;
-
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
-
-       ret = (int)cmdbuf[1];
-       if(ret==0)ret =_net_convert_error(cmdbuf[2]);
-       SOCU_errno = ret;
-
-       if(ret!=0)return -1;
-       return 0;
+       int fd = soc_get_fd(sockfd);
+       if(fd < 0)
+       {
+               SOCU_errno = fd;
+               return -1;
+       }
+
+       return close(sockfd);
 }
index 88144530033feb8c33dd6576eb81ea315551f9a8..c41491c782e162262ebd081346607ee165b1a5c6 100644 (file)
@@ -1,5 +1,6 @@
 #include "soc_common.h"
 #include <errno.h>
+#include <sys/iosupport.h>
 
 Handle SOCU_handle = 0;
 int    SOCU_errno = 0;
index 5cf5dee7819c8d121817aa374a1ec11f7c63de66..f325bf784ba85a7829a66aac38a93b1996d285c6 100644 (file)
@@ -1,13 +1,30 @@
 #pragma once
 
+#include <errno.h>
 #include <string.h>
+#include <sys/iosupport.h>
 #include <3ds/types.h>
 #include <3ds/svc.h>
 #include <3ds/srv.h>
 #include <3ds/services/soc.h>
 
+int __alloc_handle(int size);
+__handle *__get_handle(int fd);
+void __release_handle(int fd);
+
 extern Handle  SOCU_handle;
 extern int     SOCU_errno;
 extern Handle  socMemhandle;
 
+static inline int
+soc_get_fd(int fd)
+{
+       __handle *handle = __get_handle(fd);
+       if(handle == NULL)
+               return -ENODEV;
+       if(strcmp(devoptab_list[handle->device]->name, "soc") != 0)
+               return -ENOTSOCK;
+       return *(Handle*)handle->fileStruct;
+}
+
 s32 _net_convert_error(s32 sock_retval);
index 9577c77fdc713bf0112f06e3625ec6e16c0b6cee..cf01759d7e856ac85d28ccc7ea7e52fa0c2e8bc4 100644 (file)
@@ -9,6 +9,13 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
        u32 *cmdbuf = getThreadCommandBuffer();
        u8 tmpaddr[0x1c];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        memset(tmpaddr, 0, 0x1c);
 
        if(addr->sa_family == AF_INET)
index fcc873bf72837f493b1d21b391183a242c966e9e..23b5f8a4ef7b422fe3524960a9656a17cb00b1b1 100644 (file)
@@ -28,7 +28,7 @@ static int to_3ds(int flags)
        return newflags;
 }
 
-int fcntl(int fd, int cmd, ...)
+int fcntl(int sockfd, int cmd, ...)
 {
        int ret = 0;
        int arg = 0;
@@ -36,6 +36,13 @@ int fcntl(int fd, int cmd, ...)
 
        va_list args;
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        if(cmd != F_GETFL && cmd != F_SETFL)
        {
                SOCU_errno = -EINVAL;
@@ -60,7 +67,7 @@ int fcntl(int fd, int cmd, ...)
        va_end(args);
 
        cmdbuf[0] = 0x001300C2;
-       cmdbuf[1] = (u32)fd;
+       cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = (u32)cmd;
        cmdbuf[3] = (u32)arg;
        cmdbuf[4] = 0x20;
index f20be86820aba46ff54d9a3521b11267972da496..80af375f61c3533a6a01805960367f6ef0247a22 100644 (file)
@@ -8,6 +8,13 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
        u32 saved_threadstorage[2];
        u8 tmpaddr[0x1c];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x00180082;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = 0x1c;
index 80812af395a286d8b0902689d9920329ab5d038f..dceda3adca05bbf24c091050f80d21ff9fe54bc2 100644 (file)
@@ -8,6 +8,13 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
        u32 saved_threadstorage[2];
        u8 tmpaddr[0x1c];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x00170082;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = 0x1c;
index 20bf14823d7533933763fb506e0706f753679eef..85d0d4a3247694c58f22c751af37f94f06f791f1 100644 (file)
@@ -7,6 +7,13 @@ int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optl
        u32 *cmdbuf = getThreadCommandBuffer();
        u32 saved_threadstorage[2];
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x00110102;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = (u32)level;
index 2b961faff9b15bdf3a942fbb105f5babecf3294c..1837da2cf2e7f5fb8294f724bde48b5982691aa0 100644 (file)
@@ -1,4 +1,41 @@
 #include "soc_common.h"
+#include <sys/socket.h>
+
+static int     soc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
+static int     soc_close(struct _reent *r, int fd);
+static ssize_t soc_write(struct _reent *r, int fd, const char *ptr, size_t len);
+static ssize_t soc_read(struct _reent *r, int fd, char *ptr, size_t len);
+
+static devoptab_t
+soc_devoptab =
+{
+  .name         = "soc",
+  .structSize   = sizeof(Handle),
+  .open_r       = soc_open,
+  .close_r      = soc_close,
+  .write_r      = soc_write,
+  .read_r       = soc_read,
+  .seek_r       = NULL,
+  .fstat_r      = NULL,
+  .stat_r       = NULL,
+  .link_r       = NULL,
+  .unlink_r     = NULL,
+  .chdir_r      = NULL,
+  .rename_r     = NULL,
+  .mkdir_r      = NULL,
+  .dirStateSize = 0,
+  .diropen_r    = NULL,
+  .dirreset_r   = NULL,
+  .dirnext_r    = NULL,
+  .dirclose_r   = NULL,
+  .statvfs_r    = NULL,
+  .ftruncate_r  = NULL,
+  .fsync_r      = NULL,
+  .deviceData   = NULL,
+  .chmod_r      = NULL,
+  .fchmod_r     = NULL,
+};
+
 
 static Result socu_cmd1(Handle memhandle, u32 memsize)
 {
@@ -20,18 +57,43 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size)
 {
        Result ret=0;
 
+       /* check that the "soc" device doesn't already exist */
+       int dev = FindDevice("soc:");
+       if(dev >= 0)
+               return -1;
+
+       /* add the "soc" device */
+       dev = AddDevice(&soc_devoptab);
+       if(dev < 0)
+               return dev;
+
        ret = svcCreateMemoryBlock(&socMemhandle, (u32)context_addr, context_size, 0, 3);
-       if(ret!=0)return ret;
+       if(ret != 0)
+       {
+               RemoveDevice("soc");
+               return ret;
+       }
+
+       if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U")) != 0)
+       {
+               RemoveDevice("soc");
+               return ret;
+       }
 
-       if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U"))!=0)return ret;
+       if((ret = socu_cmd1(socMemhandle, context_size)) != 0)
+       {
+               RemoveDevice("soc");
+               return ret;
+       }
 
-       return socu_cmd1(socMemhandle, context_size);
+       return 0;
 }
 
 Result SOC_Shutdown(void)
 {
        Result ret=0;
        u32 *cmdbuf = getThreadCommandBuffer();
+       int dev;
 
        cmdbuf[0] = 0x00190000;
 
@@ -40,5 +102,62 @@ Result SOC_Shutdown(void)
        svcCloseHandle(SOCU_handle);
        svcCloseHandle(socMemhandle);
 
+       dev = FindDevice("soc:");
+       if(dev >= 0)
+               RemoveDevice("soc");
+
        return cmdbuf[1];
 }
+
+static int
+soc_open(struct _reent *r,
+         void          *fileStruct,
+         const char    *path,
+         int           flags,
+         int           mode)
+{
+       return -1;
+}
+
+static int
+soc_close(struct _reent *r,
+          int           fd)
+{
+       Handle sockfd = *(Handle*)fd;
+       
+       int ret=0;
+       u32 *cmdbuf = getThreadCommandBuffer();
+
+       cmdbuf[0] = 0x000B0042;
+       cmdbuf[1] = (u32)sockfd;
+       cmdbuf[2] = 0x20;
+
+       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+
+       ret = (int)cmdbuf[1];
+       if(ret==0)ret =_net_convert_error(cmdbuf[2]);
+       SOCU_errno = ret;
+
+       if(ret!=0)return -1;
+       return 0;
+}
+
+static ssize_t
+soc_write(struct _reent *r,
+          int           fd,
+          const char    *ptr,
+          size_t        len)
+{
+       Handle sockfd = *(Handle*)fd;
+       return send(sockfd, ptr, len, 0);
+}
+
+static ssize_t
+soc_read(struct _reent *r,
+         int           fd,
+         char          *ptr,
+         size_t        len)
+{
+       Handle sockfd = *(Handle*)fd;
+       return recv(sockfd, ptr, len, 0);
+}
index 41256462586dec52e575959ba59bf5dfae4109af..6f01baa25435022e30620f078be5658c8f93626e 100644 (file)
@@ -4,13 +4,20 @@
 #include <stdarg.h>
 #include <sys/ioctl.h>
 
-int ioctl(int fd, int request, ...)
+int ioctl(int sockfd, int request, ...)
 {
        int ret;
        int flags;
        int *value;
        va_list ap;
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        va_start(ap, request);
 
        switch(request) {
@@ -21,15 +28,15 @@ int ioctl(int fd, int request, ...)
                        ret = -1;
                }
 
-               flags = fcntl(fd, F_GETFL, 0);
+               flags = fcntl(sockfd, F_GETFL, 0);
                if(flags == -1) {
                        errno = SOC_GetErrno();
                        va_end(ap);
                        return -1;
                }
 
-               if(*value) ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-               else       ret = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+               if(*value) ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+               else       ret = fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
 
                if(ret != 0)
                        errno = SOC_GetErrno();
index ce7ff054397a1530b3f7a0eb52bea39192843b1a..41b73e44e79a7b96b40ca9149757f188fe59b0e0 100644 (file)
@@ -6,6 +6,13 @@ int listen(int sockfd, int max_connections)
        int ret=0;
        u32 *cmdbuf = getThreadCommandBuffer();
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x00030082;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = (u32)max_connections;
index 8cf5b349dd2b1ae433ad24f64ed1da1562224524..4bdbb2f397bbd7bd913187bfb07004aa9fbb9b1c 100644 (file)
@@ -1,19 +1,47 @@
 #include "soc_common.h"
 #include <poll.h>
+#include <stdlib.h>
 
-int poll(struct pollfd *fds, nfds_t nfsd, int timeout)
+int poll(struct pollfd *fds, nfds_t nfds, int timeout)
 {
        int ret = 0;
-       u32 size = sizeof(struct pollfd)*nfsd;
+       nfds_t i;
+       u32 size = sizeof(struct pollfd)*nfds;
        u32 *cmdbuf = getThreadCommandBuffer();
        u32 saved_threadstorage[2];
 
+       if(nfds == 0)
+       {
+               SOCU_errno = -EINVAL;
+               return -1;
+       }
+
+       struct pollfd *tmp_fds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds);
+       if(tmp_fds == NULL)
+       {
+               SOCU_errno = -ENOMEM;
+               return -1;
+       }
+
+       memcpy(tmp_fds, fds, sizeof(struct pollfd) * nfds);
+
+       for(i = 0; i < nfds; ++i)
+       {
+               tmp_fds[i].fd = soc_get_fd(fds[i].fd);
+               if(tmp_fds[i].fd < 0)
+               {
+                       SOCU_errno = tmp_fds[i].fd;
+                       free(tmp_fds);
+                       return -1;
+               }
+       }
+
        cmdbuf[0] = 0x00140084;
-       cmdbuf[1] = (u32)nfsd;
+       cmdbuf[1] = (u32)nfds;
        cmdbuf[2] = (u32)timeout;
        cmdbuf[3] = 0x20;
        cmdbuf[5] = (size<<14) | 0x2802;
-       cmdbuf[6] = (u32)fds;
+       cmdbuf[6] = (u32)tmp_fds;
 
        saved_threadstorage[0] = cmdbuf[0x100>>2];
        saved_threadstorage[1] = cmdbuf[0x104>>2];
@@ -21,7 +49,13 @@ int poll(struct pollfd *fds, nfds_t nfsd, int timeout)
        cmdbuf[0x100>>2] = (size<<14) | 2;
        cmdbuf[0x104>>2] = (u32)fds;
 
-       if((ret = svcSendSyncRequest(SOCU_handle)) != 0)return ret;
+       if((ret = svcSendSyncRequest(SOCU_handle)) != 0)
+       {
+               free(tmp_fds);
+               return ret;
+       }
+
+       free(tmp_fds);
 
        cmdbuf[0x100>>2] = saved_threadstorage[0];
         cmdbuf[0x104>>2] = saved_threadstorage[1];
index df5c56c440f40d6333a2de5872691fe7317effe5..3af3c1a1f77d0e71dc89588649778da0c149245e 100644 (file)
@@ -102,6 +102,13 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad
 
 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
 {
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen);
        return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen);
 }
index 9afd36a282b58ccc9ea626f490a9d10e9483b5ba..64eeb9ef32e49794907a59b3cd2879ceb191d09d 100644 (file)
@@ -108,6 +108,13 @@ ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const s
 
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
 {
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        if(len<0x2000)return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen);
        return socuipc_cmd9(sockfd, buf, len, flags, (struct sockaddr*)dest_addr, addrlen);
 }
index be86293c5adc9786ed1d341e520a63753aae99f9..4dca8c40d034df1adbf5cc55cdf14981e326b20d 100644 (file)
@@ -6,6 +6,13 @@ int shutdown(int sockfd, int shutdown_type)
        int ret=0;
        u32 *cmdbuf = getThreadCommandBuffer();
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x000C0082;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = (u32)shutdown_type;
index d445fb8f16050128ed51f9c506f89b73e0f96227..4fbec75e86c5e04b888ab318dcf65423ce5dbcf8 100644 (file)
@@ -6,6 +6,13 @@ int sockatmark(int sockfd)
        int ret=0;
        u32 *cmdbuf = getThreadCommandBuffer();
 
+       sockfd = soc_get_fd(sockfd);
+       if(sockfd < 0)
+       {
+               SOCU_errno = sockfd;
+               return -1;
+       }
+
        cmdbuf[0] = 0x00150042;
        cmdbuf[1] = (u32)sockfd;
        cmdbuf[2] = 0x20;
index 628138bceb66dd5187c6922c38da56e5fdcc03c4..94f2ad148eefa8eb3f7091cecd66c59946bfdfc5 100644 (file)
@@ -1,9 +1,13 @@
 #include "soc_common.h"
+#include <errno.h>
+#include <sys/iosupport.h>
 #include <sys/socket.h>
 
 int socket(int domain, int type, int protocol)
 {
        int ret=0;
+       int fd, dev;
+       __handle *handle;
        u32 *cmdbuf = getThreadCommandBuffer();
 
        cmdbuf[0] = 0x000200C2;
@@ -12,11 +16,38 @@ int socket(int domain, int type, int protocol)
        cmdbuf[3] = protocol;
        cmdbuf[4] = 0x20;
 
-       if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret;
+       dev = FindDevice("soc:");
+       if(dev < 0)
+       {
+               SOCU_errno = -ENODEV;
+               return -1;
+       }
+
+       fd = __alloc_handle(sizeof(__handle) + sizeof(Handle));
+       if(fd < 0)
+       {
+               SOCU_errno = -ENOMEM;
+               return -1;
+       }
+
+       handle = __get_handle(fd);
+       handle->device = dev;
+       handle->fileStruct = ((void *)handle) + sizeof(__handle);
+
+       if((ret = svcSendSyncRequest(SOCU_handle)) != 0)
+       {
+               __release_handle(fd);
+               return ret;
+       }
 
        ret = (int)cmdbuf[1];
-       SOCU_errno = ret;
+       if(ret != 0)
+       {
+               SOCU_errno = _net_convert_error(cmdbuf[2]);
+               __release_handle(fd);
+               return -1;
+       }
 
-       if(ret!=0)return -1;
-       return _net_convert_error(cmdbuf[2]);
+       *(Handle*)handle->fileStruct = cmdbuf[2];
+       return fd;
 }