firasuke / cross / slibtool

Forked from cross/slibtool 3 months ago
Clone

Blame src/helper/slbt_archive_import.c

4a01cf
/*******************************************************************/
4a01cf
/*  slibtool: a skinny libtool implementation, written in C        */
bb281c
/*  Copyright (C) 2016--2021  SysDeer Technologies, LLC            */
4a01cf
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
4a01cf
/*******************************************************************/
4a01cf
b8d3bb
#include <fcntl.h>
f058a6
#include <stdio.h>
4a01cf
#include <limits.h>
4a01cf
#include <unistd.h>
2da3b0
#include <string.h>
2da3b0
#include <stdlib.h>
4a01cf
#include <stdbool.h>
4a01cf
#include <sys/wait.h>
4a01cf
4a01cf
#include <slibtool/slibtool.h>
c81d16
#include "slibtool_driver_impl.h"
4a01cf
#include "slibtool_spawn_impl.h"
c100d1
#include "slibtool_dprintf_impl.h"
b91b15
#include "slibtool_symlink_impl.h"
fb50c9
#include "slibtool_readlink_impl.h"
8a1d14
#include "slibtool_errinfo_impl.h"
4a01cf
2da3b0
static char * slbt_mri_argument(
b8d3bb
	int	fdat,
2da3b0
	char *	arg,
2da3b0
	char *	buf)
2da3b0
{
2da3b0
	int	i;
2da3b0
	char *	lnk;
3c03b3
	char *	target;
2da3b0
	char 	mricwd[PATH_MAX];
3c03b3
	char 	dstbuf[PATH_MAX];
2da3b0
2da3b0
	if ((!(strchr(arg,'+'))) && (!(strchr(arg,'-'))))
2da3b0
		return arg;
2da3b0
3c03b3
	if (arg[0] == '/')
3c03b3
		target = arg;
3c03b3
	else {
688ec9
		if (slbt_realpath(fdat,".",O_DIRECTORY,mricwd,sizeof(mricwd)))
3c03b3
			return 0;
3c03b3
3c03b3
		if ((size_t)snprintf(dstbuf,sizeof(dstbuf),"%s/%s",
3c03b3
				mricwd,arg) >= sizeof(dstbuf))
3c03b3
			return 0;
2da3b0
3c03b3
		target = dstbuf;
3c03b3
	}
2da3b0
2da3b0
	for (i=0,lnk=0; i<1024 && !lnk; i++) {
2da3b0
		if (!(tmpnam(buf)))
2da3b0
			return 0;
2da3b0
b8d3bb
		if (!(symlinkat(target,fdat,buf)))
2da3b0
			lnk = buf;
2da3b0
	}
2da3b0
2da3b0
	return lnk;
2da3b0
}
2da3b0
8a3cc2
static void slbt_archive_import_child(
4a01cf
	char *	program,
4a01cf
	int	fd[2])
4a01cf
{
4a01cf
	char *	argv[3];
4a01cf
4a01cf
	argv[0] = program;
4a01cf
	argv[1] = "-M";
4a01cf
	argv[2] = 0;
4a01cf
4a01cf
	close(fd[1]);
4a01cf
f4ed8e
	if (dup2(fd[0],0) == 0)
4a01cf
		execvp(program,argv);
4a01cf
ec6d7a
	_exit(EXIT_FAILURE);
4a01cf
}
4a01cf
cfec3a
int slbt_archive_import(
4a01cf
	const struct slbt_driver_ctx *	dctx,
4a01cf
	struct slbt_exec_ctx *		ectx,
4a01cf
	char *				dstarchive,
4a01cf
	char *				srcarchive)
4a01cf
{
c81d16
	int	fdcwd;
f058a6
	pid_t	pid;
f058a6
	pid_t	rpid;
4a01cf
	int	fd[2];
2da3b0
	char *	dst;
2da3b0
	char *	src;
c100d1
	char *	fmt;
2da3b0
	char	mridst [L_tmpnam];
2da3b0
	char	mrisrc [L_tmpnam];
4a01cf
	char	program[PATH_MAX];
4a01cf
c81d16
	/* fdcwd */
c81d16
	fdcwd = slbt_driver_fdcwd(dctx);
c81d16
c100d1
	/* not needed? */
c81d16
	if (slbt_symlink_is_a_placeholder(fdcwd,srcarchive))
b91b15
		return 0;
fb50c9
c100d1
	/* program */
c100d1
	if ((size_t)snprintf(program,sizeof(program),
c100d1
				"%s",
c100d1
				dctx->cctx->host.ar)
c100d1
			>= sizeof(program))
8a1d14
		return SLBT_BUFFER_ERROR(dctx);
4a01cf
c100d1
	/* fork */
4a01cf
	if (pipe(fd))
6beda1
		return SLBT_SYSTEM_ERROR(dctx,0);
4a01cf
4a01cf
	if ((pid = fork()) < 0) {
4a01cf
		close(fd[0]);
4a01cf
		close(fd[1]);
6beda1
		return SLBT_SYSTEM_ERROR(dctx,0);
4a01cf
	}
4a01cf
c100d1
	/* child */
4a01cf
	if (pid == 0)
8a3cc2
		slbt_archive_import_child(
4a01cf
			program,
4a01cf
			fd);
4a01cf
c100d1
	/* parent */
c100d1
	close(fd[0]);
c100d1
4a01cf
	ectx->pid = pid;
4a01cf
b8d3bb
	dst = slbt_mri_argument(fdcwd,dstarchive,mridst);
b8d3bb
	src = slbt_mri_argument(fdcwd,srcarchive,mrisrc);
688ec9
688ec9
	if (!dst || !src)
688ec9
		return SLBT_SYSTEM_ERROR(dctx,0);
688ec9
c100d1
	fmt = "OPEN %s\n"
c100d1
	      "ADDLIB %s\n"
c100d1
	      "SAVE\n"
c100d1
	      "END\n";
2da3b0
c100d1
	if (slbt_dprintf(fd[1],fmt,dst,src) < 0) {
4a01cf
		close(fd[1]);
6beda1
		return SLBT_SYSTEM_ERROR(dctx,0);
4a01cf
	}
4a01cf
c100d1
	close(fd[1]);
c100d1
f058a6
	rpid = waitpid(
4a01cf
		pid,
4a01cf
		&ectx->exitcode,
4a01cf
		0);
4a01cf
2da3b0
	if (dst == mridst)
d38565
		unlinkat(fdcwd,dst,0);
2da3b0
2da3b0
	if (src == mrisrc)
d38565
		unlinkat(fdcwd,src,0);
2da3b0
c100d1
	return (rpid == pid) && (ectx->exitcode == 0)
c100d1
		? 0 : SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_ARCHIVE_IMPORT);
4a01cf
}