void PluginManager::openPlugin(const std::string &path) { LOGD("Loading plugin: <%s>", path.c_str()); void *handle = dlopen(path.c_str(), RTLD_LAZY); if (!handle) { LOGW("File could not be dlopened <%s> : <%s>", path.c_str(), dlerror()); return; } PluginLibPtr handlePtr(handle, std::ptr_fun(dlclose)); //Flush any previous errors dlerror(); create_t creator = reinterpret_cast<create_t>(dlsym(handle, "create")); char *error; if ((error = dlerror()) != NULL) { LOGE("Couldn't resolve symbol <create> from lib <%s> : <%s>", path.c_str(), error); return; } destroy_t destroyer = reinterpret_cast<destroy_t>(dlsym(handle, "destroy")); if ((error = dlerror()) != NULL) { LOGE("Couldn't resolve symbol <destroy> from lib <%s> : <%s>", path.c_str(), error); return; } ExternalPluginPtr pluginPtr(creator(), destroyer); if (!pluginPtr) { LOGE("Couldn't create plugin for <%s>", path.c_str()); return; } auto policies = pluginPtr->getSupportedPolicyDescr(); if (policies.empty()) { LOGE("Plugin <%s> does not support any type!", path.c_str()); return; } for (auto &desc : policies) { if (!m_plugins.insert(std::make_pair(desc, pluginPtr)).second) { LOGW("Policy: type [%" PRIu16 "] name <%s> was already supported.", desc.type, desc.name.c_str()); } else { LOGD("Supported policy: type [%" PRIu16 "] name <%s>", desc.type, desc.name.c_str()); } } m_pluginLibs.push_back(std::move(handlePtr)); }
void Directory::read() const { #if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) WIN32_FIND_DATA f; auto pattern = m_path + '*'; auto wpattern = charset::ToWide( pattern.c_str() ); auto h = FindFirstFile( wpattern.get(), &f ); if ( h == INVALID_HANDLE_VALUE ) { LOG_ERROR( "Failed to browse ", m_path ); throw std::system_error( GetLastError(), std::generic_category(), "Failed to browse through directory" ); } do { auto file = charset::FromWide( f.cFileName ); if ( file[0] == '.' && strcasecmp( file.get(), ".nomedia" ) ) continue; auto fullpath = m_path + file.get(); try { if ( ( f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ) m_dirs.emplace_back( m_fsFactory.createDirectory( m_mrl + utils::url::encode( file.get() ) ) ); else m_files.emplace_back( std::make_shared<File>( fullpath ) ); } catch ( const std::system_error& ex ) { LOG_WARN( "Failed to access a listed file/dir: ", ex.what() , ". Ignoring this entry." ); } } while ( FindNextFile( h, &f ) != 0 ); FindClose( h ); #else // We must remove the trailing / // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx // «Do not use a trailing backslash (\), which indicates the root directory of a drive» auto tmpPath = m_path.substr( 0, m_path.length() - 1 ); auto wpath = charset::ToWide( tmpPath.c_str() ); CREATEFILE2_EXTENDED_PARAMETERS params{}; params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS; auto handle = CreateFile2( wpath.get(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, ¶ms ); if ( handle == INVALID_HANDLE_VALUE ) { LOG_ERROR( "Failed to open directory ", m_path ); throw std::system_error( GetLastError(), std::generic_category(), "Failed to open directory" ); } std::unique_ptr<typename std::remove_pointer<HANDLE>::type, decltype(&CloseHandle)> handlePtr( handle, &CloseHandle ); // Allocating a 32 bytes buffer to contain the file name. If more is required, we'll allocate size_t buffSize = sizeof( FILE_FULL_DIR_INFO ) + 32; std::unique_ptr<FILE_FULL_DIR_INFO, void(*)(FILE_FULL_DIR_INFO*)> dirInfo( reinterpret_cast<FILE_FULL_DIR_INFO*>( malloc( buffSize ) ), [](FILE_FULL_DIR_INFO* ptr) { free( ptr ); } ); if ( dirInfo == nullptr ) throw std::bad_alloc(); while ( true ) { auto h = GetFileInformationByHandleEx( handle, FileFullDirectoryInfo, dirInfo.get(), buffSize ); if ( h == 0 ) { auto error = GetLastError(); if ( error == ERROR_FILE_NOT_FOUND ) break; else if ( error == ERROR_MORE_DATA ) { buffSize *= 2; dirInfo.reset( reinterpret_cast<FILE_FULL_DIR_INFO*>( malloc( buffSize ) ) ); if ( dirInfo == nullptr ) throw std::bad_alloc(); continue; } LOG_ERROR( "Failed to browse ", m_path, ". GetLastError(): ", GetLastError() ); throw std::system_error( GetLastError(), std::generic_category(), "Failed to browse through directory" ); } auto file = charset::FromWide( dirInfo->FileName ); if ( file[0] == '.' && strcasecmp( file.get(), ".nomedia" ) ) continue; try { if ( ( dirInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ) m_dirs.emplace_back( m_fsFactory.createDirectory( m_path + utils::url::encode( file.get() ) ) ); else m_files.emplace_back( std::make_shared<File>( m_path + file.get()) ); } catch ( const std::system_error& ex ) { LOG_WARN( "Failed to access a listed file/dir: ", ex.what() , ". Ignoring this entry." ); } } #endif }