#include <errno.h>
#include <sys/types.h>
+#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
/* Sub-version number
* (only used to avoid breakage in dev version when cache structure changes) */
-#define CACHE_SUBVERSION_NUM 15
+#define CACHE_SUBVERSION_NUM 18
/* Cache filename */
#define CACHE_NAME "plugins.dat"
* 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 )
+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;
+ int32_t i_marker;
assert( dir != NULL );
}
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 );
return 0;
}
- module_cache_t **pp_cache = malloc( i_cache * sizeof(*pp_cache) );
- if( pp_cache == NULL )
- i_cache = 0; /* don't load anything */
+ module_cache_t *cache = NULL;
#define LOAD_IMMEDIATE(a) \
if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
} \
}
- for( size_t i = 0; i < i_cache; i++ )
+ for (size_t count = 0; count < i_cache;)
{
+ module_t *module;
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();
+ module = vlc_module_create (NULL);
/* 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 )
+ 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 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] );
+ module->pp_shortcuts =
+ xmalloc (sizeof (char **) * module->i_shortcuts);
+ for (unsigned j = 0; j < module->i_shortcuts; j++)
+ LOAD_STRING(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 );
+ LOAD_STRING(module->psz_capability);
+ LOAD_IMMEDIATE(module->i_score);
+ LOAD_IMMEDIATE(module->b_unloadable);
/* Config stuff */
- if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
+ if (CacheLoadConfig (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_STRING(module->domain);
+ if (module->domain != NULL)
+ vlc_bindtextdomain (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 )
+ 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 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] );
+ submodule->pp_shortcuts =
+ xmalloc (sizeof (char **) * submodule->i_shortcuts);
+ for (unsigned j = 0; j < submodule->i_shortcuts; j++)
+ LOAD_STRING(submodule->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 );
+ 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 = pp_cache;
+ *r = cache;
return i_cache;
- error:
-
+error:
msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
/* TODO: cleanup */
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_oldname );
if (IsConfigStringType (p_module->p_config[i].i_type))
{
return VLC_EGENERIC;
}
-static int CacheSaveBank( FILE *file, module_cache_t *const *, size_t );
+static int CacheSaveBank( FILE *file, const module_cache_t *, size_t );
-/*****************************************************************************
- * SavePluginsCache: saves the plugins cache to a file
- *****************************************************************************/
+/**
+ * Saves a module cache to disk, and release cache data from memory.
+ */
void CacheSave (vlc_object_t *p_this, const char *dir,
- module_cache_t *const *pp_cache, size_t n)
+ module_cache_t *entries, size_t n)
{
- char *filename, *tmpname;
+ char *filename = NULL, *tmpname = NULL;
if (asprintf (&filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1)
- return;
+ goto out;
if (asprintf (&tmpname, "%s.%"PRIu32, filename, (uint32_t)getpid ()) == -1)
- {
- free (filename);
- return;
- }
+ goto out;
msg_Dbg (p_this, "saving plugins cache %s", filename);
FILE *file = vlc_fopen (tmpname, "wb");
goto out;
}
- if (CacheSaveBank (file, pp_cache, n))
+ if (CacheSaveBank (file, entries, n))
{
msg_Warn (p_this, "cannot write %s (%m)", tmpname);
clearerr (file);
out:
free (filename);
free (tmpname);
+
+ for (size_t i = 0; i < n; i++)
+ free (entries[i].path);
+ free (entries);
}
static int CacheSaveConfig (FILE *, const module_t *);
static int CacheSaveSubmodule (FILE *, const module_t *);
-static int CacheSaveBank (FILE *file, module_cache_t *const *pp_cache,
+static int CacheSaveBank (FILE *file, const module_cache_t *cache,
size_t i_cache)
{
uint32_t i_file_size = 0;
- /* Empty space for file size */
- if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1)
- goto error;
-
/* Contains version number */
if (fputs (CACHE_STRING, file) == EOF)
goto error;
for (unsigned i = 0; i < i_cache; i++)
{
+ module_t *module = cache[i].p_module;
uint32_t i_submodule;
- /* Save common info */
- SAVE_STRING( pp_cache[i]->path );
- SAVE_IMMEDIATE( pp_cache[i]->mtime );
- SAVE_IMMEDIATE( pp_cache[i]->size );
-
/* Save additional infos */
- SAVE_STRING( pp_cache[i]->p_module->psz_object_name );
- SAVE_STRING( pp_cache[i]->p_module->psz_shortname );
- SAVE_STRING( pp_cache[i]->p_module->psz_longname );
- SAVE_STRING( pp_cache[i]->p_module->psz_help );
- SAVE_IMMEDIATE( pp_cache[i]->p_module->i_shortcuts );
- for (unsigned j = 0; j < pp_cache[i]->p_module->i_shortcuts; j++)
- SAVE_STRING( pp_cache[i]->p_module->pp_shortcuts[j] );
-
- SAVE_STRING( pp_cache[i]->p_module->psz_capability );
- SAVE_IMMEDIATE( pp_cache[i]->p_module->i_score );
- SAVE_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
+ SAVE_STRING(module->psz_shortname);
+ SAVE_STRING(module->psz_longname);
+ SAVE_STRING(module->psz_help);
+ SAVE_IMMEDIATE(module->i_shortcuts);
+ for (unsigned j = 0; j < module->i_shortcuts; j++)
+ SAVE_STRING(module->pp_shortcuts[j]);
+
+ SAVE_STRING(module->psz_capability);
+ SAVE_IMMEDIATE(module->i_score);
+ SAVE_IMMEDIATE(module->b_unloadable);
/* Config stuff */
- if (CacheSaveConfig (file, pp_cache[i]->p_module))
+ if (CacheSaveConfig (file, module))
goto error;
- SAVE_STRING( pp_cache[i]->p_module->psz_filename );
- SAVE_STRING( pp_cache[i]->p_module->domain );
+ SAVE_STRING(module->domain);
- i_submodule = pp_cache[i]->p_module->submodule_count;
+ i_submodule = module->submodule_count;
SAVE_IMMEDIATE( i_submodule );
- if( CacheSaveSubmodule( file, pp_cache[i]->p_module->submodule ) )
+ if (CacheSaveSubmodule (file, module->submodule))
goto error;
+
+ /* Save common info */
+ SAVE_STRING(cache[i].path);
+ SAVE_IMMEDIATE(cache[i].mtime);
+ SAVE_IMMEDIATE(cache[i].size);
}
- /* Fill-up file size */
- i_file_size = ftell( file );
- fseek( file, 0, SEEK_SET );
- if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1
- || fflush (file)) /* flush libc buffers */
+ if (fflush (file)) /* flush libc buffers */
goto error;
return 0; /* success! */
if( CacheSaveSubmodule( file, p_module->next ) )
goto error;
- SAVE_STRING( p_module->psz_object_name );
SAVE_STRING( p_module->psz_shortname );
SAVE_STRING( p_module->psz_longname );
- SAVE_STRING( p_module->psz_help );
SAVE_IMMEDIATE( p_module->i_shortcuts );
for( unsigned j = 0; j < p_module->i_shortcuts; j++ )
SAVE_STRING( p_module->pp_shortcuts[j] );
SAVE_STRING( p_module->psz_capability );
SAVE_IMMEDIATE( p_module->i_score );
- SAVE_IMMEDIATE( p_module->b_unloadable );
- SAVE_STRING( p_module->domain );
return 0;
error:
SAVE_STRING( p_module->p_config[i].psz_name );
SAVE_STRING( p_module->p_config[i].psz_text );
SAVE_STRING( p_module->p_config[i].psz_longtext );
- SAVE_STRING( p_module->p_config[i].psz_oldname );
if (IsConfigStringType (p_module->p_config[i].i_type))
SAVE_STRING( p_module->p_config[i].orig.psz );
p_module->b_loaded = false;
}
-/*****************************************************************************
- * CacheFind: finds the cache entry corresponding to a file
- *****************************************************************************/
-module_t *CacheFind( module_bank_t *p_bank,
- const char *path, time_t mtime, off_t size )
+/**
+ * Looks up a plugin file in a table of cached plugins.
+ */
+module_t *CacheFind (module_cache_t *cache, size_t count,
+ const char *path, const struct stat *st)
{
- module_cache_t **cache = p_bank->pp_loaded_cache;
- size_t n = p_bank->i_loaded_cache;
-
- for( size_t i = 0; i < n; i++ )
- if( !strcmp( cache[i]->path, path )
- && cache[i]->mtime == mtime
- && cache[i]->size == size )
+ while (count > 0)
+ {
+ if (cache->path != NULL
+ && !strcmp (cache->path, path)
+ && cache->mtime == st->st_mtime
+ && cache->size == st->st_size)
{
- module_t *module = cache[i]->p_module;
- cache[i]->p_module = NULL;
+ module_t *module = cache->p_module;
+ cache->p_module = NULL;
return module;
}
+ cache++;
+ count--;
+ }
return NULL;
}
+/** Adds entry to the cache */
+int CacheAdd (module_cache_t **cachep, size_t *countp,
+ const char *path, const struct stat *st, module_t *module)
+{
+ module_cache_t *cache = *cachep;
+ const size_t count = *countp;
+
+ cache = realloc (cache, (count + 1) * sizeof (*cache));
+ if (unlikely(cache == NULL))
+ return -1;
+ *cachep = cache;
+
+ cache += count;
+ /* NOTE: strdup() could be avoided, but it would be a bit ugly */
+ cache->path = strdup (path);
+ cache->mtime = st->st_mtime;
+ cache->size = st->st_size;
+ cache->p_module = module;
+ *countp = count + 1;
+ return 0;
+}
+
#endif /* HAVE_DYNAMIC_PLUGINS */