summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2019-12-18 10:01:32 +0000
committermidipix <writeonce@midipix.org>2019-12-18 12:52:42 +0000
commit303f79f2304d426064f9da83f733c682a7d4a86a (patch)
treec2f1e2b1007a189eb167d51dcf668e06a7116bd2
parent709fded02a8c12e6b67813f5e217504a3824b953 (diff)
downloadsltdl-303f79f2304d426064f9da83f733c682a7d4a86a.tar.bz2
sltdl-303f79f2304d426064f9da83f733c682a7d4a86a.tar.xz
lt_dlopen(), dlopenext(): initial implementation and integration.
-rw-r--r--include/sltdl/sltdl.h4
-rw-r--r--src/core/lt_path.c115
-rw-r--r--src/internal/sltdl_module.h11
3 files changed, 128 insertions, 2 deletions
diff --git a/include/sltdl/sltdl.h b/include/sltdl/sltdl.h
index 1a885c0..0b39935 100644
--- a/include/sltdl/sltdl.h
+++ b/include/sltdl/sltdl.h
@@ -34,6 +34,10 @@ lt_api int lt_dlinsertsearchdir(const char *, const char *);
lt_api int lt_dlsetsearchpath(const char *);
lt_api const char * lt_dlgetsearchpath(void);
+/* module interfaces */
+lt_api lt_dlhandle lt_dlopen(const char *);
+lt_api lt_dlhandle lt_dlopenext(const char *);
+
#ifdef __cplusplus
}
#endif
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;
}
diff --git a/src/internal/sltdl_module.h b/src/internal/sltdl_module.h
new file mode 100644
index 0000000..26e47e3
--- /dev/null
+++ b/src/internal/sltdl_module.h
@@ -0,0 +1,11 @@
+#ifndef SLTDL_MODULE_H
+#define SLTDL_MODULE_H
+
+struct lt_modctx {
+ struct lt_modctx * mnext;
+ void * maddr;
+ char * mpath;
+ size_t mrefs;
+};
+
+#endif