Changeset e03e85ca01adc1639db0f9bf90aadf8d20c2cbeb

Show
Ignore:
Timestamp:
12/12/07 17:43:52 (1 year ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1197477832 +0000
git-parent:

[f0ec1547757b30942f4083d658c4a80ffc44af46]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1197477832 +0000
Message:

Split the over-large module.c

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/Makefile.am

    r2d9c9ee re03e85c  
    296296    modules/modules.h \ 
    297297    modules/modules.c \ 
     298    modules/cache.c \ 
    298299    modules/entry.c \ 
     300    modules/os.c \ 
    299301    misc/threads.c \ 
    300302    misc/stats.c \ 
  • src/modules/modules.c

    rf0ec154 re03e85c  
    2626 
    2727#include <vlc/vlc.h> 
    28 #include "../libvlc.h" 
     28#include "libvlc.h" 
    2929 
    3030/* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS 
     
    7878 
    7979#include "config/config.h" 
    80 #include "libvlc.h" 
    8180 
    8281#include "vlc_charset.h" 
     
    8483#include "modules/modules.h" 
    8584#include "modules/builtin.h" 
    86  
    87 #if defined( WIN32 ) || defined( UNDER_CE ) 
    88     /* Avoid name collisions */ 
    89 #   define LoadModule(a,b,c) LoadVlcModule(a,b,c) 
    90 #endif 
    9185 
    9286/***************************************************************************** 
     
    10498static void   DupModule        ( module_t * ); 
    10599static void   UndupModule      ( module_t * ); 
    106 static int    CallEntry        ( module_t * ); 
    107 static int    LoadModule       ( vlc_object_t *, char *, module_handle_t * ); 
    108 static void   CloseModule      ( module_handle_t ); 
    109 static void * GetSymbol        ( module_handle_t, const char * ); 
    110 static void   CacheLoad        ( vlc_object_t * ); 
    111 static int    CacheLoadConfig  ( module_t *, FILE * ); 
    112 static void   CacheSave        ( vlc_object_t * ); 
    113 static void   CacheSaveConfig  ( module_t *, FILE * ); 
    114 static char * CacheName        ( void ); 
    115 static void   CacheMerge       ( vlc_object_t *, module_t *, module_t * ); 
    116 static module_cache_t * CacheFind( vlc_object_t *, char *, int64_t, int64_t ); 
    117  
    118 #if defined(HAVE_DL_WINDOWS) 
    119 static char * GetWindowsError  ( void ); 
    120 #endif 
    121100#endif 
    122101 
    123102static void module_LoadMain( vlc_object_t *p_this ); 
    124  
    125 /* Sub-version number 
    126  * (only used to avoid breakage in dev version when cache structure changes) */ 
    127 #define CACHE_SUBVERSION_NUM 3 
    128103 
    129104/***************************************************************************** 
     
    11541129    module_handle_t handle; 
    11551130 
    1156     if( LoadModule( p_this, psz_file, &handle ) ) 
     1131    if( module_Load( p_this, psz_file, &handle ) ) 
    11571132        return NULL; 
    11581133 
     
    11631138    { 
    11641139        msg_Err( p_this, "out of memory" ); 
    1165         CloseModule( handle ); 
     1140        module_Unload( handle ); 
    11661141        return NULL; 
    11671142    } 
    11681143 
    1169     /* We need to fill these since they may be needed by CallEntry() */ 
     1144    /* We need to fill these since they may be needed by module_Call() */ 
    11701145    p_module->psz_filename = psz_file; 
    11711146    p_module->handle = handle; 
     
    11731148 
    11741149    /* Initialize the module: fill p_module, default config */ 
    1175     if( CallEntry( p_module ) != 0 ) 
     1150    if( module_Call( p_module ) != 0 ) 
    11761151    { 
    11771152        /* We couldn't call module_init() */ 
    11781153        vlc_object_destroy( p_module ); 
    1179         CloseModule( handle ); 
     1154        module_Unload( handle ); 
    11801155        return NULL; 
    11811156    } 
     
    13101285        if( p_module->b_loaded && p_module->b_unloadable ) 
    13111286        { 
    1312             CloseModule( p_module->handle ); 
     1287            module_Unload( p_module->handle ); 
    13131288        } 
    13141289        UndupModule( p_module ); 
     
    13301305    return 0; 
    13311306} 
    1332  
    1333 #ifdef HAVE_DYNAMIC_PLUGINS 
    1334 /***************************************************************************** 
    1335  * CallEntry: call an entry point. 
    1336  ***************************************************************************** 
    1337  * This function calls a symbol given its name and a module structure. The 
    1338  * symbol MUST refer to a function returning int and taking a module_t* as 
    1339  * an argument. 
    1340  *****************************************************************************/ 
    1341 static int CallEntry( module_t * p_module ) 
    1342 { 
    1343     static const char psz_name[] = "vlc_entry" MODULE_SUFFIX; 
    1344     int (* pf_symbol) ( module_t * p_module ); 
    1345  
    1346     /* Try to resolve the symbol */ 
    1347     pf_symbol = (int (*)(module_t *)) GetSymbol( p_module->handle, psz_name ); 
    1348  
    1349     if( pf_symbol == NULL ) 
    1350     { 
    1351 #if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS) 
    1352         msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s'", 
    1353                             psz_name, p_module->psz_filename ); 
    1354 #elif defined(HAVE_DL_WINDOWS) 
    1355         char *psz_error = GetWindowsError(); 
    1356         msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)", 
    1357                             psz_name, p_module->psz_filename, psz_error ); 
    1358         free( psz_error ); 
    1359 #elif defined(HAVE_DL_DLOPEN) 
    1360         msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)", 
    1361                             psz_name, p_module->psz_filename, dlerror() ); 
    1362 #elif defined(HAVE_DL_SHL_LOAD) 
    1363         msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%m)", 
    1364                             psz_name, p_module->psz_filename ); 
    1365 #else 
    1366 #   error "Something is wrong in modules.c" 
    1367 #endif 
    1368         return -1; 
    1369     } 
    1370  
    1371     /* We can now try to call the symbol */ 
    1372     if( pf_symbol( p_module ) != 0 ) 
    1373     { 
    1374         /* With a well-written module we shouldn't have to print an 
    1375          * additional error message here, but just make sure. */ 
    1376         msg_Err( p_module, "Failed to call symbol \"%s\" in file `%s'", 
    1377                            psz_name, p_module->psz_filename ); 
    1378         return -1; 
    1379     } 
    1380  
    1381     /* Everything worked fine, we can return */ 
    1382     return 0; 
    1383 } 
    1384  
    1385 /***************************************************************************** 
    1386  * LoadModule: loads a dynamic library 
    1387  ***************************************************************************** 
    1388  * This function loads a dynamically linked library using a system dependant 
    1389  * method. Will return 0 on success as well as the module handle. 
    1390  *****************************************************************************/ 
    1391 static int LoadModule( vlc_object_t *p_this, char *psz_file, 
    1392                        module_handle_t *p_handle ) 
    1393 { 
    1394     module_handle_t handle; 
    1395  
    1396 #if defined(HAVE_DL_DYLD) 
    1397     NSObjectFileImage image; 
    1398     NSObjectFileImageReturnCode ret; 
    1399  
    1400     ret = NSCreateObjectFileImageFromFile( psz_file, &image ); 
    1401  
    1402     if( ret != NSObjectFileImageSuccess ) 
    1403     { 
    1404         msg_Warn( p_this, "cannot create image from `%s'", psz_file ); 
    1405         return -1; 
    1406     } 
    1407  
    1408     /* Open the dynamic module */ 
    1409     handle = NSLinkModule( image, psz_file, 
    1410                            NSLINKMODULE_OPTION_RETURN_ON_ERROR ); 
    1411  
    1412     if( !handle ) 
    1413     { 
    1414         NSLinkEditErrors errors; 
    1415         const char *psz_file, *psz_err; 
    1416         int i_errnum; 
    1417         NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err ); 
    1418         msg_Warn( p_this, "cannot link module `%s' (%s)", psz_file, psz_err ); 
    1419         NSDestroyObjectFileImage( image ); 
    1420         return -1; 
    1421     } 
    1422  
    1423     /* Destroy our image, we won't need it */ 
    1424     NSDestroyObjectFileImage( image ); 
    1425  
    1426 #elif defined(HAVE_DL_BEOS) 
    1427     handle = load_add_on( psz_file ); 
    1428     if( handle < 0 ) 
    1429     { 
    1430         msg_Warn( p_this, "cannot load module `%s'", psz_file ); 
    1431         return -1; 
    1432     } 
    1433  
    1434 #elif defined(HAVE_DL_WINDOWS) 
    1435 #ifdef UNDER_CE 
    1436     { 
    1437         wchar_t psz_wfile[MAX_PATH]; 
    1438         MultiByteToWideChar( CP_ACP, 0, psz_file, -1, psz_wfile, MAX_PATH ); 
    1439         handle = LoadLibrary( psz_wfile ); 
    1440     } 
    1441 #else 
    1442     handle = LoadLibrary( psz_file ); 
    1443 #endif 
    1444     if( handle == NULL ) 
    1445     { 
    1446         char *psz_err = GetWindowsError(); 
    1447         msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, psz_err ); 
    1448         free( psz_err ); 
    1449         return -1; 
    1450     } 
    1451  
    1452 #elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW) 
    1453     /* static is OK, we are called atomically */ 
    1454     handle = dlopen( psz_file, RTLD_NOW ); 
    1455     if( handle == NULL ) 
    1456     { 
    1457         msg_Warn( p_this, "cannot load module `%s' (%s)", 
    1458                           psz_file, dlerror() ); 
    1459         return -1; 
    1460     } 
    1461  
    1462 #elif defined(HAVE_DL_DLOPEN) 
    1463 #   if defined(DL_LAZY) 
    1464     handle = dlopen( psz_file, DL_LAZY ); 
    1465 #   else 
    1466     handle = dlopen( psz_file, 0 ); 
    1467 #   endif 
    1468     if( handle == NULL ) 
    1469     { 
    1470         msg_Warn( p_this, "cannot load module `%s' (%s)", 
    1471                           psz_file, dlerror() ); 
    1472         return -1; 
    1473     } 
    1474  
    1475 #elif defined(HAVE_DL_SHL_LOAD) 
    1476     handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL ); 
    1477     if( handle == NULL ) 
    1478     { 
    1479         msg_Warn( p_this, "cannot load module `%s' (%m)", psz_file ); 
    1480         return -1; 
    1481     } 
    1482  
    1483 #else 
    1484 #   error "Something is wrong in modules.c" 
    1485  
    1486 #endif 
    1487  
    1488     *p_handle = handle; 
    1489     return 0; 
    1490 } 
    1491  
    1492 /***************************************************************************** 
    1493  * CloseModule: unload a dynamic library 
    1494  ***************************************************************************** 
    1495  * This function unloads a previously opened dynamically linked library 
    1496  * using a system dependant method. No return value is taken in consideration, 
    1497  * since some libraries sometimes refuse to close properly. 
    1498  *****************************************************************************/ 
    1499 static void CloseModule( module_handle_t handle ) 
    1500 { 
    1501 #if defined(HAVE_DL_DYLD) 
    1502     NSUnLinkModule( handle, FALSE ); 
    1503  
    1504 #elif defined(HAVE_DL_BEOS) 
    1505     unload_add_on( handle ); 
    1506  
    1507 #elif defined(HAVE_DL_WINDOWS) 
    1508     FreeLibrary( handle ); 
    1509  
    1510 #elif defined(HAVE_DL_DLOPEN) 
    1511 # ifdef NDEBUG 
    1512     dlclose( handle ); 
    1513 # endif 
    1514  
    1515 #elif defined(HAVE_DL_SHL_LOAD) 
    1516     shl_unload( handle ); 
    1517  
    1518 #endif 
    1519     return; 
    1520 } 
    1521  
    1522 /***************************************************************************** 
    1523  * GetSymbol: get a symbol from a dynamic library 
    1524  ***************************************************************************** 
    1525  * This function queries a loaded library for a symbol specified in a 
    1526  * string, and returns a pointer to it. We don't check for dlerror() or 
    1527  * similar functions, since we want a non-NULL symbol anyway. 
    1528  *****************************************************************************/ 
    1529 static void * _module_getsymbol( module_handle_t, const char * ); 
    1530  
    1531 static void * GetSymbol( module_handle_t handle, const char * psz_function ) 
    1532 { 
    1533     void * p_symbol = _module_getsymbol( handle, psz_function ); 
    1534  
    1535     /* MacOS X dl library expects symbols to begin with "_". So do 
    1536      * some other operating systems. That's really lame, but hey, what 
    1537      * can we do ? */ 
    1538     if( p_symbol == NULL ) 
    1539     { 
    1540         char psz_call[strlen( psz_function ) + 2]; 
    1541  
    1542         psz_call[ 0 ] = '_'; 
    1543         memcpy( psz_call + 1, psz_function, sizeof (psz_call) - 1 ); 
    1544         p_symbol = _module_getsymbol( handle, psz_call ); 
    1545     } 
    1546  
    1547     return p_symbol; 
    1548 } 
    1549  
    1550 static void * _module_getsymbol( module_handle_t handle, 
    1551                                  const char * psz_function ) 
    1552 { 
    1553 #if defined(HAVE_DL_DYLD) 
    1554     NSSymbol sym = NSLookupSymbolInModule( handle, psz_function ); 
    1555     return NSAddressOfSymbol( sym ); 
    1556  
    1557 #elif defined(HAVE_DL_BEOS) 
    1558     void * p_symbol; 
    1559     if( B_OK == get_image_symbol( handle, psz_function, 
    1560                                   B_SYMBOL_TYPE_TEXT, &p_symbol ) ) 
    1561     { 
    1562         return p_symbol; 
    1563     } 
    1564     else 
    1565     { 
    1566         return NULL; 
    1567     } 
    1568  
    1569 #elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE) 
    1570     wchar_t psz_real[256]; 
    1571     MultiByteToWideChar( CP_ACP, 0, psz_function, -1, psz_real, 256 ); 
    1572  
    1573     return (void *)GetProcAddress( handle, psz_real ); 
    1574  
    1575 #elif defined(HAVE_DL_WINDOWS) && defined(WIN32) 
    1576     return (void *)GetProcAddress( handle, (char *)psz_function ); 
    1577  
    1578 #elif defined(HAVE_DL_DLOPEN) 
    1579     return dlsym( handle, psz_function ); 
    1580  
    1581 #elif defined(HAVE_DL_SHL_LOAD) 
    1582     void *p_sym; 
    1583     shl_findsym( &handle, psz_function, TYPE_UNDEFINED, &p_sym ); 
    1584     return p_sym; 
    1585  
    1586 #endif 
    1587 } 
    1588  
    1589 #if defined(HAVE_DL_WINDOWS) 
    1590 static char * GetWindowsError( void ) 
    1591 { 
    1592 #if defined(UNDER_CE) 
    1593     wchar_t psz_tmp[MAX_PATH]; 
    1594     char * psz_buffer = malloc( MAX_PATH ); 
    1595 #else 
    1596     char * psz_tmp = malloc( MAX_PATH ); 
    1597 #endif 
    1598     int i = 0, i_error = GetLastError(); 
    1599  
    1600     FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
    1601                    NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), 
    1602                    (LPTSTR)psz_tmp, MAX_PATH, NULL ); 
    1603  
    1604     /* Go to the end of the string */ 
    1605     while( psz_tmp[i] && psz_tmp[i] != _T('\r') && psz_tmp[i] != _T('\n') ) 
    1606     { 
    1607         i++; 
    1608     } 
    1609  
    1610     if( psz_tmp[i] ) 
    1611     { 
    1612 #if defined(UNDER_CE) 
    1613         swprintf( psz_tmp + i, L" (error %i)", i_error ); 
    1614         psz_tmp[ 255 ] = L'\0'; 
    1615 #else 
    1616         snprintf( psz_tmp + i, 256 - i, " (error %i)", i_error ); 
    1617         psz_tmp[ 255 ] = '\0'; 
    1618 #endif 
    1619     } 
    1620  
    1621 #if defined(UNDER_CE) 
    1622     wcstombs( psz_buffer, psz_tmp, MAX_PATH ); 
    1623     return psz_buffer; 
    1624 #else 
    1625     return psz_tmp; 
    1626 #endif 
    1627 } 
    1628 #endif /* HAVE_DL_WINDOWS */ 
    1629  
    1630 /***************************************************************************** 
    1631  * LoadPluginsCache: loads the plugins cache file 
    1632  ***************************************************************************** 
    1633  * This function will load the plugin cache if present and valid. This cache 
    1634  * will in turn be queried by AllocateAllPlugins() to see if it needs to 
    1635  * actually load the dynamically loadable module. 
    1636  * This allows us to only fully load plugins when they are actually used. 
    1637  *****************************************************************************/ 
    1638 static void CacheLoad( vlc_object_t *p_this ) 
    1639 { 
    1640     char *psz_filename, *psz_cachedir; 
    1641     FILE *file; 
    1642     int i, j, i_size, i_read; 
    1643     char p_cachestring[sizeof("cache " COPYRIGHT_MESSAGE)]; 
    1644     char p_cachelang[6], p_lang[6]; 
    1645     int i_cache; 
    1646     module_cache_t **pp_cache = 0; 
    1647     int32_t i_file_size, i_marker; 
    1648     libvlc_global_data_t *p_libvlc_global = vlc_global(); 
    1649  
    1650     psz_cachedir = p_this->p_libvlc->psz_cachedir; 
    1651     if( !psz_cachedir ) /* XXX: this should never happen */ 
    1652     { 
    1653         msg_Err( p_this, "Unable to get cache directory" ); 
    1654         return; 
    1655     } 
    1656  
    1657     i_size = asprintf( &psz_filename, "%s"DIR_SEP"%s", 
    1658                        psz_cachedir, CacheName() ); 
    1659     if( i_size <= 0 ) 
    1660     { 
    1661         msg_Err( p_this, "out of memory" ); 
    1662         return; 
    1663     } 
    1664  
    1665     if( p_libvlc_global->p_module_bank->b_cache_delete ) 
    1666     { 
    1667 #if !defined( UNDER_CE ) 
    1668         unlink( psz_filename ); 
    1669 #else 
    1670         wchar_t psz_wf[MAX_PATH]; 
    1671         MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_wf, MAX_PATH ); 
    1672         DeleteFile( psz_wf ); 
    1673 #endif 
    1674         msg_Dbg( p_this, "removing plugins cache file %s", psz_filename ); 
    1675         free( psz_filename ); 
    1676         return; 
    1677     } 
    1678  
    1679     msg_Dbg( p_this, "loading plugins cache file %s", psz_filename ); 
    1680  
    1681     file = utf8_fopen( psz_filename, "rb" ); 
    1682     if( !file ) 
    1683     { 
    1684         msg_Warn( p_this, "could not open plugins cache file %s for reading", 
    1685                   psz_filename ); 
    1686         free( psz_filename ); 
    1687         return; 
    1688     } 
    1689     free( psz_filename ); 
    1690  
    1691     /* Check the file size */ 
    1692     i_read = fread( &i_file_size, 1, sizeof(i_file_size), file ); 
    1693     if( i_read != sizeof(i_file_size) ) 
    1694     { 
    1695         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1696                   "(too short)" ); 
    1697         fclose( file ); 
    1698         return; 
    1699     } 
    1700  
    1701     fseek( file, 0, SEEK_END ); 
    1702     if( ftell( file ) != i_file_size ) 
    1703     { 
    1704         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1705                   "(corrupted size)" ); 
    1706         fclose( file ); 
    1707         return; 
    1708     } 
    1709     fseek( file, sizeof(i_file_size), SEEK_SET ); 
    1710  
    1711     /* Check the file is a plugins cache */ 
    1712     i_size = sizeof("cache " COPYRIGHT_MESSAGE) - 1; 
    1713     i_read = fread( p_cachestring, 1, i_size, file ); 
    1714     if( i_read != i_size || 
    1715         memcmp( p_cachestring, "cache " COPYRIGHT_MESSAGE, i_size ) ) 
    1716     { 
    1717         msg_Warn( p_this, "This doesn't look like a valid plugins cache" ); 
    1718         fclose( file ); 
    1719         return; 
    1720     } 
    1721  
    1722     /* Check Sub-version number */ 
    1723     i_read = fread( &i_marker, 1, sizeof(i_marker), file ); 
    1724     if( i_read != sizeof(i_marker) || i_marker != CACHE_SUBVERSION_NUM ) 
    1725     { 
    1726         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1727                   "(corrupted header)" ); 
    1728         fclose( file ); 
    1729         return; 
    1730     } 
    1731  
    1732     /* Check the language hasn't changed */ 
    1733     sprintf( p_lang, "%5.5s", _("C") ); i_size = 5; 
    1734     i_read = fread( p_cachelang, 1, i_size, file ); 
    1735     if( i_read != i_size || memcmp( p_cachelang, p_lang, i_size ) ) 
    1736     { 
    1737         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1738                   "(language changed)" ); 
    1739         fclose( file ); 
    1740         return; 
    1741     } 
    1742  
    1743     /* Check header marker */ 
    1744     i_read = fread( &i_marker, 1, sizeof(i_marker), file ); 
    1745     if( i_read != sizeof(i_marker) || 
    1746         i_marker != ftell( file ) - (int)sizeof(i_marker) ) 
    1747     { 
    1748         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1749                   "(corrupted header)" ); 
    1750         fclose( file ); 
    1751         return; 
    1752     } 
    1753  
    1754     p_libvlc_global->p_module_bank->i_loaded_cache = 0; 
    1755     if (fread( &i_cache, 1, sizeof(i_cache), file ) != sizeof(i_cache) ) 
    1756     { 
    1757         msg_Warn( p_this, "This doesn't look like a valid plugins cache " 
    1758                   "(file too short)" ); 
    1759         fclose( file ); 
    1760         return; 
    1761     } 
    1762  
    1763     if( i_cache ) 
    1764         pp_cache = p_libvlc_global->p_module_bank->pp_loaded_cache = 
    1765                    malloc( i_cache * sizeof(void *) ); 
    1766  
    1767 #define LOAD_IMMEDIATE(a) \ 
    1768     if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error 
    1769 #define LOAD_STRING(a) \ 
    1770 { \ 
    1771     a = NULL; \ 
    1772     if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) \ 
    1773      || ( i_size > 16384 ) ) \ 
    1774         goto error; \ 
    1775     if( i_size ) { \ 
    1776         char *psz = malloc( i_size ); \ 
    1777         if( fread( psz, i_size, 1, file ) != 1 ) { \ 
    1778             free( psz ); \ 
    1779             goto error; \ 
    1780         } \ 
    1781         if( psz[i_size-1] ) { \ 
    1782             free( psz ); \ 
    1783             goto error; \ 
    1784         } \ 
    1785         a = psz; \ 
    1786     } \ 
    1787 } 
    1788  
    1789     for( i = 0; i < i_cache; i++ ) 
    1790     { 
    1791         uint16_t i_size; 
    1792         int i_submodules; 
    1793  
    1794         pp_cache[i] = malloc( sizeof(module_cache_t) ); 
    1795         p_libvlc_global->p_module_bank->i_loaded_cache++; 
    1796  
    1797         /* Load common info */ 
    1798         LOAD_STRING( pp_cache[i]->psz_file ); 
    1799         LOAD_IMMEDIATE( pp_cache[i]->i_time ); 
    1800         LOAD_IMMEDIATE( pp_cache[i]->i_size ); 
    1801         LOAD_IMMEDIATE( pp_cache[i]->b_junk ); 
    1802         pp_cache[i]->b_used = VLC_FALSE; 
    1803  
    1804         if( pp_cache[i]->b_junk ) continue; 
    1805  
    1806         pp_cache[i]->p_module = vlc_module_create( p_this ); 
    1807  
    1808         /* Load additional infos */ 
    1809         LOAD_STRING( pp_cache[i]->p_module->psz_object_name ); 
    1810         LOAD_STRING( pp_cache[i]->p_module->psz_shortname ); 
    1811         LOAD_STRING( pp_cache[i]->p_module->psz_longname ); 
    1812         LOAD_STRING( pp_cache[i]->p_module->psz_help ); 
    1813         for( j = 0; j < MODULE_SHORTCUT_MAX; j++ ) 
    1814         { 
    1815             LOAD_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); // FIX 
    1816         } 
    1817         LOAD_STRING( pp_cache[i]->p_module->psz_capability ); 
    1818         LOAD_IMMEDIATE( pp_cache[i]->p_module->i_score ); 
    1819         LOAD_IMMEDIATE( pp_cache[i]->p_module->i_cpu ); 
    1820         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_unloadable ); 
    1821         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_reentrant ); 
    1822         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule ); 
    1823  
    1824         /* Config stuff */ 
    1825         if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS ) 
    1826             goto error; 
    1827  
    1828         LOAD_STRING( pp_cache[i]->p_module->psz_filename ); 
    1829  
    1830         LOAD_IMMEDIATE( i_submodules ); 
    1831  
    1832         while( i_submodules-- ) 
    1833         { 
    1834             module_t *p_module = vlc_submodule_create( pp_cache[i]->p_module ); 
    1835             LOAD_STRING( p_module->psz_object_name ); 
    1836             LOAD_STRING( p_module->psz_shortname ); 
    1837             LOAD_STRING( p_module->psz_longname ); 
    1838             LOAD_STRING( p_module->psz_help ); 
    1839             for( j = 0; j < MODULE_SHORTCUT_MAX; j++ ) 
    1840             { 
    1841                 LOAD_STRING( p_module->pp_shortcuts[j] ); // FIX 
    1842             } 
    1843             LOAD_STRING( p_module->psz_capability ); 
    1844             LOAD_IMMEDIATE( p_module->i_score ); 
    1845             LOAD_IMMEDIATE( p_module->i_cpu ); 
    1846             LOAD_IMMEDIATE( p_module->b_unloadable ); 
    1847             LOAD_IMMEDIATE( p_module->b_reentrant ); 
    1848         } 
    1849     } 
    1850  
    1851     fclose( file ); 
    1852     return; 
    1853  
    1854  error: 
    1855  
    1856     msg_Warn( p_this, "plugins cache not loaded (corrupted)" ); 
    1857  
    1858     /* TODO: cleanup */ 
    1859     p_libvlc_global->p_module_bank->i_loaded_cache = 0; 
    1860  
    1861     fclose( file ); 
    1862     return; 
    1863 } 
    1864  
    1865  
    1866 int CacheLoadConfig( module_t *p_module, FILE *file ) 
    1867 { 
    1868     uint32_t i_lines; 
    1869     uint16_t i_size; 
    1870  
    1871     /* Calculate the structure length */ 
    1872     LOAD_IMMEDIATE( p_module->i_config_items ); 
    1873     LOAD_IMMEDIATE( p_module->i_bool_items ); 
    1874  
    1875     LOAD_IMMEDIATE( i_lines ); 
    1876  
    1877     /* Allocate memory */ 
    1878     if (i_lines) 
    1879     { 
    1880         p_module->p_config = 
    1881             (module_config_t *)calloc( i_lines, sizeof(module_config_t) ); 
    1882         if( p_module->p_config == NULL ) 
    1883         { 
    1884             p_module->confsize = 0; 
    1885             msg_Err( p_module, "config error: can't duplicate p_config" ); 
    1886             return VLC_ENOMEM; 
    1887         } 
    1888     } 
    1889     p_module->confsize = i_lines; 
    1890  
    1891     /* Do the duplication job */ 
    1892     for (size_t i = 0; i < i_lines; i++ ) 
    1893     { 
    1894         LOAD_IMMEDIATE( p_module->p_config[i] ); 
    1895  
    1896         LOAD_STRING( p_module->p_config[i].psz_type ); 
    1897         LOAD_STRING( p_module->p_config[i].psz_name ); 
    1898         LOAD_STRING( p_module->p_config[i].psz_text ); 
    1899         LOAD_STRING( p_module->p_config[i].psz_longtext ); 
    1900         LOAD_STRING( p_module->p_config[i].psz_current ); 
    1901  
    1902         if (IsConfigStringType (p_module->p_config[i].i_type)) 
    1903         { 
    1904             LOAD_STRING (p_module->p_config[i].orig.psz); 
    1905             p_module->p_config[i].value.psz = 
    1906                     (p_module->p_config[i].orig.psz != NULL) 
    1907                         ? strdup (p_module->p_config[i].orig.psz) : NULL; 
    1908             p_module->p_config[i].saved.psz = NULL; 
    1909         } 
    1910         else 
    1911         { 
    1912             memcpy (&p_module->p_config[i].value, &p_module->p_config[i].orig, 
    1913                     sizeof (p_module->p_config[i].value)); 
    1914             memcpy (&p_module->p_config[i].saved, &p_module->p_config[i].orig, 
    1915                     sizeof (p_module->p_config[i].saved)); 
    1916         } 
    1917  
    1918         p_module->p_config[i].b_dirty = VLC_FALSE; 
    1919  
    1920         p_module->p_config[i].p_lock = &p_module->object_lock; 
    1921  
    1922         if( p_module->p_config[i].i_list ) 
    1923         { 
    1924             if( p_module->p_config[i].ppsz_list ) 
    1925             { 
    1926                 int j; 
    1927                 p_module->p_config[i].ppsz_list = 
    1928                     malloc( (p_module->p_config[i].i_list+1) * sizeof(char *)); 
    1929                 if( p_module->p_config[i].ppsz_list ) 
    1930                 { 
    1931                     for( j = 0; j < p_module->p_config[i].i_list; j++ ) 
    1932                         LOAD_STRING( p_module->p_config[i].ppsz_list[j] ); 
    1933                     p_module->p_config[i].ppsz_list[j] = NULL; 
    1934                 } 
    1935             } 
    1936             if( p_module->p_config[i].ppsz_list_text ) 
    1937             { 
    1938                 int j; 
    1939                 p_module->p_config[i].ppsz_list_text = 
    1940                     malloc( (p_module->p_config[i].i_list+1) * sizeof(char *)); 
    1941                 if( p_module->p_config[i].ppsz_list_text ) 
    1942                 { 
    1943                   for( j = 0; j < p_module->p_config[i].i_list; j++ ) 
    1944                       LOAD_STRING( p_module->p_config[i].ppsz_list_text[j] ); 
    1945                   p_module->p_config[i].ppsz_list_text[j] = NULL; 
    1946                 } 
    1947             } 
    1948             if( p_module->p_config[i].pi_list ) 
    1949             { 
    1950                 p_module->p_config[i].pi_list = 
    1951                     malloc( (p_module->p_config[i].i_list + 1) * sizeof(int) ); 
    1952                 if( p_module->p_config[i].pi_list ) 
    1953                 { 
    1954                     for (int j = 0; j < p_module->p_config[i].i_list; j++) 
    1955                         LOAD_IMMEDIATE( p_module->p_config[i].pi_list[j] ); 
    1956                 } 
    1957             } 
    1958         } 
    1959  
    1960         if( p_module->p_config[i].i_action ) 
    1961         { 
    1962             p_module->p_config[i].ppf_action = 
    1963                 malloc( p_module->p_config[i].i_action * sizeof(void *) ); 
    1964             p_module->p_config[i].ppsz_action_text = 
    1965                 malloc( p_module->p_config[i].i_action * sizeof(char *) ); 
    1966  
    1967             for (int j = 0; j < p_module->p_config[i].i_action; j++) 
    1968             { 
    1969                 p_module->p_config[i].ppf_action[j] = 0; 
    1970                 LOAD_STRING( p_module->p_config[i].ppsz_action_text[j] ); 
    1971             } 
    1972         } 
    1973  
    1974         LOAD_IMMEDIATE( p_module->p_config[i].pf_callback ); 
    1975     } 
    1976  
    1977     return VLC_SUCCESS; 
    1978  
    1979  error: 
    1980  
    1981     return VLC_EGENERIC; 
    1982 } 
    1983  
    1984 /***************************************************************************** 
    1985  * SavePluginsCache: saves the plugins cache to a file 
    1986  *****************************************************************************/ 
    1987 static void CacheSave( vlc_object_t *p_this ) 
    1988 { 
    1989     static char const psz_tag[] = 
    1990         "Signature: 8a477f597d28d172789f06886806bc55\r\n" 
    1991         "# This file is a cache directory tag created by VLC.\r\n" 
    1992         "# For information about cache directory tags, see:\r\n" 
    1993         "#   http://www.brynosaurus.com/cachedir/\r\n"; 
    1994  
    1995     char *psz_cachedir; 
    1996     size_t i_len = 0; 
    1997     FILE *file; 
    1998     int i, j, i_cache; 
    1999     module_cache_t **pp_cache; 
    2000     int32_t i_file_size = 0; 
    2001     libvlc_global_data_t *p_libvlc_global = vlc_global(); 
    2002  
    2003     psz_cachedir = p_this->p_libvlc->psz_cachedir; 
    2004     if( !psz_cachedir ) /* XXX: this should never happen */ 
    2005     { 
    2006         msg_Err( p_this, "Unable to get cache directory" ); 
    2007         return; 
    2008     } 
    2009  
    2010     char psz_filename[sizeof(DIR_SEP) + 32 + strlen(psz_cachedir)]; 
    2011     config_CreateDir( p_this, psz_cachedir ); 
    2012  
    2013     snprintf( psz_filename, sizeof( psz_filename ), 
    2014               "%s"DIR_SEP"CACHEDIR.TAG", psz_cachedir ); 
    2015     file = utf8_fopen( psz_filename, "wb" ); 
    2016     if( file ) 
    2017     { 
    2018         fwrite( psz_tag, 1, strlen(psz_tag), file ); 
    2019         fclose( file ); 
    2020     } 
    2021  
    2022     snprintf( psz_filename, sizeof( psz_filename ), 
    2023               "%s"DIR_SEP"%s", psz_cachedir, CacheName() ); 
    2024     msg_Dbg( p_this, "saving plugins cache file %s", psz_filename ); 
    2025  
    2026     file = utf8_fopen( psz_filename, "wb" ); 
    2027     if( !file ) 
    2028     { 
    2029         msg_Warn( p_this, "could not open plugins cache file %s for writing", 
    2030                   psz_filename ); 
    2031         return; 
    2032     } 
    2033  
    2034     /* Empty space for file size */ 
    2035     fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file ); 
    2036  
    2037     /* Contains version number */ 
    2038     fprintf( file, "%s", "cache " COPYRIGHT_MESSAGE ); 
    2039  
    2040     /* Sub-version number (to avoid breakage in the dev version when cache 
    2041      * structure changes) */ 
    2042     i_file_size = CACHE_SUBVERSION_NUM; 
    2043     fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file ); 
    2044  
    2045     /* Language */ 
    2046     fprintf( file, "%5.5s", _("C") ); 
    2047  
    2048     /* Header marker */ 
    2049     i_file_size = ftell( file ); 
    2050     fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file ); 
    2051  
    2052     i_cache = p_libvlc_global->p_module_bank->i_cache; 
    2053     pp_cache = p_libvlc_global->p_module_bank->pp_cache; 
    2054  
    2055     fwrite( &i_cache, sizeof(char), sizeof(i_cache), file ); 
    2056  
    2057 #define SAVE_IMMEDIATE(a) \ 
    2058     fwrite( &a, sizeof(char), sizeof(a), file ) 
    2059 #define SAVE_STRING(a) \ 
    2060     { i_size = a ? strlen( a ) + 1 : 0; \ 
    2061       fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \ 
    2062       if( a ) fwrite( a, sizeof(char), i_size, file ); \ 
    2063     } while(0) 
    2064  
    2065     for( i = 0; i < i_cache; i++ ) 
    2066     { 
    2067         uint16_t i_size; 
    2068         uint32_t i_submodule; 
    2069  
    2070         /* Save common info */ 
    2071         SAVE_STRING( pp_cache[i]->psz_file ); 
    2072         SAVE_IMMEDIATE( pp_cache[i]->i_time ); 
    2073         SAVE_IMMEDIATE( pp_cache[i]->i_size ); 
    2074         SAVE_IMMEDIATE( pp_cache[i]->b_junk ); 
    2075  
    2076         if( pp_cache[i]->b_junk ) continue; 
    2077  
    2078         /* Save additional infos */ 
    2079         SAVE_STRING( pp_cache[i]->p_module->psz_object_name ); 
    2080         SAVE_STRING( pp_cache[i]->p_module->psz_shortname ); 
    2081         SAVE_STRING( pp_cache[i]->p_module->psz_longname ); 
    2082         SAVE_STRING( pp_cache[i]->p_module->psz_help ); 
    2083         for( j = 0; j < MODULE_SHORTCUT_MAX; j++ ) 
    2084         { 
    2085             SAVE_STRING( pp_cache[i]->p_module->pp_shortcuts[j] ); // FIX 
    2086         } 
    2087         SAVE_STRING( pp_cache[i]->p_module->psz_capability ); 
    2088         SAVE_IMMEDIATE( pp_cache[i]->p_module->i_score ); 
    2089         SAVE_IMMEDIATE( pp_cache[i]->p_module->i_cpu ); 
    2090         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_unloadable ); 
    2091         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_reentrant ); 
    2092         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_submodule ); 
    2093  
    2094         /* Config stuff */ 
    2095         CacheSaveConfig( pp_cache[i]->p_module, file ); 
    2096  
    2097         SAVE_STRING( pp_cache[i]->p_module->psz_filename ); 
    2098  
    2099         i_submodule = pp_cache[i]->p_module->i_children; 
    2100         SAVE_IMMEDIATE( i_submodule ); 
    2101         for( i_submodule = 0; 
    2102              i_submodule < (unsigned)pp_cache[i]->p_module->i_children; 
    2103              i_submodule++ ) 
    2104         { 
    2105             module_t *p_module = 
    2106                 (module_t *)pp_cache[i]->p_module->pp_children[i_submodule]; 
    2107  
    2108             SAVE_STRING( p_module->psz_object_name ); 
    2109             SAVE_STRING( p_module->psz_shortname ); 
    2110             SAVE_STRING( p_module->psz_longname ); 
    2111             SAVE_STRING( p_module->psz_help ); 
    2112             for( j = 0; j < MODULE_SHORTCUT_MAX; j++ ) 
    2113             { 
    2114                 SAVE_STRING( p_module->pp_shortcuts[j] ); // FIX 
    2115             } 
    2116             SAVE_STRING( p_module->psz_capability ); 
    2117             SAVE_IMMEDIATE( p_module->i_score ); 
    2118             SAVE_IMMEDIATE( p_module->i_cpu ); 
    2119             SAVE_IMMEDIATE( p_module->b_unloadable ); 
    2120             SAVE_IMMEDIATE( p_module->b_reentrant ); 
    2121         } 
    2122     } 
    2123  
    2124     /* Fill-up file size */ 
    2125     i_file_size = ftell( file ); 
    2126     fseek( file, 0, SEEK_SET ); 
    2127     fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file ); 
    2128  
    2129     fclose( file ); 
    2130 } 
    2131  
    2132 void CacheSaveConfig( module_t *p_module, FILE *file ) 
    2133 { 
    2134     uint32_t i_lines = p_module->confsize; 
    2135     uint16_t i_size; 
    2136  
    2137     SAVE_IMMEDIATE( p_module->i_config_items ); 
    2138     SAVE_IMMEDIATE( p_module->i_bool_items ); 
    2139     SAVE_IMMEDIATE( i_lines ); 
    2140  
    2141     for (size_t i = 0; i < i_lines ; i++) 
    2142     { 
    2143         SAVE_IMMEDIATE( p_module->p_config[i] ); 
    2144  
    2145         SAVE_STRING( p_module->p_config[i].psz_type ); 
    2146         SAVE_STRING( p_module->p_config[i].psz_name ); 
    2147         SAVE_STRING( p_module->p_config[i].psz_text ); 
    2148         SAVE_STRING( p_module->p_config[i].psz_longtext ); 
    2149         SAVE_STRING( p_module->p_config[i].psz_current ); 
    2150         if (IsConfigStringType (p_module->p_config[i].i_type)) 
    2151             SAVE_STRING( p_module->p_config[i].orig.psz ); 
    2152  
    2153         if( p_module->p_config[i].i_list ) 
    2154         { 
    2155             if( p_module->p_config[i].ppsz_list ) 
    2156             { 
    2157                 for (int j = 0; j < p_module->p_config[i].i_list; j++) 
    2158                     SAVE_STRING( p_module->p_config[i].ppsz_list[j] ); 
    2159             } 
    2160  
    2161             if( p_module->p_config[i].ppsz_list_text ) 
    2162             { 
    2163                 for (int j = 0; j < p_module->p_config[i].i_list; j++) 
    2164                     SAVE_STRING( p_module->p_config[i].ppsz_list_text[j] ); 
    2165             } 
    2166             if( p_module->p_config[i].pi_list ) 
    2167             { 
    2168                 for (int j = 0; j < p_module->p_config[i].i_list; j++) 
    2169                     SAVE_IMMEDIATE( p_module->p_config[i].pi_list[j] ); 
    2170             } 
    2171         } 
    2172  
    2173         for (int j = 0; j < p_module->p_config[i].i_action; j++) 
    2174             SAVE_STRING( p_module->p_config[i].ppsz_action_text[j] ); 
    2175  
    2176         SAVE_IMMEDIATE( p_module->p_config[i].pf_callback ); 
    2177     } 
    2178 } 
    2179  
    2180 /***************************************************************************** 
    2181  * CacheName: Return the cache file name for this platform. 
    2182  *****************************************************************************/ 
    2183 static char *CacheName( void ) 
    2184 { 
    2185     static char psz_cachename[32]; 
    2186  
    2187     /* Code int size, pointer size and endianness in the filename */ 
    2188     int32_t x = 0xbe00001e; 
    2189     sprintf( psz_cachename, "plugins-%.2x%.2x%.2x.dat", (int)sizeof(int), 
    2190              (int)sizeof(void *), (unsigned int)((unsigned char *)&x)[0] ); 
    2191     return psz_cachename; 
    2192 } 
    2193  
    2194 /***************************************************************************** 
    2195  * CacheMerge: Merge a cache module descriptor with a full module descriptor. 
    2196  *****************************************************************************/ 
    2197 static void CacheMerge( vlc_object_t *p_this, module_t *p_cache, 
    2198                         module_t *p_module ) 
    2199 { 
    2200     int i_submodule; 
    2201     (void)p_this; 
    2202  
    2203     p_cache->pf_activate = p_module->pf_activate; 
    2204     p_cache->pf_deactivate = p_module->pf_deactivate; 
    2205     p_cache->handle = p_module->handle; 
    2206  
    2207     for( i_submodule = 0; i_submodule < p_module->i_children; i_submodule++ ) 
    2208     { 
    2209         module_t *p_child = (module_t*)p_module->pp_children[i_submodule]; 
    2210         module_t *p_cchild = (module_t*)p_cache->pp_children[i_submodule]; 
    2211         p_cchild->pf_activate = p_child->pf_activate; 
    2212         p_cchild->pf_deactivate = p_child->pf_deactivate; 
    2213     } 
    2214  
    2215     p_cache->b_loaded = VLC_TRUE; 
    2216     p_module->b_loaded = VLC_FALSE; 
    2217 } 
    2218  
    2219 /***************************************************************************** 
    2220  * CacheFind: finds the cache entry corresponding to a file 
    2221  *********************