cache.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:25k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * cache.c: Plugins cache
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2007 the VideoLAN team
  5.  * $Id: 89d1a99a6d51f0a798c25fc33b2133097c058f5e $
  6.  *
  7.  * Authors: Sam Hocevar <sam@zoy.org>
  8.  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
  9.  *          Hans-Peter Jansen <hpj@urpla.net>
  10.  *          Gildas Bazin <gbazin@videolan.org>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include "libvlc.h"
  31. #include <stdlib.h>                                      /* free(), strtol() */
  32. #include <stdio.h>                                              /* sprintf() */
  33. #include <string.h>                                              /* strdup() */
  34. #include <vlc_plugin.h>
  35. #ifdef HAVE_SYS_TYPES_H
  36. #   include <sys/types.h>
  37. #endif
  38. #ifdef HAVE_UNISTD_H
  39. #   include <unistd.h>
  40. #endif
  41. #if !defined(HAVE_DYNAMIC_PLUGINS)
  42.     /* no support for plugins */
  43. #elif defined(HAVE_DL_DYLD)
  44. #   if defined(HAVE_MACH_O_DYLD_H)
  45. #       include <mach-o/dyld.h>
  46. #   endif
  47. #elif defined(HAVE_DL_BEOS)
  48. #   if defined(HAVE_IMAGE_H)
  49. #       include <image.h>
  50. #   endif
  51. #elif defined(HAVE_DL_WINDOWS)
  52. #   include <windows.h>
  53. #elif defined(HAVE_DL_DLOPEN)
  54. #   if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
  55. #       include <dlfcn.h>
  56. #   endif
  57. #   if defined(HAVE_SYS_DL_H)
  58. #       include <sys/dl.h>
  59. #   endif
  60. #elif defined(HAVE_DL_SHL_LOAD)
  61. #   if defined(HAVE_DL_H)
  62. #       include <dl.h>
  63. #   endif
  64. #endif
  65. #include "config/configuration.h"
  66. #include "vlc_charset.h"
  67. #include "modules/modules.h"
  68. /*****************************************************************************
  69.  * Local prototypes
  70.  *****************************************************************************/
  71. #ifdef HAVE_DYNAMIC_PLUGINS
  72. static int    CacheLoadConfig  ( module_t *, FILE * );
  73. static int    CacheSaveConfig  ( module_t *, FILE * );
  74. /* Sub-version number
  75.  * (only used to avoid breakage in dev version when cache structure changes) */
  76. #define CACHE_SUBVERSION_NUM 4
  77. /* Format string for the cache filename */
  78. #define CACHENAME_FORMAT 
  79.     "plugins-%.2zx%.2zx%.2"PRIx8".dat"
  80. /* Magic for the cache filename */
  81. #define CACHENAME_VALUES 
  82.     sizeof(int), sizeof(void *), *(uint8_t *)&(uint16_t){ 0xbe1e }
  83. /*****************************************************************************
  84.  * LoadPluginsCache: loads the plugins cache file
  85.  *****************************************************************************
  86.  * This function will load the plugin cache if present and valid. This cache
  87.  * will in turn be queried by AllocateAllPlugins() to see if it needs to
  88.  * actually load the dynamically loadable module.
  89.  * This allows us to only fully load plugins when they are actually used.
  90.  *****************************************************************************/
  91. void CacheLoad( vlc_object_t *p_this, module_bank_t *p_bank, bool b_delete )
  92. {
  93.     char *psz_filename, *psz_cachedir = config_GetCacheDir();
  94.     FILE *file;
  95.     int i, j, i_size, i_read;
  96.     char p_cachestring[sizeof("cache " COPYRIGHT_MESSAGE)];
  97.     char p_cachelang[6], p_lang[6];
  98.     int i_cache;
  99.     module_cache_t **pp_cache = 0;
  100.     int32_t i_file_size, i_marker;
  101.     if( !psz_cachedir ) /* XXX: this should never happen */
  102.     {
  103.         msg_Err( p_this, "Unable to get cache directory" );
  104.         return;
  105.     }
  106.     if( asprintf( &psz_filename, "%s"DIR_SEP CACHENAME_FORMAT,
  107.                   psz_cachedir, CACHENAME_VALUES ) == -1 )
  108.     {
  109.         free( psz_cachedir );
  110.         return;
  111.     }
  112.     free( psz_cachedir );
  113.     if( b_delete )
  114.     {
  115. #if !defined( UNDER_CE )
  116.         unlink( psz_filename );
  117. #else
  118.         wchar_t psz_wf[MAX_PATH];
  119.         MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_wf, MAX_PATH );
  120.         DeleteFile( psz_wf );
  121. #endif
  122.         msg_Dbg( p_this, "removing plugins cache file %s", psz_filename );
  123.         free( psz_filename );
  124.         return;
  125.     }
  126.     msg_Dbg( p_this, "loading plugins cache file %s", psz_filename );
  127.     file = utf8_fopen( psz_filename, "rb" );
  128.     if( !file )
  129.     {
  130.         msg_Warn( p_this, "could not open plugins cache file %s for reading",
  131.                   psz_filename );
  132.         free( psz_filename );
  133.         return;
  134.     }
  135.     free( psz_filename );
  136.     /* Check the file size */
  137.     i_read = fread( &i_file_size, 1, sizeof(i_file_size), file );
  138.     if( i_read != sizeof(i_file_size) )
  139.     {
  140.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  141.                   "(too short)" );
  142.         fclose( file );
  143.         return;
  144.     }
  145.     fseek( file, 0, SEEK_END );
  146.     if( ftell( file ) != i_file_size )
  147.     {
  148.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  149.                   "(corrupted size)" );
  150.         fclose( file );
  151.         return;
  152.     }
  153.     fseek( file, sizeof(i_file_size), SEEK_SET );
  154.     /* Check the file is a plugins cache */
  155.     i_size = sizeof("cache " COPYRIGHT_MESSAGE) - 1;
  156.     i_read = fread( p_cachestring, 1, i_size, file );
  157.     if( i_read != i_size ||
  158.         memcmp( p_cachestring, "cache " COPYRIGHT_MESSAGE, i_size ) )
  159.     {
  160.         msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
  161.         fclose( file );
  162.         return;
  163.     }
  164. #ifdef DISTRO_VERSION
  165.     /* Check for distribution specific version */
  166.     char p_distrostring[sizeof( DISTRO_VERSION )];
  167.     i_size = sizeof( DISTRO_VERSION ) - 1;
  168.     i_read = fread( p_distrostring, 1, i_size, file );
  169.     if( i_read != i_size ||
  170.         memcmp( p_distrostring, DISTRO_VERSION, i_size ) )
  171.     {
  172.         msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
  173.         fclose( file );
  174.         return;
  175.     }
  176. #endif
  177.     /* Check Sub-version number */
  178.     i_read = fread( &i_marker, 1, sizeof(i_marker), file );
  179.     if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM )
  180.     {
  181.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  182.                   "(corrupted header)" );
  183.         fclose( file );
  184.         return;
  185.     }
  186.     /* Check the language hasn't changed */
  187.     sprintf( p_lang, "%5.5s", _("C") ); i_size = 5;
  188.     i_read = fread( p_cachelang, 1, i_size, file );
  189.     if( i_read != i_size || memcmp( p_cachelang, p_lang, i_size ) )
  190.     {
  191.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  192.                   "(language changed)" );
  193.         fclose( file );
  194.         return;
  195.     }
  196.     /* Check header marker */
  197.     i_read = fread( &i_marker, 1, sizeof(i_marker), file );
  198.     if( i_read != sizeof(i_marker) ||
  199.         i_marker != ftell( file ) - (int)sizeof(i_marker) )
  200.     {
  201.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  202.                   "(corrupted header)" );
  203.         fclose( file );
  204.         return;
  205.     }
  206.     p_bank->i_loaded_cache = 0;
  207.     if (fread( &i_cache, 1, sizeof(i_cache), file ) != sizeof(i_cache) )
  208.     {
  209.         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
  210.                   "(file too short)" );
  211.         fclose( file );
  212.         return;
  213.     }
  214.     if( i_cache )
  215.         pp_cache = p_bank->pp_loaded_cache =
  216.                    malloc( i_cache * sizeof(void *) );
  217. #define LOAD_IMMEDIATE(a) 
  218.     if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
  219. #define LOAD_STRING(a) 
  220.     a = NULL; 
  221.     if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) 
  222.      || ( i_size > 16384 ) ) 
  223.         goto error; 
  224.     if( i_size ) { 
  225.         char *psz = malloc( i_size ); 
  226.         if( fread( psz, i_size, 1, file ) != 1 ) { 
  227.             free( psz ); 
  228.             goto error; 
  229.         } 
  230.         if( psz[i_size-1] ) { 
  231.             free( psz ); 
  232.             goto error; 
  233.         } 
  234.         a = psz; 
  235.     } 
  236. }
  237.     for( i = 0; i < i_cache; i++ )
  238.     {
  239.         uint16_t i_size;
  240.         int i_submodules;
  241.         pp_cache[i] = malloc( sizeof(module_cache_t) );
  242.         p_bank->i_loaded_cache++;
  243.         /* Load common info */
  244.         LOAD_STRING( pp_cache[i]->psz_file );
  245.         LOAD_IMMEDIATE( pp_cache[i]->i_time );
  246.         LOAD_IMMEDIATE( pp_cache[i]->i_size );
  247.         LOAD_IMMEDIATE( pp_cache[i]->b_junk );
  248.         pp_cache[i]->b_used = false;
  249.         if( pp_cache[i]->b_junk ) continue;
  250.         pp_cache[i]->p_module = vlc_module_create( p_this );
  251.         /* Load additional infos */
  252.         free( pp_cache[i]->p_module->psz_object_name );
  253.         LOAD_STRING( pp_cache[i]->p_module->psz_object_name );
  254.         LOAD_STRING( pp_cache[i]->p_module->psz_shortname );
  255.         LOAD_STRING( pp_cache[i]->p_module->psz_longname );
  256.         LOAD_STRING( pp_cache[i]->p_module->psz_help );
  257.         for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
  258.         {
  259.             LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); // FIX
  260.         }
  261.         LOAD_STRING( pp_cache[i]->p_module->psz_capability );
  262.         LOAD_IMMEDIATE( pp_cache[i]->p_module->i_score );
  263.         LOAD_IMMEDIATE( pp_cache[i]->p_module->i_cpu );
  264.         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
  265.         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
  266.         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
  267.         /* Config stuff */
  268.         if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
  269.             goto error;
  270.         LOAD_STRING( pp_cache[i]->p_module->psz_filename );
  271.         LOAD_IMMEDIATE( i_submodules );
  272.         while( i_submodules-- )
  273.         {
  274.             module_t *p_module = vlc_submodule_create( pp_cache[i]->p_module );
  275.             free( p_module->psz_object_name );
  276.             LOAD_STRING( p_module->psz_object_name );
  277.             LOAD_STRING( p_module->psz_shortname );
  278.             LOAD_STRING( p_module->psz_longname );
  279.             LOAD_STRING( p_module->psz_help );
  280.             for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
  281.             {
  282.                 LOAD_STRING( p_module->pp_shortcuts[j] ); // FIX
  283.             }
  284.             LOAD_STRING( p_module->psz_capability );
  285.             LOAD_IMMEDIATE( p_module->i_score );
  286.             LOAD_IMMEDIATE( p_module->i_cpu );
  287.             LOAD_IMMEDIATE( p_module->b_unloadable );
  288.             LOAD_IMMEDIATE( p_module->b_reentrant );
  289.         }
  290.     }
  291.     fclose( file );
  292.     return;
  293.  error:
  294.     msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
  295.     /* TODO: cleanup */
  296.     p_bank->i_loaded_cache = 0;
  297.     fclose( file );
  298.     return;
  299. }
  300. static int CacheLoadConfig( module_t *p_module, FILE *file )
  301. {
  302.     uint32_t i_lines;
  303.     uint16_t i_size;
  304.     /* Calculate the structure length */
  305.     LOAD_IMMEDIATE( p_module->i_config_items );
  306.     LOAD_IMMEDIATE( p_module->i_bool_items );
  307.     LOAD_IMMEDIATE( i_lines );
  308.     /* Allocate memory */
  309.     if (i_lines)
  310.     {
  311.         p_module->p_config =
  312.             (module_config_t *)calloc( i_lines, sizeof(module_config_t) );
  313.         if( p_module->p_config == NULL )
  314.         {
  315.             p_module->confsize = 0;
  316.             return VLC_ENOMEM;
  317.         }
  318.     }
  319.     p_module->confsize = i_lines;
  320.     /* Do the duplication job */
  321.     for (size_t i = 0; i < i_lines; i++ )
  322.     {
  323.         LOAD_IMMEDIATE( p_module->p_config[i] );
  324.         LOAD_STRING( p_module->p_config[i].psz_type );
  325.         LOAD_STRING( p_module->p_config[i].psz_name );
  326.         LOAD_STRING( p_module->p_config[i].psz_text );
  327.         LOAD_STRING( p_module->p_config[i].psz_longtext );
  328.         LOAD_STRING( p_module->p_config[i].psz_oldname );
  329.         LOAD_IMMEDIATE( p_module->p_config[i].b_removed );
  330.         if (IsConfigStringType (p_module->p_config[i].i_type))
  331.         {
  332.             LOAD_STRING (p_module->p_config[i].orig.psz);
  333.             p_module->p_config[i].value.psz =
  334.                     (p_module->p_config[i].orig.psz != NULL)
  335.                         ? strdup (p_module->p_config[i].orig.psz) : NULL;
  336.             p_module->p_config[i].saved.psz = NULL;
  337.         }
  338.         else
  339.         {
  340.             memcpy (&p_module->p_config[i].value, &p_module->p_config[i].orig,
  341.                     sizeof (p_module->p_config[i].value));
  342.             memcpy (&p_module->p_config[i].saved, &p_module->p_config[i].orig,
  343.                     sizeof (p_module->p_config[i].saved));
  344.         }
  345.         p_module->p_config[i].b_dirty = false;
  346.         p_module->p_config[i].p_lock = &p_module->lock;
  347.         if( p_module->p_config[i].i_list )
  348.         {
  349.             if( p_module->p_config[i].ppsz_list )
  350.             {
  351.                 int j;
  352.                 p_module->p_config[i].ppsz_list =
  353.                     malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
  354.                 if( p_module->p_config[i].ppsz_list )
  355.                 {
  356.                     for( j = 0; j < p_module->p_config[i].i_list; j++ )
  357.                         LOAD_STRING( p_module->p_config[i].ppsz_list[j] );
  358.                     p_module->p_config[i].ppsz_list[j] = NULL;
  359.                 }
  360.             }
  361.             if( p_module->p_config[i].ppsz_list_text )
  362.             {
  363.                 int j;
  364.                 p_module->p_config[i].ppsz_list_text =
  365.                     malloc( (p_module->p_config[i].i_list+1) * sizeof(char *));
  366.                 if( p_module->p_config[i].ppsz_list_text )
  367.                 {
  368.                   for( j = 0; j < p_module->p_config[i].i_list; j++ )
  369.                       LOAD_STRING( p_module->p_config[i].ppsz_list_text[j] );
  370.                   p_module->p_config[i].ppsz_list_text[j] = NULL;
  371.                 }
  372.             }
  373.             if( p_module->p_config[i].pi_list )
  374.             {
  375.                 p_module->p_config[i].pi_list =
  376.                     malloc( (p_module->p_config[i].i_list + 1) * sizeof(int) );
  377.                 if( p_module->p_config[i].pi_list )
  378.                 {
  379.                     for (int j = 0; j < p_module->p_config[i].i_list; j++)
  380.                         LOAD_IMMEDIATE( p_module->p_config[i].pi_list[j] );
  381.                 }
  382.             }
  383.         }
  384.         if( p_module->p_config[i].i_action )
  385.         {
  386.             p_module->p_config[i].ppf_action =
  387.                 malloc( p_module->p_config[i].i_action * sizeof(void *) );
  388.             p_module->p_config[i].ppsz_action_text =
  389.                 malloc( p_module->p_config[i].i_action * sizeof(char *) );
  390.             for (int j = 0; j < p_module->p_config[i].i_action; j++)
  391.             {
  392.                 p_module->p_config[i].ppf_action[j] = 0;
  393.                 LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] );
  394.             }
  395.         }
  396.         LOAD_IMMEDIATE( p_module->p_config[i].pf_callback );
  397.     }
  398.     return VLC_SUCCESS;
  399.  error:
  400.     return VLC_EGENERIC;
  401. }
  402. static int CacheSaveSubmodule( FILE *file, module_t *p_module );
  403. /*****************************************************************************
  404.  * SavePluginsCache: saves the plugins cache to a file
  405.  *****************************************************************************/
  406. void CacheSave( vlc_object_t *p_this, module_bank_t *p_bank )
  407. {
  408.     static char const psz_tag[] =
  409.         "Signature: 8a477f597d28d172789f06886806bc55rn"
  410.         "# This file is a cache directory tag created by VLC.rn"
  411.         "# For information about cache directory tags, see:rn"
  412.         "#   http://www.brynosaurus.com/cachedir/rn";
  413.     char *psz_cachedir = config_GetCacheDir();
  414.     FILE *file;
  415.     int i, j, i_cache;
  416.     module_cache_t **pp_cache;
  417.     uint32_t i_file_size = 0;
  418.     if( !psz_cachedir ) /* XXX: this should never happen */
  419.     {
  420.         msg_Err( p_this, "unable to get cache directory" );
  421.         return;
  422.     }
  423.     char psz_filename[sizeof(DIR_SEP) + 32 + strlen(psz_cachedir)];
  424.     config_CreateDir( p_this, psz_cachedir );
  425.     snprintf( psz_filename, sizeof( psz_filename ),
  426.               "%s"DIR_SEP"CACHEDIR.TAG", psz_cachedir );
  427.     file = utf8_fopen( psz_filename, "wb" );
  428.     if (file != NULL)
  429.     {
  430.         if (fwrite (psz_tag, 1, sizeof (psz_tag) - 1, file) != 1)
  431.             clearerr (file); /* what else can we do? */
  432.         fclose( file );
  433.     }
  434.     snprintf( psz_filename, sizeof( psz_filename ),
  435.               "%s"DIR_SEP CACHENAME_FORMAT, psz_cachedir,
  436.               CACHENAME_VALUES );
  437.     free( psz_cachedir );
  438.     msg_Dbg( p_this, "writing plugins cache %s", psz_filename );
  439.     char psz_tmpname[sizeof (psz_filename) + 12];
  440.     snprintf (psz_tmpname, sizeof (psz_tmpname), "%s.%"PRIu32, psz_filename,
  441. #ifdef UNDER_CE
  442.               (uint32_t)GetCurrentProcessId ()
  443. #else
  444.               (uint32_t)getpid ()
  445. #endif
  446.              );
  447.     file = utf8_fopen( psz_tmpname, "wb" );
  448.     if (file == NULL)
  449.         goto error;
  450.     /* Empty space for file size */
  451.     if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1)
  452.         goto error;
  453.     /* Contains version number */
  454.     if (fputs ("cache "COPYRIGHT_MESSAGE, file) == EOF)
  455.         goto error;
  456. #ifdef DISTRO_VERSION
  457.     /* Allow binary maintaner to pass a string to detect new binary version*/
  458.     if (fputs( DISTRO_VERSION, file ) == EOF)
  459.         goto error;
  460. #endif
  461.     /* Sub-version number (to avoid breakage in the dev version when cache
  462.      * structure changes) */
  463.     i_file_size = CACHE_SUBVERSION_NUM;
  464.     if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1 )
  465.         goto error;
  466.     /* Language */
  467.     if (fprintf (file, "%5.5s", _("C")) == EOF)
  468.         goto error;
  469.     /* Header marker */
  470.     i_file_size = ftell( file );
  471.     if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1)
  472.         goto error;
  473.     i_cache = p_bank->i_cache;
  474.     pp_cache = p_bank->pp_cache;
  475.     if (fwrite( &i_cache, sizeof (i_cache), 1, file) != 1)
  476.         goto error;
  477. #define SAVE_IMMEDIATE( a ) 
  478.     if (fwrite (&a, sizeof(a), 1, file) != 1) 
  479.         goto error
  480. #define SAVE_STRING( a ) 
  481.     { 
  482.         uint16_t i_size = (a != NULL) ? (strlen (a) + 1) : 0; 
  483.         if ((fwrite (&i_size, sizeof (i_size), 1, file) != 1) 
  484.          || (a && (fwrite (a, 1, i_size, file) != i_size))) 
  485.             goto error; 
  486.     } while(0)
  487.     for( i = 0; i < i_cache; i++ )
  488.     {
  489.         uint32_t i_submodule;
  490.         /* Save common info */
  491.         SAVE_STRING( pp_cache[i]->psz_file );
  492.         SAVE_IMMEDIATE( pp_cache[i]->i_time );
  493.         SAVE_IMMEDIATE( pp_cache[i]->i_size );
  494.         SAVE_IMMEDIATE( pp_cache[i]->b_junk );
  495.         if( pp_cache[i]->b_junk ) continue;
  496.         /* Save additional infos */
  497.         SAVE_STRING( pp_cache[i]->p_module->psz_object_name );
  498.         SAVE_STRING( pp_cache[i]->p_module->psz_shortname );
  499.         SAVE_STRING( pp_cache[i]->p_module->psz_longname );
  500.         SAVE_STRING( pp_cache[i]->p_module->psz_help );
  501.         for( j = 0; j < MODULE_SHORTCUT_MAX; j++ )
  502.         {
  503.             SAVE_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); // FIX
  504.         }
  505.         SAVE_STRING( pp_cache[i]->p_module->psz_capability );
  506.         SAVE_IMMEDIATE( pp_cache[i]->p_module->i_score );
  507.         SAVE_IMMEDIATE( pp_cache[i]->p_module->i_cpu );
  508.         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
  509.         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
  510.         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
  511.         /* Config stuff */
  512.         if (CacheSaveConfig (pp_cache[i]->p_module, file))
  513.             goto error;
  514.         SAVE_STRING( pp_cache[i]->p_module->psz_filename );
  515.         i_submodule = pp_cache[i]->p_module->submodule_count;
  516.         SAVE_IMMEDIATE( i_submodule );
  517.         if( CacheSaveSubmodule( file, pp_cache[i]->p_module->submodule ) )
  518.             goto error;
  519.     }
  520.     /* Fill-up file size */
  521.     i_file_size = ftell( file );
  522.     fseek( file, 0, SEEK_SET );
  523.     if (fwrite (&i_file_size, sizeof (i_file_size), 1, file) != 1
  524.      || fflush (file)) /* flush libc buffers */
  525.         goto error;
  526. #ifndef WIN32
  527.     utf8_rename (psz_tmpname, psz_filename); /* atomically replace old cache */
  528.     fclose (file);
  529. #else
  530.     utf8_unlink (psz_filename);
  531.     fclose (file);
  532.     utf8_rename (psz_tmpname, psz_filename);
  533. #endif
  534.     return; /* success! */
  535. error:
  536.     msg_Warn (p_this, "could not write plugins cache %s (%m)",
  537.               psz_filename);
  538.     if (file != NULL)
  539.     {
  540.         clearerr (file);
  541.         fclose (file);
  542.     }
  543. }
  544. static int CacheSaveSubmodule( FILE *file, module_t *p_module )
  545. {
  546.     if( !p_module )
  547.         return 0;
  548.     if( CacheSaveSubmodule( file, p_module->next ) )
  549.         goto error;
  550.     SAVE_STRING( p_module->psz_object_name );
  551.     SAVE_STRING( p_module->psz_shortname );
  552.     SAVE_STRING( p_module->psz_longname );
  553.     SAVE_STRING( p_module->psz_help );
  554.     for( unsigned j = 0; j < MODULE_SHORTCUT_MAX; j++ )
  555.          SAVE_STRING( p_module->pp_shortcuts[j] ); // FIXME
  556.     SAVE_STRING( p_module->psz_capability );
  557.     SAVE_IMMEDIATE( p_module->i_score );
  558.     SAVE_IMMEDIATE( p_module->i_cpu );
  559.     SAVE_IMMEDIATE( p_module->b_unloadable );
  560.     SAVE_IMMEDIATE( p_module->b_reentrant );
  561.     return 0;
  562. error:
  563.     return -1;
  564. }
  565. static int CacheSaveConfig( module_t *p_module, FILE *file )
  566. {
  567.     uint32_t i_lines = p_module->confsize;
  568.     SAVE_IMMEDIATE( p_module->i_config_items );
  569.     SAVE_IMMEDIATE( p_module->i_bool_items );
  570.     SAVE_IMMEDIATE( i_lines );
  571.     for (size_t i = 0; i < i_lines ; i++)
  572.     {
  573.         SAVE_IMMEDIATE( p_module->p_config[i] );
  574.         SAVE_STRING( p_module->p_config[i].psz_type );
  575.         SAVE_STRING( p_module->p_config[i].psz_name );
  576.         SAVE_STRING( p_module->p_config[i].psz_text );
  577.         SAVE_STRING( p_module->p_config[i].psz_longtext );
  578.         SAVE_STRING( p_module->p_config[i].psz_oldname );
  579.         SAVE_IMMEDIATE( p_module->p_config[i].b_removed );
  580.         if (IsConfigStringType (p_module->p_config[i].i_type))
  581.             SAVE_STRING( p_module->p_config[i].orig.psz );
  582.         if( p_module->p_config[i].i_list )
  583.         {
  584.             if( p_module->p_config[i].ppsz_list )
  585.             {
  586.                 for (int j = 0; j < p_module->p_config[i].i_list; j++)
  587.                     SAVE_STRING( p_module->p_config[i].ppsz_list[j] );
  588.             }
  589.             if( p_module->p_config[i].ppsz_list_text )
  590.             {
  591.                 for (int j = 0; j < p_module->p_config[i].i_list; j++)
  592.                     SAVE_STRING( p_module->p_config[i].ppsz_list_text[j] );
  593.             }
  594.             if( p_module->p_config[i].pi_list )
  595.             {
  596.                 for (int j = 0; j < p_module->p_config[i].i_list; j++)
  597.                     SAVE_IMMEDIATE( p_module->p_config[i].pi_list[j] );
  598.             }
  599.         }
  600.         for (int j = 0; j < p_module->p_config[i].i_action; j++)
  601.             SAVE_STRING( p_module->p_config[i].ppsz_action_text[j] );
  602.         SAVE_IMMEDIATE( p_module->p_config[i].pf_callback );
  603.     }
  604.     return 0;
  605. error:
  606.     return -1;
  607. }
  608. /*****************************************************************************
  609.  * CacheMerge: Merge a cache module descriptor with a full module descriptor.
  610.  *****************************************************************************/
  611. void CacheMerge( vlc_object_t *p_this, module_t *p_cache, module_t *p_module )
  612. {
  613.     (void)p_this;
  614.     p_cache->pf_activate = p_module->pf_activate;
  615.     p_cache->pf_deactivate = p_module->pf_deactivate;
  616.     p_cache->handle = p_module->handle;
  617.     /* FIXME: This looks too simplistic an algorithm to me. What if the module
  618.      * file was altered such that the number of order of submodules was
  619.      * altered... after VLC started -- Courmisch, 09/2008 */
  620.     module_t *p_child = p_module->submodule,
  621.              *p_cchild = p_cache->submodule;
  622.     while( p_child && p_cchild )
  623.     {
  624.         p_cchild->pf_activate = p_child->pf_activate;
  625.         p_cchild->pf_deactivate = p_child->pf_deactivate;
  626.         p_child = p_child->next;
  627.         p_cchild = p_cchild->next;
  628.     }
  629.     p_cache->b_loaded = true;
  630.     p_module->b_loaded = false;
  631. }
  632. /*****************************************************************************
  633.  * CacheFind: finds the cache entry corresponding to a file
  634.  *****************************************************************************/
  635. module_cache_t *CacheFind( module_bank_t *p_bank, const char *psz_file,
  636.                            int64_t i_time, int64_t i_size )
  637. {
  638.     module_cache_t **pp_cache;
  639.     int i_cache, i;
  640.     pp_cache = p_bank->pp_loaded_cache;
  641.     i_cache = p_bank->i_loaded_cache;
  642.     for( i = 0; i < i_cache; i++ )
  643.     {
  644.         if( !strcmp( pp_cache[i]->psz_file, psz_file ) &&
  645.             pp_cache[i]->i_time == i_time &&
  646.             pp_cache[i]->i_size == i_size ) return pp_cache[i];
  647.     }
  648.     return NULL;
  649. }
  650. #endif /* HAVE_DYNAMIC_PLUGINS */