Blame src/logic/slbt_exec_stoolie.c

4c3fb7
/*******************************************************************/
4c3fb7
/*  slibtool: a strong libtool implementation, written in C        */
4c3fb7
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
4c3fb7
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
4c3fb7
/*******************************************************************/
4c3fb7
967a11
#include <sys/stat.h>
4c3fb7
#include <slibtool/slibtool.h>
4c3fb7
#include <slibtool/slibtool_output.h>
4c3fb7
#include "slibtool_driver_impl.h"
4c3fb7
#include "slibtool_stoolie_impl.h"
4c3fb7
#include "slibtool_errinfo_impl.h"
0dcc39
#include "slibtool_realpath_impl.h"
0dcc39
#include "slibtool_snprintf_impl.h"
0dcc39
#include "slibtool_symlink_impl.h"
4c3fb7
#include "argv/argv.h"
4c3fb7
967a11
static const char slbt_this_dir[2] = {'.',0};
967a11
4c3fb7
static int slbt_stoolie_usage(
4c3fb7
	int				fdout,
4c3fb7
	const char *			program,
4c3fb7
	const char *			arg,
4c3fb7
	const struct argv_option **	optv,
4c3fb7
	struct argv_meta *		meta,
4c3fb7
	struct slbt_exec_ctx *		ectx,
4c3fb7
	int				noclr)
4c3fb7
{
4c3fb7
	char    header[512];
4c3fb7
	bool    stooliemode;
4c3fb7
4c3fb7
	stooliemode = !strcmp(program,"slibtoolize");
4c3fb7
4c3fb7
	snprintf(header,sizeof(header),
4c3fb7
		"Usage: %s%s [options] ...\n"
4c3fb7
		"Options:\n",
4c3fb7
		program,
4c3fb7
		stooliemode ? "" : " --mode=slibtoolize");
4c3fb7
4c3fb7
	switch (noclr) {
4c3fb7
		case 0:
4c3fb7
			slbt_argv_usage(fdout,header,optv,arg);
4c3fb7
			break;
4c3fb7
4c3fb7
		default:
4c3fb7
			slbt_argv_usage_plain(fdout,header,optv,arg);
4c3fb7
			break;
4c3fb7
	}
4c3fb7
4c3fb7
	if (ectx)
4c3fb7
		slbt_ectx_free_exec_ctx(ectx);
4c3fb7
4c3fb7
	slbt_argv_free(meta);
4c3fb7
4c3fb7
	return SLBT_USAGE;
4c3fb7
}
4c3fb7
4c3fb7
static int slbt_exec_stoolie_fail(
4c3fb7
	struct slbt_exec_ctx *	ectx,
4c3fb7
	struct argv_meta *	meta,
4c3fb7
	int			ret)
4c3fb7
{
4c3fb7
	slbt_argv_free(meta);
4c3fb7
	slbt_ectx_free_exec_ctx(ectx);
4c3fb7
	return ret;
4c3fb7
}
4c3fb7
0dcc39
static int slbt_exec_stoolie_remove_file(
0dcc39
	const struct slbt_driver_ctx *	dctx,
0dcc39
	int                             fddst,
0dcc39
	const char *			target)
0dcc39
{
0dcc39
	/* remove target (if any) */
0dcc39
	if (!unlinkat(fddst,target,0) || (errno == ENOENT))
0dcc39
		return 0;
0dcc39
0dcc39
	return SLBT_SYSTEM_ERROR(dctx,0);
0dcc39
}
0dcc39
4c3fb7
static int slbt_exec_stoolie_perform_actions(
0dcc39
	const struct slbt_driver_ctx *  dctx,
0dcc39
	struct slbt_exec_ctx *          ectx,
0dcc39
	struct slbt_stoolie_ctx *       stctx)
