Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,10 +1,24 @@ Legend: * Changes of existing features or bugfixes + New features -ObjFW 0.7.1 -> ObjFW 0.8, 14.10.2015 +ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015 + * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in + Clang 3.7 (this fixes compilation with Clang 3.7) + * Blocks: Proper handling when called from a byref handler + * Fix compilation on Solaris + * Fix compilation for Wii, PSP and Nintendo DS + * OFProcess: Send SIGTERM on close instead of SIGKILL + * OFZIPArchive: Throw invalid format exception on failed seeks + * Make sure of_hash_seed is never initialized to 0 + * Special cases for the Wii's weird network stack (fixes the tests) + * Better length checks for write / send calls + * Don't use -pedantic on platforms where it's broken by the system headers + * Documentation fixes + +ObjFW 0.7.1 -> ObjFW 0.8, 14.08.2015 + An insanely huge amount of new APIs + New classes: OFHTTPServer, OFINICategory, OFINIFile, OFInflate64Stream, OFInflateStream, OFMapTable, OFRIPEMD160Hash, OFSHA224Hash, OFSHA256Hash, OFSHA384Hash, OFSHA512Hash, OFSettings, OFStdIOStream, OFSystemInfo, Index: README-WINDOWS.md ================================================================== --- README-WINDOWS.md +++ README-WINDOWS.md @@ -62,11 +62,12 @@ Getting, building and installing ObjFW -------------------------------------- Start the MinGW-w64 Win32 or Win64 Shell (depening on what version you want - to build) and check out ObjFW: + to build - do *not* use the MSYS2 Shell shortcut, but use the MinGW-w64 Win32 + or Win64 Shell shortcut instead!) and check out ObjFW: $ git clone https://webkeks.org/git/objfw.git You can also download a release tarball if you want. Now go to the newly checked out repository and build and install it: Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,15 +1,18 @@ -AC_INIT(ObjFW, 0.8-dev, js@webkeks.org) +AC_INIT(ObjFW, 0.8.1, js@webkeks.org) BUILDSYS_INIT AS_IF([test configure.ac -nt configure], [ AC_MSG_ERROR([configure.ac is newer than configure! Run ./autogen.sh!]) ]) AC_CONFIG_SRCDIR(src) AC_CANONICAL_HOST + +dnl Used to disable checking for -pedantic on some platforms where it's broken +check_pedantic="yes" case "$host" in *-msdosdjgpp*) enable_shared="no" enable_threads="no" @@ -29,10 +32,11 @@ LIBS="$LIBS -lpspnet_inet -lpspnet_apctl -lpspnet_resolver" LIBS="$LIBS -lpsputility -lpspuser -lpspkernel" enable_shared="no" enable_threads="no" # TODO enable_sockets="no" # TODO + check_pedantic="no" AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ;; esac @@ -74,10 +78,11 @@ LDFLAGS="$LDFLAGS -specs=ds_arm9.specs" LIBS="$LIBS -L$DEVKITPRO/libnds/lib -lfilesystem -lfat -lnds9" enable_shared="no" enable_threads="no" # TODO enable_sockets="no" # TODO + check_pedantic="no" AC_DEFINE(OF_NINTENDO_DS, 1, [Whether we are compiling for the Nintendo DS]) AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) @@ -516,11 +521,11 @@ AC_MSG_ERROR(No asprintf and no snprintf returning required space!) AC_CHECK_FUNCS([arc4random random], break) AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl") -AC_CHECK_HEADERS(dlfcn.h) +AC_CHECK_HEADERS_ONCE(dlfcn.h) case "$host_os" in netbsd*) dnl dladdr exists on NetBSD, but it is completely broken. dnl When using it with code that uses __thread, it freezes the dnl process so that it has to be killed using SIGKILL. @@ -593,11 +598,11 @@ AC_ARG_ENABLE(compiler-tls, AS_HELP_STRING([--disable-compiler-tls], [disable compiler thread local storage])) AS_IF([test x"$enable_compiler_tls" != x"no"], [ - AC_CHECK_HEADERS(threads.h, [ + AC_CHECK_HEADER(threads.h, [ AC_DEFINE(OF_HAVE_THREADS_H, 1, [Whether we have threads.h]) ]) AC_MSG_CHECKING(whether _Thread_local works) @@ -765,15 +770,15 @@ AC_CHECK_HEADER(sys/socket.h, [ AC_DEFINE(OF_HAVE_SYS_SOCKET_H, 1, [Whether we have sys/socket.h]) ]) - AC_CHECK_HEADERS(netinet/in.h, [ + AC_CHECK_HEADER(netinet/in.h, [ AC_DEFINE(OF_HAVE_NETINET_IN_H, 1, [Whether we have netinet/in.h]) ]) - AC_CHECK_HEADERS(netinet/tcp.h, [ + AC_CHECK_HEADER(netinet/tcp.h, [ AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1, [Whether we have netinet/tcp.h]) ]) AC_CHECK_HEADERS([arpa/inet.h netdb.h]) @@ -962,11 +967,11 @@ AS_IF([test x"$have_processes" = x"yes"], [ AC_SUBST(OFPROCESS_M, "OFProcess.m") AC_DEFINE(OF_HAVE_PROCESSES, 1, [Whether we have processes]) ]) -AC_CHECK_HEADERS(sys/ioctl.h) +AC_CHECK_HEADERS_ONCE([sys/ioctl.h sys/termios.h]) AS_IF([test x"$objc_runtime" = x"Apple runtime"], [ AC_CHECK_HEADER(Foundation/NSObject.h, [ AC_SUBST(FOUNDATION_COMPAT_M, "foundation-compat.m") AC_SUBST(BRIDGE, "bridge") @@ -1079,34 +1084,36 @@ ], [ AC_MSG_RESULT(no) OBJCFLAGS="$old_OBJCFLAGS" ]) - old_OBJCFLAGS="$OBJCFLAGS" - OBJCFLAGS="$OBJCFLAGS -pedantic" - AC_MSG_CHECKING(whether -pedantic is buggy) - AC_TRY_COMPILE([ - #import - - #ifdef __has_attribute - # if __has_attribute(objc_root_class) - __attribute__((__objc_root_class__)) - # endif - #endif - @interface Foo - { - void *foo; - } - @end - - @interface Bar: Foo - @end - ], [], [ - AC_MSG_RESULT(no) - ], [ - AC_MSG_RESULT(yes) - OBJCFLAGS="$old_OBJCFLAGS" + AS_IF([test x"$check_pedantic" = x"yes"], [ + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -pedantic" + AC_MSG_CHECKING(whether -pedantic is buggy) + AC_TRY_COMPILE([ + #import + + #ifdef __has_attribute + # if __has_attribute(objc_root_class) + __attribute__((__objc_root_class__)) + # endif + #endif + @interface Foo + { + void *foo; + } + @end + + @interface Bar: Foo + @end + ], [], [ + AC_MSG_RESULT(no) + ], [ + AC_MSG_RESULT(yes) + OBJCFLAGS="$old_OBJCFLAGS" + ]) ]) ]) AS_IF([test x"$cross_compiling" = x"yes"], [ AC_SUBST(BIN_PREFIX, "${host_alias}-") Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -160,10 +160,11 @@ + (void)terminateWithStatus: (int)status { #ifdef _PSP sceKernelExitGame(); + abort(); /* sceKernelExitGame() is not marked noreturn */ #else exit(status); #endif } Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -239,19 +239,17 @@ OF_BLOCK_FIELD_IS_OBJECT | OF_BLOCK_FIELD_IS_BYREF); if (src_ == NULL) return; - if (flags_ & OF_BLOCK_BYREF_CALLER) - return; - switch (flags) { case OF_BLOCK_FIELD_IS_BLOCK: *(of_block_literal_t**)dst_ = _Block_copy(src_); break; case OF_BLOCK_FIELD_IS_OBJECT: - *(id*)dst_ = [(id)src_ retain]; + if (!(flags_ & OF_BLOCK_BYREF_CALLER)) + *(id*)dst_ = [(id)src_ retain]; break; case OF_BLOCK_FIELD_IS_BYREF:; of_block_byref_t *src = (of_block_byref_t*)src_; of_block_byref_t **dst = (of_block_byref_t**)dst_; @@ -266,11 +264,11 @@ if (src->forwarding == src) (*dst)->forwarding = *dst; memcpy(*dst, src, src->size); - if (src->size >= sizeof(of_block_byref_t)) + if (src->flags & OF_BLOCK_HAS_COPY_DISPOSE) src->byref_keep(*dst, src); } else *dst = src; (*dst)->flags++; @@ -285,25 +283,23 @@ OF_BLOCK_FIELD_IS_OBJECT | OF_BLOCK_FIELD_IS_BYREF); if (obj_ == NULL) return; - if (flags_ & OF_BLOCK_BYREF_CALLER) - return; - switch (flags) { case OF_BLOCK_FIELD_IS_BLOCK: _Block_release(obj_); break; case OF_BLOCK_FIELD_IS_OBJECT: - [(id)obj_ release]; + if (!(flags_ & OF_BLOCK_BYREF_CALLER)) + [(id)obj_ release]; break; case OF_BLOCK_FIELD_IS_BYREF:; of_block_byref_t *obj = (of_block_byref_t*)obj_; if ((--obj->flags & OF_BLOCK_REFCOUNT_MASK) == 0) { - if (obj->size >= sizeof(of_block_byref_t)) + if (obj->flags & OF_BLOCK_HAS_COPY_DISPOSE) obj->byref_dispose(obj); free(obj); } break; Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -151,32 +151,42 @@ + (void)changeCurrentDirectoryPath: (OFString*)path; /*! * @brief Returns the size of the specified file. * + * @param path The path to the file whose path should be returned + * * @return The size of the specified file */ + (of_offset_t)sizeOfFileAtPath: (OFString*)path; /*! - * @brief Returns the last access time of the specified file. + * @brief Returns the last access time of the specified item. + * + * @param path The path to the file whose last access time should be returned * - * @return The last access time of the specified file + * @return The last access time of the specified item */ + (OFDate*)accessTimeOfItemAtPath: (OFString*)path; /*! - * @brief Returns the last modification time of the specified file. + * @brief Returns the last modification time of the specified item. + * + * @param path The path to the file whose last modification time should be + * returned * - * @return The last modification time of the specified file + * @return The last modification time of the specified item */ + (OFDate*)modificationTimeOfItemAtPath: (OFString*)path; /*! - * @brief Returns the last status change time of the specified file. + * @brief Returns the last status change time of the specified item. + * + * @param path The path to the file whose last status change time should be + * returned * - * @return The last status change time of the specified file + * @return The last status change time of the specified item */ + (OFDate*)statusChangeTimeOfItemAtPath: (OFString*)path; #ifdef OF_HAVE_CHMOD /*! @@ -282,10 +292,11 @@ /*! * @brief Returns the destination of the symbolic link at the specified path. * * @param path The path to the symbolic link + * * @return The destination of the symbolic link at the specified path */ + (OFString*)destinationOfSymbolicLinkAtPath: (OFString*)path; #endif Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -52,10 +52,11 @@ # include # undef BOOL #endif #ifdef OF_NINTENDO_DS +# include # include #endif #import "OFFile.h" #import "OFString.h" @@ -117,14 +118,14 @@ #define DEFAULT_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH #define DIR_MODE DEFAULT_MODE | S_IXUSR | S_IXGRP | S_IXOTH #if defined(OF_HAVE_CHOWN) && defined(OF_HAVE_THREADS) -static of_mutex_t mutex; +static of_mutex_t chownMutex; #endif #if !defined(HAVE_READDIR_R) && !defined(_WIN32) && defined(OF_HAVE_THREADS) -static of_mutex_t mutex; +static of_mutex_t readdirMutex; #endif int of_stat(OFString *path, of_stat_t *buffer) { @@ -205,17 +206,17 @@ { if (self != [OFFile class]) return; #if defined(OF_HAVE_CHOWN) && defined(OF_HAVE_THREADS) - if (!of_mutex_new(&mutex)) + if (!of_mutex_new(&chownMutex)) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif #if !defined(HAVE_READDIR_R) && !defined(_WIN32) && defined(OF_HAVE_THREADS) - if (!of_mutex_new(&mutex)) + if (!of_mutex_new(&readdirMutex)) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif #ifdef __wii__ @@ -397,11 +398,11 @@ if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL) @throw [OFOpenItemFailedException exceptionWithPath: path errNo: errno]; # if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) - if (!of_mutex_lock(&mutex)) + if (!of_mutex_lock(&readdirMutex)) @throw [OFLockFailedException exception]; # endif @try { for (;;) { @@ -446,11 +447,11 @@ objc_autoreleasePoolPop(pool); } } @finally { closedir(dir); # if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) - if (!of_mutex_unlock(&mutex)) + if (!of_mutex_unlock(&readdirMutex)) @throw [OFUnlockFailedException exception]; # endif } #else void *pool = objc_autoreleasePoolPush(); @@ -608,11 +609,11 @@ @throw [OFInvalidArgumentException exception]; encoding = [OFSystemInfo native8BitEncoding]; # ifdef OF_HAVE_THREADS - if (!of_mutex_lock(&mutex)) + if (!of_mutex_lock(&chownMutex)) @throw [OFLockFailedException exception]; @try { # endif if (owner != nil) { @@ -642,11 +643,11 @@ gid = group_->gr_gid; } # ifdef OF_HAVE_THREADS } @finally { - if (!of_mutex_unlock(&mutex)) + if (!of_mutex_unlock(&chownMutex)) @throw [OFUnlockFailedException exception]; } # endif if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) @@ -1087,19 +1088,22 @@ if (_fd == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; #ifndef _WIN32 - if (write(_fd, buffer, length) < length) + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (write(_fd, buffer, length) != (ssize_t)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: errno]; #else - if (length > UINT_MAX) + if (length > INT_MAX) @throw [OFOutOfRangeException exception]; - if (write(_fd, buffer, (unsigned int)length) < length) + if (write(_fd, buffer, (int)length) != (int)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: errno]; #endif } Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -60,10 +60,15 @@ QUEUE_REMOVE = 1, QUEUE_READ = 0, QUEUE_WRITE = 2 }; #define QUEUE_ACTION (QUEUE_ADD | QUEUE_REMOVE) + +#ifdef __wii__ +/* FIXME: Add a port registry for Wii */ +static uint16_t freePort = 65535; +#endif @implementation OFKernelEventObserver + (void)initialize { if (self != [OFKernelEventObserver class]) @@ -126,12 +131,13 @@ _cancelAddr.sin_family = AF_INET; _cancelAddr.sin_port = 0; _cancelAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); # ifdef __wii__ + _cancelAddr.sin_len = 8; /* The Wii does not accept port 0 as "choose any free port" */ - _cancelAddr.sin_port = 65535; + _cancelAddr.sin_port = freePort--; # endif if (bind(_cancelFD[0], (struct sockaddr*)&_cancelAddr, sizeof(_cancelAddr))) @throw [OFInitializationFailedException @@ -353,12 +359,17 @@ - (void)cancel { #ifdef OF_HAVE_PIPE OF_ENSURE(write(_cancelFD[1], "", 1) > 0); #else - OF_ENSURE(sendto(_cancelFD[1], "", 1, 0, (struct sockaddr*)&_cancelAddr, - sizeof(_cancelAddr)) > 0); +# ifndef __wii__ + OF_ENSURE(sendto(_cancelFD[1], "", 1, 0, + (struct sockaddr*)&_cancelAddr, sizeof(_cancelAddr)) > 0); +# else + OF_ENSURE(sendto(_cancelFD[1], "", 1, 0, + (struct sockaddr*)&_cancelAddr, 8) > 0); +# endif #endif } - (void)OF_processReadBuffers { Index: src/OFKernelEventObserver_poll.m ================================================================== --- src/OFKernelEventObserver_poll.m +++ src/OFKernelEventObserver_poll.m @@ -185,11 +185,16 @@ if (FDs[i].revents & POLLIN) { if (FDs[i].fd == _cancelFD[0]) { char buffer; +#ifdef OF_HAVE_PIPE OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); +#else + OF_ENSURE(recvfrom(_cancelFD[0], &buffer, 1, + 0, NULL, NULL) == 1); +#endif FDs[i].revents = 0; continue; } Index: src/OFKernelEventObserver_select.m ================================================================== --- src/OFKernelEventObserver_select.m +++ src/OFKernelEventObserver_select.m @@ -166,11 +166,11 @@ errNo: errno]; if (FD_ISSET(_cancelFD[0], &readFDs)) { char buffer; -#ifndef _WIN32 +#ifdef OF_HAVE_PIPE OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); #else OF_ENSURE(recvfrom(_cancelFD[0], &buffer, 1, 0, NULL, NULL) == 1); #endif Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -228,23 +228,27 @@ #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumerationMutationHandler); #endif + of_hash_seed = 0; + while (of_hash_seed == 0) { #if defined(HAVE_ARC4RANDOM) - of_hash_seed = arc4random(); + of_hash_seed = arc4random(); #elif defined(HAVE_RANDOM) - struct timeval t; - gettimeofday(&t, NULL); - srandom((unsigned)(t.tv_sec ^ t.tv_usec)); - of_hash_seed = (uint32_t)((random() << 16) | (random() & 0xFFFF)); + struct timeval t; + gettimeofday(&t, NULL); + srandom((unsigned)(t.tv_sec ^ t.tv_usec)); + of_hash_seed = (uint32_t)((random() << 16) | + (random() & 0xFFFF)); #else - struct timeval t; - gettimeofday(&t, NULL); - srand((unsigned)(t.tv_sec ^ t.tv_usec)); - of_hash_seed = (uint32_t)((rand() << 16) | (rand() & 0xFFFF)); + struct timeval t; + gettimeofday(&t, NULL); + srand((unsigned)(t.tv_sec ^ t.tv_usec)); + of_hash_seed = (uint32_t)((rand() << 16) | (rand() & 0xFFFF)); #endif + } } + (void)unload { } Index: src/OFPlugin.h ================================================================== --- src/OFPlugin.h +++ src/OFPlugin.h @@ -14,20 +14,20 @@ * file. */ #import "OFObject.h" -OF_ASSUME_NONNULL_BEGIN - @class OFString; #ifndef _WIN32 typedef void* of_plugin_handle_t; #else # include typedef HMODULE of_plugin_handle_t; #endif + +OF_ASSUME_NONNULL_BEGIN /*! * @class OFPlugin OFPlugin.h ObjFW/OFPlugin.h * * @brief Provides a system for loading plugins at runtime. Index: src/OFProcess.m ================================================================== --- src/OFProcess.m +++ src/OFProcess.m @@ -496,11 +496,14 @@ #ifndef _WIN32 if (_writePipe[1] == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; - if (write(_writePipe[1], buffer, length) < length) + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (write(_writePipe[1], buffer, length) != (ssize_t)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: errno]; #else DWORD ret; @@ -511,11 +514,11 @@ if (_writePipe[1] == NULL || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; if (!WriteFile(_writePipe[1], buffer, (DWORD)length, &ret, NULL) || - ret < length) { + ret != (DWORD)length) { int errNo = 0; if (GetLastError() == ERROR_BROKEN_PIPE) errNo = EPIPE; @@ -566,11 +569,11 @@ close(_readPipe[0]); if (_writePipe[1] != -1) close(_writePipe[1]); if (_pid != -1) { - kill(_pid, SIGKILL); + kill(_pid, SIGTERM); waitpid(_pid, &_status, WNOHANG); } _pid = -1; _readPipe[0] = -1; Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -130,19 +130,22 @@ if (_fd == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; #ifndef _WIN32 - if (write(_fd, buffer, length) < length) + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (write(_fd, buffer, length) != (ssize_t)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: errno]; #else - if (length > UINT_MAX) + if (length > INT_MAX) @throw [OFOutOfRangeException exception]; - if (write(_fd, buffer, (unsigned int)length) < length) + if (write(_fd, buffer, (int)length) != (int)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: errno]; #endif } Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -99,20 +99,23 @@ @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: ENOTCONN]; #ifndef _WIN32 - if (send(_socket, buffer, length, 0) < length) + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if (send(_socket, buffer, length, 0) != (ssize_t)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #else - if (length > UINT_MAX) + if (length > INT_MAX) @throw [OFOutOfRangeException exception]; - if (send(_socket, buffer, (unsigned int)length, 0) < length) + if (send(_socket, buffer, (int)length, 0) != (int)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #endif Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -63,10 +63,13 @@ bool _listening; struct sockaddr *_address; socklen_t _addressLength; OFString *_SOCKS5Host; uint16_t _SOCKS5Port; +#ifdef __wii__ + bool _keepAliveEnabled, _TCPNoDelayEnabled; +#endif } #ifdef OF_HAVE_PROPERTIES @property (readonly, getter=isListening) bool listening; @property OF_NULLABLE_PROPERTY (copy) OFString *SOCKS5Host; Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -592,14 +592,19 @@ if (setsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&v, (socklen_t)sizeof(v)) != 0) @throw [OFSetOptionFailedException exceptionWithStream: self errNo: of_socket_errno()]; + +#ifdef __wii__ + _keepAliveEnabled = enabled; +#endif } - (bool)isKeepAliveEnabled { +#ifndef __wii__ int v; socklen_t len = sizeof(v); if (getsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&v, &len) != 0 || len != sizeof(v)) @@ -606,10 +611,13 @@ @throw [OFGetOptionFailedException exceptionWithStream: self errNo: of_socket_errno()]; return v; +#else + return _keepAliveEnabled; +#endif } - (void)setTCPNoDelayEnabled: (bool)enabled { int v = enabled; @@ -617,14 +625,19 @@ if (setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&v, (socklen_t)sizeof(v)) != 0) @throw [OFSetOptionFailedException exceptionWithStream: self errNo: of_socket_errno()]; + +#ifdef __wii__ + _TCPNoDelayEnabled = enabled; +#endif } - (bool)isTCPNoDelayEnabled { +#ifndef __wii__ int v; socklen_t len = sizeof(v); if (getsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&v, &len) != 0 || len != sizeof(v)) @@ -631,7 +644,10 @@ @throw [OFGetOptionFailedException exceptionWithStream: self errNo: of_socket_errno()]; return v; +#else + return _TCPNoDelayEnabled; +#endif } @end Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -13,10 +13,11 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #define OF_THREAD_M +#define _POSIX_TIMERS #define __NO_EXT_QNX #include "config.h" #include @@ -33,10 +34,18 @@ #endif #ifdef OF_HAVE_SCHED_YIELD # include #endif + +#ifdef __wii__ +# define BOOL OGC_BOOL +# define nanosleep ogc_nanosleep +# include +# undef BOOL +# undef nanosleep +#endif #import "OFThread.h" #import "OFThread+Private.h" #import "OFRunLoop.h" #import "OFList.h" Index: src/OFUDPSocket.h ================================================================== --- src/OFUDPSocket.h +++ src/OFUDPSocket.h @@ -237,11 +237,11 @@ * @param receiver A pointer to an @ref of_udp_socket_address_t to which the * datagram should be sent */ - (void)sendBuffer: (const void*)buffer length: (size_t)length - receiver: (of_udp_socket_address_t*)receiver; + receiver: (const of_udp_socket_address_t*)receiver; /*! * @brief Cancels all pending asyncronous requests on the socket. * * @warning You are not allowed to call this inside the handler of an Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -187,13 +187,18 @@ if (address1->address.ss_family != address2->address.ss_family) return false; switch (address1->address.ss_family) { case AF_INET: +#ifndef __wii__ if (address1->length < sizeof(struct sockaddr_in) || address2->length < sizeof(struct sockaddr_in)) @throw [OFInvalidArgumentException exception]; +#else + if (address1->length < 8 || address2->length < 8) + @throw [OFInvalidArgumentException exception]; +#endif sin_1 = (struct sockaddr_in*)&address1->address; sin_2 = (struct sockaddr_in*)&address2->address; if (sin_1->sin_port != sin_2->sin_port) @@ -240,12 +245,17 @@ hash += address->address.ss_family; switch (address->address.ss_family) { case AF_INET: +#ifndef __wii__ if (address->length < sizeof(struct sockaddr_in)) @throw [OFInvalidArgumentException exception]; +#else + if (address->length < 8) + @throw [OFInvalidArgumentException exception]; +#endif sin = (struct sockaddr_in*)&address->address; hash += (sin->sin_port << 1); hash ^= sin->sin_addr.s_addr; @@ -523,28 +533,33 @@ } #endif - (void)sendBuffer: (const void*)buffer length: (size_t)length - receiver: (of_udp_socket_address_t*)receiver + receiver: (const of_udp_socket_address_t*)receiver { if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; #ifndef _WIN32 + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + if (sendto(_socket, buffer, length, 0, - (struct sockaddr*)&receiver->address, receiver->length) < length) + (struct sockaddr*)&receiver->address, + receiver->length) != (ssize_t)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #else if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if (sendto(_socket, buffer, (int)length, 0, - (struct sockaddr*)&receiver->address, receiver->length) < length) + (struct sockaddr*)&receiver->address, + receiver->length) != (int)length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #endif Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -117,11 +117,11 @@ return field; } static uint32_t -crc32(uint32_t crc, uint8_t *bytes, size_t length) +calculateCRC32(uint32_t crc, uint8_t *bytes, size_t length) { size_t i; for (i = 0; i < length; i++) { uint_fast8_t j; @@ -132,10 +132,25 @@ crc = (crc >> 1) ^ (CRC32_MAGIC & (~(crc & 1) + 1)); } return crc; } + +static void +seekOrThrowInvalidFormat(OFSeekableStream *stream, + of_offset_t offset, int whence) +{ + @try { + [stream seekToOffset: offset + whence: whence]; + } @catch (OFSeekFailedException *e) { + if ([e errNo] == EINVAL) + @throw [OFInvalidFormatException exception]; + + @throw e; + } +} @implementation OFZIPArchive + (instancetype)archiveWithSeekableStream: (OFSeekableStream*)stream { return [[[self alloc] initWithSeekableStream: stream] autorelease]; @@ -203,19 +218,11 @@ uint16_t commentLength; of_offset_t offset = -22; bool valid = false; do { - @try { - [_stream seekToOffset: offset - whence: SEEK_END]; - } @catch (OFSeekFailedException *e) { - if ([e errNo] == EINVAL) - @throw [OFInvalidFormatException exception]; - - @throw e; - } + seekOrThrowInvalidFormat(_stream, offset, SEEK_END); if ([_stream readLittleEndianInt32] == 0x06054B50) { valid = true; break; } @@ -242,12 +249,11 @@ _centralDirectoryEntries == 0xFFFF || _centralDirectorySize == 0xFFFFFFFF || _centralDirectoryOffset == 0xFFFFFFFF) { uint64_t offset64, size; - [_stream seekToOffset: offset - 20 - whence: SEEK_END]; + seekOrThrowInvalidFormat(_stream, offset - 20, SEEK_END); if ([_stream readLittleEndianInt32] != 0x07064B50) { objc_autoreleasePoolPop(pool); return; } @@ -260,12 +266,12 @@ offset64 = [_stream readLittleEndianInt64]; if ((of_offset_t)offset64 != offset64) @throw [OFOutOfRangeException exception]; - [_stream seekToOffset: (of_offset_t)offset64 - whence: SEEK_SET]; + seekOrThrowInvalidFormat(_stream, + (of_offset_t)offset64, SEEK_SET); if ([_stream readLittleEndianInt32] != 0x06064B50) @throw [OFInvalidFormatException exception]; size = [_stream readLittleEndianInt64]; @@ -299,12 +305,12 @@ size_t i; if ((of_offset_t)_centralDirectoryOffset != _centralDirectoryOffset) @throw [OFOutOfRangeException exception]; - [_stream seekToOffset: (of_offset_t)_centralDirectoryOffset - whence: SEEK_SET]; + seekOrThrowInvalidFormat(_stream, + (of_offset_t)_centralDirectoryOffset, SEEK_SET); _entries = [[OFMutableArray alloc] init]; _pathToEntryMap = [[OFMutableDictionary alloc] init]; for (i = 0; i < _centralDirectoryEntries; i++) { @@ -353,12 +359,11 @@ offset64 = [entry OF_localFileHeaderOffset]; if ((of_offset_t)offset64 != offset64) @throw [OFOutOfRangeException exception]; - [_stream seekToOffset: (of_offset_t)offset64 - whence: SEEK_SET]; + seekOrThrowInvalidFormat(_stream, (of_offset_t)offset64, SEEK_SET); localFileHeader = [[[OFZIPArchive_LocalFileHeader alloc] initWithStream: _stream] autorelease]; if (![localFileHeader matchesEntry: entry]) @throw [OFInvalidFormatException exception]; @@ -566,15 +571,15 @@ ret = [_decompressedStream readIntoBuffer: buffer length: min]; _size -= ret; } - _CRC32 = crc32(_CRC32, buffer, ret); + _CRC32 = calculateCRC32(_CRC32, buffer, ret); return ret; } - (void)close { _closed = true; } @end Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -175,12 +175,12 @@ #endif #if __has_feature(nullability) # define OF_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") # define OF_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") -# define OF_NONNULL __nonnull -# define OF_NULLABLE __nullable +# define OF_NONNULL _Nonnull +# define OF_NULLABLE _Nullable # define OF_NULLABLE_PROPERTY(...) (__VA_ARGS__, nullable) #else # define OF_ASSUME_NONNULL_BEGIN # define OF_ASSUME_NONNULL_END # define OF_NONNULL Index: src/of_asprintf.m ================================================================== --- src/of_asprintf.m +++ src/of_asprintf.m @@ -26,10 +26,20 @@ #include #import "OFString.h" #define MAX_SUBFORMAT_LEN 64 + +#ifndef HAVE_ASPRINTF +/* + * (v)asprintf might be declared, but HAVE_ASPRINTF not defined because + * configure determined it is broken. In this case, we must make sure there is + * no name clash. + */ +# define asprintf asprintf_ +# define vasprintf vasprintf_ +#endif struct context { const char *format; size_t formatLen; char subformat[MAX_SUBFORMAT_LEN + 1]; Index: src/resolver.m ================================================================== --- src/resolver.m +++ src/resolver.m @@ -163,19 +163,26 @@ free(tmp); @throw [OFOutOfMemoryException exceptionWithRequestedSize: sizeof(*addr)]; } +#ifdef __wii__ + addr->sin_len = 8; +#endif addr->sin_family = AF_INET; addr->sin_port = OF_BSWAP16_IF_LE(port); addr->sin_addr.s_addr = s_addr; tmp->family = AF_INET; tmp->type = type; tmp->protocol = 0; tmp->address = (struct sockaddr*)addr; +#ifndef __wii__ tmp->addressLength = sizeof(*addr); +#else + tmp->addressLength = 8; +#endif ret[0] = tmp; ret[1] = NULL; return ret; Index: src/socket_helpers.h ================================================================== --- src/socket_helpers.h +++ src/socket_helpers.h @@ -25,10 +25,12 @@ # include #endif #ifdef HAVE_NETDB_H # include #endif + +#include "socket.h" #ifndef INVALID_SOCKET # define INVALID_SOCKET -1 #endif @@ -66,10 +68,12 @@ # define accept(sock, addr, addrlen) net_accept(sock, addr, addrlen) # define bind(sock, addr, addrlen) net_bind(sock, addr, addrlen) # define close(sock) net_close(sock) # define connect(sock, addr, addrlen) net_connect(sock, addr, addrlen) # define gethostbyname(name) net_gethostbyname(name) +# define h_errno 0 +# define hstrerror(err) "unknown (no hstrerror)" # define listen(sock, backlog) net_listen(sock, backlog) # define poll(fds, nfds, timeout) net_poll(fds, nfds, timeout) # define recv(sock, buf, len, flags) net_recv(sock, buf, len, flags) # define recvfrom(sock, buf, len, flags, addr, addrlen) \ net_recvfrom(sock, buf, len, flags, addr, addrlen) Index: utils/ofhttp/ProgressBar.m ================================================================== --- utils/ofhttp/ProgressBar.m +++ utils/ofhttp/ProgressBar.m @@ -15,13 +15,18 @@ */ #include "config.h" #include + +#include #ifdef HAVE_SYS_IOCTL_H # include +#endif +#ifdef HAVE_SYS_TERMIOS_H +# include #endif #import "OFDate.h" #import "OFStdIOStream.h" #import "OFTimer.h"