firasuke / cross / slibtool

Forked from cross/slibtool 3 months ago
Clone

Blame src/logic/linkcmd/slbt_linkcmd_deps.c

b08054
/*******************************************************************/
eac61a
/*  slibtool: a strong libtool implementation, written in C        */
49181b
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
b08054
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
b08054
/*******************************************************************/
b08054
b08054
#include <stdlib.h>
b08054
#include <stdio.h>
b08054
#include <string.h>
b08054
#include <fcntl.h>
b08054
#include <errno.h>
b08054
#include <sys/stat.h>
b08054
b08054
#include <slibtool/slibtool.h>
b08054
#include "slibtool_driver_impl.h"
b08054
#include "slibtool_errinfo_impl.h"
b08054
#include "slibtool_linkcmd_impl.h"
b08054
#include "slibtool_mapfile_impl.h"
b08054
#include "slibtool_metafile_impl.h"
43ee04
#include "slibtool_realpath_impl.h"
b08054
#include "slibtool_snprintf_impl.h"
4b56de
#include "slibtool_visibility_impl.h"
b08054
4b56de
slbt_hidden int slbt_get_deps_meta(
b08054
	const struct slbt_driver_ctx *	dctx,
b08054
	char *				libfilename,
b08054
	int				fexternal,
b08054
	struct slbt_deps_meta *		depsmeta)
b08054
{
b08054
	int			fdcwd;
b08054
	char *			ch;
b08054
	char *			cap;
b08054
	char *			base;
b08054
	size_t			libexlen;
b08054
	struct stat		st;
b08054
	struct slbt_map_info *	mapinfo;
b08054
	char			depfile[PATH_MAX];
b08054
b08054
	/* fdcwd */
b08054
	fdcwd = slbt_driver_fdcwd(dctx);
b08054
b08054
	/* -rpath */
b08054
	if (slbt_snprintf(depfile,sizeof(depfile),
b08054
				"%s.slibtool.rpath",
b08054
				libfilename) < 0)
b08054
		return SLBT_BUFFER_ERROR(dctx);
b08054
b08054
	/* -Wl,%s */
b08054
	if (!fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) {
b08054
		depsmeta->infolen += st.st_size + 4;
b08054
		depsmeta->infolen++;
b08054
	}
b08054
b08054
	/* .deps */
b08054
	if (slbt_snprintf(depfile,sizeof(depfile),
b08054
				"%s.slibtool.deps",
b08054
				libfilename) < 0)
b08054
		return SLBT_BUFFER_ERROR(dctx);
b08054
b08054
	/* mapinfo */
b08054
	if (!(mapinfo = slbt_map_file(fdcwd,depfile,SLBT_MAP_INPUT)))
b08054
		return (fexternal && (errno == ENOENT))
b08054
			? 0 : SLBT_SYSTEM_ERROR(dctx,depfile);
b08054
b08054
	/* copied length */
b08054
	depsmeta->infolen += mapinfo->size;
b08054
	depsmeta->infolen++;
b08054
b08054
	/* libexlen */
b08054
	libexlen = (base = strrchr(libfilename,'/'))
b08054
		? strlen(depfile) + 2 + (base - libfilename)
b08054
		: strlen(depfile) + 2;
b08054
b08054
	/* iterate */
b08054
	ch  = mapinfo->addr;
b08054
	cap = mapinfo->cap;
b08054
b08054
	for (; ch
b08054
		if (*ch++ == '\n') {
b08054
			depsmeta->infolen += libexlen;
b08054
			depsmeta->depscnt++;
b08054
		}
b08054
	}
b08054
b08054
	slbt_unmap_file(mapinfo);
b08054
b08054
	return 0;
b08054
}
b08054
b08054
43ee04
static int slbt_exec_link_normalize_dep_file(
43ee04
	const struct slbt_driver_ctx *  dctx,
43ee04
	int                             deps,
43ee04
	char                            (*depfile)[PATH_MAX])
