Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -270,11 +270,10 @@ 4B55A100133ABEA900B58A93 /* OFThreadJoinFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */; }; 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A102133ABEA900B58A93 /* OFThreadStartFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */; }; 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A104133ABEA900B58A93 /* OFThreadStillRunningException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FE133ABEA900B58A93 /* OFThreadStillRunningException.m */; }; - 4B55A109133AC05100B58A93 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A106133AC05100B58A93 /* common.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A10A133AC05100B58A93 /* OFOpenFileFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A107133AC05100B58A93 /* OFOpenFileFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A10B133AC05100B58A93 /* OFOpenFileFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A108133AC05100B58A93 /* OFOpenFileFailedException.m */; }; 4B55A112133AC24600B58A93 /* OFReadFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10C133AC24500B58A93 /* OFReadFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A113133AC24600B58A93 /* OFReadFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */; }; 4B55A114133AC24600B58A93 /* OFReadOrWriteFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -695,11 +694,10 @@ 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadJoinFailedException.m; path = src/exceptions/OFThreadJoinFailedException.m; sourceTree = ""; }; 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadStartFailedException.h; path = src/exceptions/OFThreadStartFailedException.h; sourceTree = ""; }; 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadStartFailedException.m; path = src/exceptions/OFThreadStartFailedException.m; sourceTree = ""; }; 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadStillRunningException.h; path = src/exceptions/OFThreadStillRunningException.h; sourceTree = ""; }; 4B55A0FE133ABEA900B58A93 /* OFThreadStillRunningException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadStillRunningException.m; path = src/exceptions/OFThreadStillRunningException.m; sourceTree = ""; }; - 4B55A106133AC05100B58A93 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = src/exceptions/common.h; sourceTree = ""; }; 4B55A107133AC05100B58A93 /* OFOpenFileFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFOpenFileFailedException.h; path = src/exceptions/OFOpenFileFailedException.h; sourceTree = ""; }; 4B55A108133AC05100B58A93 /* OFOpenFileFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFOpenFileFailedException.m; path = src/exceptions/OFOpenFileFailedException.m; sourceTree = ""; }; 4B55A10C133AC24500B58A93 /* OFReadFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFReadFailedException.h; path = src/exceptions/OFReadFailedException.h; sourceTree = ""; }; 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFReadFailedException.m; path = src/exceptions/OFReadFailedException.m; sourceTree = ""; }; 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFReadOrWriteFailedException.h; path = src/exceptions/OFReadOrWriteFailedException.h; sourceTree = ""; }; @@ -1133,11 +1131,10 @@ 4B17FFB0133A365C003E6DCD /* OFUnsupportedProtocolException.m */, 4BA4846015CC9F1E00D75360 /* OFUnsupportedVersionException.h */, 4BA4846115CC9F1E00D75360 /* OFUnsupportedVersionException.m */, 4B55A110133AC24500B58A93 /* OFWriteFailedException.h */, 4B55A111133AC24600B58A93 /* OFWriteFailedException.m */, - 4B55A106133AC05100B58A93 /* common.h */, ); name = Exceptions; sourceTree = ""; }; 4B17FF95133A31F9003E6DCD /* Supporting Files */ = { @@ -1762,11 +1759,10 @@ 4B91FD12196B4F5900C5C25E /* OFUnknownXMLEntityException.h in Headers */, 4B6743F5163C384A00EB1E59 /* OFUnlockFailedException.h in Headers */, 4B17FFB1133A3664003E6DCD /* OFUnsupportedProtocolException.h in Headers */, 4BA4846215CC9F1E00D75360 /* OFUnsupportedVersionException.h in Headers */, 4B55A116133AC24600B58A93 /* OFWriteFailedException.h in Headers */, - 4B55A109133AC05100B58A93 /* common.h in Headers */, 4B2B3E7D140D430500EC2F7C /* OFArray_adjacent.h in Headers */, 4B9BB7BD141CDE2D000AD1CC /* OFArray_adjacentSubarray.h in Headers */, 4B1473CB17E6391900B46BB8 /* OFAutoreleasePool+Private.h in Headers */, 4BA85BCA140ECCE800E91D51 /* OFCountedSet_hashtable.h in Headers */, 4B2B3E7F140D430500EC2F7C /* OFDictionary_hashtable.h in Headers */, Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -454,10 +454,12 @@ ], [ AC_MSG_RESULT(no) ]) ;; esac + +AC_CHECK_FUNCS(strerror_r) AC_CHECK_LIB(m, fmod, LIBS="$LIBS -lm") AC_CHECK_FUNC(asprintf, [ case "$host" in @@ -853,12 +855,10 @@ AC_MSG_RESULT($have_threadsafe_getaddrinfo) ]) ], [ AC_MSG_RESULT(no) ]) - - AC_CHECK_FUNCS([h_errno hstrerror]) ]) AS_IF([test x"$enable_sockets" != x"no" -a x"$enable_threads" != x"no"], [ AC_SUBST(OFHTTPCLIENTTESTS_M, "OFHTTPClientTests.m") ]) Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -21,15 +21,16 @@ /* Work around a bug with Clang + glibc */ #ifdef __clang__ # define _HAVE_STRING_ARCH_strcmp #endif +#include +#include #include #include #include #include -#include /* Work around __block being used by glibc */ #ifdef __GLIBC__ # undef __USE_XOPEN #endif @@ -326,11 +327,12 @@ DIR_MODE) != 0) #else if (_wmkdir([path UTF16String]) != 0) #endif @throw [OFCreateDirectoryFailedException - exceptionWithPath: path]; + exceptionWithPath: path + errNo: errno]; } + (void)createDirectoryAtPath: (OFString*)path createParents: (bool)createParents { @@ -391,11 +393,12 @@ encoding = [OFSystemInfo native8BitEncoding]; if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL) @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"r"]; + mode: @"r" + errNo: errno]; # if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) if (!of_mutex_lock(&mutex)) @throw [OFLockFailedException exception]; # endif @@ -411,17 +414,26 @@ # ifdef HAVE_READDIR_R if (readdir_r(dir, &buffer, &dirent) != 0) @throw [OFReadFailedException exceptionWithObject: self - requestedLength: 0]; -# else - dirent = readdir(dir); -# endif + requestedLength: 0 + errNo: errno]; if (dirent == NULL) break; +# else + if ((dirent = readdir(dir)) == NULL) { + if (errno == 0) + break; + else + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: errno]; + } +# endif if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) continue; @@ -446,13 +458,20 @@ WIN32_FIND_DATAW fd; path = [path stringByAppendingString: @"\\*"]; if ((handle = FindFirstFileW([path UTF16String], - &fd)) == INVALID_HANDLE_VALUE) + &fd)) == INVALID_HANDLE_VALUE) { + int errNo = 0; + + if (GetLastError() == ERROR_FILE_NOT_FOUND) + errNo = ENOENT; + @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"r"]; + mode: @"r" + errNo: errNo]; + } @try { do { void *pool2 = objc_autoreleasePoolPush(); OFString *file; @@ -464,10 +483,14 @@ file = [OFString stringWithUTF16String: fd.cFileName]; [files addObject: file]; objc_autoreleasePoolPop(pool2); } while (FindNextFileW(handle, &fd)); + + if (GetLastError() != ERROR_NO_MORE_FILES) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: 0]; } @finally { FindClose(handle); } objc_autoreleasePoolPop(pool); @@ -488,24 +511,26 @@ [OFSystemInfo native8BitEncoding]]) != 0) #else if (_wchdir([path UTF16String]) != 0) #endif @throw [OFChangeCurrentDirectoryPathFailedException - exceptionWithPath: path]; + exceptionWithPath: path + errNo: errno]; } + (of_offset_t)sizeOfFileAtPath: (OFString*)path { of_stat_t s; if (path == nil) @throw [OFInvalidArgumentException exception]; - if (of_stat(path, &s) == -1) + if (of_stat(path, &s) != 0) /* FIXME: Maybe use another exception? */ @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"r"]; + mode: @"r" + errNo: errno]; return s.st_size; } + (OFDate*)modificationDateOfFileAtPath: (OFString*)path @@ -513,14 +538,15 @@ of_stat_t s; if (path == nil) @throw [OFInvalidArgumentException exception]; - if (of_stat(path, &s) == -1) + if (of_stat(path, &s) != 0) /* FIXME: Maybe use another exception? */ @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"r"]; + mode: @"r" + errNo: errno]; /* FIXME: We could be more precise on some OSes */ return [OFDate dateWithTimeIntervalSince1970: s.st_mtime]; } @@ -537,11 +563,12 @@ # else if (_wchmod([path UTF16String], permissions) != 0) # endif @throw [OFChangePermissionsFailedException exceptionWithPath: path - permissions: permissions]; + permissions: permissions + errNo: errno]; } #endif #ifdef OF_HAVE_CHOWN + (void)changeOwnerOfItemAtPath: (OFString*)path @@ -569,11 +596,12 @@ if ((passwd = getpwnam([owner cStringWithEncoding: encoding])) == NULL) @throw [OFChangeOwnerFailedException exceptionWithPath: path owner: owner - group: group]; + group: group + errNo: errno]; uid = passwd->pw_uid; } if (group != nil) { @@ -582,11 +610,12 @@ if ((group_ = getgrnam([group cStringWithEncoding: encoding])) == NULL) @throw [OFChangeOwnerFailedException exceptionWithPath: path owner: owner - group: group]; + group: group + errNo: errno]; gid = group_->gr_gid; } # ifdef OF_HAVE_THREADS } @finally { @@ -596,11 +625,12 @@ # endif if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) @throw [OFChangeOwnerFailedException exceptionWithPath: path owner: owner - group: group]; + group: group + errNo: errno]; } #endif + (void)copyItemAtPath: (OFString*)source toPath: (OFString*)destination @@ -611,21 +641,21 @@ if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); - if (of_lstat(destination, &s) == 0) { - errno = EEXIST; + if (of_lstat(destination, &s) == 0) @throw [OFCopyItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; - } + destinationPath: destination + errNo: EEXIST]; if (of_lstat(source, &s) != 0) @throw [OFCopyItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: errno]; if (S_ISDIR(s.st_mode)) { OFArray *contents; OFEnumerator *enumerator; OFString *item; @@ -637,13 +667,23 @@ permissions: s.st_mode]; #endif contents = [OFFile contentsOfDirectoryAtPath: source]; } @catch (id e) { - @throw [OFCopyItemFailedException - exceptionWithSourcePath: source - destinationPath: destination]; + /* + * Only convert exceptions to OFCopyItemFailedException + * that have an errNo property. This covers all I/O + * related exceptions from the operations used to copy + * an item, all others should be left as is. + */ + if ([e respondsToSelector: @selector(errNo)]) + @throw [OFCopyItemFailedException + exceptionWithSourcePath: source + destinationPath: destination + errNo: [e errNo]]; + + @throw e; } enumerator = [contents objectEnumerator]; while ((item = [enumerator nextObject]) != nil) { void *pool2 = objc_autoreleasePoolPush(); @@ -687,13 +727,23 @@ #ifdef OF_HAVE_CHMOD [self changePermissionsOfItemAtPath: destination permissions: s.st_mode]; #endif } @catch (id e) { - @throw [OFCopyItemFailedException - exceptionWithSourcePath: source - destinationPath: destination]; + /* + * Only convert exceptions to OFCopyItemFailedException + * that have an errNo property. This covers all I/O + * related exceptions from the operations used to copy + * an item, all others should be left as is. + */ + if ([e respondsToSelector: @selector(errNo)]) + @throw [OFCopyItemFailedException + exceptionWithSourcePath: source + destinationPath: destination + errNo: [e errNo]]; + + @throw e; } @finally { [sourceFile close]; [destinationFile close]; free(buffer); } @@ -704,19 +754,30 @@ destinationOfSymbolicLinkAtPath: source]; [OFFile createSymbolicLinkAtPath: destination withDestinationPath: source]; } @catch (id e) { - @throw [OFCopyItemFailedException - exceptionWithSourcePath: source - destinationPath: destination]; + /* + * Only convert exceptions to OFCopyItemFailedException + * that have an errNo property. This covers all I/O + * related exceptions from the operations used to copy + * an item, all others should be left as is. + */ + if ([e respondsToSelector: @selector(errNo)]) + @throw [OFCopyItemFailedException + exceptionWithSourcePath: source + destinationPath: destination + errNo: [e errNo]]; + + @throw e; } #endif } else @throw [OFCopyItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: ENOTSUP]; objc_autoreleasePoolPop(pool); } + (void)moveItemAtPath: (OFString*)source @@ -731,16 +792,15 @@ if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); - if (of_lstat(destination, &s) == 0) { - errno = EEXIST; + if (of_lstat(destination, &s) == 0) @throw [OFCopyItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; - } + destinationPath: destination + errNo: EEXIST]; #ifndef _WIN32 encoding = [OFSystemInfo native8BitEncoding]; if (rename([source cStringWithEncoding: encoding], @@ -749,28 +809,32 @@ if (_wrename([source UTF16String], [destination UTF16String]) != 0) { #endif if (errno != EXDEV) @throw [OFMoveItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: errno]; @try { [OFFile copyItemAtPath: source toPath: destination]; } @catch (OFCopyItemFailedException *e) { [OFFile removeItemAtPath: destination]; + @throw [OFMoveItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: [e errNo]]; } @try { [OFFile removeItemAtPath: source]; } @catch (OFRemoveItemFailedException *e) { @throw [OFMoveItemFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: [e errNo]]; } } objc_autoreleasePoolPop(pool); } @@ -784,22 +848,34 @@ @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); if (of_lstat(path, &s) != 0) - @throw [OFRemoveItemFailedException exceptionWithPath: path]; + @throw [OFRemoveItemFailedException exceptionWithPath: path + errNo: errno]; if (S_ISDIR(s.st_mode)) { OFArray *contents; OFEnumerator *enumerator; OFString *item; @try { contents = [OFFile contentsOfDirectoryAtPath: path]; } @catch (id e) { - @throw [OFRemoveItemFailedException - exceptionWithPath: path]; + /* + * Only convert exceptions to + * OFRemoveItemFailedException that have an errNo + * property. This covers all I/O related exceptions + * from the operations used to remove an item, all + * others should be left as is. + */ + if ([e respondsToSelector: @selector(errNo)]) + @throw [OFRemoveItemFailedException + exceptionWithPath: path + errNo: [e errNo]]; + + @throw e; } enumerator = [contents objectEnumerator]; while ((item = [enumerator nextObject]) != nil) { void *pool2 = objc_autoreleasePoolPush(); @@ -815,11 +891,12 @@ if (remove([path cStringWithEncoding: [OFSystemInfo native8BitEncoding]]) != 0) #else if (_wremove([path UTF16String]) != 0) #endif - @throw [OFRemoveItemFailedException exceptionWithPath: path]; + @throw [OFRemoveItemFailedException exceptionWithPath: path + errNo: errno]; objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_LINK @@ -837,11 +914,12 @@ if (link([source cStringWithEncoding: encoding], [destination cStringWithEncoding: encoding]) != 0) @throw [OFLinkFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: errno]; objc_autoreleasePoolPop(pool); } #endif @@ -860,11 +938,12 @@ if (symlink([source cStringWithEncoding: encoding], [destination cStringWithEncoding: encoding]) != 0) @throw [OFCreateSymbolicLinkFailedException exceptionWithSourcePath: source - destinationPath: destination]; + destinationPath: destination + errNo: errno]; objc_autoreleasePoolPop(pool); } + (OFString*)destinationOfSymbolicLinkAtPath: (OFString*)path @@ -880,11 +959,12 @@ length = readlink([path cStringWithEncoding: encoding], destination, PATH_MAX); if (length < 0) @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"r"]; + mode: @"r" + errNo: errno]; return [OFString stringWithCString: destination encoding: encoding length: length]; } @@ -918,11 +998,12 @@ if ((_fd = open([path cStringWithEncoding: [OFSystemInfo native8BitEncoding]], flags, DEFAULT_MODE)) == -1) #endif @throw [OFOpenFileFailedException exceptionWithPath: path - mode: mode]; + mode: mode + errNo: errno]; } @catch (id e) { [self release]; @throw e; } @@ -949,23 +1030,28 @@ - (size_t)lowlevelReadIntoBuffer: (void*)buffer length: (size_t)length { ssize_t ret; -#ifndef _WIN32 - if (_fd == -1 || _atEndOfStream || - (ret = read(_fd, buffer, length)) < 0) + + if (_fd == -1 || _atEndOfStream) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; + +#ifndef _WIN32 + if ((ret = read(_fd, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; - if (_fd == -1 || _atEndOfStream || - (ret = read(_fd, buffer, (unsigned int)length)) < 0) + if ((ret = read(_fd, buffer, (unsigned int)length)) < 0) @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + requestedLength: length + errNo: errno]; #endif if (ret == 0) _atEndOfStream = true; @@ -973,22 +1059,27 @@ } - (void)lowlevelWriteBuffer: (const void*)buffer length: (size_t)length { -#ifndef _WIN32 - if (_fd == -1 || _atEndOfStream || write(_fd, buffer, length) < length) + if (_fd == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; + +#ifndef _WIN32 + if (write(_fd, buffer, length) < length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; - if (_fd == -1 || _atEndOfStream || - write(_fd, buffer, (unsigned int)length) < length) + if (write(_fd, buffer, (unsigned int)length) < length) @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; + requestedLength: length + errNo: errno]; #endif } - (of_offset_t)lowlevelSeekToOffset: (of_offset_t)offset whence: (int)whence @@ -1002,11 +1093,12 @@ #endif if (ret == -1) @throw [OFSeekFailedException exceptionWithStream: self offset: offset - whence: whence]; + whence: whence + errNo: errno]; _atEndOfStream = false; return ret; } Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -14,14 +14,13 @@ * file. */ #include "config.h" -#include #include - #include +#include #import "OFHTTPClient.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" #import "OFString.h" @@ -119,18 +118,14 @@ } - (size_t)lowlevelReadIntoBuffer: (void*)buffer length: (size_t)length { - if (_atEndOfStream) { - OFReadFailedException *e; - - e = [OFReadFailedException exceptionWithObject: self - requestedLength: length]; - e->_errNo = ENOTCONN; - @throw e; - } + if (_atEndOfStream) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: ENOTCONN]; if (!_hasContentLength && !_chunked) return [_socket readIntoBuffer: buffer length: length]; Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -13,10 +13,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFINIFile.h" #import "OFArray.h" #import "OFString.h" #import "OFFile.h" Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -63,11 +63,11 @@ + (void)initialize { if (self != [OFKernelEventObserver class]) return; - if (!of_init_sockets()) + if (!of_socket_init()) @throw [OFInitializationFailedException exceptionWithClass: self]; } + (instancetype)observer Index: src/OFKernelEventObserver_kqueue.m ================================================================== --- src/OFKernelEventObserver_kqueue.m +++ src/OFKernelEventObserver_kqueue.m @@ -14,14 +14,13 @@ * file. */ #include "config.h" -#include +#include #include - -#include +#include #include #include #include Index: src/OFProcess.m ================================================================== --- src/OFProcess.m +++ src/OFProcess.m @@ -14,10 +14,11 @@ * file. */ #include "config.h" +#include #include /* Work around __block being used by glibc */ #ifdef __GLIBC__ # undef __USE_XOPEN @@ -454,20 +455,27 @@ #else DWORD ret; #endif #ifndef _WIN32 - if (_readPipe[0] == -1 || _atEndOfStream || - (ret = read(_readPipe[0], buffer, length)) < 0) + if (_readPipe[0] == -1 || _atEndOfStream) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; + + if ((ret = read(_readPipe[0], buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else if (length > UINT32_MAX) @throw [OFOutOfRangeException exception]; - if (_readPipe[0] == NULL || _atEndOfStream || - !ReadFile(_readPipe[0], buffer, (DWORD)length, &ret, NULL)) { + if (_readPipe[0] == NULL || _atEndOfStream) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length]; + + if (!ReadFile(_readPipe[0], buffer, (DWORD)length, &ret, NULL)) { if (GetLastError() == ERROR_BROKEN_PIPE) { _atEndOfStream = true; return 0; } @@ -484,25 +492,39 @@ - (void)lowlevelWriteBuffer: (const void*)buffer length: (size_t)length { #ifndef _WIN32 - if (_writePipe[1] == -1 || _atEndOfStream || - write(_writePipe[1], buffer, length) < length) + if (_writePipe[1] == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; + + if (write(_writePipe[1], buffer, length) < length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else DWORD ret; if (length > UINT32_MAX) @throw [OFOutOfRangeException exception]; - if (_writePipe[1] == NULL || _atEndOfStream || - !WriteFile(_writePipe[1], buffer, (DWORD)length, &ret, NULL) || - ret < length) + if (_writePipe[1] == NULL || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; + + if (!WriteFile(_writePipe[1], buffer, (DWORD)length, &ret, NULL) || + ret < length) { + int errNo = 0; + + if (GetLastError() == ERROR_BROKEN_PIPE) + errNo = EPIPE; + + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + errNo: errNo]; + } #endif } - (int)fileDescriptorForReading { Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -20,10 +20,11 @@ #include /* include any libc header to get the libc defines */ #ifdef __GLIBC__ # undef __USE_XOPEN #endif +#include #include #import "OFStdIOStream.h" #import "OFDate.h" #import "OFApplication.h" @@ -96,23 +97,27 @@ - (size_t)lowlevelReadIntoBuffer: (void*)buffer length: (size_t)length { ssize_t ret; -#ifndef _WIN32 - if (_fd == -1 || _atEndOfStream || - (ret = read(_fd, buffer, length)) < 0) + if (_fd == -1 || _atEndOfStream) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; + +#ifndef _WIN32 + if ((ret = read(_fd, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; - if (_fd == -1 || _atEndOfStream || - (ret = read(_fd, buffer, (unsigned int)length)) < 0) + if ((ret = read(_fd, buffer, (unsigned int)length)) < 0) @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + requestedLength: length + errNo: errno]; #endif if (ret == 0) _atEndOfStream = true; @@ -120,22 +125,27 @@ } - (void)lowlevelWriteBuffer: (const void*)buffer length: (size_t)length { -#ifndef _WIN32 - if (_fd == -1 || _atEndOfStream || write(_fd, buffer, length) < length) + if (_fd == -1 || _atEndOfStream) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; + +#ifndef _WIN32 + if (write(_fd, buffer, length) < length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + errNo: errno]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; - if (_fd == -1 || _atEndOfStream || - write(_fd, buffer, (unsigned int)length) < length) + if (write(_fd, buffer, (unsigned int)length) < length) @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; + requestedLength: length + errNo: errno]; #endif } - (int)fileDescriptorForReading { Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -16,17 +16,17 @@ #define __NO_EXT_QNX #include "config.h" +#include +#include #include #include #include #include -#include - #include #ifndef _WIN32 # include #endif @@ -1484,21 +1484,23 @@ readImplemented = true; if (readFlags == -1) @throw [OFSetOptionFailedException - exceptionWithStream: self]; + exceptionWithStream: self + errNo: errno]; if (enable) readFlags &= ~O_NONBLOCK; else readFlags |= O_NONBLOCK; if (fcntl([self fileDescriptorForReading], F_SETFL, readFlags) == -1) @throw [OFSetOptionFailedException - exceptionWithStream: self]; + exceptionWithStream: self + errNo: errno]; } @catch (OFNotImplementedException *e) { } @try { int writeFlags; @@ -1507,21 +1509,23 @@ writeImplemented = true; if (writeFlags == -1) @throw [OFSetOptionFailedException - exceptionWithStream: self]; + exceptionWithStream: self + errNo: errno]; if (enable) writeFlags &= ~O_NONBLOCK; else writeFlags |= O_NONBLOCK; if (fcntl([self fileDescriptorForWriting], F_SETFL, writeFlags) == -1) @throw [OFSetOptionFailedException - exceptionWithStream: self]; + exceptionWithStream: self + errNo: errno]; } @catch (OFNotImplementedException *e) { } if (!readImplemented && !writeImplemented) @throw [OFNotImplementedException exceptionWithSelector: _cmd Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -16,13 +16,12 @@ #define __NO_EXT_QNX #include "config.h" -#include - #include +#include #import "OFStreamSocket.h" #import "OFInitializationFailedException.h" #import "OFNotConnectedException.h" @@ -37,11 +36,11 @@ + (void)initialize { if (self != [OFStreamSocket class]) return; - if (!of_init_sockets()) + if (!of_socket_init()) @throw [OFInitializationFailedException exceptionWithClass: self]; } + (instancetype)socket @@ -60,30 +59,30 @@ ssize_t ret; if (_socket == INVALID_SOCKET) @throw [OFNotConnectedException exceptionWithSocket: self]; - if (_atEndOfStream) { - OFReadFailedException *e; - - e = [OFReadFailedException exceptionWithObject: self - requestedLength: length]; - e->_errNo = ENOTCONN; - @throw e; - } + if (_atEndOfStream) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: ENOTCONN]; #ifndef _WIN32 if ((ret = recv(_socket, buffer, length, 0)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = recv(_socket, buffer, (unsigned int)length, 0)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #endif if (ret == 0) _atEndOfStream = true; @@ -94,30 +93,30 @@ length: (size_t)length { if (_socket == INVALID_SOCKET) @throw [OFNotConnectedException exceptionWithSocket: self]; - if (_atEndOfStream) { - OFWriteFailedException *e; - - e = [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; - e->_errNo = ENOTCONN; - @throw e; - } + if (_atEndOfStream) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + errNo: ENOTCONN]; #ifndef _WIN32 if (send(_socket, buffer, length, 0) < length) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFWriteFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; if (send(_socket, buffer, (unsigned int)length, 0) < length) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFWriteFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #endif } #ifdef _WIN32 - (void)setBlocking: (bool)enable @@ -124,11 +123,13 @@ { u_long v = enable; _blocking = enable; if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR) - @throw [OFSetOptionFailedException exceptionWithStream: self]; + @throw [OFSetOptionFailedException + exceptionWithStream: self + errNo: of_socket_errno()]; } #endif - (int)fileDescriptorForReading { Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -14,24 +14,24 @@ * file. */ #include "config.h" +#include +#include #include #include #include -#include #include #import "OFString.h" #import "OFString_UTF8.h" #import "OFString_UTF8+Private.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFDataArray.h" -#import "OFSystemInfo.h" #ifdef OF_HAVE_FILES # import "OFFile.h" #endif #import "OFURL.h" #ifdef OF_HAVE_SOCKETS @@ -819,23 +819,23 @@ - initWithContentsOfFile: (OFString*)path encoding: (of_string_encoding_t)encoding { char *tmp; - struct stat st; + of_stat_t st; @try { OFFile *file; /* Make sure the file system is initialized */ [OFFile class]; - if (stat([path cStringWithEncoding: - [OFSystemInfo native8BitEncoding]], &st) == -1) + if (of_stat(path, &st) != 0) @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"rb"]; + mode: @"rb" + errNo: errno]; if (st.st_size > SIZE_MAX) @throw [OFOutOfRangeException exception]; file = [[OFFile alloc] initWithPath: path Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -18,16 +18,16 @@ #define __NO_EXT_QNX #include "config.h" +#include +#include #include #include #include -#include - #import "OFTCPSocket.h" #import "OFTCPSocket+SOCKS5.h" #import "OFString.h" #import "OFThread.h" #import "OFTimer.h" @@ -267,10 +267,11 @@ port: (uint16_t)port { OFString *destinationHost = host; uint16_t destinationPort = port; of_resolver_result_t **results, **iter; + int errNo = 0; if (_socket != INVALID_SOCKET) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; _listening = false; @@ -294,22 +295,28 @@ int flags; #endif if ((_socket = socket(result->family, result->type | SOCK_CLOEXEC, - result->protocol)) == INVALID_SOCKET) + result->protocol)) == INVALID_SOCKET) { + errNo = of_socket_errno(); + continue; + } #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif if (connect(_socket, result->address, result->addressLength) == -1) { + errNo = of_socket_errno(); + close(_socket); _socket = INVALID_SOCKET; + continue; } break; } @@ -317,11 +324,12 @@ of_resolver_free(results); if (_socket == INVALID_SOCKET) @throw [OFConnectionFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: errNo]; if (_SOCKS5Host != nil) [self OF_SOCKS5ConnectToHost: destinationHost port: destinationPort]; } @@ -399,31 +407,35 @@ #endif if ((_socket = socket(results[0]->family, results[0]->type | SOCK_CLOEXEC, results[0]->protocol)) == INVALID_SOCKET) - @throw [OFBindFailedException exceptionWithHost: host - port: port - socket: self]; + @throw [OFBindFailedException + exceptionWithHost: host + port: port + socket: self + errNo: of_socket_errno()]; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif - if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, - (const char*)&one, (socklen_t)sizeof(one))) - @throw [OFSetOptionFailedException - exceptionWithStream: self]; + setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, + (const char*)&one, (socklen_t)sizeof(one)); if (bind(_socket, results[0]->address, results[0]->addressLength) == -1) { + int errNo = of_socket_errno(); + close(_socket); _socket = INVALID_SOCKET; + @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: errNo]; } } @finally { of_resolver_free(results); } @@ -431,15 +443,19 @@ return port; #ifndef __wii__ addrLen = (socklen_t)sizeof(addr.storage); if (getsockname(_socket, (struct sockaddr*)&addr.storage, &addrLen)) { + int errNo = of_socket_errno(); + close(_socket); _socket = INVALID_SOCKET; + @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: errNo]; } if (addr.storage.ss_family == AF_INET) return OF_BSWAP16_IF_LE(addr.in.sin_port); # ifdef AF_INET6 @@ -450,11 +466,12 @@ close(_socket); _socket = INVALID_SOCKET; @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: EAFNOSUPPORT]; } - (void)listen { [self listenWithBackLog: SOMAXCONN]; @@ -464,12 +481,14 @@ { if (_socket == INVALID_SOCKET) @throw [OFNotConnectedException exceptionWithSocket: self]; if (listen(_socket, backLog) == -1) - @throw [OFListenFailedException exceptionWithSocket: self - backLog: backLog]; + @throw [OFListenFailedException + exceptionWithSocket: self + backLog: backLog + errNo: of_socket_errno()]; _listening = true; } - (instancetype)accept @@ -486,19 +505,25 @@ client->_addressLength = (socklen_t)sizeof(struct sockaddr_storage); #if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) if ((client->_socket = paccept(_socket, client->_address, &client->_addressLength, NULL, SOCK_CLOEXEC)) == INVALID_SOCKET) - @throw [OFAcceptFailedException exceptionWithSocket: self]; + @throw [OFAcceptFailedException + exceptionWithSocket: self + errNo: of_socket_errno()]; #elif defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) if ((client->_socket = accept4(_socket, client->_address, &client->_addressLength, SOCK_CLOEXEC)) == INVALID_SOCKET) - @throw [OFAcceptFailedException exceptionWithSocket: self]; + @throw [OFAcceptFailedException + exceptionWithSocket: self + errNo: of_socket_errno()]; #else if ((client->_socket = accept(_socket, client->_address, &client->_addressLength)) == INVALID_SOCKET) - @throw [OFAcceptFailedException exceptionWithSocket: self]; + @throw [OFAcceptFailedException + exceptionWithSocket: self + errNo: of_socket_errno()]; # if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1) fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC); # endif @@ -539,11 +564,13 @@ { int v = enable; if (setsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&v, (socklen_t)sizeof(v))) - @throw [OFSetOptionFailedException exceptionWithStream: self]; + @throw [OFSetOptionFailedException + exceptionWithStream: self + errNo: of_socket_errno()]; } - (OFString*)remoteAddress { OFString *ret; Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -14,13 +14,13 @@ * file. */ #include "config.h" -#include - #include +#include +#include #import "OFUDPSocket.h" #ifdef OF_HAVE_THREADS # import "OFThread.h" #endif @@ -279,11 +279,11 @@ + (void)initialize { if (self != [OFUDPSocket class]) return; - if (!of_init_sockets()) + if (!of_socket_init()) @throw [OFInitializationFailedException exceptionWithClass: self]; } + (instancetype)socket @@ -400,26 +400,32 @@ #endif if ((_socket = socket(results[0]->family, results[0]->type | SOCK_CLOEXEC, results[0]->protocol)) == INVALID_SOCKET) - @throw [OFBindFailedException exceptionWithHost: host - port: port - socket: self]; + @throw [OFBindFailedException + exceptionWithHost: host + port: port + socket: self + errNo: of_socket_errno()]; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif if (bind(_socket, results[0]->address, results[0]->addressLength) == -1) { + int errNo = of_socket_errno(); + close(_socket); _socket = INVALID_SOCKET; + @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: errNo]; } } @finally { of_resolver_free(results); } @@ -427,15 +433,19 @@ return port; #ifndef __wii__ addrLen = (socklen_t)sizeof(addr.storage); if (getsockname(_socket, (struct sockaddr*)&addr.storage, &addrLen)) { + int errNo = of_socket_errno(); + close(_socket); _socket = INVALID_SOCKET; + @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: errNo]; } if (addr.storage.ss_family == AF_INET) return OF_BSWAP16_IF_LE(addr.in.sin_port); # ifdef AF_INET6 @@ -446,11 +456,12 @@ close(_socket); _socket = INVALID_SOCKET; @throw [OFBindFailedException exceptionWithHost: host port: port - socket: self]; + socket: self + errNo: EAFNOSUPPORT]; } - (size_t)receiveIntoBuffer: (void*)buffer length: (size_t)length sender: (of_udp_socket_address_t*)sender @@ -463,20 +474,24 @@ sender->length = (socklen_t)sizeof(sender->address); #ifndef _WIN32 if ((ret = recvfrom(_socket, buffer, length, 0, (struct sockaddr*)&sender->address, &sender->length)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #else if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = recvfrom(_socket, buffer, (int)length, 0, (struct sockaddr*)&sender->address, &sender->length)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #endif return ret; } @@ -512,20 +527,24 @@ @throw [OFNotConnectedException exceptionWithSocket: self]; #ifndef _WIN32 if (sendto(_socket, buffer, length, 0, (struct sockaddr*)&receiver->address, receiver->length) < length) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: 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) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length]; + @throw [OFWriteFailedException + exceptionWithObject: self + requestedLength: length + errNo: of_socket_errno()]; #endif } - (void)cancelAsyncRequests { Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -13,10 +13,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFZIPArchive.h" #import "OFZIPArchiveEntry.h" #import "OFZIPArchiveEntry+Private.h" #import "OFDataArray.h" @@ -319,15 +321,14 @@ void *pool = objc_autoreleasePoolPush(); OFZIPArchiveEntry *entry = [_pathToEntryMap objectForKey: path]; OFZIPArchive_LocalFileHeader *localFileHeader; uint64_t offset64; - if (entry == nil) { - errno = ENOENT; + if (entry == nil) @throw [OFOpenFileFailedException exceptionWithPath: path - mode: @"rb"]; - } + mode: @"rb" + errNo: ENOENT]; offset64 = [entry OF_localFileHeaderOffset]; if ((of_offset_t)offset64 != offset64) @throw [OFOutOfRangeException exception]; Index: src/exceptions/OFAcceptFailedException.h ================================================================== --- src/exceptions/OFAcceptFailedException.h +++ src/exceptions/OFAcceptFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif @@ -41,21 +39,25 @@ /*! * @brief Creates a new, autoreleased accept failed exception. * * @param socket The socket which could not accept a connection + * @param errNo The errno for the error * @return A new, autoreleased accept failed exception */ -+ (instancetype)exceptionWithSocket: (id)socket; ++ (instancetype)exceptionWithSocket: (id)socket + errNo: (int)errNo; /*! * @brief Initializes an already allocated accept failed exception. * * @param socket The socket which could not accept a connection + * @param errNo The errno for the error * @return An initialized accept failed exception */ -- initWithSocket: (id)socket; +- initWithSocket: (id)socket + errNo: (int)errNo; /*! * @brief Returns the socket which could not accept a connection. * * @return The socket which could not accept a connection Index: src/exceptions/OFAcceptFailedException.m ================================================================== --- src/exceptions/OFAcceptFailedException.m +++ src/exceptions/OFAcceptFailedException.m @@ -17,29 +17,30 @@ #include "config.h" #import "OFAcceptFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFAcceptFailedException + (instancetype)exceptionWithSocket: (id)socket + errNo: (int)errNo { - return [[[self alloc] initWithSocket: socket] autorelease]; + return [[[self alloc] initWithSocket: socket + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSocket: (id)socket + errNo: (int)errNo { self = [super init]; _socket = [socket retain]; - _errNo = GET_SOCK_ERRNO; + _errNo = errNo; return self; } - (void)dealloc @@ -50,23 +51,19 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to accept connection in socket of class %@! " ERRFMT, - [_socket class], ERRPARAM]; + @"Failed to accept connection in socket of class %@: %@", + [_socket class], of_strerror(_errNo)]; } - (id)socket { OF_GETTER(_socket, true) } - (int)errNo { -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else return _errNo; -#endif } @end Index: src/exceptions/OFAddressTranslationFailedException.h ================================================================== --- src/exceptions/OFAddressTranslationFailedException.h +++ src/exceptions/OFAddressTranslationFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif @@ -30,16 +28,15 @@ * @brief An exception indicating the translation of an address failed. */ @interface OFAddressTranslationFailedException: OFException { OFString *_host; - int _errNo; + int _error; } #ifdef OF_HAVE_PROPERTIES @property (readonly, copy) OFString *host; -@property (readonly) int errNo; #endif /*! * @brief Creates a new, autoreleased address translation failed exception. * @@ -46,27 +43,28 @@ * @param host The host for which translation was requested * @return A new, autoreleased address translation failed exception */ + (instancetype)exceptionWithHost: (OFString*)host; ++ (instancetype)exceptionWithHost: (OFString*)host + error: (int)error; ++ (instancetype)exceptionWithError: (int)error; + /*! * @brief Initializes an already allocated address translation failed exception. * * @param host The host for which translation was requested * @return An initialized address translation failed exception */ - initWithHost: (OFString*)host; +- initWithHost: (OFString*)host + error: (int)error; +- initWithError: (int)error; + /*! * @brief Returns the host for which the address translation was requested. * * @return The host for which the address translation was requested */ - (OFString*)host; - -/*! - * @brief Returns the errno from when the exception was created. - * - * @return The errno from when the exception was created - */ -- (int)errNo; @end Index: src/exceptions/OFAddressTranslationFailedException.m ================================================================== --- src/exceptions/OFAddressTranslationFailedException.m +++ src/exceptions/OFAddressTranslationFailedException.m @@ -17,31 +17,87 @@ #include "config.h" #import "OFAddressTranslationFailedException.h" #import "OFString.h" -#import "common.h" +#import "OFInitializationFailedException.h" +#import "OFLockFailedException.h" +#import "OFUnlockFailedException.h" + +#include "socket_helpers.h" + +#if !defined(HAVE_GETADDRINFO) && defined(OF_HAVE_THREADS) +# include "threading.h" + +static of_mutex_t mutex; +#endif @implementation OFAddressTranslationFailedException +#if !defined(HAVE_GETADDRINFO) && defined(OF_HAVE_THREADS) ++ (void)initialize +{ + if (self != [OFAddressTranslationFailedException class]) + return; + + if (!of_mutex_new(&mutex)) + @throw [OFInitializationFailedException exception]; +} +#endif + + (instancetype)exceptionWithHost: (OFString*)host { return [[[self alloc] initWithHost: host] autorelease]; } ++ (instancetype)exceptionWithHost: (OFString*)host + error: (int)error +{ + return [[[self alloc] initWithHost: host + error: error] autorelease]; +} + ++ (instancetype)exceptionWithError: (int)error +{ + return [[[self alloc] initWithError: error] autorelease]; +} + +- initWithHost: (OFString*)host +{ + self = [super init]; + + @try { + _host = [host copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - initWithHost: (OFString*)host + error: (int)error { self = [super init]; @try { - _host = [host copy]; - _errNo = GET_AT_ERRNO; + _host = [host copy]; + _error = error; } @catch (id e) { [self release]; @throw e; } + return self; +} + +- initWithError: (int)error +{ + self = [super init]; + + _error = error; + return self; } - (void)dealloc { @@ -50,32 +106,59 @@ [super dealloc]; } - (OFString*)description { + /* FIXME: Add proper description for Win32 */ +#ifndef _WIN32 + if (_error == 0) { +#endif + if (_host != nil) + return [OFString stringWithFormat: + @"The host %@ could not be translated to an " + @"address!", + _host]; + else + return @"An address could not be translated!"; +#ifndef _WIN32 + } + +# ifdef HAVE_GETADDRINFO if (_host != nil) return [OFString stringWithFormat: - @"The host %@ could not be translated to an address. This " - @"means that either the host was not found, there was a " - @"problem with the name server, there was a problem with " - @"your network connection or you specified an invalid " - @"host. " ERRFMT, _host, AT_ERRPARAM]; + @"The host %@ could not be translated to an address: %s", + _host, gai_strerror(_error)]; else return [OFString stringWithFormat: - @"An address could not be translated! " ERRFMT, - AT_ERRPARAM]; + @"An address could not be translated: %s", + gai_strerror(_error)]; +# else +# ifdef OF_HAVE_THREADS + if (!of_mutex_lock(&mutex)) + @throw [OFLockFailedException exception]; + + @try { +# endif + if (_host != nil) + return [OFString stringWithFormat: + @"The host %@ could not be translated to an " + "address: %s", + _host, hstrerror(_error)]; + else + return [OFString stringWithFormat: + @"An address could not be translated: %s", + hstrerror(_error)]; +# ifdef OF_HAVE_THREADS + } @finally { + if (!of_mutex_unlock(&mutex)) + @throw [OFUnlockFailedException exception]; + } +# endif +# endif +#endif } - (OFString*)host { OF_GETTER(_host, true) } - -- (int)errNo -{ -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else - return _errNo; -#endif -} @end Index: src/exceptions/OFAlreadyConnectedException.m ================================================================== --- src/exceptions/OFAlreadyConnectedException.m +++ src/exceptions/OFAlreadyConnectedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFAlreadyConnectedException.h" #import "OFString.h" -#import "common.h" - @implementation OFAlreadyConnectedException + (instancetype)exceptionWithSocket: (id)socket { return [[[self alloc] initWithSocket: socket] autorelease]; } Index: src/exceptions/OFBindFailedException.h ================================================================== --- src/exceptions/OFBindFailedException.h +++ src/exceptions/OFBindFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif @@ -47,27 +45,31 @@ * @brief Creates a new, autoreleased bind failed exception. * * @param host The host on which binding failed * @param port The port on which binding failed * @param socket The socket which could not be bound + * @param errNo The errno of the error * @return A new, autoreleased bind failed exception */ + (instancetype)exceptionWithHost: (OFString*)host port: (uint16_t)port - socket: (id)socket; + socket: (id)socket + errNo: (int)errNo; /*! * @brief Initializes an already allocated bind failed exception. * * @param host The host on which binding failed * @param port The port on which binding failed * @param socket The socket which could not be bound + * @param errNo The errno of the error * @return An initialized bind failed exception */ - initWithHost: (OFString*)host port: (uint16_t)port - socket: (id)socket; + socket: (id)socket + errNo: (int)errNo; /*! * @brief Returns the host on which binding failed. * * @return The host on which binding failed Index: src/exceptions/OFBindFailedException.m ================================================================== --- src/exceptions/OFBindFailedException.m +++ src/exceptions/OFBindFailedException.m @@ -17,20 +17,20 @@ #include "config.h" #import "OFBindFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFBindFailedException + (instancetype)exceptionWithHost: (OFString*)host port: (uint16_t)port socket: (id)socket + errNo: (int)errNo { return [[[self alloc] initWithHost: host port: port - socket: socket] autorelease]; + socket: socket + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD @@ -37,18 +37,19 @@ } - initWithHost: (OFString*)host port: (uint16_t)port socket: (id)socket + errNo: (int)errNo { self = [super init]; @try { - _host = [host copy]; - _port = port; + _host = [host copy]; + _port = port; _socket = [socket retain]; - _errNo = GET_SOCK_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -65,11 +66,12 @@ - (OFString*)description { return [OFString stringWithFormat: @"Binding to port %" @PRIu16 @" on host %@ failed in socket of " - @"type %@! " ERRFMT, _port, _host, [_socket class], ERRPARAM]; + @"type %@: %@", + _port, _host, [_socket class], of_strerror(_errNo)]; } - (OFString*)host { OF_GETTER(_host, true) @@ -85,12 +87,8 @@ OF_GETTER(_socket, true) } - (int)errNo { -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else return _errNo; -#endif } @end Index: src/exceptions/OFChangeCurrentDirectoryPathFailedException.h ================================================================== --- src/exceptions/OFChangeCurrentDirectoryPathFailedException.h +++ src/exceptions/OFChangeCurrentDirectoryPathFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFChangeCurrentDirectoryPathFailedException \ * OFChangeCurrentDirectoryPathFailedException.h \ @@ -41,22 +39,26 @@ * @brief Creates a new, autoreleased change current directory path failed * exception. * * @param path The path of the directory to which the current path could not be * changed + * @param errNo The errno of the error * @return A new, autoreleased change current directory path failed exception */ -+ (instancetype)exceptionWithPath: (OFString*)path; ++ (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Initializes an already allocated change directory failed exception. * * @param path The path of the directory to which the current path could not be * changed + * @param errNo The errno of the error * @return An initialized change current directory path failed exception */ -- initWithPath: (OFString*)path; +- initWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Returns the path of the directory to which the current path could not * be changed. * Index: src/exceptions/OFChangeCurrentDirectoryPathFailedException.m ================================================================== --- src/exceptions/OFChangeCurrentDirectoryPathFailedException.m +++ src/exceptions/OFChangeCurrentDirectoryPathFailedException.m @@ -17,30 +17,31 @@ #include "config.h" #import "OFChangeCurrentDirectoryPathFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFChangeCurrentDirectoryPathFailedException + (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo { - return [[[self alloc] initWithPath: path] autorelease]; + return [[[self alloc] initWithPath: path + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithPath: (OFString*)path + errNo: (int)errNo { self = [super init]; @try { _path = [path copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -55,12 +56,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to change the current directory path to %@! " ERRFMT, - _path, ERRPARAM]; + @"Failed to change the current directory path to %@: %@", + _path, of_strerror(_errNo)]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFChangeOwnerFailedException.h ================================================================== --- src/exceptions/OFChangeOwnerFailedException.h +++ src/exceptions/OFChangeOwnerFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifdef OF_HAVE_CHOWN /*! * @class OFChangeOwnerFailedException \ @@ -40,27 +38,31 @@ * @brief Creates a new, autoreleased change owner failed exception. * * @param path The path of the item * @param owner The new owner for the item * @param group The new group for the item + * @param errNo The errno of the error * @return A new, autoreleased change owner failed exception */ + (instancetype)exceptionWithPath: (OFString*)path owner: (OFString*)owner - group: (OFString*)group; + group: (OFString*)group + errNo: (int)errNo; /*! * @brief Initializes an already allocated change owner failed exception. * * @param path The path of the item * @param owner The new owner for the item * @param group The new group for the item + * @param errNo The errno of the error * @return An initialized change owner failed exception */ - initWithPath: (OFString*)path owner: (OFString*)owner - group: (OFString*)group; + group: (OFString*)group + errNo: (int)errNo; /*! * @brief Returns the path of the item. * * @return The path of the item Index: src/exceptions/OFChangeOwnerFailedException.m ================================================================== --- src/exceptions/OFChangeOwnerFailedException.m +++ src/exceptions/OFChangeOwnerFailedException.m @@ -17,21 +17,21 @@ #include "config.h" #import "OFChangeOwnerFailedException.h" #import "OFString.h" -#import "common.h" - #ifdef OF_HAVE_CHOWN @implementation OFChangeOwnerFailedException + (instancetype)exceptionWithPath: (OFString*)path owner: (OFString*)owner group: (OFString*)group + errNo: (int)errNo { return [[[self alloc] initWithPath: path owner: owner - group: group] autorelease]; + group: group + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD @@ -38,18 +38,19 @@ } - initWithPath: (OFString*)path owner: (OFString*)owner group: (OFString*)group + errNo: (int)errNo { self = [super init]; @try { _path = [path copy]; _owner = [owner copy]; _group = [group copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -67,20 +68,20 @@ - (OFString*)description { if (_group == nil) return [OFString stringWithFormat: - @"Failed to change owner of item at path %@ to %@! " - ERRFMT, _path, _owner, ERRPARAM]; + @"Failed to change owner of item at path %@ to %@: %@", + _path, _owner, of_strerror(_errNo)]; else if (_owner == nil) return [OFString stringWithFormat: - @"Failed to change group of item at path %@ to %@! " - ERRFMT, _path, _group, ERRPARAM]; + @"Failed to change group of item at path %@ to %@: %@", + _path, _group, of_strerror(_errNo)]; else return [OFString stringWithFormat: - @"Failed to change owner of item at path %@ to %@:%@! " - ERRFMT, _path, _owner, _group, ERRPARAM]; + @"Failed to change owner of item at path %@ to %@:%@: %@", + _path, _owner, _group, of_strerror(_errNo)]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFChangePermissionsFailedException.h ================================================================== --- src/exceptions/OFChangePermissionsFailedException.h +++ src/exceptions/OFChangePermissionsFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #include #import "OFException.h" /*! @@ -44,24 +42,28 @@ /*! * @brief Creates a new, autoreleased change permissions failed exception. * * @param path The path of the item * @param permissions The new permissions for the item + * @param errNo The errno of the error * @return A new, autoreleased change permissions failed exception */ + (instancetype)exceptionWithPath: (OFString*)path - permissions: (mode_t)permissions; + permissions: (mode_t)permissions + errNo: (int)errNo; /*! * @brief Initializes an already allocated change permissions failed exception. * * @param path The path of the item * @param permissions The new permissions for the item + * @param errNo The errno of the error * @return An initialized change permissions failed exception */ - initWithPath: (OFString*)path - permissions: (mode_t)permissions; + permissions: (mode_t)permissions + errNo: (int)errNo; /*! * @brief Returns the path of the item. * * @return The path of the item Index: src/exceptions/OFChangePermissionsFailedException.m ================================================================== --- src/exceptions/OFChangePermissionsFailedException.m +++ src/exceptions/OFChangePermissionsFailedException.m @@ -17,34 +17,35 @@ #include "config.h" #import "OFChangePermissionsFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFChangePermissionsFailedException + (instancetype)exceptionWithPath: (OFString*)path permissions: (mode_t)permissions + errNo: (int)errNo { return [[[self alloc] initWithPath: path - permissions: permissions] autorelease]; + permissions: permissions + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithPath: (OFString*)path permissions: (mode_t)permissions + errNo: (int)errNo { self = [super init]; @try { _path = [path copy]; _permissions = permissions; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -59,12 +60,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to change permissions of item at path %@ to %d! " ERRFMT, - _path, _permissions, ERRPARAM]; + @"Failed to change permissions of item at path %@ to %d: %@", + _path, _permissions, of_strerror(_errNo)]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFConnectionFailedException.h ================================================================== --- src/exceptions/OFConnectionFailedException.h +++ src/exceptions/OFConnectionFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif @@ -53,10 +51,24 @@ */ + (instancetype)exceptionWithHost: (OFString*)host port: (uint16_t)port socket: (id)socket; +/*! + * @brief Creates a new, autoreleased connection failed exception. + * + * @param host The host to which the connection failed + * @param port The port on the host to which the connection failed + * @param socket The socket which could not connect + * @param errNo The errno of the error + * @return A new, autoreleased connection failed exception + */ ++ (instancetype)exceptionWithHost: (OFString*)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo; + /*! * @brief Initializes an already allocated connection failed exception. * * @param host The host to which the connection failed * @param port The port on the host to which the connection failed @@ -65,10 +77,24 @@ */ - initWithHost: (OFString*)host port: (uint16_t)port socket: (id)socket; +/*! + * @brief Initializes an already allocated connection failed exception. + * + * @param host The host to which the connection failed + * @param port The port on the host to which the connection failed + * @param socket The socket which could not connect + * @param errNo The errno of the error + * @return An initialized connection failed exception + */ +- initWithHost: (OFString*)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo; + /*! * @brief Returns the socket which could not connect. * * @return The socket which could not connect */ Index: src/exceptions/OFConnectionFailedException.m ================================================================== --- src/exceptions/OFConnectionFailedException.m +++ src/exceptions/OFConnectionFailedException.m @@ -17,21 +17,30 @@ #include "config.h" #import "OFConnectionFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFConnectionFailedException + (instancetype)exceptionWithHost: (OFString*)host port: (uint16_t)port socket: (id)socket { return [[[self alloc] initWithHost: host port: port socket: socket] autorelease]; } + ++ (instancetype)exceptionWithHost: (OFString*)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo +{ + return [[[self alloc] initWithHost: host + port: port + socket: socket + errNo: errNo] autorelease]; +} - init { OF_INVALID_INIT_METHOD } @@ -41,14 +50,33 @@ socket: (id)socket { self = [super init]; @try { - _host = [host copy]; + _host = [host copy]; + _socket = [socket retain]; + _port = port; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- initWithHost: (OFString*)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo +{ + self = [super init]; + + @try { + _host = [host copy]; _socket = [socket retain]; - _port = port; - _errNo = GET_SOCK_ERRNO; + _port = port; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -63,14 +91,20 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"A connection to %@ on port %" @PRIu16 @" could not be " - @"established in socket of type %@! " ERRFMT, _host, _port, - [_socket class], ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"A connection to %@ on port %" @PRIu16 @" could not be " + @"established in socket of type %@: %@", + _host, _port, [_socket class], of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"A connection to %@ on port %" @PRIu16 @" could not be " + @"established in socket of type %@!", + _host, _port, [_socket class]]; } - (OFString*)host { OF_GETTER(_host, true) @@ -86,12 +120,8 @@ OF_GETTER(_socket, true) } - (int)errNo { -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else return _errNo; -#endif } @end Index: src/exceptions/OFCopyItemFailedException.h ================================================================== --- src/exceptions/OFCopyItemFailedException.h +++ src/exceptions/OFCopyItemFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFCopyItemFailedException \ * OFCopyItemFailedException.h ObjFW/OFCopyItemFailedException.h @@ -39,24 +37,28 @@ /*! * @brief Creates a new, autoreleased copy item failed exception. * * @param sourcePath The original path * @param destinationPath The new path + * @param errNo The errno of the error * @return A new, autoreleased copy item failed exception */ + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Initializes an already allocated copy item failed exception. * * @param sourcePath The original path * @param destinationPath The new path + * @param errNo The errno of the error * @return An initialized copy item failed exception */ - initWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Returns the path of the source item. * * @return The path of the source item Index: src/exceptions/OFCopyItemFailedException.m ================================================================== --- src/exceptions/OFCopyItemFailedException.m +++ src/exceptions/OFCopyItemFailedException.m @@ -17,34 +17,35 @@ #include "config.h" #import "OFCopyItemFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFCopyItemFailedException + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { return [[[self alloc] initWithSourcePath: sourcePath - destinationPath: destinationPath] autorelease]; + destinationPath: destinationPath + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { self = [super init]; @try { _sourcePath = [sourcePath copy]; _destinationPath = [destinationPath copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -59,13 +60,18 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to copy item %@ to %@! " ERRFMT, _sourcePath, - _destinationPath, ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to copy item %@ to %@: %@", + _sourcePath, _destinationPath, of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to copy item %@ to %@!", + _sourcePath, _destinationPath]; } - (OFString*)sourcePath { OF_GETTER(_sourcePath, true) Index: src/exceptions/OFCreateDirectoryFailedException.h ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.h +++ src/exceptions/OFCreateDirectoryFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFCreateDirectoryFailedException \ * OFCreateDirectoryFailedException.h \ @@ -39,22 +37,26 @@ /*! * @brief Creates a new, autoreleased create directory failed exception. * * @param path A string with the path of the directory which could not be * created + * @param errNo The errno of the error * @return A new, autoreleased create directory failed exception */ -+ (instancetype)exceptionWithPath: (OFString*)path; ++ (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Initializes an already allocated create directory failed exception. * * @param path A string with the path of the directory which could not be * created + * @param errNo The errno of the error * @return An initialized create directory failed exception */ -- initWithPath: (OFString*)path; +- initWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Returns a string with the path of the directory which couldn't be * created. * Index: src/exceptions/OFCreateDirectoryFailedException.m ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.m +++ src/exceptions/OFCreateDirectoryFailedException.m @@ -17,30 +17,31 @@ #include "config.h" #import "OFCreateDirectoryFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFCreateDirectoryFailedException + (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo { - return [[[self alloc] initWithPath: path] autorelease]; + return [[[self alloc] initWithPath: path + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithPath: (OFString*)path + errNo: (int)errNo { self = [super init]; @try { _path = [path copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -55,11 +56,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to create directory %@! " ERRFMT, _path, ERRPARAM]; + @"Failed to create directory %@: %@", + _path, of_strerror(_errNo)]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFCreateSymbolicLinkFailedException.h ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.h +++ src/exceptions/OFCreateSymbolicLinkFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifdef OF_HAVE_SYMLINK /*! * @class OFCreateSymbolicLinkFailedException \ @@ -40,25 +38,29 @@ /*! * @brief Creates a new, autoreleased create symbolic link failed exception. * * @param sourcePath The source for the symbolic link * @param destinationPath The destination for the symbolic link + * @param errNo The errno of the error * @return A new, autoreleased create symbolic link failed exception */ + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Initializes an already allocated create symbolic link failed * exception. * * @param sourcePath The source for the symbolic link * @param destinationPath The destination for the symbolic link + * @param errNo The errno of the error * @return An initialized create symbolic link failed exception */ - initWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Returns a string with the source for the symlink. * * @return A string with the source for the symlink Index: src/exceptions/OFCreateSymbolicLinkFailedException.m ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.m +++ src/exceptions/OFCreateSymbolicLinkFailedException.m @@ -17,35 +17,36 @@ #include "config.h" #import "OFCreateSymbolicLinkFailedException.h" #import "OFString.h" -#import "common.h" - #ifdef OF_HAVE_SYMLINK @implementation OFCreateSymbolicLinkFailedException + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { return [[[self alloc] initWithSourcePath: sourcePath - destinationPath: destinationPath] autorelease]; + destinationPath: destinationPath + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { self = [super init]; @try { _sourcePath = [sourcePath copy]; _destinationPath = [destinationPath copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -61,12 +62,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to symlink file %@ to %@! " ERRFMT, _sourcePath, - _destinationPath, ERRPARAM]; + @"Failed to symlink file %@ to %@: %@", + _sourcePath, _destinationPath, of_strerror(_errNo)]; } - (OFString*)sourcePath { OF_GETTER(_sourcePath, true) Index: src/exceptions/OFEnumerationMutationException.m ================================================================== --- src/exceptions/OFEnumerationMutationException.m +++ src/exceptions/OFEnumerationMutationException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFEnumerationMutationException.h" #import "OFString.h" -#import "common.h" - @implementation OFEnumerationMutationException + (instancetype)exceptionWithObject: (id)object { return [[[self alloc] initWithObject: object] autorelease]; } Index: src/exceptions/OFException.h ================================================================== --- src/exceptions/OFException.h +++ src/exceptions/OFException.h @@ -164,5 +164,13 @@ * * @return A backtrace of when the exception was created */ - (OFArray*)backtrace; @end + +#ifdef __cplusplus +extern "C" { +#endif +extern OFString* of_strerror(int errNo); +#ifdef __cplusplus +} +#endif Index: src/exceptions/OFException.m ================================================================== --- src/exceptions/OFException.m +++ src/exceptions/OFException.m @@ -14,32 +14,40 @@ * file. */ #include "config.h" +#include #include #ifdef HAVE_DLFCN_H # include #endif #import "OFException.h" #import "OFString.h" #import "OFArray.h" +#import "OFSystemInfo.h" + +#import "OFInitializationFailedException.h" +#import "OFLockFailedException.h" +#import "OFUnlockFailedException.h" + +#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS) +# import "threading.h" +#endif #if defined(_WIN32) && defined(OF_HAVE_SOCKETS) -# include # include #endif /* * Define HAVE_DWARF_EXCEPTIONS if OBJC_ZEROCOST_EXCEPTIONS is defined, but - * don't do so on 32-bit ARM, as it is defined there even if SjLj exceptions - * are used. + * don't do so on iOS, as it is defined there even if SjLj exceptions are used. */ #ifndef HAVE_DWARF_EXCEPTIONS -# if defined(OBJC_ZEROCOST_EXCEPTIONS) && !defined(__ARMEL__) +# if defined(OBJC_ZEROCOST_EXCEPTIONS) && !defined(OF_IOS) # define HAVE_DWARF_EXCEPTIONS # endif #endif /* @@ -67,10 +75,137 @@ # if defined(__arm__) || defined(__ARM__) extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*); # else extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*); # endif + +#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS) +static of_mutex_t mutex; + +static void __attribute__((__constructor__)) +init(void) +{ + if (!of_mutex_new(&mutex)) + @throw [OFInitializationFailedException exception]; +} +#endif + +OFString* +of_strerror(int errNo) +{ + OFString *ret; +#ifdef HAVE_STRERROR_R + char buffer[256]; +#endif + +#ifdef _WIN32 + /* + * These were translated from WSAE* errors to errno and thus Win32's + * strerror_r() does not know about them. + * + * FIXME: These could have better descriptions! + */ + switch (errNo) { + case EADDRINUSE: + return @"EADDRINUSE"; + case EADDRNOTAVAIL: + return @"EADDRNOTAVAIL"; + case EAFNOSUPPORT: + return @"EAFNOSUPPORT"; + case EALREADY: + return @"EALREADY"; + case ECONNABORTED: + return @"ECONNABORTED"; + case ECONNREFUSED: + return @"ECONNREFUSED"; + case ECONNRESET: + return @"ECONNRESET"; + case EDESTADDRREQ: + return @"EDESTADDRREQ"; + case EDQUOT: + return @"EDQUOT"; + case EHOSTDOWN: + return @"EHOSTDOWN"; + case EHOSTUNREACH: + return @"EHOSTUNREACH"; + case EINPROGRESS: + return @"EINPROGRESS"; + case EISCONN: + return @"EISCONN"; + case ELOOP: + return @"ELOOP"; + case EMSGSIZE: + return @"EMSGSIZE"; + case ENETDOWN: + return @"ENETDOWN"; + case ENETRESET: + return @"ENETRESET"; + case ENETUNREACH: + return @"ENETUNREACH"; + case ENOBUFS: + return @"ENOBUFS"; + case ENOPROTOOPT: + return @"ENOPROTOOPT"; + case ENOTCONN: + return @"ENOTCONN"; + case ENOTSOCK: + return @"ENOTSOCK"; + case EOPNOTSUPP: + return @"EOPNOTSUPP"; + case EPFNOSUPPORT: + return @"EPFNOSUPPORT"; + case EPROCLIM: + return @"EPROCLIM"; + case EPROTONOSUPPORT: + return @"EPROTONOSUPPORT"; + case EPROTOTYPE: + return @"EPROTOTYPE"; + case EREMOTE: + return @"EREMOTE"; + case ESHUTDOWN: + return @"ESHUTDOWN"; + case ESOCKTNOSUPPORT: + return @"ESOCKTNOSUPPORT"; + case ESTALE: + return @"ESTALE"; + case ETIMEDOUT: + return @"ETIMEDOUT"; + case ETOOMANYREFS: + return @"ETOOMANYREFS"; + case EUSERS: + return @"EUSERS"; + case EWOULDBLOCK: + return @"EWOULDBLOCK"; + } +#endif + +#ifdef HAVE_STRERROR_R + if (strerror_r(errNo, buffer, 256) != 0) + return @"Unknown error (strerror_r failed)"; + + ret = [OFString stringWithCString: buffer + encoding: [OFSystemInfo native8BitEncoding]]; +#else +# ifdef OF_HAVE_THREADS + if (!of_mutex_lock(&mutex)) + @throw [OFLockFailedException exception]; + + @try { +# endif + ret = [OFString + stringWithCString: strerror(errNo) + encoding: [OFSystemInfo native8BitEncoding]]; +# ifdef OF_HAVE_THREADS + } @finally { + if (!of_mutex_unlock(&mutex)) + @throw [OFUnlockFailedException exception]; + } +# endif +#endif + + return ret; +} static _Unwind_Reason_Code backtrace_callback(struct _Unwind_Context *ctx, void *data) { struct backtrace_ctx *bt = data; @@ -87,107 +222,10 @@ return _URC_OK; } return _URC_END_OF_STACK; } -#endif - -#if defined(_WIN32) && defined(OF_HAVE_SOCKETS) -int -of_wsaerr_to_errno(int wsaerr) -{ - switch (wsaerr) { - case WSAEACCES: - return EACCES; - case WSAEADDRINUSE: - return EADDRINUSE; - case WSAEADDRNOTAVAIL: - return EADDRNOTAVAIL; - case WSAEAFNOSUPPORT: - return EAFNOSUPPORT; - case WSAEALREADY: - return EALREADY; - case WSAEBADF: - return EBADF; - case WSAECONNABORTED: - return ECONNABORTED; - case WSAECONNREFUSED: - return ECONNREFUSED; - case WSAECONNRESET: - return ECONNRESET; - case WSAEDESTADDRREQ: - return EDESTADDRREQ; - case WSAEDISCON: - return EPIPE; - case WSAEDQUOT: - return EDQUOT; - case WSAEFAULT: - return EFAULT; - case WSAEHOSTDOWN: - return EHOSTDOWN; - case WSAEHOSTUNREACH: - return EHOSTUNREACH; - case WSAEINPROGRESS: - return EINPROGRESS; - case WSAEINTR: - return EINTR; - case WSAEINVAL: - return EINVAL; - case WSAEISCONN: - return EISCONN; - case WSAELOOP: - return ELOOP; - case WSAEMSGSIZE: - return EMSGSIZE; - case WSAENAMETOOLONG: - return ENAMETOOLONG; - case WSAENETDOWN: - return ENETDOWN; - case WSAENETRESET: - return ENETRESET; - case WSAENETUNREACH: - return ENETUNREACH; - case WSAENOBUFS: - return ENOBUFS; - case WSAENOPROTOOPT: - return ENOPROTOOPT; - case WSAENOTCONN: - return ENOTCONN; - case WSAENOTEMPTY: - return ENOTEMPTY; - case WSAENOTSOCK: - return ENOTSOCK; - case WSAEOPNOTSUPP: - return EOPNOTSUPP; - case WSAEPFNOSUPPORT: - return EPFNOSUPPORT; - case WSAEPROCLIM: - return EPROCLIM; - case WSAEPROTONOSUPPORT: - return EPROTONOSUPPORT; - case WSAEPROTOTYPE: - return EPROTOTYPE; - case WSAEREMOTE: - return EREMOTE; - case WSAESHUTDOWN: - return ESHUTDOWN; - case WSAESOCKTNOSUPPORT: - return ESOCKTNOSUPPORT; - case WSAESTALE: - return ESTALE; - case WSAETIMEDOUT: - return ETIMEDOUT; - case WSAETOOMANYREFS: - return ETOOMANYREFS; - case WSAEUSERS: - return EUSERS; - case WSAEWOULDBLOCK: - return EWOULDBLOCK; - default: - return wsaerr; - } -} #endif @implementation OFException + (instancetype)exception { Index: src/exceptions/OFHTTPRequestFailedException.m ================================================================== --- src/exceptions/OFHTTPRequestFailedException.m +++ src/exceptions/OFHTTPRequestFailedException.m @@ -19,12 +19,10 @@ #import "OFHTTPRequestFailedException.h" #import "OFString.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" -#import "common.h" - @implementation OFHTTPRequestFailedException + (instancetype)exceptionWithRequest: (OFHTTPRequest*)request response: (OFHTTPResponse*)response { return [[[self alloc] initWithRequest: request Index: src/exceptions/OFHashAlreadyCalculatedException.m ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.m +++ src/exceptions/OFHashAlreadyCalculatedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFHashAlreadyCalculatedException.h" #import "OFString.h" -#import "common.h" - @implementation OFHashAlreadyCalculatedException + (instancetype)exceptionWithHash: (id )hash { return [[[self alloc] initWithHash: hash] autorelease]; } Index: src/exceptions/OFInitializationFailedException.m ================================================================== --- src/exceptions/OFInitializationFailedException.m +++ src/exceptions/OFInitializationFailedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFInitializationFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFInitializationFailedException + (instancetype)exceptionWithClass: (Class)class { return [[[self alloc] initWithClass: class] autorelease]; } Index: src/exceptions/OFLinkFailedException.h ================================================================== --- src/exceptions/OFLinkFailedException.h +++ src/exceptions/OFLinkFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifdef OF_HAVE_LINK /*! * @class OFLinkFailedException \ @@ -39,24 +37,28 @@ /*! * @brief Creates a new, autoreleased link failed exception. * * @param sourcePath The source for the link * @param destinationPath The destination for the link + * @param errNo The errno of the error * @return A new, autoreleased link failed exception */ + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Initializes an already allocated link failed exception. * * @param sourcePath The source for the link * @param destinationPath The destination for the link + * @param errNo The errno of the error * @return An initialized link failed exception */ - initWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Returns a string with the source for the link. * * @return A string with the source for the link Index: src/exceptions/OFLinkFailedException.m ================================================================== --- src/exceptions/OFLinkFailedException.m +++ src/exceptions/OFLinkFailedException.m @@ -17,35 +17,36 @@ #include "config.h" #import "OFLinkFailedException.h" #import "OFString.h" -#import "common.h" - #ifdef OF_HAVE_LINK @implementation OFLinkFailedException + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { return [[[self alloc] initWithSourcePath: sourcePath - destinationPath: destinationPath] autorelease]; + destinationPath: destinationPath + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { self = [super init]; @try { _sourcePath = [sourcePath copy]; _destinationPath = [destinationPath copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -61,12 +62,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to link file %@ to %@! " ERRFMT, _sourcePath, - _destinationPath, ERRPARAM]; + @"Failed to link file %@ to %@: %@", + _sourcePath, _destinationPath, of_strerror(_errNo)]; } - (OFString*)sourcePath { OF_GETTER(_sourcePath, true) Index: src/exceptions/OFListenFailedException.h ================================================================== --- src/exceptions/OFListenFailedException.h +++ src/exceptions/OFListenFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif @@ -42,24 +40,28 @@ /*! * @brief Creates a new, autoreleased listen failed exception. * * @param socket The socket which failed to listen * @param backLog The requested size of the back log + * @param errNo The errno of the error * @return A new, autoreleased listen failed exception */ + (instancetype)exceptionWithSocket: (id)socket - backLog: (int)backLog; + backLog: (int)backLog + errNo: (int)errNo; /*! * @brief Initializes an already allocated listen failed exception * * @param socket The socket which failed to listen * @param backLog The requested size of the back log + * @param errNo The errno of the error * @return An initialized listen failed exception */ - initWithSocket: (id)socket - backLog: (int)backLog; + backLog: (int)backLog + errNo: (int)errNo; /*! * @brief Returns the socket which failed to listen. * * @return The socket which failed to listen Index: src/exceptions/OFListenFailedException.m ================================================================== --- src/exceptions/OFListenFailedException.m +++ src/exceptions/OFListenFailedException.m @@ -17,33 +17,34 @@ #include "config.h" #import "OFListenFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFListenFailedException + (instancetype)exceptionWithSocket: (id)socket backLog: (int)backLog + errNo: (int)errNo { return [[[self alloc] initWithSocket: socket - backLog: backLog] autorelease]; + backLog: backLog + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSocket: (id)socket backLog: (int)backLog + errNo: (int)errNo { self = [super init]; - _socket = [socket retain]; + _socket = [socket retain]; _backLog = backLog; - _errNo = GET_SOCK_ERRNO; + _errNo = errNo; return self; } - (void)dealloc @@ -54,12 +55,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Failed to listen in socket of type %@ with a back log of %d! " - ERRFMT, [_socket class], _backLog, ERRPARAM]; + @"Failed to listen in socket of type %@ with a back log of %d: %@", + [_socket class], _backLog, of_strerror(_errNo)]; } - (id)socket { OF_GETTER(_socket, true) @@ -70,12 +71,8 @@ return _backLog; } - (int)errNo { -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else return _errNo; -#endif } @end Index: src/exceptions/OFLockFailedException.m ================================================================== --- src/exceptions/OFLockFailedException.m +++ src/exceptions/OFLockFailedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFLockFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFLockFailedException + (instancetype)exceptionWithLock: (id )lock { return [[[self alloc] initWithLock: lock] autorelease]; } Index: src/exceptions/OFMalformedXMLException.m ================================================================== --- src/exceptions/OFMalformedXMLException.m +++ src/exceptions/OFMalformedXMLException.m @@ -18,12 +18,10 @@ #import "OFMalformedXMLException.h" #import "OFString.h" #import "OFXMLParser.h" -#import "common.h" - @implementation OFMalformedXMLException + (instancetype)exceptionWithParser: (OFXMLParser*)parser { return [[[self alloc] initWithParser: parser] autorelease]; } Index: src/exceptions/OFMoveItemFailedException.h ================================================================== --- src/exceptions/OFMoveItemFailedException.h +++ src/exceptions/OFMoveItemFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFMoveItemFailedException \ * OFMoveItemFailedException.h ObjFW/OFMoveItemFailedException.h @@ -38,24 +36,28 @@ /*! * @brief Creates a new, autoreleased move item failed exception. * * @param sourcePath The original path * @param destinationPath The new path + * @param errNo The errno of the error * @return A new, autoreleased move item failed exception */ + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Initializes an already allocated move item failed exception. * * @param sourcePath The original path * @param destinationPath The new path + * @param errNo The errno of the error * @return An initialized move item failed exception */ - initWithSourcePath: (OFString*)sourcePath - destinationPath: (OFString*)destinationPath; + destinationPath: (OFString*)destinationPath + errNo: (int)errNo; /*! * @brief Returns the original path. * * @return The original path Index: src/exceptions/OFMoveItemFailedException.m ================================================================== --- src/exceptions/OFMoveItemFailedException.m +++ src/exceptions/OFMoveItemFailedException.m @@ -17,34 +17,35 @@ #include "config.h" #import "OFMoveItemFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFMoveItemFailedException + (instancetype)exceptionWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { return [[[self alloc] initWithSourcePath: sourcePath - destinationPath: destinationPath] autorelease]; + destinationPath: destinationPath + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithSourcePath: (OFString*)sourcePath destinationPath: (OFString*)destinationPath + errNo: (int)errNo { self = [super init]; @try { _sourcePath = [sourcePath copy]; _destinationPath = [destinationPath copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -59,13 +60,18 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to move item at path %@ to %@! " ERRFMT, _sourcePath, - _destinationPath, ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to move item at path %@ to %@: %@", + _sourcePath, _destinationPath, of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to move item at path %@ to %@!", + _sourcePath, _destinationPath]; } - (OFString*)sourcePath { OF_GETTER(_sourcePath, true) Index: src/exceptions/OFNotConnectedException.m ================================================================== --- src/exceptions/OFNotConnectedException.m +++ src/exceptions/OFNotConnectedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFNotConnectedException.h" #import "OFString.h" -#import "common.h" - @implementation OFNotConnectedException + (instancetype)exceptionWithSocket: (id)socket { return [[[self alloc] initWithSocket: socket] autorelease]; } Index: src/exceptions/OFNotImplementedException.m ================================================================== --- src/exceptions/OFNotImplementedException.m +++ src/exceptions/OFNotImplementedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFNotImplementedException.h" #import "OFString.h" -#import "common.h" - @implementation OFNotImplementedException + (instancetype)exceptionWithSelector: (SEL)selector object: (id)object { return [[[self alloc] initWithSelector: selector Index: src/exceptions/OFOpenFileFailedException.h ================================================================== --- src/exceptions/OFOpenFileFailedException.h +++ src/exceptions/OFOpenFileFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFOpenFileFailedException \ * OFOpenFileFailedException.h ObjFW/OFOpenFileFailedException.h @@ -43,10 +41,22 @@ * @return A new, autoreleased open file failed exception */ + (instancetype)exceptionWithPath: (OFString*)path mode: (OFString*)mode; +/*! + * @brief Creates a new, autoreleased open file failed exception. + * + * @param path A string with the path of the file tried to open + * @param mode A string with the mode in which the file should have been opened + * @param errNo The errno of the error + * @return A new, autoreleased open file failed exception + */ ++ (instancetype)exceptionWithPath: (OFString*)path + mode: (OFString*)mode + errNo: (int)errNo; + /*! * @brief Initializes an already allocated open file failed exception. * * @param path A string with the path of the file which couldn't be opened * @param mode A string with the mode in which the file should have been opened @@ -53,10 +63,22 @@ * @return An initialized open file failed exception */ - initWithPath: (OFString*)path mode: (OFString*)mode; +/*! + * @brief Initializes an already allocated open file failed exception. + * + * @param path A string with the path of the file which couldn't be opened + * @param mode A string with the mode in which the file should have been opened + * @param errNo The errno of the error + * @return An initialized open file failed exception + */ +- initWithPath: (OFString*)path + mode: (OFString*)mode + errNo: (int)errNo; + /*! * @brief Returns a string with the path of the file which couldn't be opened. * * @return A string with the path of the file which couldn't be opened */ Index: src/exceptions/OFOpenFileFailedException.m ================================================================== --- src/exceptions/OFOpenFileFailedException.m +++ src/exceptions/OFOpenFileFailedException.m @@ -17,19 +17,26 @@ #include "config.h" #import "OFOpenFileFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFOpenFileFailedException + (instancetype)exceptionWithPath: (OFString*)path mode: (OFString*)mode { return [[[self alloc] initWithPath: path mode: mode] autorelease]; } + ++ (instancetype)exceptionWithPath: (OFString*)path + mode: (OFString*)mode + errNo: (int)errNo +{ + return [[[self alloc] initWithPath: path + mode: mode + errNo: errNo] autorelease]; +} - init { OF_INVALID_INIT_METHOD } @@ -40,11 +47,28 @@ self = [super init]; @try { _path = [path copy]; _mode = [mode copy]; - _errNo = GET_ERRNO; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- initWithPath: (OFString*)path + mode: (OFString*)mode + errNo: (int)errNo +{ + self = [super init]; + + @try { + _path = [path copy]; + _mode = [mode copy]; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -59,13 +83,18 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to open file %@ with mode %@! " ERRFMT, _path, _mode, - ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to open file %@ with mode %@: %@", + _path, _mode, of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to open file %@ with mode %@!", + _path, _mode]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFReadFailedException.m ================================================================== --- src/exceptions/OFReadFailedException.m +++ src/exceptions/OFReadFailedException.m @@ -17,15 +17,18 @@ #include "config.h" #import "OFReadFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFReadFailedException - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to read %zu bytes from an object of type %@! " ERRFMT, - _requestedLength, [_object class], ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to read %zu bytes from an object of type %@: %@", + _requestedLength, [_object class], of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to read %zu bytes from an object of type %@!", + _requestedLength, [_object class]]; } @end Index: src/exceptions/OFReadOrWriteFailedException.h ================================================================== --- src/exceptions/OFReadOrWriteFailedException.h +++ src/exceptions/OFReadOrWriteFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFReadOrWriteFailedException \ * OFReadOrWriteFailedException.h ObjFW/OFReadOrWriteFailedException.h @@ -27,11 +25,10 @@ */ @interface OFReadOrWriteFailedException: OFException { id _object; size_t _requestedLength; -@public int _errNo; } #ifdef OF_HAVE_PROPERTIES @property (readonly, retain) id object; @@ -48,10 +45,23 @@ * @return A new, autoreleased read or write failed exception */ + (instancetype)exceptionWithObject: (id)object requestedLength: (size_t)requestedLength; +/*! + * @brief Creates a new, autoreleased read or write failed exception. + * + * @param object The object from which reading or to which writing failed + * @param requestedLength The requested length of the data that couldn't be + * read / written + * @param errNo The errno of the error + * @return A new, autoreleased read or write failed exception + */ ++ (instancetype)exceptionWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo; + /*! * @brief Initializes an already allocated read or write failed exception. * * @param object The object from which reading or to which writing failed * @param requestedLength The requested length of the data that couldn't be @@ -59,10 +69,23 @@ * @return A new open file failed exception */ - initWithObject: (id)object requestedLength: (size_t)requestedLength; +/*! + * @brief Initializes an already allocated read or write failed exception. + * + * @param object The object from which reading or to which writing failed + * @param requestedLength The requested length of the data that couldn't be + * read / written + * @param errNo The errno of the error + * @return A new open file failed exception + */ +- initWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo; + /*! * @brief Returns the object from which reading or to which writing failed * * @return The stream which caused the read or write failed exception */ Index: src/exceptions/OFReadOrWriteFailedException.m ================================================================== --- src/exceptions/OFReadOrWriteFailedException.m +++ src/exceptions/OFReadOrWriteFailedException.m @@ -16,24 +16,27 @@ #include "config.h" #import "OFReadOrWriteFailedException.h" #import "OFString.h" -#ifdef OF_HAVE_SOCKETS -# import "OFStreamSocket.h" -# import "OFUDPSocket.h" -#endif - -#import "common.h" @implementation OFReadOrWriteFailedException + (instancetype)exceptionWithObject: (id)object requestedLength: (size_t)requestedLength { return [[[self alloc] initWithObject: object requestedLength: requestedLength] autorelease]; } + ++ (instancetype)exceptionWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo +{ + return [[[self alloc] initWithObject: object + requestedLength: requestedLength + errNo: errNo] autorelease]; +} - init { OF_INVALID_INIT_METHOD } @@ -44,17 +47,22 @@ self = [super init]; _object = [object retain]; _requestedLength = requestedLength; -#ifdef OF_HAVE_SOCKETS - if ([object isKindOfClass: [OFStreamSocket class]] || - [object isKindOfClass: [OFUDPSocket class]]) - _errNo = GET_SOCK_ERRNO; - else -#endif - _errNo = GET_ERRNO; + return self; +} + +- initWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo +{ + self = [super init]; + + _object = [object retain]; + _requestedLength = requestedLength; + _errNo = errNo; return self; } - (void)dealloc @@ -64,13 +72,20 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to read or write %zu bytes from / to an object of type " - @"%@! " ERRFMT, _requestedLength, [_object class], ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to read or write %zu bytes from / to an object of " + @"type %@: %@", + _requestedLength, [_object class], of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to read or write %zu bytes from / to an object of " + @"type %@!", + _requestedLength, [_object class]]; } - (id)object { OF_GETTER(_object, true) @@ -81,12 +96,8 @@ return _requestedLength; } - (int)errNo { -#ifdef _WIN32 - return of_wsaerr_to_errno(_errNo); -#else return _errNo; -#endif } @end Index: src/exceptions/OFRemoveItemFailedException.h ================================================================== --- src/exceptions/OFRemoveItemFailedException.h +++ src/exceptions/OFRemoveItemFailedException.h @@ -12,12 +12,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include - #import "OFException.h" /*! * @class OFRemoveItemFailedException \ * OFRemoveItemFailedException.h ObjFW/OFRemoveItemFailedException.h @@ -37,21 +35,25 @@ /*! * @brief Creates a new, autoreleased remove failed exception. * * @param path The path of the item which could not be removed + * @param errNo The errno of the error * @return A new, autoreleased remove item failed exception */ -+ (instancetype)exceptionWithPath: (OFString*)path; ++ (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Initializes an already allocated remove failed exception. * * @param path The path of the item which could not be removed + * @param errNo The errno of the error * @return An initialized remove item failed exception */ -- initWithPath: (OFString*)path; +- initWithPath: (OFString*)path + errNo: (int)errNo; /*! * @brief Returns the path of the item which could not be removed. * * @return The path of the item which could not be removed Index: src/exceptions/OFRemoveItemFailedException.m ================================================================== --- src/exceptions/OFRemoveItemFailedException.m +++ src/exceptions/OFRemoveItemFailedException.m @@ -17,30 +17,31 @@ #include "config.h" #import "OFRemoveItemFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFRemoveItemFailedException + (instancetype)exceptionWithPath: (OFString*)path + errNo: (int)errNo { - return [[[self alloc] initWithPath: path] autorelease]; + return [[[self alloc] initWithPath: path + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithPath: (OFString*)path + errNo: (int)errNo { self = [super init]; @try { _path = [path copy]; - _errNo = GET_ERRNO; + _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -54,12 +55,17 @@ [super dealloc]; } - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to remove item at path %@! " ERRFMT, _path, ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to remove item at path %@: %@", + _path, of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to remove item at path %@!", _path]; } - (OFString*)path { OF_GETTER(_path, true) Index: src/exceptions/OFSeekFailedException.h ================================================================== --- src/exceptions/OFSeekFailedException.h +++ src/exceptions/OFSeekFailedException.h @@ -40,27 +40,31 @@ * @brief Creates a new, autoreleased seek failed exception. * * @param stream The stream for which seeking failed * @param offset The offset to which seeking failed * @param whence To what the offset is relative + * @param errNo The errno of the error * @return A new, autoreleased seek failed exception */ + (instancetype)exceptionWithStream: (OFSeekableStream*)stream offset: (of_offset_t)offset - whence: (int)whence; + whence: (int)whence + errNo: (int)errNo; /*! * @brief Initializes an already allocated seek failed exception. * * @param stream The stream for which seeking failed * @param offset The offset to which seeking failed * @param whence To what the offset is relative + * @param errNo The errno of the error * @return An initialized seek failed exception */ - initWithStream: (OFSeekableStream*)stream offset: (of_offset_t)offset - whence: (int)whence; + whence: (int)whence + errNo: (int)errNo; /*! * @brief Returns the stream for which seeking failed. * * @return The stream for which seeking failed Index: src/exceptions/OFSeekFailedException.m ================================================================== --- src/exceptions/OFSeekFailedException.m +++ src/exceptions/OFSeekFailedException.m @@ -18,20 +18,20 @@ #import "OFSeekFailedException.h" #import "OFString.h" #import "OFSeekableStream.h" -#import "common.h" - @implementation OFSeekFailedException + (instancetype)exceptionWithStream: (OFSeekableStream*)stream offset: (of_offset_t)offset whence: (int)whence + errNo: (int)errNo { return [[[self alloc] initWithStream: stream offset: offset - whence: whence] autorelease]; + whence: whence + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD @@ -38,17 +38,18 @@ } - initWithStream: (OFSeekableStream*)stream offset: (of_offset_t)offset whence: (int)whence + errNo: (int)errNo { self = [super init]; _stream = [stream retain]; _offset = offset; _whence = whence; - _errNo = GET_ERRNO; + _errNo = errNo; return self; } - (void)dealloc @@ -59,12 +60,12 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Seeking failed in stream of type %@! " ERRFMT, [_stream class], - ERRPARAM]; + @"Seeking failed in stream of type %@: %@", + [_stream class], of_strerror(_errNo)]; } - (OFSeekableStream*)stream { OF_GETTER(_stream, true) Index: src/exceptions/OFSetOptionFailedException.h ================================================================== --- src/exceptions/OFSetOptionFailedException.h +++ src/exceptions/OFSetOptionFailedException.h @@ -25,34 +25,47 @@ * @brief An exception indicating that setting an option for a stream failed. */ @interface OFSetOptionFailedException: OFException { OFStream *_stream; + int _errNo; } #ifdef OF_HAVE_PROPERTIES @property (readonly, retain) OFStream *stream; +@property (readonly) int errNo; #endif /*! * @brief Creates a new, autoreleased set option failed exception. * * @param stream The stream for which the option could not be set + * @param errNo The errno of the error * @return A new, autoreleased set option failed exception */ -+ (instancetype)exceptionWithStream: (OFStream*)stream; ++ (instancetype)exceptionWithStream: (OFStream*)stream + errNo: (int)errNo; /*! * @brief Initializes an already allocated set option failed exception. * * @param stream The stream for which the option could not be set + * @param errNo The errno of the error * @return An initialized set option failed exception */ -- initWithStream: (OFStream*)stream; +- initWithStream: (OFStream*)stream + errNo: (int)errNo; /*! * @brief Returns the stream for which the option could not be set. * * @return The stream for which the option could not be set */ - (OFStream*)stream; + +/*! + * @brief Returns the errno from when the exception was created. + * + * @return The errno from when the exception was created + */ +- (int)errNo; @end Index: src/exceptions/OFSetOptionFailedException.m ================================================================== --- src/exceptions/OFSetOptionFailedException.m +++ src/exceptions/OFSetOptionFailedException.m @@ -18,28 +18,30 @@ #import "OFSetOptionFailedException.h" #import "OFString.h" #import "OFStream.h" -#import "common.h" - @implementation OFSetOptionFailedException + (instancetype)exceptionWithStream: (OFStream*)stream + errNo: (int)errNo { - return [[[self alloc] initWithStream: stream] autorelease]; + return [[[self alloc] initWithStream: stream + errNo: errNo] autorelease]; } - init { OF_INVALID_INIT_METHOD } - initWithStream: (OFStream*)stream + errNo: (int)errNo { self = [super init]; _stream = [stream retain]; + _errNo = errNo; return self; } - (void)dealloc @@ -50,14 +52,19 @@ } - (OFString*)description { return [OFString stringWithFormat: - @"Setting an option in a stream of type %@ failed!", - [_stream class]]; + @"Setting an option in a stream of type %@ failed: %@", + [_stream class], of_strerror(_errNo)]; } - (OFStream*)stream { OF_GETTER(_stream, true) } + +- (int)errNo +{ + return _errNo; +} @end Index: src/exceptions/OFStillLockedException.m ================================================================== --- src/exceptions/OFStillLockedException.m +++ src/exceptions/OFStillLockedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFStillLockedException.h" #import "OFString.h" -#import "common.h" - @implementation OFStillLockedException + (instancetype)exceptionWithLock: (id )lock { return [[[self alloc] initWithLock: lock] autorelease]; } Index: src/exceptions/OFUnboundNamespaceException.m ================================================================== --- src/exceptions/OFUnboundNamespaceException.m +++ src/exceptions/OFUnboundNamespaceException.m @@ -18,12 +18,10 @@ #import "OFUnboundNamespaceException.h" #import "OFString.h" #import "OFXMLElement.h" -#import "common.h" - @implementation OFUnboundNamespaceException + (instancetype)exceptionWithNamespace: (OFString*)namespace element: (OFXMLElement*)element { return [[[self alloc] initWithNamespace: namespace Index: src/exceptions/OFUnboundPrefixException.m ================================================================== --- src/exceptions/OFUnboundPrefixException.m +++ src/exceptions/OFUnboundPrefixException.m @@ -18,12 +18,10 @@ #import "OFUnboundPrefixException.h" #import "OFString.h" #import "OFXMLParser.h" -#import "common.h" - @implementation OFUnboundPrefixException + (instancetype)exceptionWithPrefix: (OFString*)prefix parser: (OFXMLParser*)parser { return [[[self alloc] initWithPrefix: prefix Index: src/exceptions/OFUnknownXMLEntityException.m ================================================================== --- src/exceptions/OFUnknownXMLEntityException.m +++ src/exceptions/OFUnknownXMLEntityException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFUnknownXMLEntityException.h" #import "OFString.h" -#import "common.h" - @implementation OFUnknownXMLEntityException + (instancetype)exceptionWithEntityName: (OFString*)entityName { return [[[self alloc] initWithEntityName: entityName] autorelease]; } Index: src/exceptions/OFUnlockFailedException.m ================================================================== --- src/exceptions/OFUnlockFailedException.m +++ src/exceptions/OFUnlockFailedException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFUnlockFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFUnlockFailedException + (instancetype)exceptionWithLock: (id )lock { return [[[self alloc] initWithLock: lock] autorelease]; } Index: src/exceptions/OFUnsupportedProtocolException.m ================================================================== --- src/exceptions/OFUnsupportedProtocolException.m +++ src/exceptions/OFUnsupportedProtocolException.m @@ -18,12 +18,10 @@ #import "OFUnsupportedProtocolException.h" #import "OFString.h" #import "OFURL.h" -#import "common.h" - @implementation OFUnsupportedProtocolException + (instancetype)exceptionWithURL: (OFURL*)url { return [[[self alloc] initWithURL: url] autorelease]; } Index: src/exceptions/OFUnsupportedVersionException.m ================================================================== --- src/exceptions/OFUnsupportedVersionException.m +++ src/exceptions/OFUnsupportedVersionException.m @@ -17,12 +17,10 @@ #include "config.h" #import "OFUnsupportedVersionException.h" #import "OFString.h" -#import "common.h" - @implementation OFUnsupportedVersionException + (instancetype)exceptionWithVersion: (OFString*)version { return [[[self alloc] initWithVersion: version] autorelease]; } Index: src/exceptions/OFWriteFailedException.m ================================================================== --- src/exceptions/OFWriteFailedException.m +++ src/exceptions/OFWriteFailedException.m @@ -17,15 +17,18 @@ #include "config.h" #import "OFWriteFailedException.h" #import "OFString.h" -#import "common.h" - @implementation OFWriteFailedException - (OFString*)description { - return [OFString stringWithFormat: - @"Failed to write %zu bytes to an object of type %@! " ERRFMT, - _requestedLength, [_object class], ERRPARAM]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to write %zu bytes to an object of type %@: %@", + _requestedLength, [_object class], of_strerror(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to write %zu bytes to an object of type %@!", + _requestedLength, [_object class]]; } @end DELETED src/exceptions/common.h Index: src/exceptions/common.h ================================================================== --- src/exceptions/common.h +++ src/exceptions/common.h @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include -#include - -#ifdef OF_HAVE_SOCKETS -# include "socket.h" -# include "socket_helpers.h" -#endif - -#ifndef _WIN32 -# define GET_ERRNO errno -# ifdef OF_HAVE_SOCKETS -# if !defined(HAVE_GETADDRINFO) && defined(HAVE_H_ERRNO) -# define GET_AT_ERRNO h_errno -# else -# define GET_AT_ERRNO errno -# endif -# define GET_SOCK_ERRNO errno -# endif -# define ERRFMT @"Error description: %s" -# define ERRPARAM strerror(_errNo) -# ifdef OF_HAVE_SOCKETS -# if !defined(HAVE_GETADDRINFO) && defined(HAVE_HSTRERROR) -# define AT_ERRPARAM hstrerror(_errNo) -# else -# define AT_ERRPARAM strerror(_errNo) -# endif -# endif -#else -# include -# define GET_ERRNO GetLastError() -# ifdef OF_HAVE_SOCKETS -# define GET_AT_ERRNO WSAGetLastError() -# define GET_SOCK_ERRNO WSAGetLastError() -# endif -# define ERRFMT @"Error code: %d" -# define ERRPARAM _errNo -# ifdef OF_HAVE_SOCKETS -# define AT_ERRPARAM _errNo -# endif -#endif Index: src/resolver.m ================================================================== --- src/resolver.m +++ src/resolver.m @@ -25,11 +25,11 @@ #import "macros.h" #import "resolver.h" #if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) -# include "OFMutex.h" +# include "threading.h" #endif #import "OFAddressTranslationFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" @@ -72,13 +72,17 @@ if (!of_mutex_lock(&mutex)) @throw [OFLockFailedException exception]; @try { # endif - if (getaddrinfo([host UTF8String], portCString, &hints, &res0)) + int error; + + if ((error = getaddrinfo([host UTF8String], portCString, &hints, + &res0)) != 0) @throw [OFAddressTranslationFailedException - exceptionWithHost: host]; + exceptionWithHost: host + error: error]; count = 0; for (res = res0; res != NULL; res = res->ai_next) count++; @@ -89,20 +93,20 @@ } if ((ret = calloc(count + 1, sizeof(*ret))) == NULL) { freeaddrinfo(res0); @throw [OFOutOfMemoryException - exceptionWithRequestedSize: - (count + 1) * sizeof(*ret)]; + exceptionWithRequestedSize: (count + 1) * + sizeof(*ret)]; } if ((results = malloc(count * sizeof(*results))) == NULL) { freeaddrinfo(res0); free(ret); @throw [OFOutOfMemoryException - exceptionWithRequestedSize: - count * sizeof(*results)]; + exceptionWithRequestedSize: count * + sizeof(*results)]; } for (retIter = ret, resultsIter = results, res = res0; res != NULL; retIter++, resultsIter++, res = res->ai_next) { resultsIter->family = res->ai_family; @@ -178,11 +182,12 @@ } if ((he = gethostbyname([host UTF8String])) == NULL || he->h_addrtype != AF_INET) @throw [OFAddressTranslationFailedException - exceptionWithHost: host]; + exceptionWithHost: host + error: h_errno]; count = 0; for (ip = he->h_addr_list; *ip != NULL; ip++) count++; @@ -190,18 +195,18 @@ @throw [OFAddressTranslationFailedException exceptionWithHost: host]; if ((ret = calloc(count + 1, sizeof(*ret))) == NULL) @throw [OFOutOfMemoryException - exceptionWithRequestedSize: - (count + 1) * sizeof(*ret)]; + exceptionWithRequestedSize: (count + 1) * + sizeof(*ret)]; if ((results = malloc(count * sizeof(*results))) == NULL) { free(ret); @throw [OFOutOfMemoryException - exceptionWithRequestedSize: - count * sizeof(*results)]; + exceptionWithRequestedSize: count * + sizeof(*results)]; } if ((addrs = calloc(count, sizeof(*addrs))) == NULL) { free(ret); free(results); @@ -251,14 +256,18 @@ if (!of_mutex_lock(&mutex)) @throw [OFLockFailedException exception]; @try { # endif + int error; + /* FIXME: Add NI_DGRAM for UDP? */ - if (getnameinfo(address, addressLength, hostCString, NI_MAXHOST, - portCString, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV)) - @throw [OFAddressTranslationFailedException exception]; + if ((error = getnameinfo(address, addressLength, hostCString, + NI_MAXHOST, portCString, NI_MAXSERV, + NI_NUMERICHOST | NI_NUMERICSERV)) != 0) + @throw [OFAddressTranslationFailedException + exceptionWithError: error]; if (host != NULL) *host = [OFString stringWithUTF8String: hostCString]; if (port != NULL) { @@ -293,11 +302,12 @@ @try { # endif if ((hostCString = inet_ntoa( ((struct sockaddr_in*)(void*)address)->sin_addr)) == NULL) - @throw [OFAddressTranslationFailedException exception]; + @throw [OFAddressTranslationFailedException + exceptionWithError: h_errno]; if (host != NULL) *host = [OFString stringWithUTF8String: hostCString]; if (port != NULL) Index: src/socket.h ================================================================== --- src/socket.h +++ src/socket.h @@ -64,6 +64,13 @@ struct in_addr ss_data2; int8_t ss_data3[8]; }; #endif -extern bool of_init_sockets(void); +#ifdef __cplusplus +extern "C" { +#endif +extern bool of_socket_init(void); +extern int of_socket_errno(void); +#ifdef __cplusplus +} +#endif Index: src/socket.m ================================================================== --- src/socket.m +++ src/socket.m @@ -14,10 +14,15 @@ * file. */ #include "config.h" +#include + +/* For some E* -> WSAE* defines */ +#import "OFException.h" + #import "socket.h" #ifdef OF_HAVE_THREADS # include "threading.h" static of_once_t onceControl = OF_ONCE_INIT; @@ -39,11 +44,11 @@ initialized = true; } bool -of_init_sockets() +of_socket_init() { #ifdef OF_HAVE_THREADS of_once(&onceControl, init); #else if (!initialized) @@ -50,5 +55,104 @@ init(); #endif return initialized; } + +int +of_socket_errno() +{ +#ifndef _WIN32 + return errno; +#else + switch (WSAGetLastError()) { + case WSAEACCES: + return EACCES; + case WSAEADDRINUSE: + return EADDRINUSE; + case WSAEADDRNOTAVAIL: + return EADDRNOTAVAIL; + case WSAEAFNOSUPPORT: + return EAFNOSUPPORT; + case WSAEALREADY: + return EALREADY; + case WSAEBADF: + return EBADF; + case WSAECONNABORTED: + return ECONNABORTED; + case WSAECONNREFUSED: + return ECONNREFUSED; + case WSAECONNRESET: + return ECONNRESET; + case WSAEDESTADDRREQ: + return EDESTADDRREQ; + case WSAEDISCON: + return EPIPE; + case WSAEDQUOT: + return EDQUOT; + case WSAEFAULT: + return EFAULT; + case WSAEHOSTDOWN: + return EHOSTDOWN; + case WSAEHOSTUNREACH: + return EHOSTUNREACH; + case WSAEINPROGRESS: + return EINPROGRESS; + case WSAEINTR: + return EINTR; + case WSAEINVAL: + return EINVAL; + case WSAEISCONN: + return EISCONN; + case WSAELOOP: + return ELOOP; + case WSAEMSGSIZE: + return EMSGSIZE; + case WSAENAMETOOLONG: + return ENAMETOOLONG; + case WSAENETDOWN: + return ENETDOWN; + case WSAENETRESET: + return ENETRESET; + case WSAENETUNREACH: + return ENETUNREACH; + case WSAENOBUFS: + return ENOBUFS; + case WSAENOPROTOOPT: + return ENOPROTOOPT; + case WSAENOTCONN: + return ENOTCONN; + case WSAENOTEMPTY: + return ENOTEMPTY; + case WSAENOTSOCK: + return ENOTSOCK; + case WSAEOPNOTSUPP: + return EOPNOTSUPP; + case WSAEPFNOSUPPORT: + return EPFNOSUPPORT; + case WSAEPROCLIM: + return EPROCLIM; + case WSAEPROTONOSUPPORT: + return EPROTONOSUPPORT; + case WSAEPROTOTYPE: + return EPROTOTYPE; + case WSAEREMOTE: + return EREMOTE; + case WSAESHUTDOWN: + return ESHUTDOWN; + case WSAESOCKTNOSUPPORT: + return ESOCKTNOSUPPORT; + case WSAESTALE: + return ESTALE; + case WSAETIMEDOUT: + return ETIMEDOUT; + case WSAETOOMANYREFS: + return ETOOMANYREFS; + case WSAEUSERS: + return EUSERS; + case WSAEWOULDBLOCK: + return EWOULDBLOCK; + } + + return 0; +#endif +}