Exemple #1
0
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, &params );
    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
}