summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arbits/slbt_archive_ctx.c106
-rw-r--r--src/internal/slibtool_driver_impl.h24
-rw-r--r--src/logic/slbt_exec_ar.c19
3 files changed, 149 insertions, 0 deletions
diff --git a/src/arbits/slbt_archive_ctx.c b/src/arbits/slbt_archive_ctx.c
new file mode 100644
index 0000000..c9c1a7d
--- /dev/null
+++ b/src/arbits/slbt_archive_ctx.c
@@ -0,0 +1,106 @@
+/*******************************************************************/
+/* slibtool: a skinny libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
+/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
+/*******************************************************************/
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
+#include "slibtool_errinfo_impl.h"
+
+static int slbt_map_raw_archive(
+ const struct slbt_driver_ctx * dctx,
+ int fd,
+ const char * path,
+ int prot,
+ struct slbt_raw_archive * map)
+{
+ struct slbt_input mapinfo = {0,0};
+
+ if (slbt_map_input(dctx,fd,path,prot,&mapinfo) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ if (mapinfo.size == 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,
+ SLBT_ERR_AR_EMPTY_FILE);
+
+ map->map_addr = mapinfo.addr;
+ map->map_size = mapinfo.size;
+
+ return 0;
+}
+
+static int slbt_unmap_raw_archive(struct slbt_raw_archive * map)
+{
+ struct slbt_input mapinfo;
+
+ mapinfo.addr = map->map_addr;
+ mapinfo.size = map->map_size;
+
+ return slbt_unmap_input(&mapinfo);
+}
+
+static int slbt_free_archive_ctx_impl(struct slbt_archive_ctx_impl * ctx, int ret)
+{
+ if (ctx) {
+ slbt_free_archive_meta(ctx->meta);
+ slbt_unmap_raw_archive(&ctx->map);
+ free(ctx);
+ }
+
+ return ret;
+}
+
+int slbt_get_archive_ctx(
+ const struct slbt_driver_ctx * dctx,
+ const char * path,
+ struct slbt_archive_ctx ** pctx)
+{
+ struct slbt_archive_ctx_impl * ctx;
+ int prot;
+
+ if (!(ctx = calloc(1,sizeof(*ctx))))
+ return SLBT_BUFFER_ERROR(dctx);
+
+ slbt_driver_set_arctx(
+ dctx,0,path);
+
+ prot = (dctx->cctx->actflags & SLBT_ACTION_MAP_READWRITE)
+ ? PROT_READ | PROT_WRITE
+ : PROT_READ;
+
+ if (slbt_map_raw_archive(dctx,-1,path,prot,&ctx->map))
+ return slbt_free_archive_ctx_impl(ctx,
+ SLBT_NESTED_ERROR(dctx));
+
+ if (slbt_get_archive_meta(dctx,&ctx->map,&ctx->meta))
+ return slbt_free_archive_ctx_impl(ctx,
+ SLBT_NESTED_ERROR(dctx));
+
+ ctx->path = path;
+ ctx->actx.path = &ctx->path;
+ ctx->actx.map = &ctx->map;
+ ctx->actx.meta = ctx->meta;
+
+ *pctx = &ctx->actx;
+ return 0;
+}
+
+void slbt_free_archive_ctx(struct slbt_archive_ctx * ctx)
+{
+ struct slbt_archive_ctx_impl * ictx;
+ uintptr_t addr;
+
+ if (ctx) {
+ addr = (uintptr_t)ctx - offsetof(struct slbt_archive_ctx_impl,actx);
+ ictx = (struct slbt_archive_ctx_impl *)addr;
+ slbt_free_archive_ctx_impl(ictx,0);
+ }
+}
diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h
index 0293308..388e1cf 100644
--- a/src/internal/slibtool_driver_impl.h
+++ b/src/internal/slibtool_driver_impl.h
@@ -116,6 +116,10 @@ struct slbt_driver_ctx_impl {
struct slbt_host_strs ahost;
struct slbt_fd_ctx fdctx;
struct slbt_obj_list * objlistv;
+
+ const struct slbt_archive_ctx * arctx;
+ const char * arpath;
+
char * libname;
char * dargs;
char ** dargv;
@@ -141,6 +145,13 @@ struct slbt_exec_ctx_impl {
char * vbuffer[];
};
+struct slbt_archive_ctx_impl {
+ const char * path;
+ struct slbt_raw_archive map;
+ struct slbt_archive_meta * meta;
+ struct slbt_archive_ctx actx;
+};
+
static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct slbt_driver_ctx * dctx)
{
uintptr_t addr;
@@ -153,6 +164,19 @@ static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct sl
return 0;
}
+static inline void slbt_driver_set_arctx(
+ const struct slbt_driver_ctx * dctx,
+ const struct slbt_archive_ctx * arctx,
+ const char * arpath)
+{
+ struct slbt_driver_ctx_impl * ictx;
+
+
+ ictx = slbt_get_driver_ictx(dctx);
+ ictx->arctx = arctx;
+ ictx->arpath = arpath;
+}
+
static inline char ** slbt_driver_envp(const struct slbt_driver_ctx * dctx)
{
struct slbt_driver_ctx_impl * ictx;
diff --git a/src/logic/slbt_exec_ar.c b/src/logic/slbt_exec_ar.c
index a68ff03..56eee4e 100644
--- a/src/logic/slbt_exec_ar.c
+++ b/src/logic/slbt_exec_ar.c
@@ -71,6 +71,7 @@ int slbt_exec_ar(
char ** argv;
char ** iargv;
struct slbt_archive_ctx ** arctxv;
+ struct slbt_archive_ctx ** arctxp;
const char ** unitv;
const char ** unitp;
size_t nunits;
@@ -160,7 +161,25 @@ int slbt_exec_ar(
if (!entry->fopt)
*unitp++ = entry->arg;
+ /* archive context vector initialization */
+ for (unitp=unitv,arctxp=arctxv; *unitp; unitp++,arctxp++) {
+ if (slbt_get_archive_ctx(dctx,*unitp,arctxp) < 0) {
+ for (arctxp=arctxv; *arctxp; arctxp++)
+ slbt_free_archive_ctx(*arctxp);
+
+ free(unitv);
+ free(arctxv);
+
+ return slbt_exec_ar_fail(
+ actx,meta,
+ SLBT_NESTED_ERROR(dctx));
+ }
+ }
+
/* all done */
+ for (arctxp=arctxv; *arctxp; arctxp++)
+ slbt_free_archive_ctx(*arctxp);
+
free(unitv);
free(arctxv);