Commit 97fbfd88 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Compute the lib directory dynamically

On Linux, this simplifies the code and improves relocability.
On Windows, OS/2 and MacOS, this should fix a small race condition.
parent 2171af17
......@@ -196,7 +196,7 @@ VLC_API void config_ResetAll( vlc_object_t * );
VLC_API module_config_t * config_FindConfig( vlc_object_t *, const char * ) VLC_USED;
VLC_API char * config_GetDataDir( vlc_object_t * ) VLC_USED VLC_MALLOC;
#define config_GetDataDir(a) config_GetDataDir(VLC_OBJECT(a))
VLC_API const char * config_GetLibDir( void ) VLC_USED;
VLC_API char *config_GetLibDir(void) VLC_USED;
VLC_API const char * config_GetConfDir( void ) VLC_USED;
typedef enum vlc_userdir
......
......@@ -230,9 +230,14 @@ int vlclua_dir_list( vlc_object_t *p_this, const char *luadirname,
free( datadir );
#if !(defined(__APPLE__) || defined(WIN32) || defined(__OS2__))
if( likely(asprintf( &ppsz_dir_list[i], "%s"DIR_SEP"lua"DIR_SEP"%s",
config_GetLibDir(), luadirname ) != -1) )
char *psz_libpath = config_GetLibDir();
if( likely(psz_libpath != NULL) )
{
if( likely(asprintf( &ppsz_dir_list[i], "%s"DIR_SEP"lua"DIR_SEP"%s",
psz_libpath, luadirname ) != -1) )
i++;
free( psz_libpath );
}
#endif
char *psz_datapath = config_GetDataDir( p_this );
......
......@@ -119,8 +119,6 @@ void vlc_object_set_destructor (vlc_object_t *, vlc_destructor_t);
/*
* To be cleaned-up module stuff:
*/
extern char *psz_vlcpath;
module_t *module_find_by_shortcut (const char *psz_shortcut);
/**
......
......@@ -245,8 +245,6 @@ module_t **module_list_get (size_t *n)
return tab;
}
char *psz_vlcpath = NULL;
#ifdef HAVE_DYNAMIC_PLUGINS
typedef enum { CACHE_USE, CACHE_RESET, CACHE_IGNORE } cache_mode_t;
......@@ -262,7 +260,6 @@ static void AllocatePluginPath (vlc_object_t *, const char *, cache_mode_t);
*/
static void AllocateAllPlugins (vlc_object_t *p_this)
{
const char *vlcpath = psz_vlcpath;
char *paths;
cache_mode_t mode;
......@@ -275,13 +272,14 @@ static void AllocateAllPlugins (vlc_object_t *p_this)
/* Contruct the special search path for system that have a relocatable
* executable. Set it to <vlc path>/plugins. */
assert( vlcpath );
if( asprintf( &paths, "%s" DIR_SEP "plugins", vlcpath ) != -1 )
char *vlcpath = config_GetLibDir ();
if (likely(vlcpath != NULL)
&& likely(asprintf (&paths, "%s" DIR_SEP "plugins", vlcpath) != -1))
{
AllocatePluginPath (p_this, paths, mode);
free( paths );
}
free (vlcpath);
/* If the user provided a plugin path, we add it to the list */
paths = getenv( "VLC_PLUGIN_PATH" );
......
......@@ -30,9 +30,20 @@
#include <vlc_charset.h>
#include "config/configuration.h"
static char *config_GetVlcDir (void)
char *config_GetLibDir (void)
{
return FromLocaleDup (psz_vlcpath);
HMODULE hmod;
CHAR psz_path[CCHMAXPATH + 4];
DosQueryModFromEIP( &hmod, NULL, 0, NULL, NULL, ( ULONG )system_Init );
DosQueryModuleName( hmod, sizeof( psz_path ), psz_path );
/* remove the DLL name */
char *slash = strrchr( psz_path, '\\');
if( slash == NULL )
abort();
strcpy(slash + 1, PACKAGE);
return FromLocaleDup(psz_path);
}
/**
......@@ -42,7 +53,7 @@ static char *config_GetVlcDir (void)
*/
char *config_GetDataDirDefault (void)
{
char *datadir = config_GetVlcDir();
char *datadir = config_GetLibDir();
if (datadir)
/* replace last lib\vlc with share */
......@@ -51,16 +62,6 @@ char *config_GetDataDirDefault (void)
return datadir;
}
/**
* Determines the architecture-dependent data directory
*
* @return a string (always succeeds).
*/
const char *config_GetLibDir (void)
{
abort ();
}
/**
* Determines the system configuration directory.
*
......@@ -68,7 +69,8 @@ const char *config_GetLibDir (void)
*/
const char *config_GetConfDir( void )
{
return config_GetVlcDir ();
#warning FIXME: memory leak
return config_GetLibDir ();
}
char *config_GetUserDir (vlc_userdir_t type)
......@@ -89,5 +91,5 @@ char *config_GetUserDir (vlc_userdir_t type)
case VLC_VIDEOS_DIR:
break;
}
return config_GetVlcDir ();
return config_GetLibDir ();
}
......@@ -32,25 +32,6 @@ extern int _fmode_bin;
void system_Init( void )
{
HMODULE hmod;
CHAR psz_path[ CCHMAXPATH ];
PSZ psz_dirsep;
DosQueryModFromEIP( &hmod, NULL, 0, NULL, NULL, ( ULONG )system_Init );
DosQueryModuleName( hmod, sizeof( psz_path ), psz_path );
/* remove the DLL name */
psz_dirsep = strrchr( psz_path, '\\');
if( psz_dirsep )
*psz_dirsep = '\0';
DosEnterCritSec();
if( !psz_vlcpath )
asprintf( &psz_vlcpath, "%s\\vlc", psz_path );
DosExitCritSec();
/* Set the default file-translation mode */
_fmode_bin = 1;
setmode( fileno( stdin ), O_BINARY ); /* Needed for pipes */
......@@ -74,6 +55,4 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_
void system_End( void )
{
free( psz_vlcpath );
psz_vlcpath = NULL;
}
......@@ -2,7 +2,7 @@
* darwin_dirs.c: Mac OS X directories configuration
*****************************************************************************
* Copyright (C) 2001-2009 VLC authors and VideoLAN
* Copyright © 2007-2009 Rémi Denis-Courmont
* Copyright © 2007-2012 Rémi Denis-Courmont
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* Felix Paul Kühne <fkuehne at videolan dot org>
......@@ -35,6 +35,10 @@
#include <vlc_configuration.h>
#include "config/configuration.h"
#include <libgen.h>
#include <dlfcn.h>
#include <mach-o/dyld.h>
static char *configdir = NULL;
static pthread_once_t once = PTHREAD_ONCE_INIT;
......@@ -50,20 +54,80 @@ const char *config_GetConfDir( void )
return configdir;
}
char *config_GetDataDirDefault (void)
static char *config_GetLibPath (void)
{
char *datadir;
/* Get the full program path and name */
/* First try to see if we are linked to the framework */
for (unsigned i = 0; i < _dyld_image_count(); i++)
{
const char *psz_img_name = _dyld_get_image_name(i);
const char *p = strstr( psz_img_name, "VLCKit.framework/Versions/" );
if (asprintf (&datadir, "%s/share", psz_vlcpath) == -1)
return NULL;
return datadir;
/* Check for "VLCKit.framework/Versions/Current/VLCKit",
* as well as "VLCKit.framework/Versions/A/VLCKit" and
* "VLC.framework/Versions/B/VLCKit" */
if( p != NULL )
{
/* Look for the next forward slash */
p += 26; /* p_char += strlen(" VLCKit.framework/Versions/" ) */
p += strcspn( p, "/" );
/* If the string ends with VLC then we've found a winner */
if ( !strcmp( p, "/VLCKit" ) )
return strdup( psz_img_name );
}
/* Do we end by "VLC"? If so we are the legacy VLC.app that doesn't
* link to VLCKit. */
size_t len = strlen(psz_img_name);
if( len >= 3 && !strcmp( psz_img_name + len - 3, "VLC") )
return strdup( psz_img_name );
}
/* We are not linked to the VLC.framework, let's use dladdr to figure
* libvlc path */
Dl_info info;
if( dladdr(system_Init, &info) )
return strdup(dirname( info.dli_fname ));
char path[MAXPATHLEN+1];
uint32_t path_len = sizeof(path) - 1;
if ( !_NSGetExecutablePath(path, &path_len) )
return strdup(path);
return NULL;
}
const char *config_GetLibDir (void)
char *config_GetLibDir (void)
{
char *path = config_GetLibPath ();
if (path != NULL)
{
char *p = strrchr (p, '/');
if (p != NULL)
{
*p = '\0';
return path;
}
free (path);
}
/* should never happen */
abort ();
}
char *config_GetDataDirDefault (void)
{
char *vlcpath = config_GetLibDir ();
char *datadir;
if (asprintf (&datadir, "%s/share", vlcpath) == -1)
datadir = NULL;
free (vlcpath);
return datadir;
}
static char *config_GetHomeDir (void)
{
const char *home = getenv ("HOME");
......
......@@ -31,10 +31,7 @@
#include <vlc_common.h>
#include "../libvlc.h"
#include <dirent.h> /* *dir() */
#include <libgen.h>
#include <dlfcn.h>
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h>
#ifdef HAVE_LOCALE_H
# include <locale.h>
......@@ -49,78 +46,6 @@
*****************************************************************************/
void system_Init(void)
{
char i_dummy;
char *p_char = NULL;
char *p_oldchar = &i_dummy;
unsigned int i;
/* Get the full program path and name */
/* First try to see if we are linked to the framework */
for (i = 0; i < _dyld_image_count(); i++)
{
const char * psz_img_name = _dyld_get_image_name(i);
/* Check for "VLCKit.framework/Versions/Current/VLCKit",
* as well as "VLCKit.framework/Versions/A/VLCKit" and
* "VLC.framework/Versions/B/VLCKit" */
if( (p_char = strstr( psz_img_name, "VLCKit.framework/Versions/" )) )
{
/* Look for the next forward slash */
p_char += 26; /* p_char += strlen(" VLCKit.framework/Versions/" ) */
while( *p_char != '\0' && *p_char != '/')
p_char++;
/* If the string ends with VLC then we've found a winner */
if ( !strcmp( p_char, "/VLCKit" ) )
{
p_char = strdup( psz_img_name );
break;
}
else
p_char = NULL;
}
else
{
size_t len = strlen(psz_img_name);
/* Do we end by "VLC"? If so we are the legacy VLC.app that doesn't
* link to VLCKit. */
if( !strcmp( psz_img_name + len - 3, "VLC") )
{
p_char = strdup( psz_img_name );
break;
}
}
}
if ( !p_char )
{
/* We are not linked to the VLC.framework, let's use dladdr to figure
* libvlc path */
Dl_info info;
if( dladdr(system_Init, &info) )
p_char = strdup(dirname( info.dli_fname ));
}
if( !p_char )
{
char path[MAXPATHLEN+1];
uint32_t path_len = MAXPATHLEN;
if ( !_NSGetExecutablePath(path, &path_len) )
p_char = strdup(path);
}
free(psz_vlcpath);
psz_vlcpath = p_char;
/* Remove trailing program name */
for( ; *p_char ; )
{
if( *p_char == '/' )
{
*p_oldchar = '/';
*p_char = '\0';
p_oldchar = p_char;
}
p_char++;
}
#ifdef ENABLE_NLS
/* Check if $LANG is set. */
if( NULL == getenv("LANG") )
......@@ -168,7 +93,5 @@ void system_Configure( libvlc_int_t *p_this,
*****************************************************************************/
void system_End( void )
{
free( psz_vlcpath );
psz_vlcpath = NULL;
}
......@@ -46,15 +46,17 @@ char *config_GetDataDirDefault (void)
return strdup (DATA_PATH);
}
#if !defined (__linux__)
/**
* Determines the architecture-dependent data directory
*
* @return a string (always succeeds).
*/
const char *config_GetLibDir (void)
char *config_GetLibDir (void)
{
return PKGLIBDIR;
return strdup (PKGLIBDIR);
}
#endif
/**
* Determines the system configuration directory.
......
/*****************************************************************************
* linux_specific.c: Linux-specific initialization
*****************************************************************************
* Copyright © 2008 Rémi Denis-Courmont
* Copyright © 2008-2012 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -28,10 +28,10 @@
#include <vlc_common.h>
#include "../libvlc.h"
static const char default_path[] = PKGLIBDIR;
static void set_libvlc_path (void)
char *config_GetLibDir (void)
{
char *path = NULL;
/* Find the path to libvlc (i.e. ourselves) */
FILE *maps = fopen ("/proc/self/maps", "rt");
if (maps == NULL)
......@@ -39,7 +39,7 @@ static void set_libvlc_path (void)
char *line = NULL;
size_t linelen = 0;
uintptr_t needle = (uintptr_t)set_libvlc_path;
uintptr_t needle = (uintptr_t)config_GetLibDir;
for (;;)
{
......@@ -50,39 +50,30 @@ static void set_libvlc_path (void)
void *start, *end;
if (sscanf (line, "%p-%p", &start, &end) < 2)
continue;
/* This mapping contains the address of this function. */
if (needle < (uintptr_t)start || (uintptr_t)end <= needle)
continue;
char *dir = strchr (line, '/');
if (dir == NULL)
continue;
char *file = strrchr (line, '/');
if (end == NULL)
continue;
*file = '\0';
if (asprintf (&psz_vlcpath, "%s/"PACKAGE, dir) == -1)
goto error;
if (asprintf (&path, "%s/"PACKAGE, dir) == -1)
path = NULL;
break;
}
free (line);
fclose (maps);
return;
error:
psz_vlcpath = (char *)default_path; /* default, cannot fail */
return (path != NULL) ? path : strdup (PKGLIBDIR);
}
static void unset_libvlc_path (void)
{
if (psz_vlcpath != default_path)
free (psz_vlcpath);
}
static struct
{
vlc_mutex_t lock;
unsigned refs;
} once = { VLC_STATIC_MUTEX, 0 };
#ifdef __GLIBC__
# include <gnu/libc-version.h>
# include <stdlib.h>
......@@ -103,11 +94,6 @@ void system_Init (void)
fflush (stderr);
}
#endif
vlc_mutex_lock (&once.lock);
if (once.refs++ == 0)
set_libvlc_path ();
vlc_mutex_unlock (&once.lock);
}
void system_Configure (libvlc_int_t *libvlc,
......@@ -118,8 +104,4 @@ void system_Configure (libvlc_int_t *libvlc,
void system_End (void)
{
vlc_mutex_lock (&once.lock);
if (--once.refs == 0)
unset_libvlc_path ();
vlc_mutex_unlock (&once.lock);
}
......@@ -24,18 +24,9 @@
#include <vlc_common.h>
#include "../libvlc.h"
#include <pthread.h>
static void set_libvlc_path (void)
{
psz_vlcpath = (char *)PKGLIBDIR;
}
void system_Init (void)
{
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once (&once, set_libvlc_path);
}
void system_Configure (libvlc_int_t *libvlc,
......
/*****************************************************************************
* dirs.c: directories configuration
*****************************************************************************
* Copyright (C) 2001-2007 VLC authors and VideoLAN
* Copyright © 2007-2008 Rémi Denis-Courmont
* Copyright (C) 2001-2010 VLC authors and VideoLAN
* Copyright © 2007-2012 Rémi Denis-Courmont
*
* Authors: Gildas Bazin <gbazin@videolan.org>
*
......@@ -25,6 +25,7 @@
# include "config.h"
#endif
#define UNICODE
#include <vlc_common.h>
#include <w32api.h>
......@@ -41,14 +42,30 @@
#include <assert.h>
#include <limits.h>
char *config_GetDataDirDefault( void )
char *config_GetLibDir (void)
{
return strdup (psz_vlcpath);
/* Get our full path */
MEMORY_BASIC_INFORMATION mbi;
if (!VirtualQuery (config_GetLibDir, &mbi, sizeof(mbi)))
goto error;
wchar_t wpath[MAX_PATH];
if (!GetModuleFileName ((HMODULE) mbi.AllocationBase, wpath, MAX_PATH))
goto error;
wchar_t *file = wcsrchr (wpath, L'\\');
if (file == NULL)
goto error;
*file = L'\0';
return FromWide (wpath);
error:
abort ();
}
const char *config_GetLibDir (void)
char *config_GetDataDirDefault( void )
{
abort ();
return config_GetLibDir ();
}
const char *config_GetConfDir (void)
......
......@@ -45,38 +45,6 @@
void system_Init( void )
{
WSADATA Data;
MEMORY_BASIC_INFORMATION mbi;
/* Get our full path */
char psz_path[MAX_PATH];
char *psz_vlc;
wchar_t psz_wpath[MAX_PATH];
if( VirtualQuery(system_Init, &mbi, sizeof(mbi) ) )
{
HMODULE hMod = (HMODULE) mbi.AllocationBase;
if( GetModuleFileName( hMod, psz_wpath, MAX_PATH ) )
{
WideCharToMultiByte( CP_UTF8, 0, psz_wpath, -1,
psz_path, MAX_PATH, NULL, NULL );
}
else psz_path[0] = '\0';
}
else psz_path[0] = '\0';
psz_vlc = strrchr( psz_path, '\\' );
if( psz_vlc )
*psz_vlc = '\0';
{
/* remove trailing \.libs from executable dir path if seen,
we assume we are running vlc through libtool wrapper in build dir */
size_t len = strlen(psz_path);
if( len >= 5 && !stricmp(psz_path + len - 5, "\\.libs" ) )
psz_path[len - 5] = '\0';
}
psz_vlcpath = strdup( psz_path );
#if !defined( UNDER_CE )
timeBeginPeriod(5);
......@@ -366,9 +334,6 @@ void system_End( void )
{
HWND ipcwindow;
free( psz_vlcpath );
psz_vlcpath = NULL;
/* FIXME: thread-safety... */
if (p_helper)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment