Blame src/logic/linkcmd/slbt_linkcmd_archive.c

3bfc81
/*******************************************************************/
3bfc81
/*  slibtool: a skinny libtool implementation, written in C        */
49181b
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
3bfc81
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
3bfc81
/*******************************************************************/
3bfc81
3bfc81
#include <stdlib.h>
3bfc81
#include <stdio.h>
3bfc81
#include <string.h>
3bfc81
#include <fcntl.h>
3bfc81
#include <errno.h>
3bfc81
#include <sys/stat.h>
3bfc81
3bfc81
#include <slibtool/slibtool.h>
3bfc81
#include "slibtool_driver_impl.h"
3bfc81
#include "slibtool_errinfo_impl.h"
3bfc81
#include "slibtool_linkcmd_impl.h"
3bfc81
#include "slibtool_mapfile_impl.h"
3bfc81
#include "slibtool_metafile_impl.h"
3bfc81
#include "slibtool_snprintf_impl.h"
3bfc81
#include "slibtool_symlink_impl.h"
3bfc81
#include "slibtool_spawn_impl.h"
3bfc81
3bfc81
static int slbt_exec_link_create_noop_symlink(
3bfc81
	const struct slbt_driver_ctx *	dctx,
3bfc81
	struct slbt_exec_ctx *		ectx,
3bfc81
	const char *			arfilename)
3bfc81
{
3bfc81
	struct stat st;
3bfc81
	int         fdcwd;
3bfc81
3bfc81
	/* fdcwd */
3bfc81
	fdcwd = slbt_driver_fdcwd(dctx);
3bfc81
3bfc81
	/* file exists? */
3bfc81
	if (!fstatat(fdcwd,arfilename,&st,AT_SYMLINK_NOFOLLOW))
3bfc81
		return 0;
3bfc81
3bfc81
	/* needed? */
3bfc81
	if (errno == ENOENT) {
3bfc81
		if (slbt_create_symlink(
3bfc81
				dctx,ectx,
3bfc81
				"/dev/null",
3bfc81
				arfilename,
3bfc81
				SLBT_SYMLINK_LITERAL))
3bfc81
			return SLBT_NESTED_ERROR(dctx);
3bfc81
		return 0;
3bfc81
	}
3bfc81
3bfc81
	return SLBT_SYSTEM_ERROR(dctx,arfilename);
3bfc81
}
3bfc81
3bfc81
static int slbt_exec_link_remove_file(
3bfc81
	const struct slbt_driver_ctx *	dctx,
3bfc81
	struct slbt_exec_ctx *		ectx,
3bfc81
	const char *			target)
3bfc81
{
3bfc81
	int fdcwd;
3bfc81
3bfc81
	(void)ectx;
3bfc81
3bfc81
	/* fdcwd */
3bfc81
	fdcwd = slbt_driver_fdcwd(dctx);
3bfc81
3bfc81
	/* remove target (if any) */
3bfc81
	if (!unlinkat(fdcwd,target,0) || (errno == ENOENT))
3bfc81
		return 0;
3bfc81
3bfc81
	return SLBT_SYSTEM_ERROR(dctx,0);
3bfc81
}
3bfc81
3bfc81
int slbt_exec_link_create_archive(
3bfc81
	const struct slbt_driver_ctx *	dctx,
3bfc81
	struct slbt_exec_ctx *		ectx,
3bfc81
	const char *			arfilename,
3bfc81
	bool				fpic)
