From 71ae462ba963e361a394b177fbee956ec553695f Mon Sep 17 00:00:00 2001 From: Slashmolder Date: Tue, 30 Dec 2014 15:30:44 -0800 Subject: [PATCH 01/13] Fix for issue #66 --- libctru/source/services/httpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libctru/source/services/httpc.c b/libctru/source/services/httpc.c index a9f1eb9..abeb989 100644 --- a/libctru/source/services/httpc.c +++ b/libctru/source/services/httpc.c @@ -43,8 +43,8 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy) ret = HTTPC_InitializeConnectionSession(context->servhandle, context->httphandle); if(ret!=0) { - HTTPC_CloseContext(__httpc_servhandle, context->httphandle); svcCloseHandle(context->servhandle); + HTTPC_CloseContext(__httpc_servhandle, context->httphandle); return ret; } @@ -52,8 +52,8 @@ Result httpcOpenContext(httpcContext *context, char* url, u32 use_defaultproxy) ret = HTTPC_SetProxyDefault(context->servhandle, context->httphandle); if(ret!=0) { - HTTPC_CloseContext(__httpc_servhandle, context->httphandle); svcCloseHandle(context->servhandle); + HTTPC_CloseContext(__httpc_servhandle, context->httphandle); return ret; } @@ -64,8 +64,8 @@ Result httpcCloseContext(httpcContext *context) { Result ret=0; - ret = HTTPC_CloseContext(context->servhandle, context->httphandle); svcCloseHandle(context->servhandle); + ret = HTTPC_CloseContext(__httpc_servhandle, context->httphandle); return ret; } From 20431deb4e739c87b03f21635027b16f0f587202 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 1 Feb 2015 07:47:18 -0500 Subject: [PATCH 02/13] Guard against potential null pointer dereferences --- libctru/source/services/csnd.c | 2 +- libctru/source/services/soc/soc_ioctl.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libctru/source/services/csnd.c b/libctru/source/services/csnd.c index 3c8012d..994443f 100644 --- a/libctru/source/services/csnd.c +++ b/libctru/source/services/csnd.c @@ -410,7 +410,7 @@ Result csndPlaySound(int chn, u32 flags, u32 sampleRate, void* data0, void* data if (data0) paddr0 = osConvertVirtToPhys((u32)data0); if (data1) paddr1 = osConvertVirtToPhys((u32)data1); - if (encoding == CSND_ENCODING_ADPCM) + if (data0 && encoding == CSND_ENCODING_ADPCM) { int adpcmSample = ((s16*)data0)[-2]; int adpcmIndex = ((u8*)data0)[-2]; diff --git a/libctru/source/services/soc/soc_ioctl.c b/libctru/source/services/soc/soc_ioctl.c index 4125646..ec4e691 100644 --- a/libctru/source/services/soc/soc_ioctl.c +++ b/libctru/source/services/soc/soc_ioctl.c @@ -18,7 +18,8 @@ int ioctl(int fd, int request, ...) value = va_arg(ap, int*); if(value == NULL) { errno = EFAULT; - ret = -1; + va_end(ap); + return -1; } flags = fcntl(fd, F_GETFL, 0); From 8af5a9946fb0a075ac87f717635f0c698d57e86e Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Sun, 1 Feb 2015 15:19:22 +0000 Subject: [PATCH 03/13] fix handle leak in sdmc_stat --- libctru/source/sdmc_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libctru/source/sdmc_dev.c b/libctru/source/sdmc_dev.c index d02c962..b879eb0 100644 --- a/libctru/source/sdmc_dev.c +++ b/libctru/source/sdmc_dev.c @@ -565,6 +565,7 @@ sdmc_stat(struct _reent *r, st->st_uid = 1; st->st_gid = 2; st->st_mode = S_IFDIR | S_IWUSR | S_IWGRP | S_IWOTH | S_IRUSR | S_IRGRP | S_IROTH; + FSFILE_Close(fd); return 0; } From 8cab1f28d49ccf971b28c617d79d5316ba5529f0 Mon Sep 17 00:00:00 2001 From: LunarCookies Date: Mon, 2 Feb 2015 13:46:58 +0000 Subject: [PATCH 04/13] HTTPC_AddRequestHeaderField Fix --- libctru/source/services/httpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/services/httpc.c b/libctru/source/services/httpc.c index abeb989..7000491 100644 --- a/libctru/source/services/httpc.c +++ b/libctru/source/services/httpc.c @@ -225,7 +225,7 @@ Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* na cmdbuf[3]=l2; cmdbuf[4]=(l1<<14)|0xC02; cmdbuf[5]=(u32)name; - cmdbuf[6]=(l1<<4)|0xA; + cmdbuf[6]=(l2<<4)|0xA; cmdbuf[7]=(u32)value; Result ret=0; From 3f19e7920cd62e39148578adc082010c383c3719 Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Mon, 2 Feb 2015 19:30:08 +0000 Subject: [PATCH 05/13] threads take void * not u32 --- libctru/include/3ds/types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/include/3ds/types.h b/libctru/include/3ds/types.h index 550c0d2..88d09fc 100644 --- a/libctru/include/3ds/types.h +++ b/libctru/include/3ds/types.h @@ -39,7 +39,7 @@ typedef volatile s64 vs64; typedef u32 Handle; typedef s32 Result; -typedef void (*ThreadFunc)(u32); +typedef void (*ThreadFunc)(void *); #define BIT(n) (1U<<(n)) From f993eac8a23c67eee83b6b132efcb14fdc2af7d6 Mon Sep 17 00:00:00 2001 From: LunarCookies Date: Mon, 2 Feb 2015 19:51:20 +0000 Subject: [PATCH 06/13] Update httpc.c --- libctru/source/services/httpc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libctru/source/services/httpc.c b/libctru/source/services/httpc.c index 7000491..8b839e8 100644 --- a/libctru/source/services/httpc.c +++ b/libctru/source/services/httpc.c @@ -216,16 +216,16 @@ Result HTTPC_AddRequestHeaderField(Handle handle, Handle contextHandle, char* na { u32* cmdbuf=getThreadCommandBuffer(); - int l1=strlen(name)+1; - int l2=strlen(value)+1; + int name_len=strlen(name)+1; + int value_len=strlen(value)+1; cmdbuf[0]=0x1100c4; //request header code cmdbuf[1]=contextHandle; - cmdbuf[2]=l1; - cmdbuf[3]=l2; - cmdbuf[4]=(l1<<14)|0xC02; + cmdbuf[2]=name_len; + cmdbuf[3]=value_len; + cmdbuf[4]=(name_len<<14)|0xC02; cmdbuf[5]=(u32)name; - cmdbuf[6]=(l2<<4)|0xA; + cmdbuf[6]=(value_len<<4)|0xA; cmdbuf[7]=(u32)value; Result ret=0; From 9fec42f38fd2a975a31e847bd095dba0ae4db8e2 Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Tue, 3 Feb 2015 09:18:22 +0000 Subject: [PATCH 07/13] fix gspEventThreadMain signature --- libctru/source/services/gsp.c | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/libctru/source/services/gsp.c b/libctru/source/services/gsp.c index 9a88c3a..0234712 100644 --- a/libctru/source/services/gsp.c +++ b/libctru/source/services/gsp.c @@ -21,7 +21,7 @@ Handle gspEventThread; static Handle gspEvent; static vu8* gspEventData; -static void gspEventThreadMain(u32 arg); +static void gspEventThreadMain(void *arg); Result gspInit() @@ -82,7 +82,7 @@ void gspWaitForEvent(GSP_Event id, bool nextEvent) svcClearEvent(gspEvents[id]); } -void gspEventThreadMain(u32 arg) +void gspEventThreadMain(void *arg) { while (gspRunEvents) { @@ -114,7 +114,7 @@ void gspEventThreadMain(u32 arg) Result GSPGPU_WriteHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size) { if(!handle)handle=&gspGpuHandle; - + if(size>0x80 || !data)return -1; u32* cmdbuf=getThreadCommandBuffer(); @@ -133,7 +133,7 @@ Result GSPGPU_WriteHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size) Result GSPGPU_WriteHWRegsWithMask(Handle* handle, u32 regAddr, u32* data, u8 datasize, u32* maskdata, u8 masksize) { if(!handle)handle=&gspGpuHandle; - + if(datasize>0x80 || !data)return -1; u32* cmdbuf=getThreadCommandBuffer(); @@ -154,7 +154,7 @@ Result GSPGPU_WriteHWRegsWithMask(Handle* handle, u32 regAddr, u32* data, u8 dat Result GSPGPU_ReadHWRegs(Handle* handle, u32 regAddr, u32* data, u8 size) { if(!handle)handle=&gspGpuHandle; - + if(size>0x80 || !data)return -1; u32* cmdbuf=getThreadCommandBuffer(); @@ -180,7 +180,7 @@ Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *f cmdbuf[0] = 0x00050200; cmdbuf[1] = screenid; memcpy(&cmdbuf[2], framebufinfo, sizeof(GSP_FramebufferInfo)); - + if((ret=svcSendSyncRequest(*handle)))return ret; return cmdbuf[1]; @@ -189,7 +189,7 @@ Result GSPGPU_SetBufferSwap(Handle* handle, u32 screenid, GSP_FramebufferInfo *f Result GSPGPU_FlushDataCache(Handle* handle, u8* adr, u32 size) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x00080082; //request header code cmdbuf[1]=(u32)adr; @@ -224,7 +224,7 @@ Result GSPGPU_InvalidateDataCache(Handle* handle, u8* adr, u32 size) Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x000B0040; //request header code cmdbuf[1]=flags; @@ -238,7 +238,7 @@ Result GSPGPU_SetLcdForceBlack(Handle* handle, u8 flags) Result GSPGPU_TriggerCmdReqQueue(Handle* handle) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x000C0000; //request header code @@ -251,7 +251,7 @@ Result GSPGPU_TriggerCmdReqQueue(Handle* handle) Result GSPGPU_RegisterInterruptRelayQueue(Handle* handle, Handle eventHandle, u32 flags, Handle* outMemHandle, u8* threadID) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x00130042; //request header code cmdbuf[1]=flags; @@ -263,27 +263,27 @@ Result GSPGPU_RegisterInterruptRelayQueue(Handle* handle, Handle eventHandle, u3 if(threadID)*threadID=cmdbuf[2]; if(outMemHandle)*outMemHandle=cmdbuf[4]; - + return cmdbuf[1]; } Result GSPGPU_UnregisterInterruptRelayQueue(Handle* handle) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x00140000; //request header code Result ret=0; if((ret=svcSendSyncRequest(*handle)))return ret; - + return cmdbuf[1]; } Result GSPGPU_AcquireRight(Handle* handle, u8 flags) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x160042; //request header code cmdbuf[1]=flags; @@ -299,7 +299,7 @@ Result GSPGPU_AcquireRight(Handle* handle, u8 flags) Result GSPGPU_ReleaseRight(Handle* handle) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x170000; //request header code @@ -312,7 +312,7 @@ Result GSPGPU_ReleaseRight(Handle* handle) Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *captureinfo) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x00180000; //request header code @@ -332,7 +332,7 @@ Result GSPGPU_ImportDisplayCaptureInfo(Handle* handle, GSP_CaptureInfo *capturei Result GSPGPU_SaveVramSysArea(Handle* handle) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x00190000; //request header code @@ -345,7 +345,7 @@ Result GSPGPU_SaveVramSysArea(Handle* handle) Result GSPGPU_RestoreVramSysArea(Handle* handle) { if(!handle)handle=&gspGpuHandle; - + u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=0x001A0000; //request header code @@ -361,7 +361,7 @@ Result GSPGPU_RestoreVramSysArea(Handle* handle) Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle* handle) { if(!sharedGspCmdBuf || !gxCommand)return -1; - + u32 cmdBufHeader; __asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf)); From 4fa477c039a1ac987823825cb81eb1afd87858f8 Mon Sep 17 00:00:00 2001 From: mtheall Date: Fri, 23 Jan 2015 14:23:59 -0600 Subject: [PATCH 08/13] First attempt at hooking sockets into a devoptab. --- libctru/source/services/soc/soc_accept.c | 60 +++++++-- libctru/source/services/soc/soc_bind.c | 7 + libctru/source/services/soc/soc_closesocket.c | 21 +-- libctru/source/services/soc/soc_common.c | 1 + libctru/source/services/soc/soc_common.h | 17 +++ libctru/source/services/soc/soc_connect.c | 7 + libctru/source/services/soc/soc_fcntl.c | 11 +- libctru/source/services/soc/soc_getpeername.c | 7 + libctru/source/services/soc/soc_getsockname.c | 7 + libctru/source/services/soc/soc_getsockopt.c | 7 + libctru/source/services/soc/soc_init.c | 125 +++++++++++++++++- libctru/source/services/soc/soc_ioctl.c | 15 ++- libctru/source/services/soc/soc_listen.c | 7 + libctru/source/services/soc/soc_poll.c | 44 +++++- libctru/source/services/soc/soc_recvfrom.c | 7 + libctru/source/services/soc/soc_sendto.c | 7 + libctru/source/services/soc/soc_shutdown.c | 7 + libctru/source/services/soc/soc_sockatmark.c | 7 + libctru/source/services/soc/soc_socket.c | 39 +++++- 19 files changed, 362 insertions(+), 41 deletions(-) diff --git a/libctru/source/services/soc/soc_accept.c b/libctru/source/services/soc/soc_accept.c index 355a744..cf64863 100644 --- a/libctru/source/services/soc/soc_accept.c +++ b/libctru/source/services/soc/soc_accept.c @@ -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; } diff --git a/libctru/source/services/soc/soc_bind.c b/libctru/source/services/soc/soc_bind.c index dba52e5..dd37f7e 100644 --- a/libctru/source/services/soc/soc_bind.c +++ b/libctru/source/services/soc/soc_bind.c @@ -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) diff --git a/libctru/source/services/soc/soc_closesocket.c b/libctru/source/services/soc/soc_closesocket.c index 85dcd52..37e1923 100644 --- a/libctru/source/services/soc/soc_closesocket.c +++ b/libctru/source/services/soc/soc_closesocket.c @@ -3,19 +3,12 @@ int closesocket(int sockfd) { - int ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); + int fd = soc_get_fd(sockfd); + if(fd < 0) + { + SOCU_errno = fd; + return -1; + } - 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; + return close(sockfd); } diff --git a/libctru/source/services/soc/soc_common.c b/libctru/source/services/soc/soc_common.c index 8814453..c41491c 100644 --- a/libctru/source/services/soc/soc_common.c +++ b/libctru/source/services/soc/soc_common.c @@ -1,5 +1,6 @@ #include "soc_common.h" #include +#include Handle SOCU_handle = 0; int SOCU_errno = 0; diff --git a/libctru/source/services/soc/soc_common.h b/libctru/source/services/soc/soc_common.h index 5cf5dee..f325bf7 100644 --- a/libctru/source/services/soc/soc_common.h +++ b/libctru/source/services/soc/soc_common.h @@ -1,13 +1,30 @@ #pragma once +#include #include +#include #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); diff --git a/libctru/source/services/soc/soc_connect.c b/libctru/source/services/soc/soc_connect.c index 9577c77..cf01759 100644 --- a/libctru/source/services/soc/soc_connect.c +++ b/libctru/source/services/soc/soc_connect.c @@ -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) diff --git a/libctru/source/services/soc/soc_fcntl.c b/libctru/source/services/soc/soc_fcntl.c index fcc873b..23b5f8a 100644 --- a/libctru/source/services/soc/soc_fcntl.c +++ b/libctru/source/services/soc/soc_fcntl.c @@ -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; diff --git a/libctru/source/services/soc/soc_getpeername.c b/libctru/source/services/soc/soc_getpeername.c index f20be86..80af375 100644 --- a/libctru/source/services/soc/soc_getpeername.c +++ b/libctru/source/services/soc/soc_getpeername.c @@ -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; diff --git a/libctru/source/services/soc/soc_getsockname.c b/libctru/source/services/soc/soc_getsockname.c index 80812af..dceda3a 100644 --- a/libctru/source/services/soc/soc_getsockname.c +++ b/libctru/source/services/soc/soc_getsockname.c @@ -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; diff --git a/libctru/source/services/soc/soc_getsockopt.c b/libctru/source/services/soc/soc_getsockopt.c index 20bf148..85d0d4a 100644 --- a/libctru/source/services/soc/soc_getsockopt.c +++ b/libctru/source/services/soc/soc_getsockopt.c @@ -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; diff --git a/libctru/source/services/soc/soc_init.c b/libctru/source/services/soc/soc_init.c index 2b961fa..1837da2 100644 --- a/libctru/source/services/soc/soc_init.c +++ b/libctru/source/services/soc/soc_init.c @@ -1,4 +1,41 @@ #include "soc_common.h" +#include + +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)return ret; + if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U")) != 0) + { + RemoveDevice("soc"); + return ret; + } - return socu_cmd1(socMemhandle, context_size); + if((ret = socu_cmd1(socMemhandle, context_size)) != 0) + { + RemoveDevice("soc"); + return ret; + } + + 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); +} diff --git a/libctru/source/services/soc/soc_ioctl.c b/libctru/source/services/soc/soc_ioctl.c index ec4e691..9e25c4f 100644 --- a/libctru/source/services/soc/soc_ioctl.c +++ b/libctru/source/services/soc/soc_ioctl.c @@ -4,13 +4,20 @@ #include #include -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) { @@ -22,15 +29,15 @@ int ioctl(int fd, int request, ...) return -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(); diff --git a/libctru/source/services/soc/soc_listen.c b/libctru/source/services/soc/soc_listen.c index ce7ff05..41b73e4 100644 --- a/libctru/source/services/soc/soc_listen.c +++ b/libctru/source/services/soc/soc_listen.c @@ -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; diff --git a/libctru/source/services/soc/soc_poll.c b/libctru/source/services/soc/soc_poll.c index 8cf5b34..4bdbb2f 100644 --- a/libctru/source/services/soc/soc_poll.c +++ b/libctru/source/services/soc/soc_poll.c @@ -1,19 +1,47 @@ #include "soc_common.h" #include +#include -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]; diff --git a/libctru/source/services/soc/soc_recvfrom.c b/libctru/source/services/soc/soc_recvfrom.c index df5c56c..3af3c1a 100644 --- a/libctru/source/services/soc/soc_recvfrom.c +++ b/libctru/source/services/soc/soc_recvfrom.c @@ -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); } diff --git a/libctru/source/services/soc/soc_sendto.c b/libctru/source/services/soc/soc_sendto.c index 9afd36a..64eeb9e 100644 --- a/libctru/source/services/soc/soc_sendto.c +++ b/libctru/source/services/soc/soc_sendto.c @@ -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); } diff --git a/libctru/source/services/soc/soc_shutdown.c b/libctru/source/services/soc/soc_shutdown.c index be86293..4dca8c4 100644 --- a/libctru/source/services/soc/soc_shutdown.c +++ b/libctru/source/services/soc/soc_shutdown.c @@ -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; diff --git a/libctru/source/services/soc/soc_sockatmark.c b/libctru/source/services/soc/soc_sockatmark.c index d445fb8..4fbec75 100644 --- a/libctru/source/services/soc/soc_sockatmark.c +++ b/libctru/source/services/soc/soc_sockatmark.c @@ -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; diff --git a/libctru/source/services/soc/soc_socket.c b/libctru/source/services/soc/soc_socket.c index 628138b..94f2ad1 100644 --- a/libctru/source/services/soc/soc_socket.c +++ b/libctru/source/services/soc/soc_socket.c @@ -1,9 +1,13 @@ #include "soc_common.h" +#include +#include #include 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; } From 67f991e452d54fdd5da7b72642469fd80b67b528 Mon Sep 17 00:00:00 2001 From: mtheall Date: Sat, 24 Jan 2015 11:48:50 -0600 Subject: [PATCH 09/13] Fix poll() to only update revents. --- libctru/source/services/soc/soc_poll.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libctru/source/services/soc/soc_poll.c b/libctru/source/services/soc/soc_poll.c index 4bdbb2f..80b6514 100644 --- a/libctru/source/services/soc/soc_poll.c +++ b/libctru/source/services/soc/soc_poll.c @@ -1,6 +1,7 @@ #include "soc_common.h" #include #include +#include int poll(struct pollfd *fds, nfds_t nfds, int timeout) { @@ -47,7 +48,7 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) saved_threadstorage[1] = cmdbuf[0x104>>2]; cmdbuf[0x100>>2] = (size<<14) | 2; - cmdbuf[0x104>>2] = (u32)fds; + cmdbuf[0x104>>2] = (u32)tmp_fds; if((ret = svcSendSyncRequest(SOCU_handle)) != 0) { @@ -55,6 +56,11 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) return ret; } + for(i = 0; i < nfds; ++i) + { + fds[i].revents = tmp_fds[i].revents; + } + free(tmp_fds); cmdbuf[0x100>>2] = saved_threadstorage[0]; From e75fd8b648a232c62ce49f4846b8dd64098ca67f Mon Sep 17 00:00:00 2001 From: mtheall Date: Sat, 24 Jan 2015 14:14:06 -0600 Subject: [PATCH 10/13] Refactor soc to use errno. --- libctru/include/3ds/services/soc.h | 3 - libctru/include/netdb.h | 2 + libctru/source/services/soc/soc_accept.c | 29 ++++---- libctru/source/services/soc/soc_bind.c | 34 +++++---- libctru/source/services/soc/soc_closesocket.c | 7 +- libctru/source/services/soc/soc_common.c | 16 ++-- libctru/source/services/soc/soc_common.h | 3 +- libctru/source/services/soc/soc_connect.c | 34 +++++---- libctru/source/services/soc/soc_fcntl.c | 43 ++++++----- .../source/services/soc/soc_gethostbyname.c | 22 ++++-- libctru/source/services/soc/soc_gethostid.c | 12 ++- libctru/source/services/soc/soc_getpeername.c | 34 +++++---- libctru/source/services/soc/soc_getsockname.c | 34 +++++---- libctru/source/services/soc/soc_getsockopt.c | 26 ++++--- libctru/source/services/soc/soc_herror.c | 10 +++ libctru/source/services/soc/soc_hstrerror.c | 26 +++++++ libctru/source/services/soc/soc_init.c | 49 ++++++++---- libctru/source/services/soc/soc_ioctl.c | 26 +++---- libctru/source/services/soc/soc_listen.c | 24 ++++-- libctru/source/services/soc/soc_poll.c | 48 ++++++------ libctru/source/services/soc/soc_recvfrom.c | 67 +++++++++++------ libctru/source/services/soc/soc_select.c | 5 +- libctru/source/services/soc/soc_sendto.c | 74 ++++++++++--------- libctru/source/services/soc/soc_setsockopt.c | 25 +++++-- libctru/source/services/soc/soc_shutdown.c | 24 ++++-- libctru/source/services/soc/soc_sockatmark.c | 24 ++++-- libctru/source/services/soc/soc_socket.c | 21 +++--- 27 files changed, 433 insertions(+), 289 deletions(-) create mode 100644 libctru/source/services/soc/soc_herror.c create mode 100644 libctru/source/services/soc/soc_hstrerror.c diff --git a/libctru/include/3ds/services/soc.h b/libctru/include/3ds/services/soc.h index 55ff21e..3ec99b7 100644 --- a/libctru/include/3ds/services/soc.h +++ b/libctru/include/3ds/services/soc.h @@ -1,11 +1,8 @@ #pragma once Result SOC_Initialize(u32 *context_addr, u32 context_size);//Example context_size: 0x48000. The specified context buffer can no longer be accessed by the process which called this function, since the userland permissions for this block are set to no-access. -Result SOC_Shutdown(); -int SOC_GetErrno(); Result SOC_Shutdown(void); -int SOC_GetErrno(void); /* this is supposed to be in unistd.h but newlib only puts it for cygwin */ long gethostid(void); diff --git a/libctru/include/netdb.h b/libctru/include/netdb.h index 7f769a4..b3fac81 100644 --- a/libctru/include/netdb.h +++ b/libctru/include/netdb.h @@ -22,6 +22,8 @@ extern "C" { extern int h_errno; struct hostent* gethostbyname(const char *name); + void herror(const char *s); + const char* hstrerror(int err); #ifdef __cplusplus } diff --git a/libctru/source/services/soc/soc_accept.c b/libctru/source/services/soc/soc_accept.c index cf64863..71ce790 100644 --- a/libctru/source/services/soc/soc_accept.c +++ b/libctru/source/services/soc/soc_accept.c @@ -1,4 +1,5 @@ #include "soc_common.h" +#include #include int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) @@ -12,23 +13,20 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) u32 saved_threadstorage[2]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } dev = FindDevice("soc:"); - if(dev < 0) - { - SOCU_errno = -ENODEV; + if(dev < 0) { + errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); - if(fd < 0) - { - SOCU_errno = -ENOMEM; + if(fd < 0) { + errno = ENOMEM; return -1; } @@ -49,9 +47,10 @@ 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) - { + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { __release_handle(fd); + errno = SYNC_ERROR; return ret; } @@ -63,18 +62,16 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) - SOCU_errno = ret; + errno = -ret; - if(ret >= 0 && addr != NULL) - { + if(ret >= 0 && addr != NULL) { addr->sa_family = tmpaddr[1]; if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); } - if(ret < 0) - { + if(ret < 0) { __release_handle(fd); return -1; } diff --git a/libctru/source/services/soc/soc_bind.c b/libctru/source/services/soc/soc_bind.c index dd37f7e..610cdf6 100644 --- a/libctru/source/services/soc/soc_bind.c +++ b/libctru/source/services/soc/soc_bind.c @@ -4,32 +4,26 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - int ret=0; - int tmp_addrlen=0; + int ret = 0; + int tmp_addrlen = 0; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } memset(tmpaddr, 0, 0x1c); if(addr->sa_family == AF_INET) - { tmp_addrlen = 8; - } else - { tmp_addrlen = 0x1c; - } - if(addrlen < tmp_addrlen) - { - SOCU_errno = EINVAL; + if(addrlen < tmp_addrlen) { + errno = EINVAL; return -1; } @@ -44,12 +38,20 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2; cmdbuf[6] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } ret = (int)cmdbuf[1]; - if(ret==0)ret = _net_convert_error(cmdbuf[2]); - SOCU_errno = ret; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return 0; } diff --git a/libctru/source/services/soc/soc_closesocket.c b/libctru/source/services/soc/soc_closesocket.c index 37e1923..9a3c93b 100644 --- a/libctru/source/services/soc/soc_closesocket.c +++ b/libctru/source/services/soc/soc_closesocket.c @@ -1,12 +1,13 @@ #include "soc_common.h" +#include #include +#include int closesocket(int sockfd) { int fd = soc_get_fd(sockfd); - if(fd < 0) - { - SOCU_errno = fd; + if(fd < 0) { + errno = -fd; return -1; } diff --git a/libctru/source/services/soc/soc_common.c b/libctru/source/services/soc/soc_common.c index c41491c..a610919 100644 --- a/libctru/source/services/soc/soc_common.c +++ b/libctru/source/services/soc/soc_common.c @@ -3,7 +3,6 @@ #include Handle SOCU_handle = 0; -int SOCU_errno = 0; Handle socMemhandle = 0; //This is based on the array from libogc network_wii.c. @@ -92,14 +91,11 @@ static u8 _net_error_code_map[] = { //This is based on the function from libogc network_wii.c. s32 _net_convert_error(s32 sock_retval) { - if (sock_retval >= 0) return sock_retval; - if (sock_retval < -sizeof(_net_error_code_map) - || !_net_error_code_map[-sock_retval]) - return NET_UNKNOWN_ERROR_OFFSET + sock_retval; + if(sock_retval >= 0) + return sock_retval; + + if(sock_retval < -sizeof(_net_error_code_map) + || !_net_error_code_map[-sock_retval]) + return NET_UNKNOWN_ERROR_OFFSET + sock_retval; return -_net_error_code_map[-sock_retval]; } - -int SOC_GetErrno(void) -{ - return SOCU_errno; -} diff --git a/libctru/source/services/soc/soc_common.h b/libctru/source/services/soc/soc_common.h index f325bf7..f35c5fe 100644 --- a/libctru/source/services/soc/soc_common.h +++ b/libctru/source/services/soc/soc_common.h @@ -8,12 +8,13 @@ #include <3ds/srv.h> #include <3ds/services/soc.h> +#define SYNC_ERROR ENODEV + 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 diff --git a/libctru/source/services/soc/soc_connect.c b/libctru/source/services/soc/soc_connect.c index cf01759..4cab7cc 100644 --- a/libctru/source/services/soc/soc_connect.c +++ b/libctru/source/services/soc/soc_connect.c @@ -4,32 +4,26 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - int ret=0; - int tmp_addrlen=0; + int ret = 0; + int tmp_addrlen = 0; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } memset(tmpaddr, 0, 0x1c); if(addr->sa_family == AF_INET) - { tmp_addrlen = 8; - } else - { tmp_addrlen = 0x1c; - } - if(addrlen < tmp_addrlen) - { - SOCU_errno = -EINVAL; + if(addrlen < tmp_addrlen) { + errno = EINVAL; return -1; } @@ -44,12 +38,20 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) cmdbuf[5] = (((u32)tmp_addrlen)<<14) | 2; cmdbuf[6] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } ret = (int)cmdbuf[1]; - if(ret==0)ret = _net_convert_error(cmdbuf[2]); - SOCU_errno = ret; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return 0; } diff --git a/libctru/source/services/soc/soc_fcntl.c b/libctru/source/services/soc/soc_fcntl.c index 23b5f8a..f14a0e0 100644 --- a/libctru/source/services/soc/soc_fcntl.c +++ b/libctru/source/services/soc/soc_fcntl.c @@ -12,7 +12,8 @@ static int from_3ds(int flags) { int newflags = 0; - if(flags & O_NONBLOCK_3DS) newflags |= O_NONBLOCK; + if(flags & O_NONBLOCK_3DS) + newflags |= O_NONBLOCK; /* add other flag translations here, but I have only seen O_NONBLOCK */ return newflags; @@ -22,7 +23,8 @@ static int to_3ds(int flags) { int newflags = 0; - if(flags & O_NONBLOCK) newflags |= O_NONBLOCK_3DS; + if(flags & O_NONBLOCK) + newflags |= O_NONBLOCK_3DS; /* add other flag translations here, but I have only seen O_NONBLOCK */ return newflags; @@ -37,34 +39,29 @@ int fcntl(int sockfd, int cmd, ...) va_list args; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } - if(cmd != F_GETFL && cmd != F_SETFL) - { - SOCU_errno = -EINVAL; + if(cmd != F_GETFL && cmd != F_SETFL) { + errno = EINVAL; return -1; } - va_start(args, cmd); - if(cmd == F_SETFL) - { + if(cmd == F_SETFL) { + va_start(args, cmd); arg = va_arg(args, int); + va_end(args); /* make sure they only used known flags */ - if(arg & ~ALL_FLAGS) - { - SOCU_errno = -EINVAL; - va_end(args); + if(arg & ~ALL_FLAGS) { + errno = EINVAL; return -1; } arg = to_3ds(arg); } - va_end(args); cmdbuf[0] = 0x001300C2; cmdbuf[1] = (u32)sockfd; @@ -72,20 +69,22 @@ int fcntl(int sockfd, int cmd, ...) cmdbuf[3] = (u32)arg; cmdbuf[4] = 0x20; - if((ret = svcSendSyncRequest(SOCU_handle)) != 0) + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; return ret; + } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); - if(ret < 0) - SOCU_errno = ret; - if(ret < 0) + if(ret < 0) { + errno = ret; return -1; + } - if(ret & ~ALL_3DS) - { + if(ret & ~ALL_3DS) { /* somehow report unknown flags */ } diff --git a/libctru/source/services/soc/soc_gethostbyname.c b/libctru/source/services/soc/soc_gethostbyname.c index 4932378..ed712db 100644 --- a/libctru/source/services/soc/soc_gethostbyname.c +++ b/libctru/source/services/soc/soc_gethostbyname.c @@ -10,11 +10,13 @@ int h_errno = 0; struct hostent* gethostbyname(const char *name) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; static u8 outbuf[0x1A88]; + h_errno = 0; + cmdbuf[0] = 0x000D0082; cmdbuf[1] = strlen(name)+1; cmdbuf[2] = sizeof(outbuf); @@ -27,17 +29,25 @@ struct hostent* gethostbyname(const char *name) cmdbuf[0x100>>2] = (sizeof(outbuf) << 14) | 2; cmdbuf[0x104>>2] = (u32)outbuf; - if(( ret = svcSendSyncRequest(SOCU_handle))!=0)return NULL; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + h_errno = NO_RECOVERY; + return NULL; + } + 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; - /* TODO: set h_errno based on SOCU_errno */ + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); - if(ret<0)return NULL; + if(ret < 0) { + /* TODO: set h_errno based on ret */ + h_errno = HOST_NOT_FOUND; + return NULL; + } u32 num_results, i; memcpy(&num_results, (char*)outbuf+4, sizeof(num_results)); diff --git a/libctru/source/services/soc/soc_gethostid.c b/libctru/source/services/soc/soc_gethostid.c index fb747c3..7a254aa 100644 --- a/libctru/source/services/soc/soc_gethostid.c +++ b/libctru/source/services/soc/soc_gethostid.c @@ -1,16 +1,22 @@ #include "soc_common.h" +#include long gethostid(void) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = 0x00160000; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return -1; + } ret = (int)cmdbuf[1]; - if(ret==0)ret = cmdbuf[2]; + if(ret == 0) + ret = cmdbuf[2]; return ret; } diff --git a/libctru/source/services/soc/soc_getpeername.c b/libctru/source/services/soc/soc_getpeername.c index 80af375..977b14b 100644 --- a/libctru/source/services/soc/soc_getpeername.c +++ b/libctru/source/services/soc/soc_getpeername.c @@ -1,17 +1,17 @@ #include "soc_common.h" +#include #include int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; u8 tmpaddr[0x1c]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -26,23 +26,29 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) cmdbuf[0x100>>2] = (0x1c<<14) | 2; cmdbuf[0x104>>2] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + 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) - { - if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0]; - memset(addr, 0, sizeof(struct sockaddr)); - addr->sa_family = tmpaddr[1]; - memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); + if(ret < 0) { + errno = -ret; + return -1; } - if(ret<0)return -1; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; + memset(addr, 0, sizeof(struct sockaddr)); + addr->sa_family = tmpaddr[1]; + memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); + return ret; } diff --git a/libctru/source/services/soc/soc_getsockname.c b/libctru/source/services/soc/soc_getsockname.c index dceda3a..2fd16b3 100644 --- a/libctru/source/services/soc/soc_getsockname.c +++ b/libctru/source/services/soc/soc_getsockname.c @@ -1,17 +1,17 @@ #include "soc_common.h" +#include #include int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; u8 tmpaddr[0x1c]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -26,23 +26,29 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) cmdbuf[0x100>>2] = (0x1c<<14) | 2; cmdbuf[0x104>>2] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + 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) - { - if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0]; - memset(addr, 0, sizeof(struct sockaddr)); - addr->sa_family = tmpaddr[1]; - memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); + if(ret < 0) { + errno = -ret; + return -1; } - if(ret<0)return -1; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; + memset(addr, 0, sizeof(struct sockaddr)); + addr->sa_family = tmpaddr[1]; + memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); + return ret; } diff --git a/libctru/source/services/soc/soc_getsockopt.c b/libctru/source/services/soc/soc_getsockopt.c index 85d0d4a..8b48994 100644 --- a/libctru/source/services/soc/soc_getsockopt.c +++ b/libctru/source/services/soc/soc_getsockopt.c @@ -1,16 +1,16 @@ #include "soc_common.h" +#include #include int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -27,17 +27,25 @@ int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optl cmdbuf[0x100>>2] = ((*optlen)<<14) | 2; cmdbuf[0x104>>2] = (u32)optval; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + 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)*optlen = cmdbuf[3]; + if(ret < 0) { + errno = -ret; + return -1; + } + + *optlen = cmdbuf[3]; - if(ret<0)return -1; return ret; } diff --git a/libctru/source/services/soc/soc_herror.c b/libctru/source/services/soc/soc_herror.c new file mode 100644 index 0000000..04a7e24 --- /dev/null +++ b/libctru/source/services/soc/soc_herror.c @@ -0,0 +1,10 @@ +#include "soc_common.h" +#include +#include + +void herror(const char *s) { + if(s) + fiprintf(stderr, "%s\n", hstrerror(h_errno)); + else + fiprintf(stderr, "%s: %s\n", s, hstrerror(h_errno)); +} diff --git a/libctru/source/services/soc/soc_hstrerror.c b/libctru/source/services/soc/soc_hstrerror.c new file mode 100644 index 0000000..cb1660c --- /dev/null +++ b/libctru/source/services/soc/soc_hstrerror.c @@ -0,0 +1,26 @@ +#include "soc_common.h" +#include + +static const struct +{ + int err; + const char *str; +} error_strings[] = +{ + { 0, "Resolver Error 0 (no error)", }, + { HOST_NOT_FOUND, "Unknown host", }, + { NO_DATA, "No address associated with name", }, + { NO_RECOVERY, "Unknown server error", }, + { TRY_AGAIN, "Host name lookup failure", }, +}; +static const size_t num_error_strings = sizeof(error_strings)/sizeof(error_strings[0]); + +const char* hstrerror(int err) { + size_t i; + for(i = 0; i < num_error_strings; ++i) { + if(error_strings[i].err == err) + return error_strings[i].str; + } + + return "Unknown resolver error"; +} diff --git a/libctru/source/services/soc/soc_init.c b/libctru/source/services/soc/soc_init.c index 1837da2..c28e1de 100644 --- a/libctru/source/services/soc/soc_init.c +++ b/libctru/source/services/soc/soc_init.c @@ -1,4 +1,5 @@ #include "soc_common.h" +#include #include static int soc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); @@ -39,7 +40,7 @@ soc_devoptab = static Result socu_cmd1(Handle memhandle, u32 memsize) { - Result ret=0; + Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = 0x00010044; @@ -48,14 +49,18 @@ static Result socu_cmd1(Handle memhandle, u32 memsize) cmdbuf[4] = 0; cmdbuf[5] = memhandle; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } return cmdbuf[1]; } Result SOC_Initialize(u32 *context_addr, u32 context_size) { - Result ret=0; + Result ret = 0; /* check that the "soc" device doesn't already exist */ int dev = FindDevice("soc:"); @@ -68,20 +73,19 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size) return dev; ret = svcCreateMemoryBlock(&socMemhandle, (u32)context_addr, context_size, 0, 3); - if(ret != 0) - { + if(ret != 0) { RemoveDevice("soc"); return ret; } - if((ret = srvGetServiceHandle(&SOCU_handle, "soc:U")) != 0) - { + ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); + if(ret != 0) { RemoveDevice("soc"); return ret; } - if((ret = socu_cmd1(socMemhandle, context_size)) != 0) - { + ret = socu_cmd1(socMemhandle, context_size); + if(ret != 0) { RemoveDevice("soc"); return ret; } @@ -91,13 +95,17 @@ Result SOC_Initialize(u32 *context_addr, u32 context_size) Result SOC_Shutdown(void) { - Result ret=0; + Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); int dev; cmdbuf[0] = 0x00190000; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } svcCloseHandle(SOCU_handle); svcCloseHandle(socMemhandle); @@ -116,6 +124,7 @@ soc_open(struct _reent *r, int flags, int mode) { + r->_errno = ENOSYS; return -1; } @@ -125,20 +134,28 @@ soc_close(struct _reent *r, { Handle sockfd = *(Handle*)fd; - int ret=0; + 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 = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } ret = (int)cmdbuf[1]; - if(ret==0)ret =_net_convert_error(cmdbuf[2]); - SOCU_errno = ret; + if(ret == 0) + ret =_net_convert_error(cmdbuf[2]); + + if(ret < 0) { + errno = -ret; + return -1; + } - if(ret!=0)return -1; return 0; } diff --git a/libctru/source/services/soc/soc_ioctl.c b/libctru/source/services/soc/soc_ioctl.c index 9e25c4f..97fb5cb 100644 --- a/libctru/source/services/soc/soc_ioctl.c +++ b/libctru/source/services/soc/soc_ioctl.c @@ -12,17 +12,17 @@ int ioctl(int sockfd, int request, ...) va_list ap; sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } - va_start(ap, request); - switch(request) { case FIONBIO: + va_start(ap, request); value = va_arg(ap, int*); + va_end(ap); + if(value == NULL) { errno = EFAULT; va_end(ap); @@ -30,17 +30,13 @@ int ioctl(int sockfd, int request, ...) } flags = fcntl(sockfd, F_GETFL, 0); - if(flags == -1) { - errno = SOC_GetErrno(); - va_end(ap); + if(flags == -1) return -1; - } - 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(); + if(*value) + ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + else + ret = fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK); break; @@ -50,7 +46,5 @@ int ioctl(int sockfd, int request, ...) break; } - va_end(ap); - return ret; } diff --git a/libctru/source/services/soc/soc_listen.c b/libctru/source/services/soc/soc_listen.c index 41b73e4..53257d2 100644 --- a/libctru/source/services/soc/soc_listen.c +++ b/libctru/source/services/soc/soc_listen.c @@ -1,15 +1,15 @@ #include "soc_common.h" +#include #include int listen(int sockfd, int max_connections) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -18,12 +18,20 @@ int listen(int sockfd, int max_connections) cmdbuf[2] = (u32)max_connections; cmdbuf[3] = 0x20; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } ret = (int)cmdbuf[1]; - if(ret==0)ret = _net_convert_error(cmdbuf[2]); - SOCU_errno = ret; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + errno = -ret; + return -1; + } - if(ret!=0)return -1; return 0; } diff --git a/libctru/source/services/soc/soc_poll.c b/libctru/source/services/soc/soc_poll.c index 80b6514..324612c 100644 --- a/libctru/source/services/soc/soc_poll.c +++ b/libctru/source/services/soc/soc_poll.c @@ -1,4 +1,5 @@ #include "soc_common.h" +#include #include #include #include @@ -11,30 +12,27 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) u32 *cmdbuf = getThreadCommandBuffer(); u32 saved_threadstorage[2]; - if(nfds == 0) - { - SOCU_errno = -EINVAL; + if(nfds == 0) { + errno = EINVAL; return -1; } struct pollfd *tmp_fds = (struct pollfd*)malloc(sizeof(struct pollfd) * nfds); - if(tmp_fds == NULL) - { - SOCU_errno = -ENOMEM; + if(tmp_fds == NULL) { + errno = ENOMEM; return -1; } memcpy(tmp_fds, fds, sizeof(struct pollfd) * nfds); - for(i = 0; i < nfds; ++i) - { + 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; + if(tmp_fds[i].fd < 0) { + errno = -tmp_fds[i].fd; free(tmp_fds); return -1; } + tmp_fds[i].revents = 0; } cmdbuf[0] = 0x00140084; @@ -50,26 +48,30 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) cmdbuf[0x100>>2] = (size<<14) | 2; cmdbuf[0x104>>2] = (u32)tmp_fds; - if((ret = svcSendSyncRequest(SOCU_handle)) != 0) - { + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { free(tmp_fds); + errno = SYNC_ERROR; return ret; } - for(i = 0; i < nfds; ++i) - { - fds[i].revents = tmp_fds[i].revents; - } - - free(tmp_fds); - 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) { + free(tmp_fds); + errno = -ret; + return -1; + } + + for(i = 0; i < nfds; ++i) + fds[i].revents = tmp_fds[i].revents; + + free(tmp_fds); - if(ret<0)return -1; return ret; } diff --git a/libctru/source/services/soc/soc_recvfrom.c b/libctru/source/services/soc/soc_recvfrom.c index 3af3c1a..8480c5f 100644 --- a/libctru/source/services/soc/soc_recvfrom.c +++ b/libctru/source/services/soc/soc_recvfrom.c @@ -1,17 +1,19 @@ #include "soc_common.h" +#include #include ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - u32 tmp_addrlen=0; + u32 tmp_addrlen = 0; u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; memset(tmpaddr, 0, 0x1c); - if(src_addr)tmp_addrlen = 0x1c; + if(src_addr) + tmp_addrlen = 0x1c; cmdbuf[0] = 0x00070104; cmdbuf[1] = (u32)sockfd; @@ -28,35 +30,44 @@ ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockad cmdbuf[0x100>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x104>>2] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return -1; + } 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 && src_addr!=NULL) - { + if(ret < 0) { + errno = -ret; + return -1; + } + + if(src_addr != NULL) { src_addr->sa_family = tmpaddr[1]; - if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0]; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2); } - if(ret<0)return -1; return ret; } ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - u32 tmp_addrlen=0; + u32 tmp_addrlen = 0; u8 tmpaddr[0x1c]; u32 saved_threadstorage[4]; - if(src_addr)tmp_addrlen = 0x1c; + if(src_addr) + tmp_addrlen = 0x1c; memset(tmpaddr, 0, 0x1c); @@ -77,7 +88,11 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x10c>>2] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } cmdbuf[0x100>>2] = saved_threadstorage[0]; cmdbuf[0x104>>2] = saved_threadstorage[1]; @@ -85,17 +100,21 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad cmdbuf[0x10c>>2] = saved_threadstorage[3]; 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 && src_addr!=NULL) - { + if(ret < 0) { + errno = -ret; + return -1; + } + + if(src_addr != NULL) { src_addr->sa_family = tmpaddr[1]; - if(*addrlen > tmpaddr[0])*addrlen = tmpaddr[0]; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2); } - if(ret<0)return -1; return ret; } @@ -103,12 +122,12 @@ 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; + if(sockfd < 0) { + errno = -sockfd; return -1; } - if(len<0x2000)return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); + if(len < 0x2000) + return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); } diff --git a/libctru/source/services/soc/soc_select.c b/libctru/source/services/soc/soc_select.c index d2cd911..7e47827 100644 --- a/libctru/source/services/soc/soc_select.c +++ b/libctru/source/services/soc/soc_select.c @@ -20,7 +20,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc pollinfo = (struct pollfd*)calloc(numfds, sizeof(struct pollfd)); if(pollinfo == NULL) { - SOCU_errno = ENOMEM; + errno = ENOMEM; return -1; } @@ -79,7 +79,8 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc FD_CLR(i, exceptfds); } - if(found) ++rc; + if(found) + ++rc; ++j; } } diff --git a/libctru/source/services/soc/soc_sendto.c b/libctru/source/services/soc/soc_sendto.c index 64eeb9e..7183c11 100644 --- a/libctru/source/services/soc/soc_sendto.c +++ b/libctru/source/services/soc/soc_sendto.c @@ -4,27 +4,21 @@ ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - u32 tmp_addrlen=0; + u32 tmp_addrlen = 0; u8 tmpaddr[0x1c]; memset(tmpaddr, 0, 0x1c); - if(dest_addr) - { + if(dest_addr) { if(dest_addr->sa_family == AF_INET) - { tmp_addrlen = 8; - } else - { tmp_addrlen = 0x1c; - } - if(addrlen < tmp_addrlen) - { - SOCU_errno = -EINVAL; + if(addrlen < tmp_addrlen) { + errno = EINVAL; return -1; } @@ -44,39 +38,41 @@ ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const s cmdbuf[9] = (((u32)len)<<4) | 10; cmdbuf[10] = (u32)buf; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } 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) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return ret; } ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - u32 tmp_addrlen=0; + u32 tmp_addrlen = 0; u8 tmpaddr[0x1c]; memset(tmpaddr, 0, 0x1c); - if(dest_addr) - { + if(dest_addr) { if(dest_addr->sa_family == AF_INET) - { tmp_addrlen = 8; - } else - { tmp_addrlen = 0x1c; - } - if(addrlen < tmp_addrlen) - { - SOCU_errno = -EINVAL; + if(addrlen < tmp_addrlen) { + errno = EINVAL; return -1; } @@ -96,25 +92,33 @@ ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const s cmdbuf[9] = (tmp_addrlen<<14) | 0x402; cmdbuf[10] = (u32)tmpaddr; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } 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) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return ret; } 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; + if(sockfd < 0) { + 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); + if(len < 0x2000) + return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); + return socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen); } diff --git a/libctru/source/services/soc/soc_setsockopt.c b/libctru/source/services/soc/soc_setsockopt.c index ff142b2..600d8cf 100644 --- a/libctru/source/services/soc/soc_setsockopt.c +++ b/libctru/source/services/soc/soc_setsockopt.c @@ -1,11 +1,18 @@ #include "soc_common.h" +#include #include int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); + sockfd = soc_get_fd(sockfd); + if(sockfd < 0) { + errno = -sockfd; + return -1; + } + cmdbuf[0] = 0x00120104; cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)level; @@ -15,12 +22,20 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t cmdbuf[7] = (optlen<<14) | 0x2402; cmdbuf[8] = (u32)optval; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } 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) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return ret; } diff --git a/libctru/source/services/soc/soc_shutdown.c b/libctru/source/services/soc/soc_shutdown.c index 4dca8c4..89b2db6 100644 --- a/libctru/source/services/soc/soc_shutdown.c +++ b/libctru/source/services/soc/soc_shutdown.c @@ -1,15 +1,15 @@ #include "soc_common.h" +#include #include int shutdown(int sockfd, int shutdown_type) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -18,12 +18,20 @@ int shutdown(int sockfd, int shutdown_type) cmdbuf[2] = (u32)shutdown_type; cmdbuf[3] = 0x20; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return ret; + } ret = (int)cmdbuf[1]; - if(ret==0)ret = _net_convert_error(cmdbuf[2]); - SOCU_errno = ret; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + errno = -ret; + return -1; + } - if(ret!=0)return -1; return 0; } diff --git a/libctru/source/services/soc/soc_sockatmark.c b/libctru/source/services/soc/soc_sockatmark.c index 4fbec75..f774389 100644 --- a/libctru/source/services/soc/soc_sockatmark.c +++ b/libctru/source/services/soc/soc_sockatmark.c @@ -1,15 +1,15 @@ #include "soc_common.h" +#include #include int sockatmark(int sockfd) { - int ret=0; + int ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); sockfd = soc_get_fd(sockfd); - if(sockfd < 0) - { - SOCU_errno = sockfd; + if(sockfd < 0) { + errno = -sockfd; return -1; } @@ -17,12 +17,20 @@ int sockatmark(int sockfd) cmdbuf[1] = (u32)sockfd; cmdbuf[2] = 0x20; - if((ret = svcSendSyncRequest(SOCU_handle))!=0)return ret; + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { + errno = SYNC_ERROR; + return -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) { + errno = -ret; + return -1; + } - if(ret<0)return -1; return ret; } diff --git a/libctru/source/services/soc/soc_socket.c b/libctru/source/services/soc/soc_socket.c index 94f2ad1..5072275 100644 --- a/libctru/source/services/soc/soc_socket.c +++ b/libctru/source/services/soc/soc_socket.c @@ -5,7 +5,7 @@ int socket(int domain, int type, int protocol) { - int ret=0; + int ret = 0; int fd, dev; __handle *handle; u32 *cmdbuf = getThreadCommandBuffer(); @@ -17,16 +17,14 @@ int socket(int domain, int type, int protocol) cmdbuf[4] = 0x20; dev = FindDevice("soc:"); - if(dev < 0) - { - SOCU_errno = -ENODEV; + if(dev < 0) { + errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); - if(fd < 0) - { - SOCU_errno = -ENOMEM; + if(fd < 0) { + errno = ENOMEM; return -1; } @@ -34,17 +32,18 @@ int socket(int domain, int type, int protocol) handle->device = dev; handle->fileStruct = ((void *)handle) + sizeof(__handle); - if((ret = svcSendSyncRequest(SOCU_handle)) != 0) + ret = svcSendSyncRequest(SOCU_handle); + if(ret != 0) { __release_handle(fd); + errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; - if(ret != 0) - { - SOCU_errno = _net_convert_error(cmdbuf[2]); + if(ret != 0) { __release_handle(fd); + errno = _net_convert_error(cmdbuf[2]); return -1; } From e4b636ed418ee6ac86750695b9f38dec8d7395b9 Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Mon, 26 Jan 2015 02:04:19 +0000 Subject: [PATCH 11/13] correct alloc_handle prototype --- libctru/source/services/soc/soc_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/services/soc/soc_common.h b/libctru/source/services/soc/soc_common.h index f35c5fe..87c592a 100644 --- a/libctru/source/services/soc/soc_common.h +++ b/libctru/source/services/soc/soc_common.h @@ -10,7 +10,7 @@ #define SYNC_ERROR ENODEV -int __alloc_handle(int size); +int __alloc_handle(size_t size); __handle *__get_handle(int fd); void __release_handle(int fd); From 2cf2b7f1e9dc4571eb23bbbc6857d4960a9aa0a6 Mon Sep 17 00:00:00 2001 From: mtheall Date: Tue, 27 Jan 2015 17:06:30 -0600 Subject: [PATCH 12/13] Fix soc_read/soc_write. --- libctru/source/services/soc/soc_common.h | 5 +++++ libctru/source/services/soc/soc_init.c | 4 ++-- libctru/source/services/soc/soc_recvfrom.c | 10 +++++++--- libctru/source/services/soc/soc_sendto.c | 11 ++++++++--- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/libctru/source/services/soc/soc_common.h b/libctru/source/services/soc/soc_common.h index 87c592a..a9fd779 100644 --- a/libctru/source/services/soc/soc_common.h +++ b/libctru/source/services/soc/soc_common.h @@ -3,6 +3,7 @@ #include #include #include +#include #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> @@ -29,3 +30,7 @@ soc_get_fd(int fd) } s32 _net_convert_error(s32 sock_retval); + +ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); + +ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); diff --git a/libctru/source/services/soc/soc_init.c b/libctru/source/services/soc/soc_init.c index c28e1de..9f5a88f 100644 --- a/libctru/source/services/soc/soc_init.c +++ b/libctru/source/services/soc/soc_init.c @@ -166,7 +166,7 @@ soc_write(struct _reent *r, size_t len) { Handle sockfd = *(Handle*)fd; - return send(sockfd, ptr, len, 0); + return soc_sendto(sockfd, ptr, len, 0, NULL, 0); } static ssize_t @@ -176,5 +176,5 @@ soc_read(struct _reent *r, size_t len) { Handle sockfd = *(Handle*)fd; - return recv(sockfd, ptr, len, 0); + return soc_recvfrom(sockfd, ptr, len, 0, NULL, 0); } diff --git a/libctru/source/services/soc/soc_recvfrom.c b/libctru/source/services/soc/soc_recvfrom.c index 8480c5f..f9b206a 100644 --- a/libctru/source/services/soc/soc_recvfrom.c +++ b/libctru/source/services/soc/soc_recvfrom.c @@ -118,6 +118,12 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad return ret; } +ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) +{ + if(len < 0x2000) + return socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); + return socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); +} ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { @@ -127,7 +133,5 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * 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); + return soc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); } diff --git a/libctru/source/services/soc/soc_sendto.c b/libctru/source/services/soc/soc_sendto.c index 7183c11..4b84749 100644 --- a/libctru/source/services/soc/soc_sendto.c +++ b/libctru/source/services/soc/soc_sendto.c @@ -110,6 +110,13 @@ ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const s return ret; } +ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) +{ + if(len < 0x2000) + return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); + return socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen); +} + 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); @@ -118,7 +125,5 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct return -1; } - if(len < 0x2000) - return socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); - return socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen); + return soc_sendto(sockfd, buf, len, flags, dest_addr, addrlen); } From dc7ef6fd2889a720c1ba98435a7b05c5e723364b Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Wed, 11 Feb 2015 22:14:37 +0000 Subject: [PATCH 13/13] correct aptEventHandler signature --- libctru/source/services/apt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libctru/source/services/apt.c b/libctru/source/services/apt.c index 1d9bc48..9560c79 100644 --- a/libctru/source/services/apt.c +++ b/libctru/source/services/apt.c @@ -380,7 +380,7 @@ static bool __handle_incoming_parameter() { return true; } -void aptEventHandler(u32 arg) +void aptEventHandler(void *arg) { bool runThread = true;