43ee04
{
43ee04
	int                             ret;
43ee04
	int                             fdcwd;
43ee04
	int                             fdtgt;
43ee04
	char *                          dot;
43ee04
	char *                          slash;
198205
	const char *                    base;
43ee04
	const char *                    mark;
43ee04
	struct slbt_txtfile_ctx *       tctx;
43ee04
	const char **                   pline;
43ee04
	char *                          tgtmark;
43ee04
	char *                          depmark;
43ee04
	char *                          relmark;
43ee04
	char *                          tgtnext;
43ee04
	char *                          depnext;
43ee04
	char                            tgtdir  [PATH_MAX];
43ee04
	char                            tgtpath [PATH_MAX];
43ee04
	char                            deppath [PATH_MAX];
43ee04
	char                            pathbuf [PATH_MAX];
43ee04
	char                            depsbuf [PATH_MAX];
198205
	char                            basebuf [PATH_MAX];
43ee04
	char                            relapath[PATH_MAX];
43ee04
43ee04
	/* fdcwd */
43ee04
	fdcwd = slbt_driver_fdcwd(dctx);
43ee04
43ee04
	/* first-pass dependency file */
43ee04
	if (slbt_impl_get_txtfile_ctx(dctx,*depfile,deps,&tctx) < 0)
43ee04
		return SLBT_NESTED_ERROR(dctx);
43ee04
43ee04
	/* second-pass dependency file */
43ee04
	dot = strrchr(*depfile,'.');
43ee04
	strcpy(dot,".tmp2");
43ee04
43ee04
	if ((deps = openat(fdcwd,*depfile,O_RDWR|O_CREAT|O_TRUNC,0644)) < 0) {
43ee04
		slbt_lib_free_txtfile_ctx(tctx);
43ee04
		return SLBT_SYSTEM_ERROR(dctx,depfile);
43ee04
	}
43ee04
43ee04
	/* fdtgt */
43ee04
	strcpy(tgtdir,*depfile);
43ee04
43ee04
	if (!(slash = strrchr(tgtdir,'/')))
43ee04
		slash = tgtdir;
43ee04
43ee04
	slash[0] = '\0';
43ee04
43ee04
	if ((slash = strrchr(tgtdir,'/'))) {
43ee04
		slash[0] = '\0';
43ee04
		slash++;
43ee04
	} else {
43ee04
		slash    = tgtdir;
43ee04
		slash[0] = '.';
43ee04
		slash[1] = '/';
43ee04
		slash[2] = '\0';
43ee04
	}
43ee04
43ee04
	if ((slash > tgtdir) && strcmp(slash,".libs")) {
43ee04
		close(deps);
43ee04
		slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
		return SLBT_CUSTOM_ERROR(
43ee04
			dctx,
43ee04
			SLBT_ERR_FLOW_ERROR);
43ee04
	}
43ee04
43ee04
	if ((fdtgt = openat(fdcwd,tgtdir,O_DIRECTORY|O_CLOEXEC,0)) < 0) {
43ee04
		close(deps);
43ee04
		slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
		return SLBT_CUSTOM_ERROR(
43ee04
			dctx,
43ee04
			SLBT_ERR_FLOW_ERROR);
43ee04
	}
43ee04
43ee04
	if (slbt_realpath(fdcwd,tgtdir,0,tgtpath,sizeof(tgtpath)) < 0) {
43ee04
				close(fdtgt);
43ee04
				close(deps);
43ee04
				slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
				return SLBT_CUSTOM_ERROR(
43ee04
					dctx,
43ee04
					SLBT_ERR_FLOW_ERROR);
43ee04
	}
43ee04
43ee04
	strcpy(pathbuf,tgtpath);
43ee04
43ee04
	/* normalize dependency lines as needed */
43ee04
	for (pline=tctx->txtlinev; *pline; pline++) {
43ee04
		if ((mark = *pline)) {
198205
			if ((mark[0] == '-') && (mark[1] == 'L')) {
43ee04
					mark = &mark[2];
198205
					base = 0;
198205
198205
			} else if ((mark[0] == ':') && (mark[1] == ':')) {
198205
					mark = &mark[2];
198205
					base = mark;
198205
			}
43ee04
43ee04
			if ((mark > *pline) && (mark[0] == '/'))
43ee04
				mark = *pline;
43ee04
		}
43ee04
43ee04
		if (mark > *pline) {
43ee04
			if (slbt_realpath(
43ee04
					fdtgt,mark,0,deppath,
43ee04
					sizeof(deppath)) < 0)
43ee04
				mark = *pline;
43ee04
43ee04
			else if ((tgtpath[0] != '/') || (deppath[0] != '/'))
43ee04
				mark = 0;
43ee04
43ee04
			else
43ee04
				strcpy(depsbuf,deppath);
198205
198205
			if ((mark > *pline) && base) {
198205
				slash  = strrchr(deppath,'/');
198205
				*slash = '\0';
198205
198205
				slash  = strrchr(deppath,'/');
198205
				*slash = '\0';
198205
198205
				base  = basebuf;
198205
				slash = &depsbuf[slash - deppath];
198205
198205
				strcpy(basebuf,++slash);
198205
				strcpy(depsbuf,deppath);
198205
			}
43ee04
		}
43ee04
198205
		if (mark > *pline) {
43ee04
			tgtmark = tgtpath;
43ee04
			depmark = deppath;
43ee04
43ee04
			tgtnext = strchr(tgtmark,'/');
43ee04
			depnext = strchr(depmark,'/');
43ee04
43ee04
			while (tgtnext && depnext) {
43ee04
				*tgtnext = '\0';
43ee04
				*depnext = '\0';
43ee04
43ee04
				if (strcmp(tgtmark,depmark)) {
43ee04
					tgtnext = 0;
43ee04
					depnext = 0;
43ee04
				} else {
43ee04
					tgtmark = &tgtnext[1];
43ee04
					depmark = &depnext[1];
43ee04
43ee04
					if (*tgtmark && *depmark) {
43ee04
						tgtnext = strchr(tgtmark,'/');
43ee04
						depnext = strchr(depmark,'/');
43ee04
					} else {
43ee04
						tgtnext = 0;
43ee04
						depnext = 0;
43ee04
					}
43ee04
				}
43ee04
			}
43ee04
43ee04
			strcpy(tgtmark,&pathbuf[tgtmark-tgtpath]);
43ee04
			strcpy(depmark,&depsbuf[depmark-deppath]);
43ee04
43ee04
			if ((tgtmark - tgtpath) == (depmark - deppath)) {
43ee04
				mark = &depmark[strlen(tgtmark)];
43ee04
43ee04
				if ((mark[0] == '/') && !strncmp(tgtmark,depmark,mark-depmark))
43ee04
					sprintf(relapath,"-L.%s",mark);
43ee04
				else
43ee04
					mark = relapath;
43ee04
			} else {
43ee04
				mark = relapath;
43ee04
			}
43ee04
43ee04
			if (mark == relapath) {
43ee04
				relmark = relapath;
43ee04
				relmark += sprintf(relapath,"-L../");
43ee04
43ee04
				while ((tgtnext = strchr(tgtmark,'/'))) {
43ee04
					tgtmark = &tgtnext[1];
43ee04
					relmark += sprintf(relmark,"../");
43ee04
				}
43ee04
43ee04
				strcpy(relmark,depmark);
43ee04
			}
43ee04
198205
			if (base) {
198205
				relapath[0] = ':';
198205
				relapath[1] = ':';
198205
			}
43ee04
43ee04
			mark = relapath;
43ee04
		}
43ee04
198205
		if ((mark == relapath) && base) {
198205
			ret =  slbt_dprintf(deps,"%s/%s\n",mark,base);
198205
198205
		} else if (mark) {
198205
			ret = slbt_dprintf(deps,"%s\n",mark);
198205
198205
		} else {
198205
			ret = (-1);
198205
		}
43ee04
43ee04
		if (ret < 0) {
43ee04
			close(deps);
43ee04
			close(fdtgt);
43ee04
			slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
			return mark
43ee04
				? SLBT_SYSTEM_ERROR(dctx,0)
43ee04
				: SLBT_NESTED_ERROR(dctx);
43ee04
		}
43ee04
43ee04
		if (mark == relapath)
43ee04
			strcpy(tgtpath,pathbuf);
43ee04
	}
43ee04
43ee04
	close(fdtgt);
43ee04
	slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
	return deps;
43ee04
}
43ee04
43ee04
43ee04
static int slbt_exec_link_compact_dep_file(
43ee04
	const struct slbt_driver_ctx *  dctx,
43ee04
	int                             deps,
43ee04
	char                            (*depfile)[PATH_MAX])
