Blame src/stoolie/slbt_stoolie_ctx.c

83bcd3
/*******************************************************************/
83bcd3
/*  slibtool: a strong libtool implementation, written in C        */
83bcd3
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
83bcd3
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
83bcd3
/*******************************************************************/
83bcd3
83bcd3
#include <ctype.h>
83bcd3
#include <fcntl.h>
83bcd3
#include <errno.h>
83bcd3
#include <stdint.h>
83bcd3
#include <stddef.h>
83bcd3
#include <stdlib.h>
83bcd3
#include <string.h>
83bcd3
#include <sys/stat.h>
83bcd3
83bcd3
#include <slibtool/slibtool.h>
83bcd3
#include "slibtool_driver_impl.h"
83bcd3
#include "slibtool_errinfo_impl.h"
83bcd3
#include "slibtool_realpath_impl.h"
83bcd3
#include "slibtool_stoolie_impl.h"
83bcd3
#include "slibtool_txtline_impl.h"
83bcd3
#include "slibtool_m4fake_impl.h"
83bcd3
be21a3
static const char slbt_this_dir[2] = {'.',0};
be21a3
83bcd3
static int slbt_st_free_stoolie_ctx_impl(
83bcd3
	struct slbt_stoolie_ctx_impl *  ctx,
83bcd3
	int                             fdsrc,
83bcd3
	int                             ret)
83bcd3
{
83bcd3
	char ** parg;
83bcd3
83bcd3
	if (ctx) {
83bcd3
		if (fdsrc >= 0)
83bcd3
			close(fdsrc);
83bcd3
83bcd3
		if (ctx->fdtgt >= 0)
83bcd3
			close(ctx->fdtgt);
83bcd3
83bcd3
		if (ctx->fdaux >= 0)
83bcd3
			close(ctx->fdaux);
83bcd3
83bcd3
		if (ctx->fdm4 >= 0)
83bcd3
			close(ctx->fdm4);
83bcd3
83bcd3
		for (parg=ctx->m4argv; parg && *parg; parg++)
83bcd3
			free(*parg);
83bcd3
83bcd3
		free(ctx->m4buf);
83bcd3
		free(ctx->m4argv);
83bcd3
		free(ctx->auxbuf);
83bcd3
		free(ctx->pathbuf);
83bcd3
83bcd3
		slbt_lib_free_txtfile_ctx(ctx->acinc);
83bcd3
		slbt_lib_free_txtfile_ctx(ctx->cfgac);
83bcd3
		slbt_lib_free_txtfile_ctx(ctx->makam);
83bcd3
83bcd3
		free(ctx);
83bcd3
	}
83bcd3
83bcd3
	return ret;
83bcd3
}
83bcd3
83bcd3
int slbt_st_get_stoolie_ctx(
83bcd3
	const struct slbt_driver_ctx *	dctx,
83bcd3
	const char *			path,
83bcd3
	struct slbt_stoolie_ctx **	pctx)
83bcd3
{
83bcd3
	struct slbt_stoolie_ctx_impl *	ctx;
83bcd3
	int                             cint;
83bcd3
	int                             fdcwd;
83bcd3
	int                             fdtgt;
83bcd3
	int                             fdsrc;
83bcd3
	const char **                   pline;
83bcd3
	char **                         margv;
83bcd3
	const char *                    mark;
be21a3
	const char *                    dpath;
83bcd3
	char                            pathbuf[PATH_MAX];
83bcd3
83bcd3
	/* target directory: fd and real path*/
83bcd3
	fdcwd = slbt_driver_fdcwd(dctx);
83bcd3
83bcd3
	if ((fdtgt = openat(fdcwd,path,O_DIRECTORY|O_CLOEXEC,0)) < 0)
83bcd3
		return SLBT_SYSTEM_ERROR(dctx,path);
83bcd3
83bcd3
	if (slbt_realpath(fdtgt,".",0,pathbuf,sizeof(pathbuf)) < 0) {
83bcd3
		close(fdtgt);
83bcd3
		return SLBT_SYSTEM_ERROR(dctx,path);
83bcd3
	}
83bcd3
83bcd3
	/* context alloc and init */
83bcd3
	if (!(ctx = calloc(1,sizeof(*ctx)))) {
83bcd3
		close(fdtgt);
83bcd3
		return SLBT_BUFFER_ERROR(dctx);
83bcd3
	}
83bcd3
83bcd3
	ctx->fdtgt = fdtgt;
83bcd3
	ctx->fdaux = (-1);
83bcd3
	ctx->fdm4  = (-1);
83bcd3
83bcd3
	/* target directory real path */
83bcd3
	if (!(ctx->pathbuf = strdup(pathbuf)))
83bcd3
		return slbt_st_free_stoolie_ctx_impl(ctx,(-1),
83bcd3
			SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
	/* acinclude.m4, configure.ac, Makefile.am */
83bcd3
	if ((fdsrc = openat(fdtgt,"acinlcude.m4",O_RDONLY,0)) < 0) {
83bcd3
		if (errno != ENOENT)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_SYSTEM_ERROR(dctx,"acinlcude.m4"));
83bcd3
	} else {
83bcd3
		if (slbt_impl_get_txtfile_ctx(dctx,"acinclude.m4",fdsrc,&ctx->acinc) < 0)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
		close(fdsrc);
83bcd3
	}
83bcd3
83bcd3
	if ((fdsrc = openat(fdtgt,"configure.ac",O_RDONLY,0)) < 0) {
83bcd3
		if (errno != ENOENT)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_SYSTEM_ERROR(dctx,"configure.ac"));
83bcd3
	} else {
83bcd3
		if (slbt_impl_get_txtfile_ctx(dctx,"configure.ac",fdsrc,&ctx->cfgac) < 0)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
		close(fdsrc);
83bcd3
	}
