diff options
Diffstat (limited to 'src/internal/slibtool_lconf_impl.c')
-rw-r--r-- | src/internal/slibtool_lconf_impl.c | 374 |
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; } |