cache.c 22.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*****************************************************************************
 * cache.c: Plugins cache
 *****************************************************************************
 * Copyright (C) 2001-2007 the VideoLAN team
 * $Id$
 *
 * Authors: Sam Hocevar <sam@zoy.org>
 *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
 *          Hans-Peter Jansen <hpj@urpla.net>
 *          Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

27
28
29
30
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

31
#include <vlc_common.h>
32
33
34
35
36
#include "libvlc.h"

#include <stdlib.h>                                      /* free(), strtol() */
#include <stdio.h>                                              /* sprintf() */
#include <string.h>                                              /* strdup() */
37
#include <vlc_plugin.h>
38
#include <errno.h>
39

40
#include <sys/types.h>
41
42
43
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif
44
#include <assert.h>
45

46
#include "config/configuration.h"
47

48
#include <vlc_fs.h>
49
50
51
52
53
54
55
56
57
58
59
60

#include "modules/modules.h"


/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
static int    CacheLoadConfig  ( module_t *, FILE * );

/* Sub-version number
 * (only used to avoid breakage in dev version when cache structure changes) */
61
#define CACHE_SUBVERSION_NUM 12
62

63
64
/* Cache filename */
#define CACHE_NAME "plugins.dat"
65
/* Magic for the cache filename */
66
#define CACHE_STRING "cache "PACKAGE_NAME" "PACKAGE_VERSION
67
68


69
70
71
72
73
74
void CacheDelete( vlc_object_t *obj, const char *dir )
{
    char *path;

    assert( dir != NULL );

75
    if( asprintf( &path, "%s"DIR_SEP CACHE_NAME, dir ) == -1 )
76
77
        return;
    msg_Dbg( obj, "removing plugins cache file %s", path );
78
    vlc_unlink( path );
79
80
81
    free( path );
}

82
83
84
85
86
87
88
89
/*****************************************************************************
 * LoadPluginsCache: loads the 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.
 *****************************************************************************/
90
void CacheLoad( vlc_object_t *p_this, module_bank_t *p_bank, const char *dir )
91
{
92
    char *psz_filename;
93
    FILE *file;
ivoire's avatar
ivoire committed
94
    int i_size, i_read;
95
    char p_cachestring[sizeof(CACHE_STRING)];
96
    size_t i_cache;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
97
    module_cache_t **pp_cache = NULL;
98
99
    int32_t i_file_size, i_marker;

100
    assert( dir != NULL );
101

102
    if( !p_bank->b_cache )
103
104
        return;

105
    if( asprintf( &psz_filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1 )
106
107
108
109
        return;

    msg_Dbg( p_this, "loading plugins cache file %s", psz_filename );

110
    file = vlc_fopen( psz_filename, "rb" );
111
112
    if( !file )
    {
113
        msg_Warn( p_this, "cannot read %s (%m)",
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
                  psz_filename );
        free( psz_filename );
        return;
    }
    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;
    }

    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 */
141
    i_size = sizeof(CACHE_STRING) - 1;
142
143
    i_read = fread( p_cachestring, 1, i_size, file );
    if( i_read != i_size ||
144
        memcmp( p_cachestring, CACHE_STRING, i_size ) )
145
146
147
148
149
150
    {
        msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
        fclose( file );
        return;
    }

151
152
153
154
155
156
157
158
159
160
161
162
163
164
#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;
    }
#endif

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    /* 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;
    }

    /* 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;
    }

    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;
    }

    if( i_cache )
195
    {
196
        size_t i_already = p_bank->i_loaded_cache;
197
198
199
200
201
202
203
204
205
206
        pp_cache = realloc( p_bank->pp_loaded_cache,
                            (i_already + i_cache) * sizeof(*pp_cache) );
        if( unlikely(pp_cache == NULL) )
            i_cache = 0; /* don't load */
        else
        {
            p_bank->pp_loaded_cache = pp_cache;
            pp_cache += i_already;
        }
   }
207
208
209
210
211
212
213
214
215
216

#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 ) { \
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
217
        char *psz = xmalloc( i_size ); \
218
219
220
221
222
223
224
225
226
227
228
229
        if( fread( psz, i_size, 1, file ) != 1 ) { \
            free( psz ); \
            goto error; \
        } \
        if( psz[i_size-1] ) { \
            free( psz ); \
            goto error; \
        } \
        a = psz; \
    } \
}

230
    for( size_t i = 0; i < i_cache; i++ )
