summaryrefslogtreecommitdiff
path: root/src/internal/slibtool_lconf_impl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/slibtool_lconf_impl.c')
-rw-r--r--src/internal/slibtool_lconf_impl.c374
1 files changed, 275 insertions, 99 deletions
diff --git a/src/internal/slibtool_lconf_impl.c b/src/internal/slibtool_lconf_impl.c
index fee39e5..ffe92b0 100644
--- a/src/internal/slibtool_lconf_impl.c
+++ b/src/internal/slibtool_lconf_impl.c
@@ -1,10 +1,10 @@
-
/*******************************************************************/
-/* slibtool: a skinny libtool implementation, written in C */
-/* Copyright (C) 2016--2021 SysDeer Technologies, LLC */
+/* slibtool: a strong libtool implementation, written in C */
+/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
/*******************************************************************/
+#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
@@ -18,6 +18,8 @@
#include "slibtool_errinfo_impl.h"
#include "slibtool_symlink_impl.h"
#include "slibtool_readlink_impl.h"
+#include "slibtool_realpath_impl.h"
+#include "slibtool_visibility_impl.h"
enum slbt_lconf_opt {
SLBT_LCONF_OPT_UNKNOWN,
@@ -364,13 +366,21 @@ static int slbt_lconf_trace_result_silent(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
(void)dctx;
(void)fd;
(void)fdat;
(void)lconf;
- return err ? (-1) : fd;
+
+ if (err)
+ return -1;
+
+ if (slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)) <0)
+ return -1;
+
+ return fd;
}
static int slbt_lconf_trace_result_plain(
@@ -378,16 +388,16 @@ static int slbt_lconf_trace_result_plain(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
int fderr;
const char * cpath;
- char path[PATH_MAX];
fderr = slbt_driver_fderr(dctx);
- cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
- ? path : lconf;
+ cpath = !(slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)))
+ ? *pathbuf : lconf;
switch (err) {
case 0:
@@ -426,16 +436,16 @@ static int slbt_lconf_trace_result_annotated(
int fd,
int fdat,
const char * lconf,
- int err)
+ int err,
+ char (*pathbuf)[PATH_MAX])
{
int fderr;
const char * cpath;
- char path[PATH_MAX];
fderr = slbt_driver_fderr(dctx);
- cpath = !(slbt_realpath(fdat,lconf,0,path,sizeof(path)))
- ? path : lconf;
+ cpath = !(slbt_realpath(fdat,lconf,0,*pathbuf,sizeof(*pathbuf)))
+ ? *pathbuf : lconf;
switch (err) {
case 0:
@@ -504,7 +514,9 @@ static int slbt_lconf_trace_result_annotated(
static int slbt_lconf_open(
struct slbt_driver_ctx * dctx,
- const char * lconf)
+ const char * lconf,
+ bool fsilent,
+ char (*lconfpath)[PATH_MAX])
{
int fderr;
int fdcwd;
@@ -514,6 +526,7 @@ static int slbt_lconf_open(
struct stat stcwd;
struct stat stparent;
ino_t stinode;
+ const char * mconf;
int (*trace_lconf)(struct slbt_driver_ctx *,
const char *);
@@ -525,14 +538,22 @@ static int slbt_lconf_open(
int,const char *,int,int);
int (*trace_result)(struct slbt_driver_ctx *,
- int,int,const char *,int);
+ int,int,const char *,int,
+ char (*)[PATH_MAX]);
- lconf = lconf ? lconf : "libtool";
fderr = slbt_driver_fderr(dctx);
fdcwd = slbt_driver_fdcwd(dctx);
fdlconfdir = fdcwd;
+ fsilent |= (dctx->cctx->drvflags & SLBT_DRIVER_SILENT);
- if (dctx->cctx->drvflags & SLBT_DRIVER_SILENT) {
+ if (lconf) {
+ mconf = 0;
+ } else {
+ mconf = "slibtool.cfg";
+ lconf = "libtool";
+ }
+
+ if (fsilent) {
trace_lconf = 0;
trace_fstat = slbt_lconf_trace_fstat_silent;
trace_openat = slbt_lconf_trace_openat_silent;
@@ -563,21 +584,35 @@ static int slbt_lconf_open(
trace_result = slbt_lconf_trace_result_plain;
}
- if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
- trace_lconf(dctx,lconf);
+ if (!(dctx->cctx->drvflags & SLBT_DRIVER_DEBUG)) {
+ trace_fstat = slbt_lconf_trace_fstat_silent;
+ trace_openat = slbt_lconf_trace_openat_silent;
+ }
+
+ if (!fsilent) {
+ if (!mconf)
+ trace_lconf(dctx,lconf);
+
slbt_output_fdcwd(dctx);
}
if (lconf && strchr(lconf,'/'))
return ((fdlconf = trace_openat(dctx,fdcwd,lconf,O_RDONLY,0)) < 0)
? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_LCONF_OPEN)
- : trace_result(dctx,fdlconf,fdcwd,lconf,0);
+ : trace_result(dctx,fdlconf,fdcwd,lconf,0,lconfpath);
if (trace_fstat(dctx,fdlconfdir,".",&stcwd) < 0)
return SLBT_SYSTEM_ERROR(dctx,0);
stinode = stcwd.st_ino;
- fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
+ fdlconf = -1;
+
+ if (mconf)
+ if ((fdlconf = trace_openat(dctx,fdlconfdir,mconf,O_RDONLY,0)) >= 0)
+ lconf = mconf;
+
+ if (fdlconf < 0)
+ fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
while (fdlconf < 0) {
fdparent = trace_openat(dctx,fdlconfdir,"../",O_DIRECTORY,0);
@@ -592,52 +627,153 @@ static int slbt_lconf_open(
}
if (stparent.st_dev != stcwd.st_dev) {
- trace_result(dctx,fdparent,fdparent,".",EXDEV);
+ trace_result(dctx,fdparent,fdparent,".",EXDEV,lconfpath);
close(fdparent);
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_OPEN);
}
if (stparent.st_ino == stinode) {
- trace_result(dctx,fdparent,fdparent,".",ELOOP);
+ trace_result(dctx,fdparent,fdparent,".",ELOOP,lconfpath);
close(fdparent);
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_OPEN);
}
fdlconfdir = fdparent;
- fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
stinode = stparent.st_ino;
+
+ if (mconf)
+ if ((fdlconf = trace_openat(dctx,fdlconfdir,mconf,O_RDONLY,0)) >= 0)
+ lconf = mconf;
+
+ if (fdlconf < 0)
+ fdlconf = trace_openat(dctx,fdlconfdir,lconf,O_RDONLY,0);
}
- trace_result(dctx,fdlconf,fdlconfdir,lconf,0);
+ trace_result(dctx,fdlconf,fdlconfdir,lconf,0,lconfpath);
slbt_lconf_close(fdcwd,fdlconfdir);
return fdlconf;
}
-int slbt_get_lconf_flags(
+static int slbt_get_lconf_var(
+ const struct slbt_txtfile_ctx * tctx,
+ const char * var,
+ const char space,
+ char (*val)[PATH_MAX])
+{
+ const char ** pline;
+ const char * mark;
+ const char * match;
+ const char * cap;
+ ssize_t len;
+ int cint;
+
+ /* init */
+ match = 0;
+ pline = tctx->txtlinev;
+ len = strlen(var);
+
+ /* search for ^var= */
+ for (; *pline && !match; ) {
+ if (!strncmp(*pline,var,len)) {
+ match = *pline;
+ } else {
+ pline++;
+ }
+ }
+
+ /* not found? */
+ if (!match) {
+ (*val)[0] = '\0';
+ return 0;
+ }
+
+ /* support a single pair of double quotes */
+ match = &match[len];
+ mark = match;
+
+ if (match[0] == '"') {
+ match++;
+ mark++;
+
+ for (; *mark && (*mark != '"'); )
+ mark++;
+
+ /* unpaired quote? */
+ if (*mark != '"')
+ return -1;
+ } else {
+ for (; *mark && !isspace((cint=*mark)); )
+ mark++;
+ }
+
+ cap = mark;
+
+ /* validate */
+ for (mark=match; mark<cap; mark++) {
+ if ((*mark >= 'a') && (*mark <= 'z'))
+ (void)0;
+
+ else if ((*mark >= 'A') && (*mark <= 'Z'))
+ (void)0;
+
+ else if ((*mark >= '0') && (*mark <= '9'))
+ (void)0;
+
+ else if ((*mark == '+') || (*mark == '-'))
+ (void)0;
+
+ else if ((*mark == '/') || (*mark == '@'))
+ (void)0;
+
+ else if ((*mark == '.') || (*mark == '_'))
+ (void)0;
+
+ else if ((*mark == ':') || (*mark == space))
+ (void)0;
+
+ else
+ return -1;
+ }
+
+ /* all done */
+ memcpy(*val,match,cap-match);
+ (*val)[cap-match] = '\0';
+
+ return 0;
+}
+
+slbt_hidden int slbt_get_lconf_flags(
struct slbt_driver_ctx * dctx,
const char * lconf,
- uint64_t * flags)
+ uint64_t * flags,
+ bool fsilent)
{
+ struct slbt_driver_ctx_impl * ctx;
+ struct slbt_txtfile_ctx * confctx;
int fdlconf;
struct stat st;
void * addr;
- const char * mark;
- const char * cap;
uint64_t optshared;
uint64_t optstatic;
- int optsharedlen;
- int optstaticlen;
- const char * optsharedstr;
- const char * optstaticstr;
+ char val[PATH_MAX];
+
+ /* driver context (ar, ranlib, cc) */
+ ctx = slbt_get_driver_ictx(dctx);
/* open relative libtool script */
- if ((fdlconf = slbt_lconf_open(dctx,lconf)) < 0)
+ if ((fdlconf = slbt_lconf_open(dctx,lconf,fsilent,&val)) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
+ /* cache the configuration in library friendly form) */
+ if (slbt_lib_get_txtfile_ctx(dctx,val,&ctx->lconfctx) < 0)
return SLBT_NESTED_ERROR(dctx);
+ confctx = ctx->lconfctx;
+
/* map relative libtool script */
if (fstat(fdlconf,&st) < 0)
return SLBT_SYSTEM_ERROR(dctx,0);
@@ -653,78 +789,34 @@ int slbt_get_lconf_flags(
return SLBT_CUSTOM_ERROR(
dctx,SLBT_ERR_LCONF_MAP);
- mark = addr;
- cap = &mark[st.st_size];
-
/* scan */
optshared = 0;
optstatic = 0;
- optsharedstr = "build_libtool_libs=";
- optstaticstr = "build_old_libs=";
-
- optsharedlen = strlen(optsharedstr);
- optstaticlen = strlen(optstaticstr);
-
- for (; mark && mark<cap; ) {
- if (!optshared && (cap - mark < optsharedlen)) {
- mark = 0;
-
- } else if (!optstatic && (cap - mark < optstaticlen)) {
- mark = 0;
-
- } else if (!optshared && !strncmp(mark,optsharedstr,optsharedlen)) {
- mark += optsharedlen;
-
- if ((cap - mark >= 3)
- && (mark[0]=='n')
- && (mark[1]=='o')
- && (mark[2]=='\n')
- && (mark = &mark[3]))
- optshared = SLBT_DRIVER_DISABLE_SHARED;
-
- else if ((cap - mark >= 4)
- && (mark[0]=='y')
- && (mark[1]=='e')
- && (mark[2]=='s')
- && (mark[3]=='\n')
- && (mark = &mark[4]))
- optshared = SLBT_DRIVER_SHARED;
-
- if (!optshared)
- mark--;
-
- } else if (!optstatic && !strncmp(mark,optstaticstr,optstaticlen)) {
- mark += optstaticlen;
-
- if ((cap - mark >= 3)
- && (mark[0]=='n')
- && (mark[1]=='o')
- && (mark[2]=='\n')
- && (mark = &mark[3]))
- optstatic = SLBT_DRIVER_DISABLE_STATIC;
-
- else if ((cap - mark >= 4)
- && (mark[0]=='y')
- && (mark[1]=='e')
- && (mark[2]=='s')
- && (mark[3]=='\n')
- && (mark = &mark[4]))
- optstatic = SLBT_DRIVER_STATIC;
-
- if (!optstatic)
- mark--;
- } else {
- for (; (mark<cap) && (*mark!='\n'); )
- mark++;
- mark++;
- }
+ /* shared libraries option */
+ if (slbt_get_lconf_var(confctx,"build_libtool_libs=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
- if (optshared && optstatic)
- mark = 0;
+ if (!strcmp(val,"yes")) {
+ optshared = SLBT_DRIVER_SHARED;
+
+ } else if (!strcmp(val,"no")) {
+ optshared = SLBT_DRIVER_DISABLE_SHARED;
}
- munmap(addr,st.st_size);
+
+ /* static libraries option */
+ if (slbt_get_lconf_var(confctx,"build_old_libs=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (!strcmp(val,"yes")) {
+ optstatic = SLBT_DRIVER_STATIC;
+
+ } else if (!strcmp(val,"no")) {
+ optstatic = SLBT_DRIVER_DISABLE_STATIC;
+ }
if (!optshared || !optstatic)
return SLBT_CUSTOM_ERROR(
@@ -732,5 +824,89 @@ int slbt_get_lconf_flags(
*flags = optshared | optstatic;
+
+ /* host */
+ if (!ctx->cctx.host.host) {
+ if (slbt_get_lconf_var(confctx,"host=",0,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.host = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.host = ctx->host.host;
+ }
+
+
+ /* ar tool */
+ if (!ctx->cctx.host.ar) {
+ if (slbt_get_lconf_var(confctx,"AR=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.ar = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ar = ctx->host.ar;
+ }
+
+
+ /* nm tool */
+ if (!ctx->cctx.host.nm) {
+ if (slbt_get_lconf_var(confctx,"NM=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.nm = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.nm = ctx->host.nm;
+ }
+
+
+ /* ranlib tool */
+ if (!ctx->cctx.host.ranlib) {
+ if (slbt_get_lconf_var(confctx,"RANLIB=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.ranlib = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.ranlib = ctx->host.ranlib;
+ }
+
+
+ /* as tool (optional) */
+ if (!ctx->cctx.host.as) {
+ if (slbt_get_lconf_var(confctx,"AS=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.as = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+
+ ctx->cctx.host.as = ctx->host.as;
+ }
+
+
+ /* dlltool tool (optional) */
+ if (!ctx->cctx.host.dlltool) {
+ if (slbt_get_lconf_var(confctx,"DLLTOOL=",0x20,&val) < 0)
+ return SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_PARSE);
+
+ if (val[0] && !(ctx->host.dlltool = strdup(val)))
+ return SLBT_SYSTEM_ERROR(dctx,0);
+
+ ctx->cctx.host.dlltool = ctx->host.dlltool;
+ }
+
+
+ /* all done */
+ ctx->lconf.addr = addr;
+ ctx->lconf.size = st.st_size;
+
return 0;
}