summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/slibtool/slibtool.h8
-rw-r--r--project/common.mk1
-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
5 files changed, 158 insertions, 0 deletions
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h
index 1743262..1eac876 100644
--- a/include/slibtool/slibtool.h
+++ b/include/slibtool/slibtool.h
@@ -74,6 +74,9 @@ extern "C" {
#define SLBT_DRIVER_MODE_AR SLBT_DRIVER_XFLAG(0x010000)
+/* unit action flags */
+#define SLBT_ACTION_MAP_READWRITE 0x0001
+
/* error flags */
#define SLBT_ERROR_TOP_LEVEL 0x0001
#define SLBT_ERROR_NESTED 0x0002
@@ -357,6 +360,11 @@ slbt_api int slbt_dump_machine (const char * compiler, char * machine,
slbt_api int slbt_realpath (int, const char *, int, char *, size_t);
/* archiver api */
+slbt_api int slbt_get_archive_ctx (const struct slbt_driver_ctx *, const char * path,
+ struct slbt_archive_ctx **);
+
+slbt_api void slbt_free_archive_ctx (struct slbt_archive_ctx *);
+
slbt_api int slbt_get_archive_meta (const struct slbt_driver_ctx *,
const struct slbt_raw_archive *,
struct slbt_archive_meta **);
diff --git a/project/common.mk b/project/common.mk
index d8cda7b..f314281 100644
--- a/project/common.mk
+++ b/project/common.mk
@@ -1,4 +1,5 @@
API_SRCS = \
+ src/arbits/slbt_archive_ctx.c \
src/arbits/slbt_archive_meta.c \
src/driver/slbt_amain.c \
src/driver/slbt_driver_ctx.c \
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);