231
232
233
234
    {
        uint16_t i_size;
        int i_submodules;

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
235
        pp_cache[i] = xmalloc( sizeof(module_cache_t) );
236
237
238
239
240
241
242
243
244

        /* Load common info */
        LOAD_STRING( pp_cache[i]->psz_file );
        LOAD_IMMEDIATE( pp_cache[i]->i_time );
        LOAD_IMMEDIATE( pp_cache[i]->i_size );

        pp_cache[i]->p_module = vlc_module_create( p_this );

        /* Load additional infos */
245
        free( pp_cache[i]->p_module->psz_object_name );
246
247
248
249
        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 );
250
251
252
253
254
255
256

        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
257
        {
258
259
            pp_cache[i]->p_module->pp_shortcuts =
                    xmalloc( sizeof( char ** ) * pp_cache[i]->p_module->i_shortcuts );
ivoire's avatar
ivoire committed
260
            for( unsigned j = 0; j < pp_cache[i]->p_module->i_shortcuts; j++ )
261
                LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] );
262
        }
263

264
265
266
267
268
269
270
271
272
273
        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_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 );
274
        LOAD_STRING( pp_cache[i]->p_module->domain );
275
276
        if( pp_cache[i]->p_module->domain != NULL )
            vlc_bindtextdomain( pp_cache[i]->p_module->domain );
277
278
279
280
281
282

        LOAD_IMMEDIATE( i_submodules );

        while( i_submodules-- )
        {
            module_t *p_module = vlc_submodule_create( pp_cache[i]->p_module );
Rafaël Carré's avatar
Rafaël Carré committed
283
            free( p_module->psz_object_name );
284
            free( p_module->pp_shortcuts );
285
286
287
288
            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 );
289
290
291
292
293
294
295

            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
296
            {
297
                p_module->pp_shortcuts = xmalloc( sizeof( char ** ) * p_module->i_shortcuts );
ivoire's avatar
ivoire committed
298
                for( unsigned j = 0; j < p_module->i_shortcuts; j++ )
299
                    LOAD_STRING( p_module->pp_shortcuts[j] );
300
            }
301

302
303
304
            LOAD_STRING( p_module->psz_capability );
            LOAD_IMMEDIATE( p_module->i_score );
            LOAD_IMMEDIATE( p_module->b_unloadable );
305
            LOAD_STRING( p_module->domain );
306
307
        }
    }
308
    p_bank->i_loaded_cache += i_cache;
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

    fclose( file );
    return;

 error:

    msg_Warn( p_this, "plugins cache not loaded (corrupted)" );

    /* TODO: cleanup */
    fclose( file );
    return;
}


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 );
356
357
        LOAD_STRING( p_module->p_config[i].psz_oldname );
        LOAD_IMMEDIATE( p_module->p_config[i].b_removed );
358
359
360
361
362
363
364
365
366
367
368
369

        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));

370
        p_module->p_config[i].b_dirty = false;
371
372
373
374
375
376
377

        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 =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
378
                    xmalloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
379
380
381
382
383
384
385
386
387
388
389
                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 =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
390
                    xmalloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
391
392
393
394
395
396
397
398
399
400
                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 =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
401
                    xmalloc( (p_module->p_config[i].i_list + 1) * sizeof(int) );
402
403
404
405
406
407
408
409
410
411
412
                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 =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
413
                xmalloc( p_module->p_config[i].i_action * sizeof(void *) );
414
            p_module->p_config[i].ppsz_action_text =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
415
                xmalloc( p_module->p_config[i].i_action * sizeof(char *) );
416
417
418

            for (int j = 0; j < p_module->p_config[i].i_action; j++)
            {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
419
                p_module->p_config[i].ppf_action[j] = NULL;
420
421
422
423
424
425
426
427
428
429
430
431
                LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] );
            }
        }
    }

    return VLC_SUCCESS;

 error:

    return VLC_EGENERIC;
}

432
static int CacheSaveBank( FILE *file, module_cache_t *const *, size_t );
433

434
435
436
/*****************************************************************************
 * SavePluginsCache: saves the plugins cache to a file
 *****************************************************************************/
437
438
void CacheSave (vlc_object_t *p_this, const char *dir,
                module_cache_t *const *pp_cache, size_t n)
