summaryrefslogtreecommitdiff
path: root/src/core/lt_path.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lt_path.c')
-rw-r--r--src/core/lt_path.c115
1 files changed, 113 insertions, 2 deletions
diff --git a/src/core/lt_path.c b/src/core/lt_path.c
index bc9ac07..b0335de 100644
--- a/src/core/lt_path.c
+++ b/src/core/lt_path.c
@@ -5,14 +5,17 @@
/*******************************************************************/
#include <limits.h>
+#include <dlfcn.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
+
#include <sltdl/sltdl.h>
#include "sltdl_core.h"
+#include "sltdl_module.h"
static off_t lt_plen;
static off_t lt_plocs;
@@ -21,6 +24,12 @@ static char * lt_vpath;
static char ** lt_vmark;
static char ** lt_pathv;
+static struct lt_modctx * lt_modv_head;
+static struct lt_modctx * lt_modv_tail;
+
+static struct lt_modctx * lt_modv_next;
+static struct lt_modctx * lt_modv_cap;
+
const char * lt_dlgetsearchpath(void)
{
return lt_upath;
@@ -243,12 +252,16 @@ int lt_dlinsertsearchdir(const char * mark, const char * path)
return lt_sunlock(ret);
}
-static int lt_dlpathopen_locked(const char * module, const char ** extv)
+static int lt_dlpathopen_locked(
+ const char * module,
+ const char ** extv,
+ char ** mpath)
{
int fdat;
int fdmod;
char ** ppath;
const char ** pext;
+ size_t plen;
size_t mlen;
size_t elen;
char path[1024];
@@ -274,6 +287,19 @@ static int lt_dlpathopen_locked(const char * module, const char ** extv)
fdmod = openat(fdat,path,O_EXEC|O_CLOEXEC,0);
if (fdmod >= 0) {
+ if (mpath) {
+ plen = strlen(*ppath);
+ plen += mlen + 1 + elen + 1;
+
+ if (!(*mpath = malloc(plen))) {
+ close(fdat);
+ close(fdmod);
+ return (-1);
+ }
+
+ sprintf(*mpath,"%s/%s",*ppath,path);
+ }
+
close(fdat);
return fdmod;
}
@@ -289,5 +315,90 @@ static int lt_dlpathopen_locked(const char * module, const char ** extv)
int lt_dlpathopen(const char * module, const char ** extv)
{
lt_slock();
- return lt_sunlock(lt_dlpathopen_locked(module,extv));
+ return lt_sunlock(lt_dlpathopen_locked(module,extv,0));
+}
+
+static struct lt_modctx * lt_dlopen_locked(
+ const char * module,
+ const char ** extv,
+ int mode)
+{
+ int fdmod;
+ char * mpath;
+ void * maddr;
+ struct lt_modctx * modctx;
+ struct lt_modctx * modctx_buf;
+
+ /* path open */
+ if ((fdmod = lt_dlpathopen_locked(module,extv,&mpath)) < 0)
+ return 0;
+
+ close(fdmod);
+
+ /* entry alloc */
+ if (lt_modv_next == lt_modv_cap) {
+ if (!(modctx_buf = calloc(64,sizeof(*modctx)))) {
+ free(mpath);
+ return 0;
+ }
+
+ lt_modv_next = modctx_buf;
+ lt_modv_cap = &lt_modv_next[64];
+ }
+
+ /* dlopen */
+ if (!(maddr = dlopen(mpath,mode))) {
+ free(mpath);
+ return 0;
+ }
+
+ /* already dlopen'ed? */
+ for (modctx=lt_modv_head; modctx; modctx=modctx->mnext) {
+ if (!strcmp(modctx->mpath,mpath)) {
+ free(mpath);
+ modctx->mrefs++;
+ return modctx;
+ }
+ }
+
+ /* module entry */
+ modctx = lt_modv_next;
+ modctx->maddr = maddr;
+ modctx->mpath = mpath;
+ modctx->mrefs = 1;
+ lt_modv_next++;
+
+ /* add to list */
+ if (lt_modv_tail) {
+ lt_modv_tail->mnext = modctx;
+ lt_modv_tail = modctx;
+ } else {
+ lt_modv_head = modctx;
+ lt_modv_tail = modctx;
+ }
+
+ /* all done */
+ return modctx;
+}
+
+struct lt_modctx * lt_dlopen(const char * module)
+{
+ struct lt_modctx * modctx;
+ const char * extv[2] = {"",0};
+
+ lt_slock();
+ modctx = lt_dlopen_locked(module,extv,RTLD_NOW);
+ lt_sunlock(0);
+ return modctx;
+}
+
+struct lt_modctx * lt_dlopenext(const char * module)
+{
+ struct lt_modctx * modctx;
+ const char * extv[3] = {"",OS_LIB_SUFFIX,0};
+
+ lt_slock();
+ modctx = lt_dlopen_locked(module,extv,RTLD_NOW);
+ lt_sunlock(0);
+ return modctx;
}