Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
e03e85ca
Commit
e03e85ca
authored
Dec 12, 2007
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split the over-large module.c
parent
f0ec1547
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1102 additions
and
943 deletions
+1102
-943
src/Makefile.am
src/Makefile.am
+2
-0
src/modules/cache.c
src/modules/cache.c
+709
-0
src/modules/modules.c
src/modules/modules.c
+7
-943
src/modules/modules.h
src/modules/modules.h
+11
-0
src/modules/os.c
src/modules/os.c
+373
-0
No files found.
src/Makefile.am
View file @
e03e85ca
...
...
@@ -295,7 +295,9 @@ SOURCES_libvlc_common = \
misc/block.c
\
modules/modules.h
\
modules/modules.c
\
modules/cache.c
\
modules/entry.c
\
modules/os.c
\
misc/threads.c
\
misc/stats.c
\
misc/cpu.c
\
...
...
src/modules/cache.c
0 → 100644
View file @
e03e85ca
/*****************************************************************************
* 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.
*****************************************************************************/
#include <vlc/vlc.h>
#include "libvlc.h"
/* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
* is set to 64. Don't try to be cleverer. */
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
#endif
#include <stdlib.h>
/* free(), strtol() */
#include <stdio.h>
/* sprintf() */
#include <string.h>
/* strdup() */
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if !defined(HAVE_DYNAMIC_PLUGINS)
/* no support for plugins */
#elif defined(HAVE_DL_DYLD)
# if defined(HAVE_MACH_O_DYLD_H)
# include <mach-o/dyld.h>
# endif
#elif defined(HAVE_DL_BEOS)
# if defined(HAVE_IMAGE_H)
# include <image.h>
# endif
#elif defined(HAVE_DL_WINDOWS)
# include <windows.h>
#elif defined(HAVE_DL_DLOPEN)
# if defined(HAVE_DLFCN_H)
/* Linux, BSD, Hurd */
# include <dlfcn.h>
# endif
# if defined(HAVE_SYS_DL_H)
# include <sys/dl.h>
# endif
#elif defined(HAVE_DL_SHL_LOAD)
# if defined(HAVE_DL_H)
# include <dl.h>
# endif
#endif
#include "config/config.h"
#include "vlc_charset.h"
#include "modules/modules.h"
#include "modules/builtin.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
static
int
CacheLoadConfig
(
module_t
*
,
FILE
*
);
static
void
CacheSaveConfig
(
module_t
*
,
FILE
*
);
static
char
*
CacheName
(
void
);
/* Sub-version number
* (only used to avoid breakage in dev version when cache structure changes) */
#define CACHE_SUBVERSION_NUM 3
/*****************************************************************************
* 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.
*****************************************************************************/
void
CacheLoad
(
vlc_object_t
*
p_this
)
{
char
*
psz_filename
,
*
psz_cachedir
;
FILE
*
file
;
int
i
,
j
,
i_size
,
i_read
;
char
p_cachestring
[
sizeof
(
"cache "
COPYRIGHT_MESSAGE
)];
char
p_cachelang
[
6
],
p_lang
[
6
];
int
i_cache
;
module_cache_t
**
pp_cache
=
0
;
int32_t
i_file_size
,
i_marker
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
psz_cachedir
=
p_this
->
p_libvlc
->
psz_cachedir
;
if
(
!
psz_cachedir
)
/* XXX: this should never happen */
{
msg_Err
(
p_this
,
"Unable to get cache directory"
);
return
;
}
i_size
=
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s"
,
psz_cachedir
,
CacheName
()
);
if
(
i_size
<=
0
)
{
msg_Err
(
p_this
,
"out of memory"
);
return
;
}
if
(
p_libvlc_global
->
p_module_bank
->
b_cache_delete
)
{
#if !defined( UNDER_CE )
unlink
(
psz_filename
);
#else
wchar_t
psz_wf
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_filename
,
-
1
,
psz_wf
,
MAX_PATH
);
DeleteFile
(
psz_wf
);
#endif
msg_Dbg
(
p_this
,
"removing plugins cache file %s"
,
psz_filename
);
free
(
psz_filename
);
return
;
}
msg_Dbg
(
p_this
,
"loading plugins cache file %s"
,
psz_filename
);
file
=
utf8_fopen
(
psz_filename
,
"rb"
);
if
(
!
file
)
{
msg_Warn
(
p_this
,
"could not open plugins cache file %s for reading"
,
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 */
i_size
=
sizeof
(
"cache "
COPYRIGHT_MESSAGE
)
-
1
;
i_read
=
fread
(
p_cachestring
,
1
,
i_size
,
file
);
if
(
i_read
!=
i_size
||
memcmp
(
p_cachestring
,
"cache "
COPYRIGHT_MESSAGE
,
i_size
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache"
);
fclose
(
file
);
return
;
}
/* 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 the language hasn't changed */
sprintf
(
p_lang
,
"%5.5s"
,
_
(
"C"
)
);
i_size
=
5
;
i_read
=
fread
(
p_cachelang
,
1
,
i_size
,
file
);
if
(
i_read
!=
i_size
||
memcmp
(
p_cachelang
,
p_lang
,
i_size
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache "
"(language changed)"
);
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
;
}
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
=
0
;
if
(
fread
(
&
i_cache
,
1
,
sizeof
(
i_cache
),
file
)
!=
sizeof
(
i_cache
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache "
"(file too short)"
);
fclose
(
file
);
return
;
}
if
(
i_cache
)
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_loaded_cache
=
malloc
(
i_cache
*
sizeof
(
void
*
)
);
#define LOAD_IMMEDIATE(a) \
if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
#define LOAD_STRING(a) \
{ \
a = NULL; \
if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) \
|| ( i_size > 16384 ) ) \
goto error; \
if( i_size ) { \
char *psz = malloc( i_size ); \
if( fread( psz, i_size, 1, file ) != 1 ) { \
free( psz ); \
goto error; \
} \
if( psz[i_size-1] ) { \
free( psz ); \
goto error; \
} \
a = psz; \
} \
}
for
(
i
=
0
;
i
<
i_cache
;
i
++
)
{
uint16_t
i_size
;
int
i_submodules
;
pp_cache
[
i
]
=
malloc
(
sizeof
(
module_cache_t
)
);
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
++
;
/* Load common info */
LOAD_STRING
(
pp_cache
[
i
]
->
psz_file
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
i_time
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
i_size
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
b_junk
);
pp_cache
[
i
]
->
b_used
=
VLC_FALSE
;
if
(
pp_cache
[
i
]
->
b_junk
)
continue
;
pp_cache
[
i
]
->
p_module
=
vlc_module_create
(
p_this
);
/* Load additional infos */
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
LOAD_STRING
(
pp_cache
[
i
]
->
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
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
->
i_cpu
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_unloadable
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_reentrant
);
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
);
LOAD_IMMEDIATE
(
i_submodules
);
while
(
i_submodules
--
)
{
module_t
*
p_module
=
vlc_submodule_create
(
pp_cache
[
i
]
->
p_module
);
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
LOAD_STRING
(
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
LOAD_STRING
(
p_module
->
psz_capability
);
LOAD_IMMEDIATE
(
p_module
->
i_score
);
LOAD_IMMEDIATE
(
p_module
->
i_cpu
);
LOAD_IMMEDIATE
(
p_module
->
b_unloadable
);
LOAD_IMMEDIATE
(
p_module
->
b_reentrant
);
}
}
fclose
(
file
);
return
;
error:
msg_Warn
(
p_this
,
"plugins cache not loaded (corrupted)"
);
/* TODO: cleanup */
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
=
0
;
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
;
msg_Err
(
p_module
,
"config error: can't duplicate p_config"
);
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
);
LOAD_STRING
(
p_module
->
p_config
[
i
].
psz_current
);
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
;
p_module
->
p_config
[
i
].
saved
.
psz
=
NULL
;
}
else
{
memcpy
(
&
p_module
->
p_config
[
i
].
value
,
&
p_module
->
p_config
[
i
].
orig
,
sizeof
(
p_module
->
p_config
[
i
].
value
));
memcpy
(
&
p_module
->
p_config
[
i
].
saved
,
&
p_module
->
p_config
[
i
].
orig
,
sizeof
(
p_module
->
p_config
[
i
].
saved
));
}
p_module
->
p_config
[
i
].
b_dirty
=
VLC_FALSE
;
p_module
->
p_config
[
i
].
p_lock
=
&
p_module
->
object_lock
;
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
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
char
*
));
if
(
p_module
->
p_config
[
i
].
ppsz_list
)
{
for
(
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_list
[
j
]
);
p_module
->
p_config
[
i
].
ppsz_list
[
j
]
=
NULL
;
}
}
if
(
p_module
->
p_config
[
i
].
ppsz_list_text
)
{
int
j
;
p_module
->
p_config
[
i
].
ppsz_list_text
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
char
*
));
if
(
p_module
->
p_config
[
i
].
ppsz_list_text
)
{
for
(
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_list_text
[
j
]
);
p_module
->
p_config
[
i
].
ppsz_list_text
[
j
]
=
NULL
;
}
}
if
(
p_module
->
p_config
[
i
].
pi_list
)
{
p_module
->
p_config
[
i
].
pi_list
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
int
)
);
if
(
p_module
->
p_config
[
i
].
pi_list
)
{
for
(
int
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_IMMEDIATE
(
p_module
->
p_config
[
i
].
pi_list
[
j
]
);
}
}
}
if
(
p_module
->
p_config
[
i
].
i_action
)
{
p_module
->
p_config
[
i
].
ppf_action
=
malloc
(
p_module
->
p_config
[
i
].
i_action
*
sizeof
(
void
*
)
);
p_module
->
p_config
[
i
].
ppsz_action_text
=
malloc
(
p_module
->
p_config
[
i
].
i_action
*
sizeof
(
char
*
)
);
for
(
int
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_action
;
j
++
)
{
p_module
->
p_config
[
i
].
ppf_action
[
j
]
=
0
;
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_action_text
[
j
]
);
}
}
LOAD_IMMEDIATE
(
p_module
->
p_config
[
i
].
pf_callback
);
}
return
VLC_SUCCESS
;
error:
return
VLC_EGENERIC
;
}
/*****************************************************************************
* SavePluginsCache: saves the plugins cache to a file
*****************************************************************************/
void
CacheSave
(
vlc_object_t
*
p_this
)
{
static
char
const
psz_tag
[]
=
"Signature: 8a477f597d28d172789f06886806bc55
\r\n
"
"# This file is a cache directory tag created by VLC.
\r\n
"
"# For information about cache directory tags, see:
\r\n
"
"# http://www.brynosaurus.com/cachedir/
\r\n
"
;
char
*
psz_cachedir
;
FILE
*
file
;
int
i
,
j
,
i_cache
;
module_cache_t
**
pp_cache
;
int32_t
i_file_size
=
0
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
psz_cachedir
=
p_this
->
p_libvlc
->
psz_cachedir
;
if
(
!
psz_cachedir
)
/* XXX: this should never happen */
{
msg_Err
(
p_this
,
"Unable to get cache directory"
);
return
;
}
char
psz_filename
[
sizeof
(
DIR_SEP
)
+
32
+
strlen
(
psz_cachedir
)];
config_CreateDir
(
p_this
,
psz_cachedir
);
snprintf
(
psz_filename
,
sizeof
(
psz_filename
),
"%s"
DIR_SEP
"CACHEDIR.TAG"
,
psz_cachedir
);
file
=
utf8_fopen
(
psz_filename
,
"wb"
);
if
(
file
)
{
fwrite
(
psz_tag
,
1
,
strlen
(
psz_tag
),
file
);
fclose
(
file
);
}
snprintf
(
psz_filename
,
sizeof
(
psz_filename
),
"%s"
DIR_SEP
"%s"
,
psz_cachedir
,
CacheName
()
);
msg_Dbg
(
p_this
,
"saving plugins cache file %s"
,
psz_filename
);
file
=
utf8_fopen
(
psz_filename
,
"wb"
);
if
(
!
file
)
{
msg_Warn
(
p_this
,
"could not open plugins cache file %s for writing"
,
psz_filename
);
return
;
}
/* Empty space for file size */
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
/* Contains version number */
fprintf
(
file
,
"%s"
,
"cache "
COPYRIGHT_MESSAGE
);
/* Sub-version number (to avoid breakage in the dev version when cache
* structure changes) */
i_file_size
=
CACHE_SUBVERSION_NUM
;
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
/* Language */
fprintf
(
file
,
"%5.5s"
,
_
(
"C"
)
);
/* Header marker */
i_file_size
=
ftell
(
file
);
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
i_cache
=
p_libvlc_global
->
p_module_bank
->
i_cache
;
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_cache
;
fwrite
(
&
i_cache
,
sizeof
(
char
),
sizeof
(
i_cache
),
file
);
#define SAVE_IMMEDIATE(a) \
fwrite( &a, sizeof(char), sizeof(a), file )
#define SAVE_STRING(a) \
{ i_size = a ? strlen( a ) + 1 : 0; \
fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \
if( a ) fwrite( a, sizeof(char), i_size, file ); \
} while(0)
for
(
i
=
0
;
i
<
i_cache
;
i
++
)
{
uint16_t
i_size
;
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_IMMEDIATE
(
pp_cache
[
i
]
->
b_junk
);
if
(
pp_cache
[
i
]
->
b_junk
)
continue
;
/* 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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
SAVE_STRING
(
pp_cache
[
i
]
->
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
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
->
i_cpu
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_unloadable
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_reentrant
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_submodule
);
/* Config stuff */
CacheSaveConfig
(
pp_cache
[
i
]
->
p_module
,
file
);
SAVE_STRING
(
pp_cache
[
i
]
->
p_module
->
psz_filename
);
i_submodule
=
pp_cache
[
i
]
->
p_module
->
i_children
;
SAVE_IMMEDIATE
(
i_submodule
);
for
(
i_submodule
=
0
;
i_submodule
<
(
unsigned
)
pp_cache
[
i
]
->
p_module
->
i_children
;
i_submodule
++
)
{
module_t
*
p_module
=
(
module_t
*
)
pp_cache
[
i
]
->
p_module
->
pp_children
[
i_submodule
];
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
SAVE_STRING
(
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
SAVE_STRING
(
p_module
->
psz_capability
);
SAVE_IMMEDIATE
(
p_module
->
i_score
);
SAVE_IMMEDIATE
(
p_module
->
i_cpu
);
SAVE_IMMEDIATE
(
p_module
->
b_unloadable
);
SAVE_IMMEDIATE
(
p_module
->
b_reentrant
);
}
}
/* Fill-up file size */
i_file_size
=
ftell
(
file
);
fseek
(
file
,
0
,
SEEK_SET
);
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
fclose
(
file
);
}
static
void
CacheSaveConfig
(
module_t
*
p_module
,
FILE
*
file
)
{
uint32_t
i_lines
=
p_module
->
confsize
;
uint16_t
i_size
;
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
);
SAVE_STRING
(
p_module
->
p_config
[
i
].
psz_current
);
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
]
);
SAVE_IMMEDIATE
(
p_module
->
p_config
[
i
].
pf_callback
);
}
}
/*****************************************************************************
* CacheName: Return the cache file name for this platform.
*****************************************************************************/
static
char
*
CacheName
(
void
)
{
static
char
psz_cachename
[
32
];
/* Code int size, pointer size and endianness in the filename */
int32_t
x
=
0xbe00001e
;
sprintf
(
psz_cachename
,
"plugins-%.2x%.2x%.2x.dat"
,
(
int
)
sizeof
(
int
),
(
int
)
sizeof
(
void
*
),
(
unsigned
int
)((
unsigned
char
*
)
&
x
)[
0
]
);
return
psz_cachename
;
}
/*****************************************************************************
* 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
)
{
int
i_submodule
;
(
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
;
for
(
i_submodule
=
0
;
i_submodule
<
p_module
->
i_children
;
i_submodule
++
)
{
module_t
*
p_child
=
(
module_t
*
)
p_module
->
pp_children
[
i_submodule
];
module_t
*
p_cchild
=
(
module_t
*
)
p_cache
->
pp_children
[
i_submodule
];
p_cchild
->
pf_activate
=
p_child
->
pf_activate
;
p_cchild
->
pf_deactivate
=
p_child
->
pf_deactivate
;
}
p_cache
->
b_loaded
=
VLC_TRUE
;
p_module
->
b_loaded
=
VLC_FALSE
;
}
/*****************************************************************************
* CacheFind: finds the cache entry corresponding to a file
*****************************************************************************/
module_cache_t
*
CacheFind
(
vlc_object_t
*
p_this
,
const
char
*
psz_file
,
int64_t
i_time
,
int64_t
i_size
)
{
module_cache_t
**
pp_cache
;
int
i_cache
,
i
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_loaded_cache
;
i_cache
=
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
;
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 */
src/modules/modules.c
View file @
e03e85ca
...
...
@@ -25,7 +25,7 @@
*****************************************************************************/
#include <vlc/vlc.h>
#include "
../
libvlc.h"
#include "libvlc.h"
/* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
* is set to 64. Don't try to be cleverer. */
...
...
@@ -77,18 +77,12 @@
#endif
#include "config/config.h"
#include "libvlc.h"
#include "vlc_charset.h"
#include "modules/modules.h"
#include "modules/builtin.h"
#if defined( WIN32 ) || defined( UNDER_CE )
/* Avoid name collisions */
# define LoadModule(a,b,c) LoadVlcModule(a,b,c)
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
...
...
@@ -103,29 +97,10 @@ static int DeleteModule ( module_t *, vlc_bool_t );
#ifdef HAVE_DYNAMIC_PLUGINS
static
void
DupModule
(
module_t
*
);
static
void
UndupModule
(
module_t
*
);
static
int
CallEntry
(
module_t
*
);
static
int
LoadModule
(
vlc_object_t
*
,
char
*
,
module_handle_t
*
);
static
void
CloseModule
(
module_handle_t
);
static
void
*
GetSymbol
(
module_handle_t
,
const
char
*
);
static
void
CacheLoad
(
vlc_object_t
*
);
static
int
CacheLoadConfig
(
module_t
*
,
FILE
*
);
static
void
CacheSave
(
vlc_object_t
*
);
static
void
CacheSaveConfig
(
module_t
*
,
FILE
*
);
static
char
*
CacheName
(
void
);
static
void
CacheMerge
(
vlc_object_t
*
,
module_t
*
,
module_t
*
);
static
module_cache_t
*
CacheFind
(
vlc_object_t
*
,
char
*
,
int64_t
,
int64_t
);
#if defined(HAVE_DL_WINDOWS)
static
char
*
GetWindowsError
(
void
);
#endif
#endif
static
void
module_LoadMain
(
vlc_object_t
*
p_this
);
/* Sub-version number
* (only used to avoid breakage in dev version when cache structure changes) */
#define CACHE_SUBVERSION_NUM 3
/*****************************************************************************
* module_InitBank: create the module bank.
*****************************************************************************
...
...
@@ -1153,7 +1128,7 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
module_t
*
p_module
=
NULL
;
module_handle_t
handle
;
if
(
LoadModule
(
p_this
,
psz_file
,
&
handle
)
)
if
(
module_Load
(
p_this
,
psz_file
,
&
handle
)
)
return
NULL
;
/* Now that we have successfully loaded the module, we can
...
...
@@ -1162,21 +1137,21 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
if
(
p_module
==
NULL
)
{
msg_Err
(
p_this
,
"out of memory"
);
CloseModule
(
handle
);
module_Unload
(
handle
);
return
NULL
;
}
/* We need to fill these since they may be needed by
CallEntry
() */
/* We need to fill these since they may be needed by
module_Call
() */
p_module
->
psz_filename
=
psz_file
;
p_module
->
handle
=
handle
;
p_module
->
b_loaded
=
VLC_TRUE
;
/* Initialize the module: fill p_module, default config */
if
(
CallEntry
(
p_module
)
!=
0
)
if
(
module_Call
(
p_module
)
!=
0
)
{
/* We couldn't call module_init() */
vlc_object_destroy
(
p_module
);
CloseModule
(
handle
);
module_Unload
(
handle
);
return
NULL
;
}
...
...
@@ -1309,7 +1284,7 @@ static int DeleteModule( module_t * p_module, vlc_bool_t b_detach )
{
if
(
p_module
->
b_loaded
&&
p_module
->
b_unloadable
)
{
CloseModule
(
p_module
->
handle
);
module_Unload
(
p_module
->
handle
);
}
UndupModule
(
p_module
);
free
(
p_module
->
psz_filename
);
...
...
@@ -1329,914 +1304,3 @@ static int DeleteModule( module_t * p_module, vlc_bool_t b_detach )
p_module
=
NULL
;
return
0
;
}
#ifdef HAVE_DYNAMIC_PLUGINS
/*****************************************************************************
* CallEntry: call an entry point.
*****************************************************************************
* This function calls a symbol given its name and a module structure. The
* symbol MUST refer to a function returning int and taking a module_t* as
* an argument.
*****************************************************************************/
static
int
CallEntry
(
module_t
*
p_module
)
{
static
const
char
psz_name
[]
=
"vlc_entry"
MODULE_SUFFIX
;
int
(
*
pf_symbol
)
(
module_t
*
p_module
);
/* Try to resolve the symbol */
pf_symbol
=
(
int
(
*
)(
module_t
*
))
GetSymbol
(
p_module
->
handle
,
psz_name
);
if
(
pf_symbol
==
NULL
)
{
#if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s'"
,
psz_name
,
p_module
->
psz_filename
);
#elif defined(HAVE_DL_WINDOWS)
char
*
psz_error
=
GetWindowsError
();
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%s)"
,
psz_name
,
p_module
->
psz_filename
,
psz_error
);
free
(
psz_error
);
#elif defined(HAVE_DL_DLOPEN)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%s)"
,
psz_name
,
p_module
->
psz_filename
,
dlerror
()
);
#elif defined(HAVE_DL_SHL_LOAD)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%m)"
,
psz_name
,
p_module
->
psz_filename
);
#else
# error "Something is wrong in modules.c"
#endif
return
-
1
;
}
/* We can now try to call the symbol */
if
(
pf_symbol
(
p_module
)
!=
0
)
{
/* With a well-written module we shouldn't have to print an
* additional error message here, but just make sure. */
msg_Err
(
p_module
,
"Failed to call symbol
\"
%s
\"
in file `%s'"
,
psz_name
,
p_module
->
psz_filename
);
return
-
1
;
}
/* Everything worked fine, we can return */
return
0
;
}
/*****************************************************************************
* LoadModule: loads a dynamic library
*****************************************************************************
* This function loads a dynamically linked library using a system dependant
* method. Will return 0 on success as well as the module handle.
*****************************************************************************/
static
int
LoadModule
(
vlc_object_t
*
p_this
,
char
*
psz_file
,
module_handle_t
*
p_handle
)
{
module_handle_t
handle
;
#if defined(HAVE_DL_DYLD)
NSObjectFileImage
image
;
NSObjectFileImageReturnCode
ret
;
ret
=
NSCreateObjectFileImageFromFile
(
psz_file
,
&
image
);
if
(
ret
!=
NSObjectFileImageSuccess
)
{
msg_Warn
(
p_this
,
"cannot create image from `%s'"
,
psz_file
);
return
-
1
;
}
/* Open the dynamic module */
handle
=
NSLinkModule
(
image
,
psz_file
,
NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
if
(
!
handle
)
{
NSLinkEditErrors
errors
;
const
char
*
psz_file
,
*
psz_err
;
int
i_errnum
;
NSLinkEditError
(
&
errors
,
&
i_errnum
,
&
psz_file
,
&
psz_err
);
msg_Warn
(
p_this
,
"cannot link module `%s' (%s)"
,
psz_file
,
psz_err
);
NSDestroyObjectFileImage
(
image
);
return
-
1
;
}
/* Destroy our image, we won't need it */
NSDestroyObjectFileImage
(
image
);
#elif defined(HAVE_DL_BEOS)
handle
=
load_add_on
(
psz_file
);
if
(
handle
<
0
)
{
msg_Warn
(
p_this
,
"cannot load module `%s'"
,
psz_file
);
return
-
1
;
}
#elif defined(HAVE_DL_WINDOWS)
#ifdef UNDER_CE
{
wchar_t
psz_wfile
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_file
,
-
1
,
psz_wfile
,
MAX_PATH
);
handle
=
LoadLibrary
(
psz_wfile
);
}
#else
handle
=
LoadLibrary
(
psz_file
);
#endif
if
(
handle
==
NULL
)
{
char
*
psz_err
=
GetWindowsError
();
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
psz_err
);
free
(
psz_err
);
return
-
1
;
}
#elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
/* static is OK, we are called atomically */
handle
=
dlopen
(
psz_file
,
RTLD_NOW
);
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
dlerror
()
);
return
-
1
;
}
#elif defined(HAVE_DL_DLOPEN)
# if defined(DL_LAZY)
handle
=
dlopen
(
psz_file
,
DL_LAZY
);
# else
handle
=
dlopen
(
psz_file
,
0
);
# endif
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
dlerror
()
);
return
-
1
;
}
#elif defined(HAVE_DL_SHL_LOAD)
handle
=
shl_load
(
psz_file
,
BIND_IMMEDIATE
|
BIND_NONFATAL
,
NULL
);
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%m)"
,
psz_file
);
return
-
1
;
}
#else
# error "Something is wrong in modules.c"
#endif
*
p_handle
=
handle
;
return
0
;
}
/*****************************************************************************
* CloseModule: unload a dynamic library
*****************************************************************************
* This function unloads a previously opened dynamically linked library
* using a system dependant method. No return value is taken in consideration,
* since some libraries sometimes refuse to close properly.
*****************************************************************************/
static
void
CloseModule
(
module_handle_t
handle
)
{
#if defined(HAVE_DL_DYLD)
NSUnLinkModule
(
handle
,
FALSE
);
#elif defined(HAVE_DL_BEOS)
unload_add_on
(
handle
);
#elif defined(HAVE_DL_WINDOWS)
FreeLibrary
(
handle
);
#elif defined(HAVE_DL_DLOPEN)
# ifdef NDEBUG
dlclose
(
handle
);
# endif
#elif defined(HAVE_DL_SHL_LOAD)
shl_unload
(
handle
);
#endif
return
;
}
/*****************************************************************************
* GetSymbol: get a symbol from a dynamic library
*****************************************************************************
* This function queries a loaded library for a symbol specified in a
* string, and returns a pointer to it. We don't check for dlerror() or
* similar functions, since we want a non-NULL symbol anyway.
*****************************************************************************/
static
void
*
_module_getsymbol
(
module_handle_t
,
const
char
*
);
static
void
*
GetSymbol
(
module_handle_t
handle
,
const
char
*
psz_function
)
{
void
*
p_symbol
=
_module_getsymbol
(
handle
,
psz_function
);
/* MacOS X dl library expects symbols to begin with "_". So do
* some other operating systems. That's really lame, but hey, what
* can we do ? */
if
(
p_symbol
==
NULL
)
{
char
psz_call
[
strlen
(
psz_function
)
+
2
];
psz_call
[
0
]
=
'_'
;
memcpy
(
psz_call
+
1
,
psz_function
,
sizeof
(
psz_call
)
-
1
);
p_symbol
=
_module_getsymbol
(
handle
,
psz_call
);
}
return
p_symbol
;
}
static
void
*
_module_getsymbol
(
module_handle_t
handle
,
const
char
*
psz_function
)
{
#if defined(HAVE_DL_DYLD)
NSSymbol
sym
=
NSLookupSymbolInModule
(
handle
,
psz_function
);
return
NSAddressOfSymbol
(
sym
);
#elif defined(HAVE_DL_BEOS)
void
*
p_symbol
;
if
(
B_OK
==
get_image_symbol
(
handle
,
psz_function
,
B_SYMBOL_TYPE_TEXT
,
&
p_symbol
)
)
{
return
p_symbol
;
}
else
{
return
NULL
;
}
#elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
wchar_t
psz_real
[
256
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_function
,
-
1
,
psz_real
,
256
);
return
(
void
*
)
GetProcAddress
(
handle
,
psz_real
);
#elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
return
(
void
*
)
GetProcAddress
(
handle
,
(
char
*
)
psz_function
);
#elif defined(HAVE_DL_DLOPEN)
return
dlsym
(
handle
,
psz_function
);
#elif defined(HAVE_DL_SHL_LOAD)
void
*
p_sym
;
shl_findsym
(
&
handle
,
psz_function
,
TYPE_UNDEFINED
,
&
p_sym
);
return
p_sym
;
#endif
}
#if defined(HAVE_DL_WINDOWS)
static
char
*
GetWindowsError
(
void
)
{
#if defined(UNDER_CE)
wchar_t
psz_tmp
[
MAX_PATH
];
char
*
psz_buffer
=
malloc
(
MAX_PATH
);
#else
char
*
psz_tmp
=
malloc
(
MAX_PATH
);
#endif
int
i
=
0
,
i_error
=
GetLastError
();
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
NULL
,
i_error
,
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
(
LPTSTR
)
psz_tmp
,
MAX_PATH
,
NULL
);
/* Go to the end of the string */
while
(
psz_tmp
[
i
]
&&
psz_tmp
[
i
]
!=
_T
(
'\r'
)
&&
psz_tmp
[
i
]
!=
_T
(
'\n'
)
)
{
i
++
;
}
if
(
psz_tmp
[
i
]
)
{
#if defined(UNDER_CE)
swprintf
(
psz_tmp
+
i
,
L" (error %i)"
,
i_error
);
psz_tmp
[
255
]
=
L'\0'
;
#else
snprintf
(
psz_tmp
+
i
,
256
-
i
,
" (error %i)"
,
i_error
);
psz_tmp
[
255
]
=
'\0'
;
#endif
}
#if defined(UNDER_CE)
wcstombs
(
psz_buffer
,
psz_tmp
,
MAX_PATH
);
return
psz_buffer
;
#else
return
psz_tmp
;
#endif
}
#endif
/* HAVE_DL_WINDOWS */
/*****************************************************************************
* 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.
*****************************************************************************/
static
void
CacheLoad
(
vlc_object_t
*
p_this
)
{
char
*
psz_filename
,
*
psz_cachedir
;
FILE
*
file
;
int
i
,
j
,
i_size
,
i_read
;
char
p_cachestring
[
sizeof
(
"cache "
COPYRIGHT_MESSAGE
)];
char
p_cachelang
[
6
],
p_lang
[
6
];
int
i_cache
;
module_cache_t
**
pp_cache
=
0
;
int32_t
i_file_size
,
i_marker
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
psz_cachedir
=
p_this
->
p_libvlc
->
psz_cachedir
;
if
(
!
psz_cachedir
)
/* XXX: this should never happen */
{
msg_Err
(
p_this
,
"Unable to get cache directory"
);
return
;
}
i_size
=
asprintf
(
&
psz_filename
,
"%s"
DIR_SEP
"%s"
,
psz_cachedir
,
CacheName
()
);
if
(
i_size
<=
0
)
{
msg_Err
(
p_this
,
"out of memory"
);
return
;
}
if
(
p_libvlc_global
->
p_module_bank
->
b_cache_delete
)
{
#if !defined( UNDER_CE )
unlink
(
psz_filename
);
#else
wchar_t
psz_wf
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_filename
,
-
1
,
psz_wf
,
MAX_PATH
);
DeleteFile
(
psz_wf
);
#endif
msg_Dbg
(
p_this
,
"removing plugins cache file %s"
,
psz_filename
);
free
(
psz_filename
);
return
;
}
msg_Dbg
(
p_this
,
"loading plugins cache file %s"
,
psz_filename
);
file
=
utf8_fopen
(
psz_filename
,
"rb"
);
if
(
!
file
)
{
msg_Warn
(
p_this
,
"could not open plugins cache file %s for reading"
,
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 */
i_size
=
sizeof
(
"cache "
COPYRIGHT_MESSAGE
)
-
1
;
i_read
=
fread
(
p_cachestring
,
1
,
i_size
,
file
);
if
(
i_read
!=
i_size
||
memcmp
(
p_cachestring
,
"cache "
COPYRIGHT_MESSAGE
,
i_size
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache"
);
fclose
(
file
);
return
;
}
/* 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 the language hasn't changed */
sprintf
(
p_lang
,
"%5.5s"
,
_
(
"C"
)
);
i_size
=
5
;
i_read
=
fread
(
p_cachelang
,
1
,
i_size
,
file
);
if
(
i_read
!=
i_size
||
memcmp
(
p_cachelang
,
p_lang
,
i_size
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache "
"(language changed)"
);
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
;
}
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
=
0
;
if
(
fread
(
&
i_cache
,
1
,
sizeof
(
i_cache
),
file
)
!=
sizeof
(
i_cache
)
)
{
msg_Warn
(
p_this
,
"This doesn't look like a valid plugins cache "
"(file too short)"
);
fclose
(
file
);
return
;
}
if
(
i_cache
)
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_loaded_cache
=
malloc
(
i_cache
*
sizeof
(
void
*
)
);
#define LOAD_IMMEDIATE(a) \
if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
#define LOAD_STRING(a) \
{ \
a = NULL; \
if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) \
|| ( i_size > 16384 ) ) \
goto error; \
if( i_size ) { \
char *psz = malloc( i_size ); \
if( fread( psz, i_size, 1, file ) != 1 ) { \
free( psz ); \
goto error; \
} \
if( psz[i_size-1] ) { \
free( psz ); \
goto error; \
} \
a = psz; \
} \
}
for
(
i
=
0
;
i
<
i_cache
;
i
++
)
{
uint16_t
i_size
;
int
i_submodules
;
pp_cache
[
i
]
=
malloc
(
sizeof
(
module_cache_t
)
);
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
++
;
/* Load common info */
LOAD_STRING
(
pp_cache
[
i
]
->
psz_file
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
i_time
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
i_size
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
b_junk
);
pp_cache
[
i
]
->
b_used
=
VLC_FALSE
;
if
(
pp_cache
[
i
]
->
b_junk
)
continue
;
pp_cache
[
i
]
->
p_module
=
vlc_module_create
(
p_this
);
/* Load additional infos */
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
LOAD_STRING
(
pp_cache
[
i
]
->
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
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
->
i_cpu
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_unloadable
);
LOAD_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_reentrant
);
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
);
LOAD_IMMEDIATE
(
i_submodules
);
while
(
i_submodules
--
)
{
module_t
*
p_module
=
vlc_submodule_create
(
pp_cache
[
i
]
->
p_module
);
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
LOAD_STRING
(
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
LOAD_STRING
(
p_module
->
psz_capability
);
LOAD_IMMEDIATE
(
p_module
->
i_score
);
LOAD_IMMEDIATE
(
p_module
->
i_cpu
);
LOAD_IMMEDIATE
(
p_module
->
b_unloadable
);
LOAD_IMMEDIATE
(
p_module
->
b_reentrant
);
}
}
fclose
(
file
);
return
;
error:
msg_Warn
(
p_this
,
"plugins cache not loaded (corrupted)"
);
/* TODO: cleanup */
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
=
0
;
fclose
(
file
);
return
;
}
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
;
msg_Err
(
p_module
,
"config error: can't duplicate p_config"
);
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
);
LOAD_STRING
(
p_module
->
p_config
[
i
].
psz_current
);
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
;
p_module
->
p_config
[
i
].
saved
.
psz
=
NULL
;
}
else
{
memcpy
(
&
p_module
->
p_config
[
i
].
value
,
&
p_module
->
p_config
[
i
].
orig
,
sizeof
(
p_module
->
p_config
[
i
].
value
));
memcpy
(
&
p_module
->
p_config
[
i
].
saved
,
&
p_module
->
p_config
[
i
].
orig
,
sizeof
(
p_module
->
p_config
[
i
].
saved
));
}
p_module
->
p_config
[
i
].
b_dirty
=
VLC_FALSE
;
p_module
->
p_config
[
i
].
p_lock
=
&
p_module
->
object_lock
;
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
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
char
*
));
if
(
p_module
->
p_config
[
i
].
ppsz_list
)
{
for
(
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_list
[
j
]
);
p_module
->
p_config
[
i
].
ppsz_list
[
j
]
=
NULL
;
}
}
if
(
p_module
->
p_config
[
i
].
ppsz_list_text
)
{
int
j
;
p_module
->
p_config
[
i
].
ppsz_list_text
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
char
*
));
if
(
p_module
->
p_config
[
i
].
ppsz_list_text
)
{
for
(
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_list_text
[
j
]
);
p_module
->
p_config
[
i
].
ppsz_list_text
[
j
]
=
NULL
;
}
}
if
(
p_module
->
p_config
[
i
].
pi_list
)
{
p_module
->
p_config
[
i
].
pi_list
=
malloc
(
(
p_module
->
p_config
[
i
].
i_list
+
1
)
*
sizeof
(
int
)
);
if
(
p_module
->
p_config
[
i
].
pi_list
)
{
for
(
int
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_list
;
j
++
)
LOAD_IMMEDIATE
(
p_module
->
p_config
[
i
].
pi_list
[
j
]
);
}
}
}
if
(
p_module
->
p_config
[
i
].
i_action
)
{
p_module
->
p_config
[
i
].
ppf_action
=
malloc
(
p_module
->
p_config
[
i
].
i_action
*
sizeof
(
void
*
)
);
p_module
->
p_config
[
i
].
ppsz_action_text
=
malloc
(
p_module
->
p_config
[
i
].
i_action
*
sizeof
(
char
*
)
);
for
(
int
j
=
0
;
j
<
p_module
->
p_config
[
i
].
i_action
;
j
++
)
{
p_module
->
p_config
[
i
].
ppf_action
[
j
]
=
0
;
LOAD_STRING
(
p_module
->
p_config
[
i
].
ppsz_action_text
[
j
]
);
}
}
LOAD_IMMEDIATE
(
p_module
->
p_config
[
i
].
pf_callback
);
}
return
VLC_SUCCESS
;
error:
return
VLC_EGENERIC
;
}
/*****************************************************************************
* SavePluginsCache: saves the plugins cache to a file
*****************************************************************************/
static
void
CacheSave
(
vlc_object_t
*
p_this
)
{
static
char
const
psz_tag
[]
=
"Signature: 8a477f597d28d172789f06886806bc55
\r\n
"
"# This file is a cache directory tag created by VLC.
\r\n
"
"# For information about cache directory tags, see:
\r\n
"
"# http://www.brynosaurus.com/cachedir/
\r\n
"
;
char
*
psz_cachedir
;
size_t
i_len
=
0
;
FILE
*
file
;
int
i
,
j
,
i_cache
;
module_cache_t
**
pp_cache
;
int32_t
i_file_size
=
0
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
psz_cachedir
=
p_this
->
p_libvlc
->
psz_cachedir
;
if
(
!
psz_cachedir
)
/* XXX: this should never happen */
{
msg_Err
(
p_this
,
"Unable to get cache directory"
);
return
;
}
char
psz_filename
[
sizeof
(
DIR_SEP
)
+
32
+
strlen
(
psz_cachedir
)];
config_CreateDir
(
p_this
,
psz_cachedir
);
snprintf
(
psz_filename
,
sizeof
(
psz_filename
),
"%s"
DIR_SEP
"CACHEDIR.TAG"
,
psz_cachedir
);
file
=
utf8_fopen
(
psz_filename
,
"wb"
);
if
(
file
)
{
fwrite
(
psz_tag
,
1
,
strlen
(
psz_tag
),
file
);
fclose
(
file
);
}
snprintf
(
psz_filename
,
sizeof
(
psz_filename
),
"%s"
DIR_SEP
"%s"
,
psz_cachedir
,
CacheName
()
);
msg_Dbg
(
p_this
,
"saving plugins cache file %s"
,
psz_filename
);
file
=
utf8_fopen
(
psz_filename
,
"wb"
);
if
(
!
file
)
{
msg_Warn
(
p_this
,
"could not open plugins cache file %s for writing"
,
psz_filename
);
return
;
}
/* Empty space for file size */
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
/* Contains version number */
fprintf
(
file
,
"%s"
,
"cache "
COPYRIGHT_MESSAGE
);
/* Sub-version number (to avoid breakage in the dev version when cache
* structure changes) */
i_file_size
=
CACHE_SUBVERSION_NUM
;
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
/* Language */
fprintf
(
file
,
"%5.5s"
,
_
(
"C"
)
);
/* Header marker */
i_file_size
=
ftell
(
file
);
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
i_cache
=
p_libvlc_global
->
p_module_bank
->
i_cache
;
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_cache
;
fwrite
(
&
i_cache
,
sizeof
(
char
),
sizeof
(
i_cache
),
file
);
#define SAVE_IMMEDIATE(a) \
fwrite( &a, sizeof(char), sizeof(a), file )
#define SAVE_STRING(a) \
{ i_size = a ? strlen( a ) + 1 : 0; \
fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \
if( a ) fwrite( a, sizeof(char), i_size, file ); \
} while(0)
for
(
i
=
0
;
i
<
i_cache
;
i
++
)
{
uint16_t
i_size
;
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_IMMEDIATE
(
pp_cache
[
i
]
->
b_junk
);
if
(
pp_cache
[
i
]
->
b_junk
)
continue
;
/* 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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
SAVE_STRING
(
pp_cache
[
i
]
->
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
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
->
i_cpu
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_unloadable
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_reentrant
);
SAVE_IMMEDIATE
(
pp_cache
[
i
]
->
p_module
->
b_submodule
);
/* Config stuff */
CacheSaveConfig
(
pp_cache
[
i
]
->
p_module
,
file
);
SAVE_STRING
(
pp_cache
[
i
]
->
p_module
->
psz_filename
);
i_submodule
=
pp_cache
[
i
]
->
p_module
->
i_children
;
SAVE_IMMEDIATE
(
i_submodule
);
for
(
i_submodule
=
0
;
i_submodule
<
(
unsigned
)
pp_cache
[
i
]
->
p_module
->
i_children
;
i_submodule
++
)
{
module_t
*
p_module
=
(
module_t
*
)
pp_cache
[
i
]
->
p_module
->
pp_children
[
i_submodule
];
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
);
for
(
j
=
0
;
j
<
MODULE_SHORTCUT_MAX
;
j
++
)
{
SAVE_STRING
(
p_module
->
pp_shortcuts
[
j
]
);
// FIX
}
SAVE_STRING
(
p_module
->
psz_capability
);
SAVE_IMMEDIATE
(
p_module
->
i_score
);
SAVE_IMMEDIATE
(
p_module
->
i_cpu
);
SAVE_IMMEDIATE
(
p_module
->
b_unloadable
);
SAVE_IMMEDIATE
(
p_module
->
b_reentrant
);
}
}
/* Fill-up file size */
i_file_size
=
ftell
(
file
);
fseek
(
file
,
0
,
SEEK_SET
);
fwrite
(
&
i_file_size
,
sizeof
(
char
),
sizeof
(
i_file_size
),
file
);
fclose
(
file
);
}
void
CacheSaveConfig
(
module_t
*
p_module
,
FILE
*
file
)
{
uint32_t
i_lines
=
p_module
->
confsize
;
uint16_t
i_size
;
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
);
SAVE_STRING
(
p_module
->
p_config
[
i
].
psz_current
);
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
]
);
SAVE_IMMEDIATE
(
p_module
->
p_config
[
i
].
pf_callback
);
}
}
/*****************************************************************************
* CacheName: Return the cache file name for this platform.
*****************************************************************************/
static
char
*
CacheName
(
void
)
{
static
char
psz_cachename
[
32
];
/* Code int size, pointer size and endianness in the filename */
int32_t
x
=
0xbe00001e
;
sprintf
(
psz_cachename
,
"plugins-%.2x%.2x%.2x.dat"
,
(
int
)
sizeof
(
int
),
(
int
)
sizeof
(
void
*
),
(
unsigned
int
)((
unsigned
char
*
)
&
x
)[
0
]
);
return
psz_cachename
;
}
/*****************************************************************************
* CacheMerge: Merge a cache module descriptor with a full module descriptor.
*****************************************************************************/
static
void
CacheMerge
(
vlc_object_t
*
p_this
,
module_t
*
p_cache
,
module_t
*
p_module
)
{
int
i_submodule
;
(
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
;
for
(
i_submodule
=
0
;
i_submodule
<
p_module
->
i_children
;
i_submodule
++
)
{
module_t
*
p_child
=
(
module_t
*
)
p_module
->
pp_children
[
i_submodule
];
module_t
*
p_cchild
=
(
module_t
*
)
p_cache
->
pp_children
[
i_submodule
];
p_cchild
->
pf_activate
=
p_child
->
pf_activate
;
p_cchild
->
pf_deactivate
=
p_child
->
pf_deactivate
;
}
p_cache
->
b_loaded
=
VLC_TRUE
;
p_module
->
b_loaded
=
VLC_FALSE
;
}
/*****************************************************************************
* CacheFind: finds the cache entry corresponding to a file
*****************************************************************************/
static
module_cache_t
*
CacheFind
(
vlc_object_t
*
p_this
,
char
*
psz_file
,
int64_t
i_time
,
int64_t
i_size
)
{
module_cache_t
**
pp_cache
;
int
i_cache
,
i
;
libvlc_global_data_t
*
p_libvlc_global
=
vlc_global
();
pp_cache
=
p_libvlc_global
->
p_module_bank
->
pp_loaded_cache
;
i_cache
=
p_libvlc_global
->
p_module_bank
->
i_loaded_cache
;
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 */
src/modules/modules.h
View file @
e03e85ca
...
...
@@ -161,4 +161,15 @@ void __module_EndBank ( vlc_object_t * );
#define module_ResetBank(a) __module_ResetBank(VLC_OBJECT(a))
void
__module_ResetBank
(
vlc_object_t
*
);
/* Low-level OS-dependant handler */
int
module_Call
(
module_t
*
);
int
module_Load
(
vlc_object_t
*
,
const
char
*
,
module_handle_t
*
);
void
module_Unload
(
module_handle_t
);
/* Plugins cache */
void
CacheMerge
(
vlc_object_t
*
,
module_t
*
,
module_t
*
);
void
CacheLoad
(
vlc_object_t
*
);
void
CacheSave
(
vlc_object_t
*
);
module_cache_t
*
CacheFind
(
vlc_object_t
*
,
const
char
*
,
int64_t
,
int64_t
);
#endif
/* !__LIBVLC_MODULES_H */
src/modules/os.c
0 → 100644
View file @
e03e85ca
/*****************************************************************************
* os.c : Low-level dynamic library handling
*****************************************************************************
* 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.
*****************************************************************************/
#include <vlc/vlc.h>
#include "libvlc.h"
#include "modules.h"
#include <stdlib.h>
/* free(), strtol() */
#include <stdio.h>
/* sprintf() */
#include <string.h>
/* strdup() */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if !defined(HAVE_DYNAMIC_PLUGINS)
/* no support for plugins */
#elif defined(HAVE_DL_DYLD)
# if defined(HAVE_MACH_O_DYLD_H)
# include <mach-o/dyld.h>
# endif
#elif defined(HAVE_DL_BEOS)
# if defined(HAVE_IMAGE_H)
# include <image.h>
# endif
#elif defined(HAVE_DL_WINDOWS)
# include <windows.h>
#elif defined(HAVE_DL_DLOPEN)
# if defined(HAVE_DLFCN_H)
/* Linux, BSD, Hurd */
# include <dlfcn.h>
# endif
# if defined(HAVE_SYS_DL_H)
# include <sys/dl.h>
# endif
#elif defined(HAVE_DL_SHL_LOAD)
# if defined(HAVE_DL_H)
# include <dl.h>
# endif
#endif
//#include "config/config.h"
//#include "vlc_charset.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
static
void
*
GetSymbol
(
module_handle_t
,
const
char
*
);
#if defined(HAVE_DL_WINDOWS)
static
char
*
GetWindowsError
(
void
);
#endif
/*****************************************************************************
* module_Call: call an entry point.
*****************************************************************************
* This function calls a symbol given its name and a module structure. The
* symbol MUST refer to a function returning int and taking a module_t* as
* an argument.
*****************************************************************************/
int
module_Call
(
module_t
*
p_module
)
{
static
const
char
psz_name
[]
=
"vlc_entry"
MODULE_SUFFIX
;
int
(
*
pf_symbol
)
(
module_t
*
p_module
);
/* Try to resolve the symbol */
pf_symbol
=
(
int
(
*
)(
module_t
*
))
GetSymbol
(
p_module
->
handle
,
psz_name
);
if
(
pf_symbol
==
NULL
)
{
#if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s'"
,
psz_name
,
p_module
->
psz_filename
);
#elif defined(HAVE_DL_WINDOWS)
char
*
psz_error
=
GetWindowsError
();
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%s)"
,
psz_name
,
p_module
->
psz_filename
,
psz_error
);
free
(
psz_error
);
#elif defined(HAVE_DL_DLOPEN)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%s)"
,
psz_name
,
p_module
->
psz_filename
,
dlerror
()
);
#elif defined(HAVE_DL_SHL_LOAD)
msg_Warn
(
p_module
,
"cannot find symbol
\"
%s
\"
in file `%s' (%m)"
,
psz_name
,
p_module
->
psz_filename
);
#else
# error "Something is wrong in modules.c"
#endif
return
-
1
;
}
/* We can now try to call the symbol */
if
(
pf_symbol
(
p_module
)
!=
0
)
{
/* With a well-written module we shouldn't have to print an
* additional error message here, but just make sure. */
msg_Err
(
p_module
,
"Failed to call symbol
\"
%s
\"
in file `%s'"
,
psz_name
,
p_module
->
psz_filename
);
return
-
1
;
}
/* Everything worked fine, we can return */
return
0
;
}
/*****************************************************************************
* module_Load: loads a dynamic library
*****************************************************************************
* This function loads a dynamically linked library using a system dependant
* method. Will return 0 on success as well as the module handle.
*****************************************************************************/
int
module_Load
(
vlc_object_t
*
p_this
,
const
char
*
psz_file
,
module_handle_t
*
p_handle
)
{
module_handle_t
handle
;
#if defined(HAVE_DL_DYLD)
NSObjectFileImage
image
;
NSObjectFileImageReturnCode
ret
;
ret
=
NSCreateObjectFileImageFromFile
(
psz_file
,
&
image
);
if
(
ret
!=
NSObjectFileImageSuccess
)
{
msg_Warn
(
p_this
,
"cannot create image from `%s'"
,
psz_file
);
return
-
1
;
}
/* Open the dynamic module */
handle
=
NSLinkModule
(
image
,
psz_file
,
NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
if
(
!
handle
)
{
NSLinkEditErrors
errors
;
const
char
*
psz_file
,
*
psz_err
;
int
i_errnum
;
NSLinkEditError
(
&
errors
,
&
i_errnum
,
&
psz_file
,
&
psz_err
);
msg_Warn
(
p_this
,
"cannot link module `%s' (%s)"
,
psz_file
,
psz_err
);
NSDestroyObjectFileImage
(
image
);
return
-
1
;
}
/* Destroy our image, we won't need it */
NSDestroyObjectFileImage
(
image
);
#elif defined(HAVE_DL_BEOS)
handle
=
load_add_on
(
psz_file
);
if
(
handle
<
0
)
{
msg_Warn
(
p_this
,
"cannot load module `%s'"
,
psz_file
);
return
-
1
;
}
#elif defined(HAVE_DL_WINDOWS)
#ifdef UNDER_CE
{
wchar_t
psz_wfile
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_file
,
-
1
,
psz_wfile
,
MAX_PATH
);
handle
=
LoadLibrary
(
psz_wfile
);
}
#else
handle
=
LoadLibrary
(
psz_file
);
#endif
if
(
handle
==
NULL
)
{
char
*
psz_err
=
GetWindowsError
();
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
psz_err
);
free
(
psz_err
);
return
-
1
;
}
#elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
/* static is OK, we are called atomically */
handle
=
dlopen
(
psz_file
,
RTLD_NOW
);
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
dlerror
()
);
return
-
1
;
}
#elif defined(HAVE_DL_DLOPEN)
# if defined(DL_LAZY)
handle
=
dlopen
(
psz_file
,
DL_LAZY
);
# else
handle
=
dlopen
(
psz_file
,
0
);
# endif
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%s)"
,
psz_file
,
dlerror
()
);
return
-
1
;
}
#elif defined(HAVE_DL_SHL_LOAD)
handle
=
shl_load
(
psz_file
,
BIND_IMMEDIATE
|
BIND_NONFATAL
,
NULL
);
if
(
handle
==
NULL
)
{
msg_Warn
(
p_this
,
"cannot load module `%s' (%m)"
,
psz_file
);
return
-
1
;
}
#else
# error "Something is wrong in modules.c"
#endif
*
p_handle
=
handle
;
return
0
;
}
/*****************************************************************************
* CloseModule: unload a dynamic library
*****************************************************************************
* This function unloads a previously opened dynamically linked library
* using a system dependant method. No return value is taken in consideration,
* since some libraries sometimes refuse to close properly.
*****************************************************************************/
void
module_Unload
(
module_handle_t
handle
)
{
#if defined(HAVE_DL_DYLD)
NSUnLinkModule
(
handle
,
FALSE
);
#elif defined(HAVE_DL_BEOS)
unload_add_on
(
handle
);
#elif defined(HAVE_DL_WINDOWS)
FreeLibrary
(
handle
);
#elif defined(HAVE_DL_DLOPEN)
# ifdef NDEBUG
dlclose
(
handle
);
# endif
#elif defined(HAVE_DL_SHL_LOAD)
shl_unload
(
handle
);
#endif
return
;
}
/*****************************************************************************
* GetSymbol: get a symbol from a dynamic library
*****************************************************************************
* This function queries a loaded library for a symbol specified in a
* string, and returns a pointer to it. We don't check for dlerror() or
* similar functions, since we want a non-NULL symbol anyway.
*****************************************************************************/
static
void
*
_module_getsymbol
(
module_handle_t
,
const
char
*
);
static
void
*
GetSymbol
(
module_handle_t
handle
,
const
char
*
psz_function
)
{
void
*
p_symbol
=
_module_getsymbol
(
handle
,
psz_function
);
/* MacOS X dl library expects symbols to begin with "_". So do
* some other operating systems. That's really lame, but hey, what
* can we do ? */
if
(
p_symbol
==
NULL
)
{
char
psz_call
[
strlen
(
psz_function
)
+
2
];
psz_call
[
0
]
=
'_'
;
memcpy
(
psz_call
+
1
,
psz_function
,
sizeof
(
psz_call
)
-
1
);
p_symbol
=
_module_getsymbol
(
handle
,
psz_call
);
}
return
p_symbol
;
}
static
void
*
_module_getsymbol
(
module_handle_t
handle
,
const
char
*
psz_function
)
{
#if defined(HAVE_DL_DYLD)
NSSymbol
sym
=
NSLookupSymbolInModule
(
handle
,
psz_function
);
return
NSAddressOfSymbol
(
sym
);
#elif defined(HAVE_DL_BEOS)
void
*
p_symbol
;
if
(
B_OK
==
get_image_symbol
(
handle
,
psz_function
,
B_SYMBOL_TYPE_TEXT
,
&
p_symbol
)
)
{
return
p_symbol
;
}
else
{
return
NULL
;
}
#elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
wchar_t
psz_real
[
256
];
MultiByteToWideChar
(
CP_ACP
,
0
,
psz_function
,
-
1
,
psz_real
,
256
);
return
(
void
*
)
GetProcAddress
(
handle
,
psz_real
);
#elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
return
(
void
*
)
GetProcAddress
(
handle
,
(
char
*
)
psz_function
);
#elif defined(HAVE_DL_DLOPEN)
return
dlsym
(
handle
,
psz_function
);
#elif defined(HAVE_DL_SHL_LOAD)
void
*
p_sym
;
shl_findsym
(
&
handle
,
psz_function
,
TYPE_UNDEFINED
,
&
p_sym
);
return
p_sym
;
#endif
}
#if defined(HAVE_DL_WINDOWS)
static
char
*
GetWindowsError
(
void
)
{
#if defined(UNDER_CE)
wchar_t
psz_tmp
[
MAX_PATH
];
char
*
psz_buffer
=
malloc
(
MAX_PATH
);
#else
char
*
psz_tmp
=
malloc
(
MAX_PATH
);
#endif
int
i
=
0
,
i_error
=
GetLastError
();
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
NULL
,
i_error
,
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
(
LPTSTR
)
psz_tmp
,
MAX_PATH
,
NULL
);
/* Go to the end of the string */
while
(
psz_tmp
[
i
]
&&
psz_tmp
[
i
]
!=
_T
(
'\r'
)
&&
psz_tmp
[
i
]
!=
_T
(
'\n'
)
)
{
i
++
;
}
if
(
psz_tmp
[
i
]
)
{
#if defined(UNDER_CE)
swprintf
(
psz_tmp
+
i
,
L" (error %i)"
,
i_error
);
psz_tmp
[
255
]
=
L'\0'
;
#else
snprintf
(
psz_tmp
+
i
,
256
-
i
,
" (error %i)"
,
i_error
);
psz_tmp
[
255
]
=
'\0'
;
#endif
}
#if defined(UNDER_CE)
wcstombs
(
psz_buffer
,
psz_tmp
,
MAX_PATH
);
return
psz_buffer
;
#else
return
psz_tmp
;
#endif
}
#endif
/* HAVE_DL_WINDOWS */
#endif
/* HAVE_DYNAMIC_PLUGINS */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment