Blame src/helper/slbt_archive_import.c

4a01cf
/*******************************************************************/
4a01cf
/*  slibtool: a skinny libtool implementation, written in C        */
78d96a
/*  Copyright (C) 2016--2017  Z. Gilboa                            */
4a01cf
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
4a01cf
/*******************************************************************/
4a01cf
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>
4a01cf
#include "slibtool_spawn_impl.h"
fb50c9
#include "slibtool_readlink_impl.h"
8a1d14
#include "slibtool_errinfo_impl.h"
4a01cf
2da3b0
static char * slbt_mri_argument(
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 {
3c03b3
		if (!(getcwd(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
2da3b0
		if (!(symlink(target,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
{
4a01cf
	int	ret;
f058a6
	pid_t	pid;
f058a6
	pid_t	rpid;
4a01cf
	int	fd[2];
4a01cf
	FILE *	fout;
2da3b0
	char *	dst;
2da3b0
	char *	src;
2da3b0
	char	mridst [L_tmpnam];
2da3b0
	char	mrisrc [L_tmpnam];
4a01cf
	char	program[PATH_MAX];
4a01cf
fb50c9
	if (!slbt_readlink(srcarchive,program,sizeof(program)))
fb50c9
		if (!(strcmp(program,"/dev/null")))
fb50c9
			return 0;
fb50c9
4a01cf
	if ((size_t)snprintf(program,sizeof(program),"%s",
4a01cf
			dctx->cctx->host.ar) >= sizeof(program))
8a1d14
		return SLBT_BUFFER_ERROR(dctx);
4a01cf
4a01cf
	if (pipe(fd))
8a1d14
		return SLBT_SYSTEM_ERROR(dctx);
4a01cf
4a01cf
	if ((pid = fork()) < 0) {
4a01cf
		close(fd[0]);
4a01cf
		close(fd[1]);
8a1d14
		return SLBT_SYSTEM_ERROR(dctx);
4a01cf
	}
4a01cf
4a01cf
	if (pid == 0)
8a3cc2
		slbt_archive_import_child(
4a01cf
			program,
4a01cf
			fd);
4a01cf
4a01cf
	ectx->pid = pid;
4a01cf
2da3b0
	dst = slbt_mri_argument(dstarchive,mridst);
2da3b0
	src = slbt_mri_argument(srcarchive,mrisrc);
2da3b0
4a01cf
	if ((fout = fdopen(fd[1],"a"))) {
4a01cf
		ret = (fprintf(
4a01cf
				fout,
4a01cf
				"OPEN %s\n"
4a01cf
				"ADDLIB %s\n"
4a01cf
				"SAVE\n"
4a01cf
				"END\n",
2da3b0
				dst,
2da3b0
				src) < 0)
8a1d14
			? SLBT_SYSTEM_ERROR(dctx)
8a1d14
			: 0;
4a01cf
4a01cf
		fclose(fout);
4a01cf
		close(fd[0]);
4a01cf
	} else {
8a1d14
		ret = SLBT_SYSTEM_ERROR(dctx);
4a01cf
		close(fd[0]);
4a01cf
		close(fd[1]);
4a01cf
	}
4a01cf
f058a6
	rpid = waitpid(
4a01cf
		pid,
4a01cf
		&ectx->exitcode,
4a01cf
		0);
4a01cf
2da3b0
	if (dst == mridst)
2da3b0
		unlink(dst);
2da3b0
2da3b0
	if (src == mrisrc)
2da3b0
		unlink(src);
2da3b0
f058a6
	return ret || (rpid != pid) || ectx->exitcode
Kylie McClain 7ce25c
		? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_ARCHIVE_IMPORT) : 0;
4a01cf
}