in src/extensions/extension_manager/src/extension_manager.cpp [68:189]
ADUC_Result ExtensionManager::LoadExtensionLibrary(
const char* extensionName,
const char* extensionPath,
const char* extensionSubfolder,
const char* extensionRegFileName,
const char* requiredFunction,
int facilityCode,
int componentCode,
void** libHandle)
{
ADUC_Result result{ ADUC_GeneralResult_Failure };
ADUC_FileEntity entity = {};
SHAversion algVersion;
std::stringstream path;
path << extensionPath << "/" << extensionSubfolder << "/" << extensionRegFileName;
Log_Info("Loading extension '%s'. Reg file : %s", extensionName, path.str().c_str());
if (libHandle == nullptr)
{
Log_Error("Invalid argument(s).");
result.ExtendedResultCode = ADUC_ERC_EXTENSION_CREATE_FAILURE_INVALID_ARG(facilityCode, componentCode);
goto done;
}
// Try to find cached handler.
if (ExtensionManager::_libs.count(extensionName) > 0)
{
try
{
*libHandle = ExtensionManager::_libs.at(extensionName);
result.ResultCode = ADUC_Result_Success;
goto done;
}
catch (const std::exception& ex)
{
Log_Debug("An exception occurred: %s", ex.what());
}
catch (...)
{
Log_Debug("Unknown exception occurred while try to reuse '%s'", extensionName);
}
}
memset(&entity, 0, sizeof(entity));
if (!GetExtensionFileEntity(path.str().c_str(), &entity))
{
Log_Info("Failed to load extension from '%s'.", path.str().c_str());
result.ExtendedResultCode = ADUC_ERC_EXTENSION_CREATE_FAILURE_NOT_FOUND(facilityCode, componentCode);
goto done;
}
// Validate file hash.
if (!ADUC_HashUtils_GetShaVersionForTypeString(
ADUC_HashUtils_GetHashType(entity.Hash, entity.HashCount, 0), &algVersion))
{
Log_Error(
"FileEntity for %s has unsupported hash type %s",
entity.TargetFilename,
ADUC_HashUtils_GetHashType(entity.Hash, entity.HashCount, 0));
result.ExtendedResultCode = ADUC_ERC_EXTENSION_CREATE_FAILURE_VALIDATE(facilityCode, componentCode);
goto done;
}
if (!ADUC_HashUtils_IsValidFileHash(
entity.TargetFilename,
ADUC_HashUtils_GetHashValue(entity.Hash, entity.HashCount, 0),
algVersion,
true /* suppressErrorLog */))
{
Log_Error("Hash for %s is not valid", entity.TargetFilename);
result.ExtendedResultCode = ADUC_ERC_EXTENSION_CREATE_FAILURE_VALIDATE(facilityCode, componentCode);
goto done;
}
*libHandle = ADUCPAL_dlopen(entity.TargetFilename, RTLD_LAZY);
if (*libHandle == nullptr)
{
Log_Error("Cannot load handler file %s. %s.", entity.TargetFilename, ADUCPAL_dlerror());
result.ExtendedResultCode = ADUC_ERC_EXTENSION_CREATE_FAILURE_LOAD(facilityCode, componentCode);
goto done;
}
ADUCPAL_dlerror(); // Clear any existing error
// Only check whether required function exist, if specified.
if (requiredFunction != nullptr && *requiredFunction != '\0')
{
void* reqFunc = ADUCPAL_dlsym(*libHandle, requiredFunction);
if (reqFunc == nullptr)
{
Log_Error("The specified function ('%s') doesn't exist. %s", requiredFunction, ADUCPAL_dlerror());
result.ExtendedResultCode =
ADUC_ERC_EXTENSION_FAILURE_REQUIRED_FUNCTION_NOTIMPL(facilityCode, componentCode);
goto done;
}
}
// Cache the loaded library.
ExtensionManager::_libs.emplace(extensionName, *libHandle);
result = { ADUC_Result_Success };
done:
if (IsAducResultCodeFailure(result.ResultCode))
{
if (*libHandle != nullptr)
{
ADUCPAL_dlclose(*libHandle);
*libHandle = nullptr;
}
}
// Done with file entity.
ADUC_FileEntity_Uninit(&entity);
return result;
}