summaryrefslogtreecommitdiff
path: root/src/stoolie/slbt_stoolie_ctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stoolie/slbt_stoolie_ctx.c')
-rw-r--r--src/stoolie/slbt_stoolie_ctx.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/stoolie/slbt_stoolie_ctx.c b/src/stoolie/slbt_stoolie_ctx.c
new file mode 100644
index 0000000..b74edd3
--- /dev/null
+++ b/src/stoolie/slbt_stoolie_ctx.c
@@ -0,0 +1,303 @@
+/*******************************************************************/
+/* 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 const char slbt_this_dir[2] = {'.',0};
+
+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;
+ const char * dpath;
+ 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));
+ }
+
+ 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->acinc) {
+ if (slbt_m4fake_expand_cmdarg(
+ dctx,ctx->acinc,
+ "AC_CONFIG_MACRO_DIR",
+ &pathbuf) < 0)
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_NESTED_ERROR(dctx));
+
+ if (pathbuf[0])
+ if (!(ctx->m4buf = strdup(pathbuf)))
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_NESTED_ERROR(dctx));
+ }
+
+ if (!ctx->m4buf && ctx->cfgac) {
+ if (slbt_m4fake_expand_cmdarg(
+ dctx,ctx->cfgac,
+ "AC_CONFIG_MACRO_DIR",
+ &pathbuf) < 0)
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_NESTED_ERROR(dctx));
+
+ if (pathbuf[0])
+ if (!(ctx->m4buf = strdup(pathbuf)))
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_NESTED_ERROR(dctx));
+ }
+ if (!ctx->m4buf && 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 (!(dpath = ctx->auxbuf))
+ dpath = slbt_this_dir;
+
+ if ((ctx->fdaux = openat(fdtgt,dpath,O_DIRECTORY,0)) < 0)
+ if (errno == ENOENT)
+ if (!mkdirat(fdtgt,dpath,0755))
+ ctx->fdaux = openat(fdtgt,dpath,O_DIRECTORY,0);
+
+ if (ctx->fdaux < 0)
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_SYSTEM_ERROR(dctx,dpath));
+
+ /* m4 directory */
+ if ((dpath = ctx->m4buf))
+ if ((ctx->fdm4 = openat(fdtgt,dpath,O_DIRECTORY,0)) < 0)
+ if (errno == ENOENT)
+ if (!mkdirat(fdtgt,dpath,0755))
+ ctx->fdm4 = openat(fdtgt,dpath,O_DIRECTORY,0);
+
+ if (dpath && (ctx->fdm4 < 0))
+ return slbt_st_free_stoolie_ctx_impl(
+ ctx,(-1),
+ SLBT_SYSTEM_ERROR(dctx,dpath));
+
+ /* 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);
+ }
+}