static int CacheLoadModuleConfig (module_t *module, FILE *file) { uint16_t lines; /* Calculate the structure length */ LOAD_IMMEDIATE (module->i_config_items); LOAD_IMMEDIATE (module->i_bool_items); LOAD_IMMEDIATE (lines); /* Allocate memory */ if (lines) { module->p_config = malloc (lines * sizeof (module_config_t)); if (unlikely(module->p_config == NULL)) { module->confsize = 0; return -1; } } else module->p_config = NULL; module->confsize = lines; /* Do the duplication job */ for (size_t i = 0; i < lines; i++) if (CacheLoadConfig (module->p_config + i, file)) return -1; return 0; error: return -1; /* FIXME: leaks */ }
static int CacheLoadString (char **p, FILE *file) { char *psz = NULL; uint16_t size; LOAD_IMMEDIATE (size); if (size > 16384) { error: return -1; } if (size > 0) { psz = malloc (size+1); if (unlikely(psz == NULL)) goto error; if (fread (psz, 1, size, file) != size) { free (psz); goto error; } psz[size] = '\0'; } *p = psz; return 0; }
static int CacheLoadConfig (module_config_t *cfg, FILE *file) { LOAD_IMMEDIATE (cfg->flags); LOAD_STRING (cfg->psz_type); LOAD_STRING (cfg->psz_name); LOAD_STRING (cfg->psz_text); LOAD_STRING (cfg->psz_longtext); LOAD_IMMEDIATE (cfg->list_count); if (IsConfigStringType (cfg->i_type)) { LOAD_STRING (cfg->orig.psz); if (cfg->orig.psz != NULL) cfg->value.psz = strdup (cfg->orig.psz); else cfg->value.psz = NULL; if (cfg->list_count) cfg->list.psz = xmalloc (cfg->list_count * sizeof (char *)); else /* TODO: fix config_GetPszChoices() instead of this hack: */ LOAD_IMMEDIATE(cfg->list.psz_cb); for (unsigned i = 0; i < cfg->list_count; i++) { LOAD_STRING (cfg->list.psz[i]); if (cfg->list.psz[i] == NULL /* NULL -> empty string */ && (cfg->list.psz[i] = calloc (1, 1)) == NULL) goto error; } } else { LOAD_IMMEDIATE (cfg->orig); LOAD_IMMEDIATE (cfg->min); LOAD_IMMEDIATE (cfg->max); cfg->value = cfg->orig; if (cfg->list_count) cfg->list.i = xmalloc (cfg->list_count * sizeof (int)); else /* TODO: fix config_GetPszChoices() instead of this hack: */ LOAD_IMMEDIATE(cfg->list.i_cb); for (unsigned i = 0; i < cfg->list_count; i++) LOAD_IMMEDIATE (cfg->list.i[i]); } cfg->list_text = xmalloc (cfg->list_count * sizeof (char *)); for (unsigned i = 0; i < cfg->list_count; i++) { LOAD_STRING (cfg->list_text[i]); if (cfg->list_text[i] == NULL /* NULL -> empty string */ && (cfg->list_text[i] = calloc (1, 1)) == NULL) goto error; } return 0; error: return -1; /* FIXME: leaks */ }
/** * Loads a plugins cache file. * * This function will load the plugin cache if present and valid. This cache * will in turn be queried by AllocateAllPlugins() to see if it needs to * actually load the dynamically loadable module. * This allows us to only fully load plugins when they are actually used. */ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r ) { char *psz_filename; FILE *file; int i_size, i_read; char p_cachestring[sizeof(CACHE_STRING)]; size_t i_cache; int32_t i_marker; assert( dir != NULL ); *r = NULL; if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 ) return 0; msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); file = vlc_fopen( psz_filename, "rb" ); if( !file ) { msg_Warn( p_this, "cannot read %s: %s", psz_filename, vlc_strerror_c(errno) ); free( psz_filename ); return 0; } free( psz_filename ); /* Check the file is a plugins cache */ i_size = sizeof(CACHE_STRING) - 1; i_read = fread( p_cachestring, 1, i_size, file ); if( i_read != i_size || memcmp( p_cachestring, CACHE_STRING, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #ifdef DISTRO_VERSION /* Check for distribution specific version */ char p_distrostring[sizeof( DISTRO_VERSION )]; i_size = sizeof( DISTRO_VERSION ) - 1; i_read = fread( p_distrostring, 1, i_size, file ); if( i_read != i_size || memcmp( p_distrostring, DISTRO_VERSION, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #endif /* Check Sub-version number */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } /* Check header marker */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != ftell( file ) - (int)sizeof(i_marker) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } if (fread( &i_cache, 1, sizeof(i_cache), file ) != sizeof(i_cache) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(file too short)" ); fclose( file ); return 0; } module_cache_t *cache = NULL; for (size_t count = 0; count < i_cache;) { module_t *module; int i_submodules; module = vlc_module_create (NULL); /* Load additional infos */ LOAD_STRING(module->psz_shortname); LOAD_STRING(module->psz_longname); LOAD_STRING(module->psz_help); LOAD_IMMEDIATE(module->i_shortcuts); if (module->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { module->pp_shortcuts = xmalloc (sizeof (*module->pp_shortcuts) * module->i_shortcuts); for (unsigned j = 0; j < module->i_shortcuts; j++) LOAD_STRING(module->pp_shortcuts[j]); } LOAD_STRING(module->psz_capability); LOAD_IMMEDIATE(module->i_score); LOAD_IMMEDIATE(module->b_unloadable); /* Config stuff */ if (CacheLoadModuleConfig (module, file) != VLC_SUCCESS) goto error; LOAD_STRING(module->domain); if (module->domain != NULL) vlc_bindtextdomain (module->domain); LOAD_IMMEDIATE( i_submodules ); while( i_submodules-- ) { module_t *submodule = vlc_module_create (module); free (submodule->pp_shortcuts); LOAD_STRING(submodule->psz_shortname); LOAD_STRING(submodule->psz_longname); LOAD_IMMEDIATE(submodule->i_shortcuts); if (submodule->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { submodule->pp_shortcuts = xmalloc (sizeof (*submodule->pp_shortcuts) * submodule->i_shortcuts); for (unsigned j = 0; j < submodule->i_shortcuts; j++) LOAD_STRING(submodule->pp_shortcuts[j]); } LOAD_STRING(submodule->psz_capability); LOAD_IMMEDIATE(submodule->i_score); } char *path; struct stat st; /* Load common info */ LOAD_STRING(path); if (path == NULL) goto error; LOAD_IMMEDIATE(st.st_mtime); LOAD_IMMEDIATE(st.st_size); CacheAdd (&cache, &count, path, &st, module); free (path); /* TODO: deal with errors */ } fclose( file ); *r = cache; return i_cache; error: msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); /* TODO: cleanup */ fclose( file ); return 0; }
static int CacheLoadConfig( module_t *p_module, FILE *file ) { uint32_t i_lines; uint16_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 */ if (i_lines) { p_module->p_config = (module_config_t *)calloc( i_lines, sizeof(module_config_t) ); if( p_module->p_config == NULL ) { p_module->confsize = 0; return VLC_ENOMEM; } } p_module->confsize = i_lines; /* Do the duplication job */ for (size_t 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 ); if (IsConfigStringType (p_module->p_config[i].i_type)) { LOAD_STRING (p_module->p_config[i].orig.psz); p_module->p_config[i].value.psz = (p_module->p_config[i].orig.psz != NULL) ? strdup (p_module->p_config[i].orig.psz) : NULL; } else memcpy (&p_module->p_config[i].value, &p_module->p_config[i].orig, sizeof (p_module->p_config[i].value)); p_module->p_config[i].b_dirty = false; if( p_module->p_config[i].i_list ) { if( p_module->p_config[i].ppsz_list ) { int j; p_module->p_config[i].ppsz_list = xmalloc( (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 ) { int j; p_module->p_config[i].ppsz_list_text = xmalloc( (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 = xmalloc( (p_module->p_config[i].i_list + 1) * sizeof(int) ); if( p_module->p_config[i].pi_list ) { for (int 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 = xmalloc( p_module->p_config[i].i_action * sizeof(void *) ); p_module->p_config[i].ppsz_action_text = xmalloc( p_module->p_config[i].i_action * sizeof(char *) ); for (int j = 0; j < p_module->p_config[i].i_action; j++) { p_module->p_config[i].ppf_action[j] = NULL; LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] ); } } } return VLC_SUCCESS; error: return VLC_EGENERIC; }
/** * Loads a plugins cache file. * * This function will load the plugin cache if present and valid. This cache * will in turn be queried by AllocateAllPlugins() to see if it needs to * actually load the dynamically loadable module. * This allows us to only fully load plugins when they are actually used. */ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t ***r ) { char *psz_filename; FILE *file; int i_size, i_read; char p_cachestring[sizeof(CACHE_STRING)]; size_t i_cache; int32_t i_file_size, i_marker; assert( dir != NULL ); *r = NULL; if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 ) return 0; msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); file = vlc_fopen( psz_filename, "rb" ); if( !file ) { msg_Warn( p_this, "cannot read %s (%m)", psz_filename ); free( psz_filename ); return 0; } free( psz_filename ); /* Check the file size */ i_read = fread( &i_file_size, 1, sizeof(i_file_size), file ); if( i_read != sizeof(i_file_size) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(too short)" ); fclose( file ); return 0; } 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 0; } fseek( file, sizeof(i_file_size), SEEK_SET ); /* Check the file is a plugins cache */ i_size = sizeof(CACHE_STRING) - 1; i_read = fread( p_cachestring, 1, i_size, file ); if( i_read != i_size || memcmp( p_cachestring, CACHE_STRING, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #ifdef DISTRO_VERSION /* Check for distribution specific version */ char p_distrostring[sizeof( DISTRO_VERSION )]; i_size = sizeof( DISTRO_VERSION ) - 1; i_read = fread( p_distrostring, 1, i_size, file ); if( i_read != i_size || memcmp( p_distrostring, DISTRO_VERSION, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #endif /* Check Sub-version number */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } /* Check header marker */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != ftell( file ) - (int)sizeof(i_marker) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } if (fread( &i_cache, 1, sizeof(i_cache), file ) != sizeof(i_cache) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(file too short)" ); fclose( file ); return 0; } module_cache_t **pp_cache = malloc( i_cache * sizeof(*pp_cache) ); if( pp_cache == NULL ) i_cache = 0; /* don't load anything */ #define LOAD_IMMEDIATE(a) \ if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error #define LOAD_STRING(a) \ { \ a = NULL; \ if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) \ || ( i_size > 16384 ) ) \ goto error; \ if( i_size ) { \ char *psz = xmalloc( i_size ); \ if( fread( psz, i_size, 1, file ) != 1 ) { \ free( psz ); \ goto error; \ } \ if( psz[i_size-1] ) { \ free( psz ); \ goto error; \ } \ a = psz; \ } \ } for( size_t i = 0; i < i_cache; i++ ) { uint16_t i_size; int i_submodules; pp_cache[i] = xmalloc( sizeof(module_cache_t) ); /* Load common info */ LOAD_STRING( pp_cache[i]->path ); LOAD_IMMEDIATE( pp_cache[i]->mtime ); LOAD_IMMEDIATE( pp_cache[i]->size ); pp_cache[i]->p_module = vlc_module_create(); /* Load additional infos */ free( pp_cache[i]->p_module->psz_object_name ); 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_help ); LOAD_IMMEDIATE( pp_cache[i]->p_module->i_shortcuts ); if( pp_cache[i]->p_module->i_shortcuts > MODULE_SHORTCUT_MAX ) goto error; else if( pp_cache[i]->p_module->i_shortcuts == 0 ) pp_cache[i]->p_module->pp_shortcuts = NULL; else { pp_cache[i]->p_module->pp_shortcuts = xmalloc( sizeof( char ** ) * pp_cache[i]->p_module->i_shortcuts ); for( unsigned j = 0; j < pp_cache[i]->p_module->i_shortcuts; j++ ) LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); } 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->b_unloadable ); /* Config stuff */ if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS ) goto error; LOAD_STRING( pp_cache[i]->p_module->psz_filename ); LOAD_STRING( pp_cache[i]->p_module->domain ); if( pp_cache[i]->p_module->domain != NULL ) vlc_bindtextdomain( pp_cache[i]->p_module->domain ); LOAD_IMMEDIATE( i_submodules ); while( i_submodules-- ) { module_t *p_module = vlc_submodule_create( pp_cache[i]->p_module ); free( p_module->psz_object_name ); free( p_module->pp_shortcuts ); LOAD_STRING( p_module->psz_object_name ); LOAD_STRING( p_module->psz_shortname ); LOAD_STRING( p_module->psz_longname ); LOAD_STRING( p_module->psz_help ); LOAD_IMMEDIATE( p_module->i_shortcuts ); if( p_module->i_shortcuts > MODULE_SHORTCUT_MAX ) goto error; else if( p_module->i_shortcuts == 0 ) p_module->pp_shortcuts = NULL; else { p_module->pp_shortcuts = xmalloc( sizeof( char ** ) * p_module->i_shortcuts ); for( unsigned j = 0; j < p_module->i_shortcuts; j++ ) LOAD_STRING( p_module->pp_shortcuts[j] ); } LOAD_STRING( p_module->psz_capability ); LOAD_IMMEDIATE( p_module->i_score ); LOAD_IMMEDIATE( p_module->b_unloadable ); LOAD_STRING( p_module->domain ); } } fclose( file ); *r = pp_cache; return i_cache; error: msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); /* TODO: cleanup */ fclose( file ); return 0; }
/** * Loads a plugins cache file. * * This function will load the plugin cache if present and valid. This cache * will in turn be queried by AllocateAllPlugins() to see if it needs to * actually load the dynamically loadable module. * This allows us to only fully load plugins when they are actually used. */ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r ) { char *psz_filename; FILE *file; int i_size, i_read; char p_cachestring[sizeof(CACHE_STRING)]; int32_t i_marker; assert( dir != NULL ); *r = NULL; if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 ) return 0; msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); file = vlc_fopen( psz_filename, "rb" ); if( !file ) { msg_Warn( p_this, "cannot read %s: %s", psz_filename, vlc_strerror_c(errno) ); free( psz_filename ); return 0; } free( psz_filename ); /* Check the file is a plugins cache */ i_size = sizeof(CACHE_STRING) - 1; i_read = fread( p_cachestring, 1, i_size, file ); if( i_read != i_size || memcmp( p_cachestring, CACHE_STRING, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #ifdef DISTRO_VERSION /* Check for distribution specific version */ char p_distrostring[sizeof( DISTRO_VERSION )]; i_size = sizeof( DISTRO_VERSION ) - 1; i_read = fread( p_distrostring, 1, i_size, file ); if( i_read != i_size || memcmp( p_distrostring, DISTRO_VERSION, i_size ) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); fclose( file ); return 0; } #endif /* Check sub-version number */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } /* Check header marker */ i_read = fread( &i_marker, 1, sizeof(i_marker), file ); if( i_read != sizeof(i_marker) || i_marker != ftell( file ) - (int)sizeof(i_marker) ) { msg_Warn( p_this, "This doesn't look like a valid plugins cache " "(corrupted header)" ); fclose( file ); return 0; } module_cache_t *cache = NULL; size_t count = 0; char *path = NULL; for (;;) { module_t *module = CacheLoadModule (file); if (module == NULL) { if (feof (file)) break; goto error; } struct stat st; /* Load common info */ LOAD_STRING(path); if (path == NULL) goto error; LOAD_IMMEDIATE(st.st_mtime); LOAD_IMMEDIATE(st.st_size); CacheAdd (&cache, &count, path, &st, module); free (path); path = NULL; /* TODO: deal with errors */ } fclose( file ); *r = cache; return count; error: free( path ); if (ferror (file)) msg_Err(p_this, "plugins cache read error: %s", vlc_strerror_c(errno)); msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); /* TODO: cleanup */ fclose( file ); return 0; }
static module_t *CacheLoadModule (FILE *file) { module_t *module = vlc_module_create (NULL); if (unlikely(module == NULL)) return NULL; /* Load additional infos */ LOAD_STRING(module->psz_shortname); LOAD_STRING(module->psz_longname); LOAD_STRING(module->psz_help); LOAD_IMMEDIATE(module->i_shortcuts); if (module->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { module->pp_shortcuts = xmalloc (sizeof (*module->pp_shortcuts) * module->i_shortcuts); for (unsigned j = 0; j < module->i_shortcuts; j++) LOAD_STRING(module->pp_shortcuts[j]); } LOAD_STRING(module->psz_capability); LOAD_IMMEDIATE(module->i_score); LOAD_IMMEDIATE(module->b_unloadable); /* Config stuff */ if (CacheLoadModuleConfig (module, file) != VLC_SUCCESS) goto error; LOAD_STRING(module->domain); if (module->domain != NULL) vlc_bindtextdomain (module->domain); uint32_t submodules; LOAD_IMMEDIATE(submodules); for (; submodules > 0; submodules--) { module_t *submodule = vlc_module_create (module); free (submodule->pp_shortcuts); LOAD_STRING(submodule->psz_shortname); LOAD_STRING(submodule->psz_longname); LOAD_IMMEDIATE(submodule->i_shortcuts); if (submodule->i_shortcuts > MODULE_SHORTCUT_MAX) goto error; else { submodule->pp_shortcuts = xmalloc (sizeof (*submodule->pp_shortcuts) * submodule->i_shortcuts); for (unsigned j = 0; j < submodule->i_shortcuts; j++) LOAD_STRING(submodule->pp_shortcuts[j]); } LOAD_STRING(submodule->psz_capability); LOAD_IMMEDIATE(submodule->i_score); } return module; error: vlc_module_destroy(module); return NULL; }