4c3fb7
{
0dcc39
	struct slbt_stoolie_ctx_impl *  ictx;
0dcc39
	struct stat                     st;
0dcc39
	char                            m4dir [PATH_MAX];
0dcc39
	char                            auxdir[PATH_MAX];
0dcc39
	char                            slibm4[PATH_MAX];
0dcc39
	char                            ltmain[PATH_MAX];
f98cb2
	char                            arlib [PATH_MAX];
0dcc39
	bool                            fslibm4;
0dcc39
	bool                            fltmain;
0dcc39
0dcc39
	ictx = slbt_get_stoolie_ictx(stctx);
0dcc39
0dcc39
	/* source files */
0dcc39
	if (slbt_snprintf(
0dcc39
			slibm4,sizeof(slibm4),"%s/%s",
0dcc39
			SLBT_PACKAGE_DATADIR,
0dcc39
			"slibtool.m4") < 0)
0dcc39
		return SLBT_BUFFER_ERROR(dctx);
0dcc39
0dcc39
	if (slbt_snprintf(
0dcc39
			ltmain,sizeof(slibm4),"%s/%s",
0dcc39
			SLBT_PACKAGE_DATADIR,
0dcc39
			"ltmain.sh") < 0)
0dcc39
		return SLBT_BUFFER_ERROR(dctx);
0dcc39
f98cb2
	if (slbt_snprintf(
f98cb2
			arlib,sizeof(arlib),"%s/%s",
f98cb2
			SLBT_PACKAGE_DATADIR,
f98cb2
			"ar-lib") < 0)
f98cb2
		return SLBT_BUFFER_ERROR(dctx);
f98cb2
0dcc39
	/* --force? */
0dcc39
	if (dctx->cctx->drvflags & SLBT_DRIVER_STOOLIE_FORCE) {
54044c
		if (ictx->fdm4 >= 0)
54044c
			if (slbt_exec_stoolie_remove_file(dctx,ictx->fdm4,"slibtool.m4") < 0)
54044c
				return SLBT_NESTED_ERROR(dctx);
0dcc39
0dcc39
		if (slbt_exec_stoolie_remove_file(dctx,ictx->fdaux,"ltmain.sh") < 0)
0dcc39
			return SLBT_NESTED_ERROR(dctx);
0dcc39
f98cb2
		if (slbt_exec_stoolie_remove_file(dctx,ictx->fdaux,"ar-lib") < 0)
f98cb2
			return SLBT_NESTED_ERROR(dctx);
f98cb2
54044c
		fslibm4 = (ictx->fdm4 >= 0);
0dcc39
		fltmain = true;
0dcc39
	} else {
54044c
		if (ictx->fdm4 < 0) {
54044c
			fslibm4 = false;
54044c
54044c
		} else if (fstatat(ictx->fdm4,"slibtool.m4",&st,AT_SYMLINK_NOFOLLOW) == 0) {
0dcc39
			fslibm4 = false;
0dcc39
0dcc39
		} else if (errno == ENOENT) {
0dcc39
			fslibm4 = true;
0dcc39
0dcc39
		} else {
0dcc39
			return SLBT_SYSTEM_ERROR(dctx,"slibtool.m4");
0dcc39
		}
0dcc39
0dcc39
		if (fstatat(ictx->fdaux,"ltmain.sh",&st,AT_SYMLINK_NOFOLLOW) == 0) {
0dcc39
			fltmain = false;
0dcc39
0dcc39
		} else if (errno == ENOENT) {
0dcc39
			fltmain = true;
0dcc39
0dcc39
		} else {
0dcc39
			return SLBT_SYSTEM_ERROR(dctx,"ltmain.sh");
0dcc39
		}
0dcc39
	}
0dcc39
0dcc39
	/* --copy? */
0dcc39
	if (dctx->cctx->drvflags & SLBT_DRIVER_STOOLIE_COPY) {
0dcc39
		if (fslibm4) {
0dcc39
			if (slbt_realpath(ictx->fdm4,".",0,m4dir,sizeof(m4dir)) < 0)
0dcc39
				return SLBT_SYSTEM_ERROR(dctx,0);
0dcc39
0dcc39
			if (slbt_util_copy_file(ectx,slibm4,m4dir) < 0)
0dcc39
				return SLBT_NESTED_ERROR(dctx);
0dcc39
		}
0dcc39
0dcc39
		if (fltmain) {
0dcc39
			if (slbt_realpath(ictx->fdaux,".",0,auxdir,sizeof(auxdir)) < 0)
0dcc39
				return SLBT_SYSTEM_ERROR(dctx,0);
0dcc39
0dcc39
			if (slbt_util_copy_file(ectx,ltmain,auxdir) < 0)
0dcc39
				return SLBT_NESTED_ERROR(dctx);
f98cb2
f98cb2
			if (slbt_util_copy_file(ectx,arlib,auxdir) < 0)
f98cb2
				return SLBT_NESTED_ERROR(dctx);
0dcc39
		}
0dcc39
	} else {
0dcc39
		/* default to symlinks */
0dcc39
		if (fslibm4)
0dcc39
			if (slbt_create_symlink_ex(
0dcc39
					dctx,ectx,
0dcc39
					ictx->fdm4,
0dcc39
					slibm4,
0dcc39
					"slibtool.m4",
0dcc39
					SLBT_SYMLINK_LITERAL) < 0)
0dcc39
				return SLBT_NESTED_ERROR(dctx);
0dcc39
f98cb2
		if (fltmain) {
0dcc39
			if (slbt_create_symlink_ex(
0dcc39
					dctx,ectx,
0dcc39
					ictx->fdaux,
0dcc39
					ltmain,
0dcc39
					"ltmain.sh",
0dcc39
					SLBT_SYMLINK_LITERAL) < 0)
0dcc39
				return SLBT_NESTED_ERROR(dctx);
f98cb2
f98cb2
			if (slbt_create_symlink_ex(
f98cb2
					dctx,ectx,
f98cb2
					ictx->fdaux,
f98cb2
					arlib,
f98cb2
					"ar-lib",
f98cb2
					SLBT_SYMLINK_LITERAL) < 0)
f98cb2
				return SLBT_NESTED_ERROR(dctx);
f98cb2
		}
0dcc39
	}
0dcc39
4c3fb7
	return 0;
4c3fb7
}
4c3fb7
4c3fb7
int slbt_exec_stoolie(const struct slbt_driver_ctx * dctx)
4c3fb7
{
4c3fb7
	int				ret;
4c3fb7
	int				fdout;
4c3fb7
	int				fderr;
4c3fb7
	char **				argv;
4c3fb7
	char **				iargv;
4c3fb7
	struct slbt_exec_ctx *		ectx;
4c3fb7
	struct slbt_driver_ctx_impl *	ictx;
4c3fb7
	const struct slbt_common_ctx *	cctx;
4c3fb7
	struct argv_meta *		meta;
4c3fb7
	struct argv_entry *		entry;
4c3fb7
	size_t				nunits;
967a11
	size_t                          cunits;
967a11
	const char **                   unitv;
967a11
	const char **                   unitp;
967a11
	struct slbt_stoolie_ctx **      stctxv;
967a11
	struct slbt_stoolie_ctx **      stctxp;
4c3fb7
	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
4c3fb7
4c3fb7
	/* context */
4c3fb7
	if (slbt_ectx_get_exec_ctx(dctx,&ectx) < 0)
4c3fb7
		return SLBT_NESTED_ERROR(dctx);
4c3fb7
4c3fb7
	/* initial state, slibtoolize (stoolie) mode skin */
4c3fb7
	slbt_ectx_reset_arguments(ectx);
4c3fb7
	slbt_disable_placeholders(ectx);
4c3fb7
4c3fb7
	ictx  = slbt_get_driver_ictx(dctx);
4c3fb7
	cctx  = dctx->cctx;
4c3fb7
	iargv = ectx->cargv;
4c3fb7
4c3fb7
	fdout = slbt_driver_fdout(dctx);
4c3fb7
	fderr = slbt_driver_fderr(dctx);
4c3fb7
4c3fb7
	(void)fderr;
4c3fb7
967a11
	/* <stoolie> argv meta */
4c3fb7
	slbt_optv_init(slbt_stoolie_options,optv);
4c3fb7
4c3fb7
	if (!(meta = slbt_argv_get(
4c3fb7
			iargv,optv,
4c3fb7
			dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS
4c3fb7
				? ARGV_VERBOSITY_ERRORS
4c3fb7
				: ARGV_VERBOSITY_NONE,
4c3fb7
			fdout)))
4c3fb7
		return slbt_exec_stoolie_fail(
4c3fb7
			ectx,meta,
4c3fb7
			SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_AR_FAIL));
