Index: src/OFPlugin.h ================================================================== --- src/OFPlugin.h +++ src/OFPlugin.h @@ -55,11 +55,12 @@ #ifdef __cplusplus extern "C" { #endif extern of_plugin_handle_t of_dlopen(OFString *path, int flags); extern void *of_dlsym(of_plugin_handle_t handle, const char *symbol); +extern OFString *of_dlerror(void); extern void of_dlclose(of_plugin_handle_t handle); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -27,11 +27,11 @@ #import "OFPlugin.h" #import "OFString.h" #import "OFLocalization.h" #import "OFInitializationFailedException.h" -#import "OFOpenItemFailedException.h" +#import "OFLoadPluginFailedException.h" typedef OFPlugin *(*init_plugin_t)(void); of_plugin_handle_t of_dlopen(OFString *path, int flags) @@ -64,10 +64,21 @@ dlclose(handle); #else FreeLibrary(handle); #endif } + +OFString * +of_dlerror(void) +{ +#ifndef OF_WINDOWS + return [OFString stringWithCString: dlerror() + encoding: [OFLocalization encoding]]; +#else + return nil; +#endif +} @implementation OFPlugin + (id)pluginFromFile: (OFString *)path { void *pool = objc_autoreleasePoolPush(); @@ -84,13 +95,13 @@ #else path = [path stringByAppendingString: @PLUGIN_SUFFIX]; #endif if ((handle = of_dlopen(path, OF_RTLD_LAZY)) == NULL) - @throw [OFOpenItemFailedException exceptionWithPath: path - mode: nil - errNo: 0]; + @throw [OFLoadPluginFailedException + exceptionWithPath: path + error: of_dlerror()]; objc_autoreleasePoolPop(pool); initPlugin = (init_plugin_t)(uintptr_t)of_dlsym(handle, "init_plugin"); if (initPlugin == (init_plugin_t)0 || (plugin = initPlugin()) == nil) { Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -153,10 +153,13 @@ #import "OFInvalidServerReplyException.h" #import "OFLinkFailedException.h" #ifdef OF_HAVE_SOCKETS # import "OFListenFailedException.h" #endif +#ifdef OF_HAVE_PLUGINS +# import "OFLoadPluginFailedException.h" +#endif #import "OFLockFailedException.h" #import "OFMalformedXMLException.h" #import "OFMemoryNotPartOfObjectException.h" #import "OFMoveItemFailedException.h" #import "OFNotImplementedException.h" Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -46,11 +46,12 @@ OFUnlockFailedException.m \ OFUnsupportedProtocolException.m \ OFUnsupportedVersionException.m \ OFWriteFailedException.m \ ${USE_SRCS_SOCKETS} \ - ${USE_SRCS_THREADS} + ${USE_SRCS_THREADS} \ + ${USE_SRCS_PLUGINS} SRCS_SOCKETS = OFAcceptFailedException.m \ OFAddressTranslationFailedException.m \ OFAlreadyConnectedException.m \ OFBindFailedException.m \ OFConnectionFailedException.m \ @@ -62,11 +63,12 @@ OFConditionStillWaitingException.m \ OFConditionWaitFailedException.m \ OFThreadJoinFailedException.m \ OFThreadStartFailedException.m \ OFThreadStillRunningException.m +SRCS_PLUGINS = OFLoadPluginFailedException.m INCLUDES = ${SRCS:.m=.h} include ../../buildsys.mk CPPFLAGS += -I. -I.. -I../.. -I../runtime ADDED src/exceptions/OFLoadPluginFailedException.h Index: src/exceptions/OFLoadPluginFailedException.h ================================================================== --- src/exceptions/OFLoadPluginFailedException.h +++ src/exceptions/OFLoadPluginFailedException.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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. + */ + +#import "OFException.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFLoadPluginFailedException \ + * OFLoadPluginFailedException.h ObjFW/OFLoadPluginFailedException.h + * + * @brief An exception indicating a plugin could not be loaded. + */ +@interface OFLoadPluginFailedException: OFException +{ + OFString *_path, *_Nullable _error; +} + +/*! + * @brief The path of the plugin which could not be loaded + */ +@property (readonly, nonatomic) OFString *path; + +/*! + * @brief The error why the plugin could not be loaded, as a string + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *error; + ++ (instancetype)exception OF_UNAVAILABLE; + +/*! + * @brief Creates a new, autoreleased load plugin failed exception. + * + * @param path The path of the plugin which could not be loaded + * @param error The error why the plugin could not be loaded, as a string + * @return A new, autoreleased load plugin failed exception + */ ++ (instancetype)exceptionWithPath: (OFString *)path + error: (nullable OFString *)error; + +- (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated load plugin failed exception. + * + * @param path The path of the plugin which could not be loaded + * @param error The error why the plugin could not be loaded, as a string + * @return An initialized load plugin failed exception + */ +- (instancetype)initWithPath: (OFString *)path + error: (nullable OFString *)error + OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFLoadPluginFailedException.m Index: src/exceptions/OFLoadPluginFailedException.m ================================================================== --- src/exceptions/OFLoadPluginFailedException.m +++ src/exceptions/OFLoadPluginFailedException.m @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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 "config.h" + +#import "OFLoadPluginFailedException.h" +#import "OFString.h" + +@implementation OFLoadPluginFailedException +@synthesize path = _path, error = _error; + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithPath: (OFString *)path + error: (OFString *)error +{ + return [[[self alloc] initWithPath: path + error: error] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithPath: (OFString *)path + error: (OFString *)error +{ + self = [super init]; + + @try { + _path = [path copy]; + _error = [error copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_path release]; + [_error release]; + + [super dealloc]; +} + +- (OFString *)description +{ + if (_error != nil) + return [OFString stringWithFormat: + @"Failed to load plugin %@: %@", _path, _error]; + else + return [OFString stringWithFormat: + @"Failed to load plugin: %@", _path]; +} +@end