439
{
440
441
    char *filename, *tmpname;

442
    if (asprintf (&filename, "%s"DIR_SEP CACHE_NAME, dir ) == -1)
443
444
445
        return;

    if (asprintf (&tmpname, "%s.%"PRIu32, filename, (uint32_t)getpid ()) == -1)
446
    {
447
        free (filename);
448
449
        return;
    }
450
    msg_Dbg (p_this, "saving plugins cache %s", filename);
451

452
    FILE *file = vlc_fopen (tmpname, "wb");
453
    if (file == NULL)
454
455
456
457
458
    {
        if (errno != EACCES && errno != ENOENT)
            msg_Warn (p_this, "cannot create %s (%m)", tmpname);
        goto out;
    }
459

460
    if (CacheSaveBank (file, pp_cache, n))
461
462
463
464
    {
        msg_Warn (p_this, "cannot write %s (%m)", tmpname);
        clearerr (file);
        fclose (file);
465
        vlc_unlink (tmpname);
466
467
        goto out;
    }
468

469
#if !defined( WIN32 ) && !defined( __OS2__ )
470
    vlc_rename (tmpname, filename); /* atomically replace old cache */
471
472
    fclose (file);
#else
473
    vlc_unlink (filename);
474
    fclose (file);
475
    vlc_rename (tmpname, filename);
476
#endif
477
out:
478
479
    free (filename);
    free (tmpname);
480
481
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
482
483
static int CacheSaveConfig (FILE *, const module_t *);
static int CacheSaveSubmodule (FILE *, const module_t *);
484

485
486
static int CacheSaveBank (FILE *file, module_cache_t *const *pp_cache,
                          size_t i_cache)
487
488
489
{
    uint32_t i_file_size = 0;

490
    /* Empty space for file size */
491
492
    if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1)
        goto error;
493
494

    /* Contains version number */
495
    if (fputs (CACHE_STRING, file) == EOF)
496
        goto error;
497
498
499
500
501
#ifdef DISTRO_VERSION
    /* Allow binary maintaner to pass a string to detect new binary version*/
    if (fputs( DISTRO_VERSION, file ) == EOF)
        goto error;
#endif
502
503
504
    /* Sub-version number (to avoid breakage in the dev version when cache
     * structure changes) */
    i_file_size = CACHE_SUBVERSION_NUM;
505
506
    if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1 )
        goto error;
507
508
509

    /* Header marker */
    i_file_size = ftell( file );
510
511
    if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1)
        goto error;
512

513
514
515
516
517
518
519
520
521
522
523
524
    if (fwrite( &i_cache, sizeof (i_cache), 1, file) != 1)
        goto error;

#define SAVE_IMMEDIATE( a ) \
    if (fwrite (&a, sizeof(a), 1, file) != 1) \
        goto error
#define SAVE_STRING( a ) \
    { \
        uint16_t i_size = (a != NULL) ? (strlen (a) + 1) : 0; \
        if ((fwrite (&i_size, sizeof (i_size), 1, file) != 1) \
         || (a && (fwrite (a, 1, i_size, file) != i_size))) \
            goto error; \
525
526
    } while(0)

527
    for (unsigned i = 0; i < i_cache; i++)
528
529
530
531
532
533
534
535
536
537
538
539
540
    {
        uint32_t i_submodule;

        /* Save common info */
        SAVE_STRING( pp_cache[i]->psz_file );
        SAVE_IMMEDIATE( pp_cache[i]->i_time );
        SAVE_IMMEDIATE( pp_cache[i]->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 );
541
542
543
544
        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] );

545
546
547
548
549
550
        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_IMMEDIATE( pp_cache[i]->p_module->b_submodule );

        /* Config stuff */
551
        if (CacheSaveConfig (file, pp_cache[i]->p_module))
552
            goto error;
553
554

        SAVE_STRING( pp_cache[i]->p_module->psz_filename );
555
        SAVE_STRING( pp_cache[i]->p_module->domain );
556

557
        i_submodule = pp_cache[i]->p_module->submodule_count;
558
        SAVE_IMMEDIATE( i_submodule );
559
560
        if( CacheSaveSubmodule( file, pp_cache[i]->p_module->submodule ) )
            goto error;
561
562
563
564
565
    }

    /* Fill-up file size */
    i_file_size = ftell( file );
    fseek( file, 0, SEEK_SET );
566
567
    if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1
     || fflush (file)) /* flush libc buffers */
568
        goto error;
569
    return 0; /* success! */
570
571

error:
572
    return -1;
573
574
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
575
static int CacheSaveSubmodule( FILE *file, const module_t *p_module )
576
{
577
578
579
    if( !p_module )
        return 0;
    if( CacheSaveSubmodule( file, p_module->next ) )
580
581
582
583
584
585
        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 );
