From 7bab5a71cefe37b583b08fec0177fc569f041980 Mon Sep 17 00:00:00 2001 From: midipix Date: Jan 22 2024 03:49:50 +0000 Subject: ar mode: slbt_get_archive_ctx(): initial implementation and integration. --- 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 +#include +#include +#include +#include + +#include +#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);