+ fseek( file, 0, SEEK_END );
+ if( ftell( file ) != i_file_size )
+ {
+ msg_Warn( p_this, "This doesn't look like a valid plugins cache "
+ "(corrupted size)" );
+ fclose( file );
+ return;
+ }
+ fseek( file, sizeof(i_file_size), SEEK_SET );
+
+ /* Check the file is a plugins cache */
+ i_size = sizeof(PLUGINSCACHE_FILE COPYRIGHT_MESSAGE) - 1;
+ i_read = fread( p_cachestring, sizeof(char), i_size, file );
+ if( i_read != i_size ||
+ memcmp( p_cachestring, PLUGINSCACHE_FILE COPYRIGHT_MESSAGE, i_size ) )
+ {
+ msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
+ fclose( file );
+ return;
+ }
+
+ p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
+ fread( &i_cache, sizeof(char), sizeof(i_cache), file );
+ pp_cache = p_this->p_libvlc->p_module_bank->pp_loaded_cache =
+ malloc( i_cache * sizeof(void *) );
+
+#define LOAD_IMMEDIATE(a) \
+ if( fread( &a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
+#define LOAD_STRING(a) \
+ { if( fread( &i_size, sizeof(char), sizeof(i_size), file ) \
+ != sizeof(i_size) ) goto error; \
+ if( i_size ) { \
+ a = malloc( i_size ); \
+ if( fread( a, sizeof(char), i_size, file ) != (size_t)i_size ) \
+ goto error; \
+ } else a = 0; \
+ } while(0)
+
+
+ for( i = 0; i < i_cache; i++ )
+ {
+ int16_t i_size;
+ int i_submodules;
+
+ pp_cache[i] = malloc( sizeof(module_cache_t) );
+ p_this->p_libvlc->p_module_bank->i_loaded_cache++;
+
+ /* Save common info */
+ LOAD_STRING( pp_cache[i]->psz_file );
+ LOAD_IMMEDIATE( pp_cache[i]->i_time );
+ LOAD_IMMEDIATE( pp_cache[i]->i_size );
+ LOAD_IMMEDIATE( pp_cache[i]->b_junk );
+
+ if( pp_cache[i]->b_junk ) continue;
+
+ pp_cache[i]->p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE );
+
+ /* Save additional infos */
+ LOAD_STRING( pp_cache[i]->p_module->psz_object_name );
+ LOAD_STRING( pp_cache[i]->p_module->psz_shortname );
+ LOAD_STRING( pp_cache[i]->p_module->psz_longname );
+ LOAD_STRING( pp_cache[i]->p_module->psz_program );
+ for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
+ {
+ LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); // FIX
+ }
+ LOAD_STRING( pp_cache[i]->p_module->psz_capability );
+ LOAD_IMMEDIATE( pp_cache[i]->p_module->i_score );
+ LOAD_IMMEDIATE( pp_cache[i]->p_module->i_cpu );
+ LOAD_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
+ LOAD_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
+ LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
+
+ /* Config stuff */
+ if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
+ goto error;
+
+ LOAD_STRING( pp_cache[i]->p_module->psz_filename );
+
+ LOAD_IMMEDIATE( i_submodules );
+
+ while( i_submodules-- )
+ {
+ module_t *p_module = vlc_object_create( p_this, VLC_OBJECT_MODULE);
+ vlc_object_attach( p_module, pp_cache[i]->p_module );
+ p_module->b_submodule = VLC_TRUE;
+
+ LOAD_STRING( p_module->psz_object_name );
+ LOAD_STRING( p_module->psz_shortname );
+ LOAD_STRING( p_module->psz_longname );
+ LOAD_STRING( p_module->psz_program );
+ for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
+ {
+ LOAD_STRING( p_module->pp_shortcuts[j] ); // FIX
+ }
+ LOAD_STRING( p_module->psz_capability );
+ LOAD_IMMEDIATE( p_module->i_score );
+ LOAD_IMMEDIATE( p_module->i_cpu );
+ LOAD_IMMEDIATE( p_module->b_unloadable );
+ LOAD_IMMEDIATE( p_module->b_reentrant );
+ }
+ }
+
+ fclose( file );
+ return;
+
+ error:
+
+ msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
+
+ /* TODO: cleanup */
+ p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
+
+ fclose( file );
+ return;
+}
+
+int CacheLoadConfig( module_t *p_module, FILE *file )
+{
+ int i, j, i_lines;
+ int16_t i_size;
+
+ /* Calculate the structure length */
+ LOAD_IMMEDIATE( p_module->i_config_items );
+ LOAD_IMMEDIATE( p_module->i_bool_items );
+
+ LOAD_IMMEDIATE( i_lines );
+
+ /* Allocate memory */
+ p_module->p_config =
+ (module_config_t *)malloc( sizeof(module_config_t) * (i_lines + 1));
+ if( p_module->p_config == NULL )
+ {
+ msg_Err( p_module, "config error: can't duplicate p_config" );
+ return VLC_ENOMEM;
+ }
+
+ /* Do the duplication job */
+ for( i = 0; i < i_lines ; i++ )
+ {
+ LOAD_IMMEDIATE( p_module->p_config[i] );
+
+ LOAD_STRING( p_module->p_config[i].psz_type );
+ LOAD_STRING( p_module->p_config[i].psz_name );
+ LOAD_STRING( p_module->p_config[i].psz_text );
+ LOAD_STRING( p_module->p_config[i].psz_longtext );
+ LOAD_STRING( p_module->p_config[i].psz_value_orig );
+
+ p_module->p_config[i].psz_value =
+ p_module->p_config[i].psz_value_orig ?
+ strdup( p_module->p_config[i].psz_value_orig ) : 0;
+ p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
+ p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
+
+ p_module->p_config[i].p_lock = &p_module->object_lock;
+
+ if( p_module->p_config[i].i_list )
+ {
+ if( p_module->p_config[i].ppsz_list )
+ {
+ p_module->p_config[i].ppsz_list =
+ malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
+ if( p_module->p_config[i].ppsz_list )
+ {
+ for( j = 0; j < p_module->p_config[i].i_list; j++ )
+ LOAD_STRING( p_module->p_config[i].ppsz_list[j] );
+ p_module->p_config[i].ppsz_list[j] = NULL;
+ }
+ }
+ if( p_module->p_config[i].ppsz_list_text )
+ {
+ p_module->p_config[i].ppsz_list_text =
+ malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
+ if( p_module->p_config[i].ppsz_list_text )
+ {
+ for( j = 0; j < p_module->p_config[i].i_list; j++ )
+ LOAD_STRING( p_module->p_config[i].ppsz_list_text[j] );
+ p_module->p_config[i].ppsz_list_text[j] = NULL;
+ }
+ }
+ if( p_module->p_config[i].pi_list )
+ {
+ p_module->p_config[i].pi_list =
+ malloc( (p_module->p_config[i].i_list + 1) * sizeof(int) );
+ if( p_module->p_config[i].pi_list )
+ {
+ for( j = 0; j < p_module->p_config[i].i_list; j++ )
+ LOAD_IMMEDIATE( p_module->p_config[i].pi_list[j] );
+ }
+ }
+ }
+
+ if( p_module->p_config[i].i_action )
+ {
+ p_module->p_config[i].ppf_action =
+ malloc( p_module->p_config[i].i_action * sizeof(void *) );
+ p_module->p_config[i].ppsz_action_text =
+ malloc( p_module->p_config[i].i_action * sizeof(char *) );
+
+ for( j = 0; j < p_module->p_config[i].i_action; j++ )
+ {
+ p_module->p_config[i].ppf_action[j] = 0;
+ LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] );
+ }
+ }
+
+ LOAD_IMMEDIATE( p_module->p_config[i].pf_callback );
+ }
+
+ p_module->p_config[i].i_type = CONFIG_HINT_END;
+
+ return VLC_SUCCESS;
+
+ error:
+
+ return VLC_EGENERIC;