diff options
-rw-r--r-- | include/slibtool/slibtool.h | 15 | ||||
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | project/tree.mk | 1 | ||||
-rw-r--r-- | src/internal/slibtool_driver_impl.h | 17 | ||||
-rw-r--r-- | src/stoolie/slbt_stoolie_ctx.c | 266 |
5 files changed, 300 insertions, 0 deletions
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h index cd3b3c4..d428e54 100644 --- a/include/slibtool/slibtool.h +++ b/include/slibtool/slibtool.h @@ -391,6 +391,15 @@ struct slbt_txtfile_ctx { const char ** txtlinev; }; +struct slbt_stoolie_ctx { + const char * const * path; + const struct slbt_txtfile_ctx * acinc; + const struct slbt_txtfile_ctx * cfgac; + const struct slbt_txtfile_ctx * makam; + const char * const * auxarg; + const char * const * m4arg; +}; + /* raw input api */ slbt_api int slbt_fs_map_input (const struct slbt_driver_ctx *, int, const char *, int, @@ -490,6 +499,12 @@ slbt_api int slbt_ar_create_symfile (const struct slbt_archive_meta *, const slbt_api int slbt_ar_create_dlsyms (struct slbt_archive_ctx **, const char *, const char *, mode_t); +/* slibtoolize api */ +slbt_api int slbt_st_get_stoolie_ctx (const struct slbt_driver_ctx *, const char * path, + struct slbt_stoolie_ctx **); + +slbt_api void slbt_st_free_stoolie_ctx (struct slbt_stoolie_ctx *); + /* utility api */ slbt_api int slbt_main (char **, char **, const struct slbt_fd_ctx *); diff --git a/project/common.mk b/project/common.mk index 1e2ae5e..ace734f 100644 --- a/project/common.mk +++ b/project/common.mk @@ -61,6 +61,7 @@ API_SRCS = \ src/skin/slbt_skin_install.c \ src/skin/slbt_skin_stoolie.c \ src/skin/slbt_skin_uninstall.c \ + src/stoolie/slbt_stoolie_ctx.c \ FALLBACK_SRCS = \ src/fallback/slbt_archive_import_mri.c \ diff --git a/project/tree.mk b/project/tree.mk index 1edd9b9..f855e82 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -9,6 +9,7 @@ tree.tag: mkdir -p src/logic mkdir -p src/output mkdir -p src/skin + mkdir -p src/stoolie mkdir -p src/arbits/output mkdir -p src/logic/linkcmd touch tree.tag diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index b35f375..43ac576 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -232,6 +232,23 @@ struct slbt_txtfile_ctx_impl { struct slbt_txtfile_ctx tctx; }; +struct slbt_stoolie_ctx_impl { + const struct slbt_driver_ctx * dctx; + const char * path; + char * pathbuf; + int fdtgt; + int fdaux; + int fdm4; + const char * auxarg; + char * auxbuf; + const char * m4arg; + char * m4buf; + char ** m4argv; + struct slbt_txtfile_ctx * acinc; + struct slbt_txtfile_ctx * cfgac; + struct slbt_txtfile_ctx * makam; + struct slbt_stoolie_ctx zctx; +}; const char * slbt_program_name(const char *); diff --git a/src/stoolie/slbt_stoolie_ctx.c b/src/stoolie/slbt_stoolie_ctx.c new file mode 100644 index 0000000..f562cf9 --- /dev/null +++ b/src/stoolie/slbt_stoolie_ctx.c @@ -0,0 +1,266 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <stdint.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include <slibtool/slibtool.h> +#include "slibtool_driver_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_realpath_impl.h" +#include "slibtool_stoolie_impl.h" +#include "slibtool_txtline_impl.h" +#include "slibtool_m4fake_impl.h" + +static int slbt_st_free_stoolie_ctx_impl( + struct slbt_stoolie_ctx_impl * ctx, + int fdsrc, + int ret) +{ + char ** parg; + + if (ctx) { + if (fdsrc >= 0) + close(fdsrc); + + if (ctx->fdtgt >= 0) + close(ctx->fdtgt); + + if (ctx->fdaux >= 0) + close(ctx->fdaux); + + if (ctx->fdm4 >= 0) + close(ctx->fdm4); + + for (parg=ctx->m4argv; parg && *parg; parg++) + free(*parg); + + free(ctx->m4buf); + free(ctx->m4argv); + free(ctx->auxbuf); + free(ctx->pathbuf); + + slbt_lib_free_txtfile_ctx(ctx->acinc); + slbt_lib_free_txtfile_ctx(ctx->cfgac); + slbt_lib_free_txtfile_ctx(ctx->makam); + + free(ctx); + } + + return ret; +} + +int slbt_st_get_stoolie_ctx( + const struct slbt_driver_ctx * dctx, + const char * path, + struct slbt_stoolie_ctx ** pctx) +{ + struct slbt_stoolie_ctx_impl * ctx; + int cint; + int fdcwd; + int fdtgt; + int fdsrc; + const char ** pline; + char ** margv; + const char * mark; + char pathbuf[PATH_MAX]; + + /* target directory: fd and real path*/ + fdcwd = slbt_driver_fdcwd(dctx); + + if ((fdtgt = openat(fdcwd,path,O_DIRECTORY|O_CLOEXEC,0)) < 0) + return SLBT_SYSTEM_ERROR(dctx,path); + + if (slbt_realpath(fdtgt,".",0,pathbuf,sizeof(pathbuf)) < 0) { + close(fdtgt); + return SLBT_SYSTEM_ERROR(dctx,path); + } + + /* context alloc and init */ + if (!(ctx = calloc(1,sizeof(*ctx)))) { + close(fdtgt); + return SLBT_BUFFER_ERROR(dctx); + } + + ctx->fdtgt = fdtgt; + ctx->fdaux = (-1); + ctx->fdm4 = (-1); + + /* target directory real path */ + if (!(ctx->pathbuf = strdup(pathbuf))) + return slbt_st_free_stoolie_ctx_impl(ctx,(-1), + SLBT_NESTED_ERROR(dctx)); + + /* acinclude.m4, configure.ac, Makefile.am */ + if ((fdsrc = openat(fdtgt,"acinlcude.m4",O_RDONLY,0)) < 0) { + if (errno != ENOENT) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_SYSTEM_ERROR(dctx,"acinlcude.m4")); + } else { + if (slbt_impl_get_txtfile_ctx(dctx,"acinclude.m4",fdsrc,&ctx->acinc) < 0) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_NESTED_ERROR(dctx)); + + close(fdsrc); + } + + if ((fdsrc = openat(fdtgt,"configure.ac",O_RDONLY,0)) < 0) { + if (errno != ENOENT) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_SYSTEM_ERROR(dctx,"configure.ac")); + } else { + if (slbt_impl_get_txtfile_ctx(dctx,"configure.ac",fdsrc,&ctx->cfgac) < 0) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_NESTED_ERROR(dctx)); + + close(fdsrc); + } + + if ((fdsrc = openat(fdtgt,"Makefile.am",O_RDONLY,0)) < 0) { + if (errno != ENOENT) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_SYSTEM_ERROR(dctx,"Makefile.am")); + } else { + if (slbt_impl_get_txtfile_ctx(dctx,"Makefile.am",fdsrc,&ctx->makam) < 0) + return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc, + SLBT_NESTED_ERROR(dctx)); + + close(fdsrc); + } + + /* aux dir */ + if (ctx->acinc) { + if (slbt_m4fake_expand_cmdarg( + dctx,ctx->acinc, + "AC_CONFIG_AUX_DIR", + &pathbuf) < 0) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_NESTED_ERROR(dctx)); + + if (pathbuf[0]) + if (!(ctx->auxbuf = strdup(pathbuf))) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_NESTED_ERROR(dctx)); + } + + /* aux dir */ + if (!ctx->auxbuf && ctx->cfgac) { + if (slbt_m4fake_expand_cmdarg( + dctx,ctx->cfgac, + "AC_CONFIG_AUX_DIR", + &pathbuf) < 0) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_NESTED_ERROR(dctx)); + + if (pathbuf[0]) + if (!(ctx->auxbuf = strdup(pathbuf))) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_NESTED_ERROR(dctx)); + } + + /* m4 dir */ + if (ctx->makam) { + for (pline=ctx->makam->txtlinev; !ctx->m4argv && *pline; pline++) { + if (!strncmp(*pline,"ACLOCAL_AMFLAGS",15)) { + if (isspace((*pline)[15]) || ((*pline)[15] == '=')) { + mark = &(*pline)[15]; + + for (; isspace(cint = *mark); ) + mark++; + + if (mark[0] != '=') + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_FLOW_ERROR)); + + if (slbt_txtline_to_string_vector(++mark,&margv) < 0) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_FLOW_ERROR)); + + ctx->m4argv = margv; + + if (!strcmp((mark = margv[0]),"-I")) { + ctx->m4buf = strdup(margv[1]); + + } else if (!strncmp(mark,"-I",2)) { + ctx->m4buf = strdup(&mark[2]); + } + + if (!ctx->m4buf) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_FLOW_ERROR)); + } + } + } + } + + /* build-aux directory */ + if ((ctx->fdaux = openat(fdtgt,ctx->auxbuf,O_DIRECTORY,0)) < 0) + if (errno == ENOENT) + if (!mkdirat(fdtgt,ctx->auxbuf,0755)) + ctx->fdaux = openat(fdtgt,ctx->auxbuf,O_DIRECTORY,0); + + if (ctx->fdaux < 0) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_SYSTEM_ERROR(dctx,ctx->auxbuf)); + + /* m4 directory */ + if ((ctx->fdm4 = openat(fdtgt,ctx->m4buf,O_DIRECTORY,0)) < 0) + if (errno == ENOENT) + if (!mkdirat(fdtgt,ctx->m4buf,0755)) + ctx->fdm4 = openat(fdtgt,ctx->m4buf,O_DIRECTORY,0); + + if (ctx->fdm4 < 0) + return slbt_st_free_stoolie_ctx_impl( + ctx,(-1), + SLBT_SYSTEM_ERROR(dctx,ctx->m4buf)); + + /* all done */ + ctx->path = ctx->pathbuf; + ctx->auxarg = ctx->auxbuf; + ctx->m4arg = ctx->m4buf; + + ctx->zctx.path = &ctx->path; + ctx->zctx.acinc = ctx->acinc; + ctx->zctx.cfgac = ctx->cfgac; + ctx->zctx.makam = ctx->makam; + ctx->zctx.auxarg = &ctx->auxarg; + ctx->zctx.m4arg = &ctx->m4arg; + + *pctx = &ctx->zctx; + return 0; +} + +void slbt_st_free_stoolie_ctx(struct slbt_stoolie_ctx * ctx) +{ + struct slbt_stoolie_ctx_impl * ictx; + uintptr_t addr; + + if (ctx) { + addr = (uintptr_t)ctx - offsetof(struct slbt_stoolie_ctx_impl,zctx); + ictx = (struct slbt_stoolie_ctx_impl *)addr; + slbt_st_free_stoolie_ctx_impl(ictx,(-1),0); + } +} |