586
587
588
    SAVE_IMMEDIATE( p_module->i_shortcuts );
    for( unsigned j = 0; j < p_module->i_shortcuts; j++ )
         SAVE_STRING( p_module->pp_shortcuts[j] );
589
590
591
592

    SAVE_STRING( p_module->psz_capability );
    SAVE_IMMEDIATE( p_module->i_score );
    SAVE_IMMEDIATE( p_module->b_unloadable );
593
    SAVE_STRING( p_module->domain );
594
595
596
597
598
599
600
    return 0;

error:
    return -1;
}


Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
601
static int CacheSaveConfig (FILE *file, const module_t *p_module)
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
{
    uint32_t i_lines = p_module->confsize;

    SAVE_IMMEDIATE( p_module->i_config_items );
    SAVE_IMMEDIATE( p_module->i_bool_items );
    SAVE_IMMEDIATE( i_lines );

    for (size_t i = 0; i < i_lines ; i++)
    {
        SAVE_IMMEDIATE( p_module->p_config[i] );

        SAVE_STRING( p_module->p_config[i].psz_type );
        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 );
617
618
619
        SAVE_STRING( p_module->p_config[i].psz_oldname );
        SAVE_IMMEDIATE( p_module->p_config[i].b_removed );

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
        if (IsConfigStringType (p_module->p_config[i].i_type))
            SAVE_STRING( p_module->p_config[i].orig.psz );

        if( p_module->p_config[i].i_list )
        {
            if( p_module->p_config[i].ppsz_list )
            {
                for (int j = 0; j < p_module->p_config[i].i_list; j++)
                    SAVE_STRING( p_module->p_config[i].ppsz_list[j] );
            }

            if( p_module->p_config[i].ppsz_list_text )
            {
                for (int j = 0; j < p_module->p_config[i].i_list; j++)
                    SAVE_STRING( p_module->p_config[i].ppsz_list_text[j] );
            }
            if( p_module->p_config[i].pi_list )
            {
                for (int j = 0; j < p_module->p_config[i].i_list; j++)
                    SAVE_IMMEDIATE( p_module->p_config[i].pi_list[j] );
            }
        }

        for (int j = 0; j < p_module->p_config[i].i_action; j++)
            SAVE_STRING( p_module->p_config[i].ppsz_action_text[j] );
    }
646
647
648
649
    return 0;

error:
    return -1;
650
651
652
653
654
655
656
657
658
659
660
661
662
}

/*****************************************************************************
 * CacheMerge: Merge a cache module descriptor with a full module descriptor.
 *****************************************************************************/
void CacheMerge( vlc_object_t *p_this, module_t *p_cache, module_t *p_module )
{
    (void)p_this;

    p_cache->pf_activate = p_module->pf_activate;
    p_cache->pf_deactivate = p_module->pf_deactivate;
    p_cache->handle = p_module->handle;

663
664
665
666
667
668
    /* FIXME: This looks too simplistic an algorithm to me. What if the module
     * file was altered such that the number of order of submodules was
     * altered... after VLC started -- Courmisch, 09/2008 */
    module_t *p_child = p_module->submodule,
             *p_cchild = p_cache->submodule;
    while( p_child && p_cchild )
669
670
671
    {
        p_cchild->pf_activate = p_child->pf_activate;
        p_cchild->pf_deactivate = p_child->pf_deactivate;
672
673
        p_child = p_child->next;
        p_cchild = p_cchild->next;
674
675
    }

676
677
    p_cache->b_loaded = true;
    p_module->b_loaded = false;
678
679
680
681
682
}

/*****************************************************************************
 * CacheFind: finds the cache entry corresponding to a file
 *****************************************************************************/
683
module_cache_t *CacheFind( module_bank_t *p_bank, const char *psz_file,
684
685
686
687
688
                           int64_t i_time, int64_t i_size )
{
    module_cache_t **pp_cache;
    int i_cache, i;

689
690
    pp_cache = p_bank->pp_loaded_cache;
    i_cache = p_bank->i_loaded_cache;
691
692
693
694
695
696
697
698
699
700
701
702

    for( i = 0; i < i_cache; i++ )
    {
        if( !strcmp( pp_cache[i]->psz_file, psz_file ) &&
            pp_cache[i]->i_time == i_time &&
            pp_cache[i]->i_size == i_size ) return pp_cache[i];
    }

    return NULL;
}

#endif /* HAVE_DYNAMIC_PLUGINS */