3bfc81
{
3bfc81
	int		fdcwd;
a1c68a
	char **         argv;
3bfc81
	char ** 	aarg;
3bfc81
	char ** 	parg;
3bfc81
	char		program[PATH_MAX];
3bfc81
	char		output [PATH_MAX];
3bfc81
3bfc81
	/* -disable-static? */
3bfc81
	if (dctx->cctx->drvflags & SLBT_DRIVER_DISABLE_STATIC)
3bfc81
		if (dctx->cctx->rpath)
3bfc81
			return slbt_exec_link_create_noop_symlink(
3bfc81
				dctx,ectx,arfilename);
3bfc81
3bfc81
	/* initial state */
3bfc81
	slbt_reset_arguments(ectx);
3bfc81
3bfc81
	/* placeholders */
3bfc81
	slbt_reset_placeholders(ectx);
3bfc81
3bfc81
	/* alternate program (ar, ranlib) */
3bfc81
	ectx->program = program;
3bfc81
3bfc81
	/* output */
3bfc81
	if (slbt_snprintf(output,sizeof(output),
3bfc81
			"%s",arfilename) < 0)
3bfc81
		return SLBT_BUFFER_ERROR(dctx);
3bfc81
a1c68a
	/* tool-specific argument vector */
a1c68a
	argv = (slbt_get_driver_ictx(dctx))->host.ar_argv;
3bfc81
a1c68a
	/* ar alternate argument vector */
a1c68a
	if (!argv)
a1c68a
		if (slbt_snprintf(program,sizeof(program),
a1c68a
				"%s",dctx->cctx->host.ar) < 0)
a1c68a
			return SLBT_BUFFER_ERROR(dctx);
3bfc81
3bfc81
	/* fdcwd */
3bfc81
	fdcwd   = slbt_driver_fdcwd(dctx);
3bfc81
3bfc81
	/* input argument adjustment */
3bfc81
	aarg    = ectx->altv;
a1c68a
a1c68a
	if ((parg = argv)) {
a1c68a
		ectx->program = argv[0];
a1c68a
a1c68a
		for (; *parg; )
a1c68a
			*aarg++ = *parg++;
a1c68a
	} else {
a1c68a
		*aarg++ = program;
a1c68a
	}
a1c68a
3bfc81
	*aarg++ = "-crs";
3bfc81
	*aarg++ = output;
3bfc81
3bfc81
	for (parg=ectx->cargv; *parg; parg++)
3bfc81
		if (slbt_adjust_object_argument(*parg,fpic,!fpic,fdcwd))
3bfc81
			*aarg++ = *parg;
3bfc81
3bfc81
	*aarg = 0;
3bfc81
	ectx->argv = ectx->altv;
3bfc81
3bfc81
	/* step output */
3bfc81
	if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
3bfc81
		if (slbt_output_link(dctx,ectx))
3bfc81
			return SLBT_NESTED_ERROR(dctx);
3bfc81
3bfc81
	/* remove old archive as needed */
3bfc81
	if (slbt_exec_link_remove_file(dctx,ectx,output))
3bfc81
		return SLBT_NESTED_ERROR(dctx);
3bfc81
3bfc81
	/* .deps */
3bfc81
	if (slbt_exec_link_create_dep_file(
3bfc81
			dctx,ectx,ectx->cargv,
3bfc81
			arfilename,true))
3bfc81
		return SLBT_NESTED_ERROR(dctx);
3bfc81
3bfc81
	/* ar spawn */
3bfc81
	if ((slbt_spawn(ectx,true) < 0) && (ectx->pid < 0)) {
3bfc81
		return SLBT_SPAWN_ERROR(dctx);
3bfc81
3bfc81
	} else if (ectx->exitcode) {
3bfc81
		return SLBT_CUSTOM_ERROR(
3bfc81
			dctx,
3bfc81
			SLBT_ERR_AR_ERROR);
3bfc81
	}
3bfc81
3bfc81
	/* input objects associated with .la archives */
3bfc81
	for (parg=ectx->cargv; *parg; parg++)
3bfc81
		if (slbt_adjust_wrapper_argument(*parg,true))
3bfc81
			if (slbt_archive_import(dctx,ectx,output,*parg))
3bfc81
				return SLBT_NESTED_ERROR(dctx);
3bfc81
3bfc81
	return 0;
3bfc81
}