83bcd3
83bcd3
	if ((fdsrc = openat(fdtgt,"Makefile.am",O_RDONLY,0)) < 0) {
83bcd3
		if (errno != ENOENT)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_SYSTEM_ERROR(dctx,"Makefile.am"));
83bcd3
	} else {
83bcd3
		if (slbt_impl_get_txtfile_ctx(dctx,"Makefile.am",fdsrc,&ctx->makam) < 0)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(ctx,fdsrc,
83bcd3
				SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
		close(fdsrc);
83bcd3
	}
83bcd3
83bcd3
	/* aux dir */
83bcd3
	if (ctx->acinc) {
83bcd3
		if (slbt_m4fake_expand_cmdarg(
83bcd3
				dctx,ctx->acinc,
83bcd3
				"AC_CONFIG_AUX_DIR",
83bcd3
				&pathbuf) < 0)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(
83bcd3
				ctx,(-1),
83bcd3
				SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
		if (pathbuf[0])
83bcd3
			if (!(ctx->auxbuf = strdup(pathbuf)))
83bcd3
				return slbt_st_free_stoolie_ctx_impl(
83bcd3
					ctx,(-1),
83bcd3
					SLBT_NESTED_ERROR(dctx));
83bcd3
	}
83bcd3
83bcd3
	if (!ctx->auxbuf && ctx->cfgac) {
83bcd3
		if (slbt_m4fake_expand_cmdarg(
83bcd3
				dctx,ctx->cfgac,
83bcd3
				"AC_CONFIG_AUX_DIR",
83bcd3
				&pathbuf) < 0)
83bcd3
			return slbt_st_free_stoolie_ctx_impl(
83bcd3
				ctx,(-1),
83bcd3
				SLBT_NESTED_ERROR(dctx));
83bcd3
83bcd3
		if (pathbuf[0])
83bcd3
			if (!(ctx->auxbuf = strdup(pathbuf)))
83bcd3
				return slbt_st_free_stoolie_ctx_impl(
83bcd3
					ctx,(-1),
83bcd3
					SLBT_NESTED_ERROR(dctx));
83bcd3
	}
83bcd3
83bcd3
	/* m4 dir */
a98361
	if (ctx->acinc) {
a98361
		if (slbt_m4fake_expand_cmdarg(
a98361
				dctx,ctx->acinc,
a98361
				"AC_CONFIG_MACRO_DIR",
a98361
				&pathbuf) < 0)
a98361
			return slbt_st_free_stoolie_ctx_impl(
a98361
				ctx,(-1),
a98361
				SLBT_NESTED_ERROR(dctx));
a98361
a98361
		if (pathbuf[0])
a98361
			if (!(ctx->m4buf = strdup(pathbuf)))
a98361
				return slbt_st_free_stoolie_ctx_impl(
a98361
					ctx,(-1),
a98361
					SLBT_NESTED_ERROR(dctx));
a98361
	}
a98361
a98361
	if (!ctx->m4buf && ctx->cfgac) {
a98361
		if (slbt_m4fake_expand_cmdarg(
a98361
				dctx,ctx->cfgac,
a98361
				"AC_CONFIG_MACRO_DIR",
a98361
				&pathbuf) < 0)
a98361
			return slbt_st_free_stoolie_ctx_impl(
a98361
				ctx,(-1),
a98361
				SLBT_NESTED_ERROR(dctx));
a98361
a98361
		if (pathbuf[0])
a98361
			if (!(ctx->m4buf = strdup(pathbuf)))
a98361
				return slbt_st_free_stoolie_ctx_impl(
a98361
					ctx,(-1),
a98361
					SLBT_NESTED_ERROR(dctx));
a98361
	}
a98361
	if (!ctx->m4buf && ctx->makam) {
83bcd3
		for (pline=ctx->makam->txtlinev; !ctx->m4argv && *pline; pline++) {
83bcd3
			if (!strncmp(*pline,"ACLOCAL_AMFLAGS",15)) {
83bcd3
				if (isspace((*pline)[15]) || ((*pline)[15] == '=')) {
83bcd3
					mark = &(*pline)[15];
83bcd3
83bcd3
					for (; isspace(cint = *mark); )
83bcd3
						mark++;
83bcd3
83bcd3
					if (mark[0] != '=')
83bcd3
						return slbt_st_free_stoolie_ctx_impl(
83bcd3
							ctx,(-1),
83bcd3
							SLBT_CUSTOM_ERROR(
83bcd3
								dctx,
83bcd3
								SLBT_ERR_FLOW_ERROR));
83bcd3
83bcd3
					if (slbt_txtline_to_string_vector(++mark,&margv) < 0)
83bcd3
						return slbt_st_free_stoolie_ctx_impl(
83bcd3
							ctx,(-1),
83bcd3
							SLBT_CUSTOM_ERROR(
83bcd3
								dctx,
83bcd3
								SLBT_ERR_FLOW_ERROR));
83bcd3
83bcd3
					ctx->m4argv = margv;
83bcd3
83bcd3
					if (!strcmp((mark = margv[0]),"-I")) {
83bcd3
						ctx->m4buf = strdup(margv[1]);
83bcd3
83bcd3
					} else if (!strncmp(mark,"-I",2)) {
83bcd3
						ctx->m4buf = strdup(&mark[2]);
83bcd3
					}
83bcd3
83bcd3
					if (!ctx->m4buf)
83bcd3
						return slbt_st_free_stoolie_ctx_impl(
83bcd3
							ctx,(-1),
83bcd3
							SLBT_CUSTOM_ERROR(
83bcd3
								dctx,
83bcd3
								SLBT_ERR_FLOW_ERROR));
83bcd3
				}
83bcd3
			}
83bcd3
		}
83bcd3
	}
83bcd3
83bcd3
	/* build-aux directory */
be21a3
	if (!(dpath = ctx->auxbuf))
be21a3
		dpath = slbt_this_dir;
be21a3
be21a3
	if ((ctx->fdaux = openat(fdtgt,dpath,O_DIRECTORY,0)) < 0)
83bcd3
		if (errno == ENOENT)
be21a3
			if (!mkdirat(fdtgt,dpath,0755))
be21a3
				ctx->fdaux = openat(fdtgt,dpath,O_DIRECTORY,0);
83bcd3
83bcd3
	if (ctx->fdaux < 0)
83bcd3
		return slbt_st_free_stoolie_ctx_impl(
83bcd3
			ctx,(-1),
be21a3
			SLBT_SYSTEM_ERROR(dctx,dpath));
83bcd3
83bcd3
	/* m4 directory */
54044c
	if ((dpath = ctx->m4buf))
54044c
		if ((ctx->fdm4 = openat(fdtgt,dpath,O_DIRECTORY,0)) < 0)
54044c
			if (errno == ENOENT)
54044c
				if (!mkdirat(fdtgt,dpath,0755))
54044c
					ctx->fdm4 = openat(fdtgt,dpath,O_DIRECTORY,0);
83bcd3
54044c
	if (dpath && (ctx->fdm4 < 0))
83bcd3
		return slbt_st_free_stoolie_ctx_impl(
83bcd3
			ctx,(-1),
be21a3
			SLBT_SYSTEM_ERROR(dctx,dpath));
83bcd3
83bcd3
	/* all done */
83bcd3
	ctx->path        = ctx->pathbuf;
83bcd3
	ctx->auxarg      = ctx->auxbuf;
83bcd3
	ctx->m4arg       = ctx->m4buf;
83bcd3
83bcd3
	ctx->zctx.path   = &ctx->path;
83bcd3
	ctx->zctx.acinc  = ctx->acinc;
83bcd3
	ctx->zctx.cfgac  = ctx->cfgac;
83bcd3
	ctx->zctx.makam  = ctx->makam;
83bcd3
	ctx->zctx.auxarg = &ctx->auxarg;
83bcd3
	ctx->zctx.m4arg  = &ctx->m4arg;
83bcd3
83bcd3
	*pctx = &ctx->zctx;
83bcd3
	return 0;
83bcd3
}
83bcd3
83bcd3
void slbt_st_free_stoolie_ctx(struct slbt_stoolie_ctx * ctx)
83bcd3
{
83bcd3
	struct slbt_stoolie_ctx_impl *	ictx;
83bcd3
	uintptr_t			addr;
83bcd3
83bcd3
	if (ctx) {
83bcd3
		addr = (uintptr_t)ctx - offsetof(struct slbt_stoolie_ctx_impl,zctx);
83bcd3
		ictx = (struct slbt_stoolie_ctx_impl *)addr;
83bcd3
		slbt_st_free_stoolie_ctx_impl(ictx,(-1),0);
83bcd3
	}
83bcd3
}