43ee04
{
43ee04
	int                             fdcwd;
43ee04
	struct slbt_txtfile_ctx *       tctx;
43ee04
	const char **                   pline;
43ee04
	const char **                   pcomp;
43ee04
	const char *                    depline;
43ee04
	char *                          dot;
43ee04
43ee04
	/* fdcwd */
43ee04
	fdcwd = slbt_driver_fdcwd(dctx);
43ee04
43ee04
	/* second-pass dependency file */
43ee04
	if (slbt_impl_get_txtfile_ctx(dctx,*depfile,deps,&tctx) < 0)
43ee04
		return SLBT_NESTED_ERROR(dctx);
43ee04
43ee04
	/* second-pass dependency file */
43ee04
	dot = strrchr(*depfile,'.');
43ee04
	dot[0] = '\0';
43ee04
43ee04
	if ((deps = openat(fdcwd,*depfile,O_RDWR|O_CREAT|O_TRUNC,0644)) < 0) {
43ee04
		slbt_lib_free_txtfile_ctx(tctx);
43ee04
		return SLBT_SYSTEM_ERROR(dctx,depfile);
43ee04
	}
43ee04
43ee04
	/* iterate, only write unique entries */
43ee04
	for (pline=tctx->txtlinev; *pline; pline++) {
43ee04
		depline = *pline;
43ee04
43ee04
		if ((depline[0] == '-') && (depline[1] == 'L'))
43ee04
			for (pcomp=tctx->txtlinev; depline && pcomp
43ee04
				if (!strcmp(*pcomp,depline))
43ee04
					depline = 0;
43ee04
43ee04
		if (depline && (slbt_dprintf(deps,"%s\n",depline) < 0)) {
43ee04
			close(deps);
43ee04
			slbt_lib_free_txtfile_ctx(tctx);
43ee04
			return SLBT_SYSTEM_ERROR(dctx,0);
43ee04
		}
43ee04
	}
43ee04
43ee04
	slbt_lib_free_txtfile_ctx(tctx);
43ee04
43ee04
	return deps;
43ee04
}
43ee04
43ee04
198205
static bool slbt_archive_is_convenience_library(int fdcwd, const char * arpath)
198205
{
198205
	int     fd;
198205
	char    laipath[PATH_MAX];
198205
	char *  dot;
198205
198205
	strcpy(laipath,arpath);
198205
	dot = strrchr(laipath,'.');
198205
	strcpy(dot,".lai");
198205
198205
	if ((fd = openat(fdcwd,laipath,O_RDONLY,0)) >= 0) {
198205
		close(fd);
198205
		return false;
198205
	}
198205
198205
	return true;
198205
}
198205
198205
4b56de
slbt_hidden int slbt_exec_link_create_dep_file(
b08054
	const struct slbt_driver_ctx *	dctx,
b08054
	struct slbt_exec_ctx *		ectx,
b08054
	char **				altv,
b08054
	const char *			libfilename,
b08054
	bool				farchive)
b08054
{
b08054
	int			ret;
b08054
	int			deps;
43ee04
	int			fdtmp;
b08054
	int			slen;
b08054
	int			fdcwd;
b08054
	char **			parg;
b08054
	char *			popt;
b08054
	char *			plib;
b08054
	char *			path;
b08054
	char *			mark;
b08054
	char *			base;
b08054
	size_t			size;
6ccc20
	bool                    fdep;
b08054
	char			deplib [PATH_MAX];
62a007
	char			deppref[PATH_MAX];
b08054
	char			reladir[PATH_MAX];
b08054
	char			depfile[PATH_MAX];
43ee04
	char			pathbuf[PATH_MAX];
b08054
	struct stat		st;
b08054
	int			ldepth;
198205
	int			fardep;
b08054
	int			fdyndep;
b08054
	struct slbt_map_info *  mapinfo;
62a007
	bool			is_reladir;
b08054
b08054
	/* fdcwd */
b08054
	fdcwd = slbt_driver_fdcwd(dctx);
b08054
b08054
	/* depfile */
b08054
	if (slbt_snprintf(depfile,sizeof(depfile),
43ee04
			"%s.slibtool.deps.tmp1",
b08054
			libfilename) < 0)
b08054
		return SLBT_BUFFER_ERROR(dctx);
b08054
43ee04
	strcpy(pathbuf,depfile);
43ee04
62a007
	/* dependency prefix */
62a007
	if (depfile[0] == '/') {
62a007
		deppref[0] = '\0';
62a007
	} else {
62a007
		if ((mark = strrchr(depfile,'/')))
62a007
			*mark = 0;
62a007
62a007
		if (!mark)
62a007
			mark = depfile;
62a007
62a007
		if (slbt_realpath(fdcwd,depfile,0,reladir,sizeof(reladir)) < 0)
62a007
			return SLBT_SYSTEM_ERROR(dctx,0);
62a007
62a007
		if (slbt_realpath(fdcwd,"./",0,deppref,sizeof(deppref)) < 0)
62a007
			return SLBT_SYSTEM_ERROR(dctx,0);
62a007
62a007
		if (mark > depfile)
62a007
			*mark = '/';
62a007
62a007
		mark = &reladir[strlen(deppref)];
62a007
		*mark++ = '\0';
62a007
62a007
		if (strcmp(reladir,deppref))
62a007
			return SLBT_CUSTOM_ERROR(
62a007
				dctx,
62a007
				SLBT_ERR_FLOW_ERROR);
62a007
62a007
		if ((base = strrchr(mark,'/')))
62a007
			base++;
62a007
62a007
		if (!base)
62a007
			base = mark;
62a007
62a007
		if (strcmp(base,".libs"))
62a007
			return SLBT_CUSTOM_ERROR(
62a007
				dctx,
62a007
				SLBT_ERR_FLOW_ERROR);
62a007
62a007
		base = mark;
62a007
		mark = deppref;
62a007
62a007
		for (; base; ) {
62a007
			if ((base = strchr(base,'/'))) {
62a007
				mark += sprintf(mark,"../");
62a007
				base++;
62a007
			}
62a007
		}
97cd9f
97cd9f
		*mark = '\0';
62a007
	}
62a007
b08054
	/* deps */
b08054
	if ((deps = openat(fdcwd,depfile,O_RDWR|O_CREAT|O_TRUNC,0644)) < 0)
b08054
		return SLBT_SYSTEM_ERROR(dctx,depfile);
b08054
6ccc20
	/* informational header */
6ccc20
	if (slbt_realpath(fdcwd,"./",0,reladir,sizeof(reladir)) < 0)
6ccc20
		return SLBT_SYSTEM_ERROR(dctx,0);
6ccc20
6ccc20
	if (slbt_dprintf(deps,
6ccc20
			"# makefile target: %s\n"
6ccc20
			"# slibtool target: %s\n"
6ccc20
			"# cprocess fdcwd:  %s\n",
6ccc20
			dctx->cctx->output,
6ccc20
			libfilename,
6ccc20
			reladir) < 0)
6ccc20
		return SLBT_SYSTEM_ERROR(dctx,0);
6ccc20
6ccc20
	fdep = 0;
6ccc20
b08054
	/* iterate */
b08054
	for (parg=altv; *parg; parg++) {
b08054
		popt    = 0;
b08054
		plib    = 0;
b08054
		path    = 0;
b08054
		mapinfo = 0;
b08054
b08054
		if (!strncmp(*parg,"-l",2)) {
6ccc20
			if (fdep) {
6ccc20
				if (slbt_dprintf(
6ccc20
						deps,
6ccc20
						"#\n# makefile target: %s\n",
6ccc20
						dctx->cctx->output) < 0)
6ccc20
					return SLBT_SYSTEM_ERROR(dctx,0);
6ccc20
6ccc20
				fdep = false;
6ccc20
			}
6ccc20
b08054
			popt = *parg;
b08054
			plib = popt + 2;
b08054
b08054
		} else if (!strncmp(*parg,"-L",2)) {
6ccc20
			if (fdep) {
6ccc20
				if (slbt_dprintf(
6ccc20
						deps,
6ccc20
						"#\n# makefile target: %s\n",
6ccc20
						dctx->cctx->output) < 0)
6ccc20
					return SLBT_SYSTEM_ERROR(dctx,0);
6ccc20
6ccc20
				fdep = false;
6ccc20
			}
6ccc20
b08054
			popt = *parg;
b08054
			path = popt + 2;
b08054
b08054
		} else if (!strncmp(*parg,"-f",2)) {
b08054
			(void)0;
b08054
b08054
		} else if ((popt = strrchr(*parg,'.')) && !strcmp(popt,".la")) {
b08054
			/* import dependency list */
6ccc20
			fdep = true;
6ccc20
b08054
			if ((base = strrchr(*parg,'/')))
b08054
				base++;
b08054
			else
b08054
				base = *parg;
b08054
b08054
			/* [relative .la directory] */
b08054
			if (base > *parg) {
b08054
				slen = slbt_snprintf(
b08054
					reladir,
b08054
					sizeof(reladir),
b08054
					"%s",*parg);
b08054
b08054
				if (slen < 0) {
b08054
					close(deps);
b08054
					return SLBT_BUFFER_ERROR(dctx);
b08054
				}
b08054
b08054
				is_reladir = true;
b08054
				reladir[base - *parg - 1] = 0;
b08054
			} else {
b08054
				is_reladir = false;
b08054
				reladir[0] = '.';
b08054
				reladir[1] = 0;
b08054
			}
b08054
b08054
b08054
			/* dynamic library dependency? */
b08054
			strcpy(depfile,*parg);
b08054
			mark = depfile + (base - *parg);
b08054
			size = sizeof(depfile) - (base - *parg);
b08054
			slen = slbt_snprintf(mark,size,".libs/%s",base);
b08054
b08054
			if (slen < 0) {
b08054
				close(deps);
b08054
				return SLBT_BUFFER_ERROR(dctx);
b08054
			}
b08054
b08054
			mark = strrchr(mark,'.');
b08054
			strcpy(mark,dctx->cctx->settings.dsosuffix);
b08054
198205
			fardep  = 0;
b08054
			fdyndep = !fstatat(fdcwd,depfile,&st,0);
b08054
198205
			if (fdyndep && farchive) {
198205
				mark = strrchr(mark,'.');
198205
				strcpy(mark,dctx->cctx->settings.arsuffix);
198205
198205
				if (fstatat(fdcwd,depfile,&st,0) < 0) {
198205
					strcpy(mark,dctx->cctx->settings.dsosuffix);
198205
				} else {
198205
					fdyndep = 0;
198205
				}
198205
			}
198205
b08054
			/* [-L... as needed] */
b08054
			if (fdyndep && (ectx->ldirdepth >= 0)) {
b08054
				if (slbt_dprintf(deps,"-L") < 0) {
b08054
					close(deps);
b08054
					return SLBT_SYSTEM_ERROR(dctx,0);
b08054
				}
b08054
b08054
				for (ldepth=ectx->ldirdepth; ldepth; ldepth--) {
b08054
					if (slbt_dprintf(deps,"../") < 0) {
b08054
						close(deps);
b08054
						return SLBT_SYSTEM_ERROR(dctx,0);
b08054
					}
b08054
				}
b08054
b08054
				if (slbt_dprintf(deps,"%s%s.libs\n",
b08054
						 (is_reladir ? reladir : ""),
b08054
						 (is_reladir ? "/" : "")) < 0) {
b08054
					close(deps);
b08054
					return SLBT_SYSTEM_ERROR(dctx,0);
b08054
				}
b08054
			}
b08054
b08054
			/* -ldeplib */
b08054
			if (fdyndep) {
b08054
				*popt = 0;
b08054
				mark  = base;
b08054
				mark += strlen(dctx->cctx->settings.dsoprefix);
b08054
b08054
				if (slbt_dprintf(deps,"-l%s\n",mark) < 0) {
b08054
					close(deps);
b08054
					return SLBT_SYSTEM_ERROR(dctx,0);
b08054
				}
b08054
b08054
				*popt = '.';
198205
			} else {
198205
				strcpy(depfile,*parg);
198205
198205
				slbt_adjust_wrapper_argument(
198205
					depfile,true,
198205
					dctx->cctx->settings.arsuffix);
198205
198205
198205
				fardep  = farchive;
198205
				fardep |= !slbt_archive_is_convenience_library(fdcwd,depfile);
198205
			}
198205
198205
			if (fardep) {
198205
				if (slbt_dprintf(deps,"::") < 0) {
198205
					close(deps);
198205
					return SLBT_SYSTEM_ERROR(dctx,0);
198205
				}
198205
198205
				for (ldepth=ectx->ldirdepth; ldepth; ldepth--) {
198205
					if (slbt_dprintf(deps,"../") < 0) {
198205
						close(deps);
198205
						return SLBT_SYSTEM_ERROR(dctx,0);
198205
					}
198205
				}
198205
198205
198205
				if (ectx->ldirdepth >= 0) {
198205
					if (slbt_dprintf(deps,"%s\n",depfile) < 0) {
198205
						close(deps);
198205
						return SLBT_SYSTEM_ERROR(dctx,0);
198205
					}
198205
				} else {
198205
					if (slbt_dprintf(deps,"::./%s\n",depfile) < 0) {
198205
						close(deps);
198205
						return SLBT_SYSTEM_ERROR(dctx,0);
198205
					}
198205
				}
b08054
			}
b08054
b08054
			/* [open dependency list] */
b08054
			strcpy(depfile,*parg);
b08054
			mark = depfile + (base - *parg);
b08054
			size = sizeof(depfile) - (base - *parg);
b08054
			slen = slbt_snprintf(mark,size,".libs/%s",base);
b08054
b08054
			if (slen < 0) {
b08054
				close(deps);
b08054
				return SLBT_BUFFER_ERROR(dctx);
b08054
			}
b08054
b08054
			mapinfo = 0;
b08054
b08054
			mark = strrchr(mark,'.');
b08054
			size = sizeof(depfile) - (mark - depfile);
b08054
198205
			if (!fardep) {
b08054
				slen = slbt_snprintf(mark,size,
b08054
					"%s.slibtool.deps",
b08054
					dctx->cctx->settings.dsosuffix);
b08054
b08054
				if (slen < 0) {
b08054
					close(deps);
b08054
					return SLBT_BUFFER_ERROR(dctx);
b08054
				}
b08054
b08054
				mapinfo = slbt_map_file(
b08054
					fdcwd,depfile,
b08054
					SLBT_MAP_INPUT);
b08054
b08054
				if (!mapinfo && (errno != ENOENT)) {
b08054
					close(deps);
b08054
					return SLBT_SYSTEM_ERROR(dctx,0);
b08054
				}
b08054
			}
b08054
b08054
			if (!mapinfo) {
b08054
				slen = slbt_snprintf(mark,size,
b08054
					".a.slibtool.deps");
b08054
b08054
				if (slen < 0) {
b08054
					close(deps);
b08054
					return SLBT_BUFFER_ERROR(dctx);
b08054
				}
b08054
b08054
				mapinfo = slbt_map_file(
b08054
					fdcwd,depfile,
b08054
					SLBT_MAP_INPUT);
b08054
b08054
				if (!mapinfo) {
b08054
					strcpy(mark,".a.disabled");
b08054
b08054
					if (fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) {
b08054
						close(deps);
b08054
						return SLBT_SYSTEM_ERROR(dctx,depfile);
b08054
					}
b08054
				}
b08054
			}
b08054
b08054
			/* [-l... as needed] */
b08054
			while (mapinfo && (mapinfo->mark < mapinfo->cap)) {
b08054
				ret = slbt_mapped_readline(
b08054
					dctx,mapinfo,
b08054
					deplib,sizeof(deplib));
b08054
b08054
				if (ret) {
b08054
					close(deps);
b08054
					return SLBT_NESTED_ERROR(dctx);
b08054
				}
b08054
198205
				if ((deplib[0] == '-') && (deplib[1] == 'L') && (deplib[2] != '/')) {
198205
					ret = slbt_dprintf(
62a007
						deps,"-L%s%s/%s",
198205
						deppref,reladir,&deplib[2]);
198205
198205
				} else if ((deplib[0] == ':') && (deplib[1] == ':') && (deplib[2] != '/')) {
198205
					ret = slbt_dprintf(
198205
						deps,"::%s%s/%s",
198205
						deppref,reladir,&deplib[2]);
198205
198205
				} else {
198205
					ret = slbt_dprintf(
b08054
						deps,"%s",
b08054
						deplib);
198205
				}
b08054
b08054
				if (ret < 0) {
b08054
					close(deps);
b08054
					return SLBT_SYSTEM_ERROR(dctx,0);
b08054
				}
b08054
			}
b08054
b08054
			if (mapinfo)
b08054
				slbt_unmap_file(mapinfo);
b08054
		}
b08054
b08054
		if (plib && (slbt_dprintf(deps,"-l%s\n",plib) < 0)) {
b08054
			close(deps);
b08054
			return SLBT_SYSTEM_ERROR(dctx,0);
b08054
		}
b08054
b08054
		if (path && (slbt_dprintf(deps,"-L%s\n",path) < 0)) {
b08054
			close(deps);
b08054
			return SLBT_SYSTEM_ERROR(dctx,0);
b08054
		}
b08054
	}
b08054
43ee04
	if ((fdtmp = slbt_exec_link_normalize_dep_file(dctx,deps,&pathbuf)) < 0)
43ee04
		return SLBT_NESTED_ERROR(dctx);
43ee04
43ee04
	close(deps);
43ee04
43ee04
	if ((deps = slbt_exec_link_compact_dep_file(dctx,fdtmp,&pathbuf)) < 0)
43ee04
		return SLBT_NESTED_ERROR(dctx);
43ee04
43ee04
	close(deps);
43ee04
	close(fdtmp);
43ee04
b08054
	return 0;
b08054
}