4c3fb7
4c3fb7
	/* dest, alternate argument vector options */
4c3fb7
	argv    = ectx->altv;
4c3fb7
	*argv++ = iargv[0];
4c3fb7
	nunits  = 0;
4c3fb7
4c3fb7
	for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
4c3fb7
		if (entry->fopt) {
4c3fb7
			switch (entry->tag) {
4c3fb7
				case TAG_STLE_HELP:
4c3fb7
					slbt_stoolie_usage(
4c3fb7
						fdout,
4c3fb7
						dctx->program,
4c3fb7
						0,optv,0,ectx,
4c3fb7
						dctx->cctx->drvflags
4c3fb7
							& SLBT_DRIVER_ANNOTATE_NEVER);
4c3fb7
4c3fb7
					ictx->cctx.drvflags |= SLBT_DRIVER_VERSION;
4c3fb7
					ictx->cctx.drvflags ^= SLBT_DRIVER_VERSION;
4c3fb7
4c3fb7
					slbt_argv_free(meta);
4c3fb7
4c3fb7
					return SLBT_OK;
4c3fb7
4c3fb7
				case TAG_STLE_VERSION:
4c3fb7
					ictx->cctx.drvflags |= SLBT_DRIVER_VERSION;
4c3fb7
					break;
af48d3
af48d3
				case TAG_STLE_COPY:
af48d3
					ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_COPY;
af48d3
					break;
af48d3
af48d3
				case TAG_STLE_FORCE:
af48d3
					ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_FORCE;
af48d3
					break;
af48d3
af48d3
				case TAG_STLE_INSTALL:
af48d3
					ictx->cctx.drvflags |= SLBT_DRIVER_STOOLIE_INSTALL;
af48d3
					break;
e6c34e
e6c34e
				case TAG_STLE_DEBUG:
e6c34e
					ictx->cctx.drvflags |= SLBT_DRIVER_DEBUG;
e6c34e
					break;
e6c34e
e6c34e
				case TAG_STLE_DRY_RUN:
e6c34e
					ictx->cctx.drvflags |= SLBT_DRIVER_DRY_RUN;
e6c34e
					break;
8fb92c
8fb92c
				case TAG_STLE_SILENT:
8fb92c
					ictx->cctx.drvflags &= ~(uint64_t)SLBT_DRIVER_VERBOSE;
8fb92c
					ictx->cctx.drvflags |= SLBT_DRIVER_SILENT;
8fb92c
					break;
8fb92c
8fb92c
				case TAG_STLE_VERBOSE:
8fb92c
					ictx->cctx.drvflags &= ~(uint64_t)SLBT_DRIVER_SILENT;
8fb92c
					ictx->cctx.drvflags |= SLBT_DRIVER_VERBOSE;
8fb92c
					break;
4c3fb7
			}
4c3fb7
4c3fb7
			if (entry->fval) {
4c3fb7
				*argv++ = (char *)entry->arg;
4c3fb7
			}
4c3fb7
		} else {
4c3fb7
			nunits++;
4c3fb7
		};
