Blame src/internal/slibtool_symlink_impl.c

6529aa
/*******************************************************************/
6529aa
/*  slibtool: a skinny libtool implementation, written in C        */
78d96a
/*  Copyright (C) 2016--2017  Z. Gilboa                            */
6529aa
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
6529aa
/*******************************************************************/
6529aa
6529aa
#include <stdio.h>
6529aa
#include <string.h>
6529aa
#include <stdbool.h>
6529aa
#include <unistd.h>
6529aa
d56ead
#include "slibtool_errinfo_impl.h"
6529aa
#include "slibtool_symlink_impl.h"
6529aa
ec5e56
#define SLBT_DEV_NULL_FLAGS	(SLBT_DRIVER_ALL_STATIC      \
ec5e56
				| SLBT_DRIVER_DISABLE_SHARED \
ec5e56
				| SLBT_DRIVER_DISABLE_STATIC)
d1e257
6529aa
int slbt_create_symlink(
6529aa
	const struct slbt_driver_ctx *	dctx,
6529aa
	struct slbt_exec_ctx *		ectx,
6529aa
	const char *			target,
e0a045
	const char *			lnkname,
6529aa
	bool				flawrapper)
6529aa
{
660491
	char **		oargv;
6529aa
	const char *	slash;
6529aa
	char *		ln[5];
6529aa
	char *		dotdot;
6529aa
	char		tmplnk [PATH_MAX];
e0a045
	char		lnkarg [PATH_MAX];
6529aa
	char		atarget[PATH_MAX];
6529aa
6529aa
	/* atarget */
d1e257
	if ((dctx->cctx->drvflags & SLBT_DEV_NULL_FLAGS)
372423
			&& !strcmp(target,"/dev/null"))
372423
		slash = target;
372423
	else if ((slash = strrchr(target,'/')))
6529aa
		slash++;
6529aa
	else
6529aa
		slash = target;
6529aa
6529aa
	dotdot = flawrapper ? "../" : "";
6529aa
6529aa
	if ((size_t)snprintf(atarget,sizeof(atarget),"%s%s",
6529aa
			dotdot,slash) >= sizeof(atarget))
d56ead
		return SLBT_BUFFER_ERROR(dctx);
6529aa
6529aa
	/* tmplnk */
6529aa
	if ((size_t)snprintf(tmplnk,sizeof(tmplnk),"%s.symlink.tmp",
6529aa
			lnkname) >= sizeof(tmplnk))
d56ead
		return SLBT_BUFFER_ERROR(dctx);
6529aa
e0a045
	/* lnkarg */
e0a045
	strcpy(lnkarg,lnkname);
e0a045
6529aa
	/* ln argv (fake) */
6529aa
	ln[0] = "ln";
6529aa
	ln[1] = "-s";
6529aa
	ln[2] = atarget;
e0a045
	ln[3] = lnkarg;
6529aa
	ln[4] = 0;
660491
660491
	oargv      = ectx->argv;
6529aa
	ectx->argv = ln;
6529aa
6529aa
	/* step output */
dc77cb
	if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
5e1c21
		if (dctx->cctx->mode == SLBT_MODE_LINK) {
660491
			if (slbt_output_link(dctx,ectx)) {
660491
				ectx->argv = oargv;
d56ead
				return SLBT_NESTED_ERROR(dctx);
660491
			}
5e1c21
		} else {
660491
			if (slbt_output_install(dctx,ectx)) {
660491
				ectx->argv = oargv;
d56ead
				return SLBT_NESTED_ERROR(dctx);
660491
			}
5e1c21
		}
dc77cb
	}
dc77cb
660491
	/* restore execution context */
660491
	ectx->argv = oargv;
660491
6529aa
	/* create symlink */
6529aa
	if (symlink(atarget,tmplnk))
d56ead
		return SLBT_SYSTEM_ERROR(dctx);
6529aa
d56ead
	return rename(tmplnk,lnkname)
d56ead
		? SLBT_SYSTEM_ERROR(dctx)
d56ead
		: 0;
6529aa
}