4c3fb7
	}
4c3fb7
4c3fb7
	/* defer --version printing to slbt_main() as needed */
4c3fb7
	if (cctx->drvflags & SLBT_DRIVER_VERSION) {
4c3fb7
		slbt_argv_free(meta);
4c3fb7
		slbt_ectx_free_exec_ctx(ectx);
4c3fb7
		return SLBT_OK;
4c3fb7
	}
4c3fb7
967a11
	/* default to this-dir as needed */
967a11
	if (!(cunits = nunits))
967a11
		nunits++;
967a11
967a11
	/* slibtoolize target directory vector allocation */
967a11
	if (!(stctxv = calloc(nunits+1,sizeof(struct slbt_stoolie_ctx *))))
967a11
		return slbt_exec_stoolie_fail(
967a11
			ectx,meta,
967a11
			SLBT_SYSTEM_ERROR(dctx,0));
967a11
967a11
	/* unit vector allocation */
967a11
	if (!(unitv = calloc(nunits+1,sizeof(const char *)))) {
967a11
		free (stctxv);
967a11
967a11
		return slbt_exec_stoolie_fail(
967a11
			ectx,meta,
967a11
			SLBT_SYSTEM_ERROR(dctx,0));
967a11
	}
967a11
967a11
	/* unit vector initialization */
967a11
	for (entry=meta->entries,unitp=unitv; entry->fopt || entry->arg; entry++)
967a11
		if (!entry->fopt)
967a11
			*unitp++ = entry->arg;
967a11
967a11
	if (!cunits)
967a11
		unitp[0] = slbt_this_dir;
967a11
967a11
	/* slibtoolize target directory vector initialization */
967a11
	for (unitp=unitv,stctxp=stctxv; *unitp; unitp++,stctxp++) {
967a11
		if (slbt_st_get_stoolie_ctx(dctx,*unitp,stctxp) < 0) {
967a11
			for (stctxp=stctxv; *stctxp; stctxp++)
967a11
				slbt_st_free_stoolie_ctx(*stctxp);
967a11
967a11
			free(unitv);
967a11
			free(stctxv);
967a11
967a11
			return slbt_exec_stoolie_fail(
967a11
				ectx,meta,
967a11
				SLBT_NESTED_ERROR(dctx));
967a11
		}
967a11
	}
967a11
4c3fb7
	/* slibtoolize operations */
0dcc39
	for (ret=0,stctxp=stctxv; !ret && *stctxp; stctxp++)
0dcc39
		ret = slbt_exec_stoolie_perform_actions(dctx,ectx,*stctxp);
4c3fb7
4c3fb7
	/* all done */
967a11
	for (stctxp=stctxv; *stctxp; stctxp++)
967a11
		slbt_st_free_stoolie_ctx(*stctxp);
967a11
967a11
	free(unitv);
967a11
	free(stctxv);
967a11
4c3fb7
	slbt_argv_free(meta);
4c3fb7
	slbt_ectx_free_exec_ctx(ectx);
4c3fb7
4c3fb7
	return ret;
4c3fb7
}
4c3fb7
4c3fb7
int slbt_exec_slibtoolize(const struct slbt_driver_ctx * dctx)
4c3fb7
{
4c3fb7
	return slbt_exec_stoolie(dctx);
4c3fb7
}