diff options
Diffstat (limited to 'src/internal')
38 files changed, 1964 insertions, 229 deletions
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h index 20568e9..d17865b 100644 --- a/src/internal/argv/argv.h +++ b/src/internal/argv/argv.h @@ -1,6 +1,6 @@ /****************************************************************************/ /* argv.h: a thread-safe argument vector parser and usage screen generator */ -/* Copyright (C) 2015--2021 Z. Gilboa */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /****************************************************************************/ @@ -83,6 +83,7 @@ enum argv_error { ARGV_ERROR_INTERNAL, ARGV_ERROR_SHORT_OPTION, ARGV_ERROR_LONG_OPTION, + ARGV_ERROR_VENDOR_OPTION, ARGV_ERROR_OPTARG_NONE, ARGV_ERROR_OPTARG_REQUIRED, ARGV_ERROR_OPTARG_PARADIGM, @@ -398,7 +399,11 @@ static void argv_scan( fval = ch; } } else { - ferr = ARGV_ERROR_SHORT_OPTION; + if ((ch == &parg[0][1]) && (ch[0] == 'W') && ch[1]) { + ferr = ARGV_ERROR_VENDOR_OPTION; + } else { + ferr = ARGV_ERROR_SHORT_OPTION; + } } } else if (!fnoscan && (fhybrid || is_long_option(ch))) { @@ -413,49 +418,72 @@ static void argv_scan( ch = *parg; } - if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH)) + /* now verify the proper setting of option values */ + if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH)) { ferr = ARGV_ERROR_HYBRID_NONE; - else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY)) + + } else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY)) { ferr = ARGV_ERROR_HYBRID_ONLY; - else if (option->optarg == ARGV_OPTARG_NONE) { + + } else if (option->optarg == ARGV_OPTARG_NONE) { if (val[0]) { ferr = ARGV_ERROR_OPTARG_NONE; ctx->errch = val + 1; - } else + } else { fval = false; + } + } else if (val[0] && (option->flags & ARGV_OPTION_HYBRID_JOINED)) { fval = true; ch = val; - } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE)) - ferr = ARGV_ERROR_HYBRID_SPACE; - else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL)) + + } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE)) { + if (option->optarg == ARGV_OPTARG_OPTIONAL) { + fval = false; + + } else { + ferr = ARGV_ERROR_HYBRID_SPACE; + } + + } else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL)) { ferr = ARGV_ERROR_HYBRID_EQUAL; - else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA)) + + } else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA)) { ferr = ARGV_ERROR_HYBRID_COMMA; - else if (!fhybrid && (val[0]==',')) + + } else if (!fhybrid && (val[0]==',')) { ferr = ARGV_ERROR_HYBRID_COMMA; - else if (val[0] && !val[1]) + + } else if (val[0] && !val[1]) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (val[0] && val[1]) { + + } else if (val[0] && val[1]) { fval = true; ch = ++val; + } else if (option->optarg == ARGV_OPTARG_REQUIRED) { - if (!val[0] && !*parg) + if (!val[0] && !*parg) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_short_option(*parg)) + + } else if (*parg && is_short_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_long_option(*parg)) + + } else if (*parg && is_long_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_last_option(*parg)) + + } else if (*parg && is_last_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else + + } else { fval = true; + } } else { /* ARGV_OPTARG_OPTIONAL */ fval = val[0]; } - } else + } else { ferr = ARGV_ERROR_LONG_OPTION; + } } if (ferr == ARGV_ERROR_OK) @@ -531,7 +559,11 @@ static const char * argv_program_name(const char * program_path) static void argv_show_error(int fd, struct argv_ctx * ctx) { - char opt_short_name[2] = {0,0}; + const char * src; + char * dst; + char * cap; + char opt_vendor_buf[256]; + char opt_short_name[2] = {0,0}; if (ctx->erropt && ctx->erropt->short_name) opt_short_name[0] = ctx->erropt->short_name; @@ -547,6 +579,27 @@ static void argv_show_error(int fd, struct argv_ctx * ctx) argv_dprintf(fd,"'--%s' is not a valid long option\n",ctx->errch); break; + case ARGV_ERROR_VENDOR_OPTION: + src = ctx->errch; + dst = opt_vendor_buf; + cap = &opt_vendor_buf[sizeof(opt_vendor_buf)]; + + for (; src && *src && dst<cap; ) { + if ((*src == '=') || (*src == ',') || (*src == ':')) { + src = 0; + } else { + *dst++ = *src++; + } + } + + if (dst == cap) + dst--; + + *dst = '\0'; + + argv_dprintf(fd,"'-%s' is not a valid vendor option\n",opt_vendor_buf); + break; + case ARGV_ERROR_OPTARG_NONE: argv_dprintf(fd,"'%s' is not a valid option value for [%s%s%s%s%s] " "(option values may not be specified)\n", @@ -563,7 +616,9 @@ static void argv_show_error(int fd, struct argv_ctx * ctx) opt_short_name[0] ? "-" : "", opt_short_name, opt_short_name[0] ? "," : "", - ctx->erropt->long_name ? "--" : "", + ctx->erropt->long_name + ? (ctx->erropt->flags & ARGV_OPTION_HYBRID_ONLY) ? "-" : "--" + : "", ctx->erropt->long_name, ctx->erropt->paradigm ? "one of the following values:" : "a value", ctx->erropt->paradigm ? "{" : "", diff --git a/src/internal/slibtool_ar_impl.h b/src/internal/slibtool_ar_impl.h new file mode 100644 index 0000000..57ff1cc --- /dev/null +++ b/src/internal/slibtool_ar_impl.h @@ -0,0 +1,100 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#ifndef SLIBTOOL_AR_IMPL_H +#define SLIBTOOL_AR_IMPL_H + +#include "argv/argv.h" +#include <slibtool/slibtool.h> +#include <slibtool/slibtool_arbits.h> + +/* decimal values in archive header are right padded with ascii spaces */ +#define AR_DEC_PADDING (0x20) + +/* archive file members are right padded as needed with ascii newline */ +#define AR_OBJ_PADDING (0x0A) + +/* initial number of elements in the transient, on-stack vector */ +# define AR_STACK_VECTOR_ELEMENTS (0x200) + +extern const struct argv_option slbt_ar_options[]; + +struct ar_armaps_impl { + struct ar_meta_armap_ref_32 * armap_symrefs_32; + struct ar_meta_armap_ref_64 * armap_symrefs_64; + struct ar_raw_armap_bsd_32 armap_bsd_32; + struct ar_raw_armap_bsd_64 armap_bsd_64; + struct ar_raw_armap_sysv_32 armap_sysv_32; + struct ar_raw_armap_sysv_64 armap_sysv_64; + struct ar_meta_armap_common_32 armap_common_32; + struct ar_meta_armap_common_64 armap_common_64; + uint64_t armap_nsyms; +}; + +struct slbt_archive_meta_impl { + const struct slbt_driver_ctx * dctx; + struct slbt_archive_ctx * actx; + size_t ofmtattr; + size_t nentries; + void * hdrinfov; + char * namestrs; + const char * symstrs; + const char ** symstrv; + const char ** mapstrv; + off_t * offsetv; + struct ar_meta_symbol_info * syminfo; + struct ar_meta_symbol_info ** syminfv; + struct ar_meta_member_info ** memberv; + struct ar_meta_member_info * members; + struct ar_armaps_impl armaps; + struct slbt_txtfile_ctx * nminfo; + struct slbt_archive_meta armeta; +}; + +struct ar_meta_member_info * slbt_archive_member_from_offset( + struct slbt_archive_meta_impl * meta, + off_t offset); + +int slbt_ar_parse_primary_armap_bsd_32( + const struct slbt_driver_ctx * dctx, + struct slbt_archive_meta_impl * m); + +int slbt_ar_parse_primary_armap_bsd_64( + const struct slbt_driver_ctx * dctx, + struct slbt_archive_meta_impl * m); + +int slbt_ar_parse_primary_armap_sysv_32( + const struct slbt_driver_ctx * dctx, + struct slbt_archive_meta_impl * m); + +int slbt_ar_parse_primary_armap_sysv_64( + const struct slbt_driver_ctx * dctx, + struct slbt_archive_meta_impl * m); + +int slbt_update_mapstrv( + const struct slbt_driver_ctx * dctx, + struct slbt_archive_meta_impl * m); + +int slbt_ar_update_syminfo( + struct slbt_archive_ctx * actx); + +int slbt_ar_update_syminfo_ex( + struct slbt_archive_ctx * actx, + int fdout); + +static inline struct slbt_archive_meta_impl * slbt_archive_meta_ictx(const struct slbt_archive_meta * meta) +{ + uintptr_t addr; + + if (meta) { + addr = (uintptr_t)meta - offsetof(struct slbt_archive_meta_impl,armeta); + return (struct slbt_archive_meta_impl *)addr; + } + + return 0; +} + +#endif diff --git a/src/internal/slibtool_coff_impl.c b/src/internal/slibtool_coff_impl.c new file mode 100644 index 0000000..ac6a2fd --- /dev/null +++ b/src/internal/slibtool_coff_impl.c @@ -0,0 +1,46 @@ +/*******************************************************************/ +/* 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 <string.h> +#include "slibtool_visibility_impl.h" + +slbt_hidden int slbt_coff_qsort_strcmp(const void * a, const void * b) +{ + const char * dot; + const char * mark; + const char * stra; + const char * strb; + const char ** pstra; + const char ** pstrb; + char strbufa[4096]; + char strbufb[4096]; + + pstra = (const char **)a; + pstrb = (const char **)b; + + stra = *pstra; + strb = *pstrb; + + if (!strncmp(*pstra,".weak.",6)) { + stra = strbufa; + mark = &(*pstra)[6]; + dot = strchr(mark,'.'); + + strncpy(strbufa,mark,dot-mark); + strbufa[dot-mark] = '\0'; + } + + if (!strncmp(*pstrb,".weak.",6)) { + strb = strbufb; + mark = &(*pstrb)[6]; + dot = strchr(mark,'.'); + + strncpy(strbufb,mark,dot-mark); + strbufb[dot-mark] = '\0'; + } + + return strcmp(stra,strb); +} diff --git a/src/internal/slibtool_coff_impl.h b/src/internal/slibtool_coff_impl.h new file mode 100644 index 0000000..b08c858 --- /dev/null +++ b/src/internal/slibtool_coff_impl.h @@ -0,0 +1,6 @@ +#ifndef SLIBTOOL_COFF_IMPL_H +#define SLIBTOOL_COFF_IMPL_H + +int slbt_coff_qsort_strcmp(const void * a, const void * b); + +#endif diff --git a/src/internal/slibtool_dprintf_impl.c b/src/internal/slibtool_dprintf_impl.c index 434c96d..58c7eed 100644 --- a/src/internal/slibtool_dprintf_impl.c +++ b/src/internal/slibtool_dprintf_impl.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -11,8 +11,9 @@ #include <errno.h> #include "slibtool_dprintf_impl.h" +#include "slibtool_visibility_impl.h" -int slbt_dprintf(int fd, const char * fmt, ...) +slbt_hidden int slbt_dprintf(int fd, const char * fmt, ...) { int ret; int cnt; diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index 270e9d6..429cdc4 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -9,13 +9,16 @@ #include <stdint.h> #include <stdio.h> +#include <sys/stat.h> #include <sys/types.h> #include <slibtool/slibtool.h> #include "slibtool_dprintf_impl.h" +#include "slibtool_mapfile_impl.h" +#include "slibtool_visibility_impl.h" #include "argv/argv.h" -#define SLBT_OPTV_ELEMENTS 64 +#define SLBT_OPTV_ELEMENTS 128 extern const struct argv_option slbt_default_options[]; @@ -23,8 +26,12 @@ enum app_tags { TAG_HELP, TAG_HELP_ALL, TAG_VERSION, + TAG_INFO, TAG_CONFIG, + TAG_MKVARS, TAG_DUMPMACHINE, + TAG_PRINT_AUX_DIR, + TAG_PRINT_M4_DIR, TAG_DEBUG, TAG_DRY_RUN, TAG_FEATURES, @@ -42,6 +49,8 @@ enum app_tags { TAG_HOST, TAG_FLAVOR, TAG_AR, + TAG_AS, + TAG_NM, TAG_RANLIB, TAG_WINDRES, TAG_DLLTOOL, @@ -54,11 +63,12 @@ enum app_tags { TAG_RPATH, TAG_SYSROOT, TAG_RELEASE, + TAG_OBJECTLIST, TAG_DLOPEN, TAG_DLPREOPEN, TAG_EXPORT_DYNAMIC, - TAG_EXPSYM_FILE, - TAG_EXPSYM_REGEX, + TAG_EXPSYMS_FILE, + TAG_EXPSYMS_REGEX, TAG_VERSION_INFO, TAG_VERSION_NUMBER, TAG_NO_SUPPRESS, @@ -78,6 +88,36 @@ enum app_tags { TAG_COMPILER_FLAG, TAG_VERBATIM_FLAG, TAG_THREAD_SAFE, + TAG_WEAK, + /* ar mode */ + TAG_AR_HELP, + TAG_AR_VERSION, + TAG_AR_CHECK, + TAG_AR_PRINT, + TAG_AR_MAPFILE, + TAG_AR_DLUNIT, + TAG_AR_DLSYMS, + TAG_AR_NOSORT, + TAG_AR_REGEX, + TAG_AR_PRETTY, + TAG_AR_POSIX, + TAG_AR_YAML, + TAG_AR_MERGE, + TAG_AR_OUTPUT, + TAG_AR_VERBOSE, + /* slibtoolize (stoolie) mode */ + TAG_STLE_VERSION, + TAG_STLE_HELP, + TAG_STLE_COPY, + TAG_STLE_FORCE, + TAG_STLE_INSTALL, + TAG_STLE_DEBUG, + TAG_STLE_DRY_RUN, + TAG_STLE_SILENT, + TAG_STLE_VERBOSE, + TAG_STLE_WARNINGS, + TAG_STLE_NO_WARNINGS, + TAG_STLE_LTDL, }; struct slbt_split_vector { @@ -92,43 +132,251 @@ struct slbt_host_strs { char * host; char * flavor; char * ar; + char * as; + char * nm; char * ranlib; char * windres; char * dlltool; char * mdso; + char ** ar_argv; + char ** as_argv; + char ** nm_argv; + char ** ranlib_argv; + char ** windres_argv; + char ** dlltool_argv; + char ** mdso_argv; +}; + +struct slbt_obj_list { + const char * name; + void * addr; + size_t size; + int objc; + char ** objv; }; struct slbt_driver_ctx_impl { - struct slbt_common_ctx cctx; - struct slbt_driver_ctx ctx; - struct slbt_host_strs host; - struct slbt_host_strs ahost; - struct slbt_fd_ctx fdctx; - char * libname; - char * dargs; - char ** dargv; - char ** targv; - char ** cargv; - char ** envp; - struct slbt_error_info**errinfp; - struct slbt_error_info**erricap; - struct slbt_error_info *erriptr[64]; - struct slbt_error_info erribuf[64]; + struct argv_meta * meta; + struct slbt_common_ctx cctx; + struct slbt_driver_ctx ctx; + struct slbt_host_strs host; + struct slbt_host_strs ahost; + struct slbt_fd_ctx fdctx; + struct slbt_map_info lconf; + struct slbt_txtfile_ctx * lconfctx; + struct slbt_txtfile_ctx * mkvarsctx; + struct slbt_obj_list * objlistv; + + struct argv_entry ** dlopenv; + size_t ndlopen; + + const struct slbt_archive_ctx * arctx; + const char * arpath; + + char * libname; + char * dargs; + char ** dargv; + char ** targv; + char ** cargv; + char ** envp; + + struct slbt_error_info** errinfp; + struct slbt_error_info** erricap; + struct slbt_error_info * erriptr[64]; + struct slbt_error_info erribuf[64]; +}; + +struct slbt_driver_ctx_alloc { + struct slbt_driver_ctx_impl ctx; + uint64_t guard; }; struct slbt_exec_ctx_impl { - int argc; - char * args; - char * shadow; - char * dsoprefix; - size_t size; - struct slbt_exec_ctx ctx; - int fdwrapper; - char ** lout[2]; - char ** mout[2]; - char * vbuffer[]; + const struct slbt_driver_ctx * dctx; + struct slbt_symlist_ctx * sctx; + struct slbt_exec_ctx ctx; + struct slbt_archive_ctx ** dlactxv; + struct slbt_archive_ctx * dlpreopen; + char ** dlargv; + int argc; + char * args; + char * shadow; + char * dsoprefix; + size_t size; + size_t exts; + int fdwrapper; + char sbuf[PATH_MAX]; + char ** lout[2]; + char ** mout[2]; + char ** vbuffer; }; +struct slbt_archive_ctx_impl { + const struct slbt_driver_ctx * dctx; + const char * path; + char * pathbuf; + struct slbt_raw_archive map; + struct slbt_archive_meta * meta; + struct slbt_archive_ctx actx; +}; + +struct slbt_symlist_ctx_impl { + const struct slbt_driver_ctx * dctx; + const char * path; + char * pathbuf; + char * symstrs; + const char ** symstrv; + struct slbt_symlist_ctx sctx; +}; + + +struct slbt_txtfile_ctx_impl { + const struct slbt_driver_ctx * dctx; + const char * path; + char * pathbuf; + char * txtlines; + const char ** txtlinev; + struct slbt_txtfile_ctx tctx; +}; + +struct slbt_stoolie_ctx_impl { + const struct slbt_driver_ctx * dctx; + const char * path; + char * pathbuf; + int fdtgt; + int fdaux; + int fdm4; + const char * auxarg; + char * auxbuf; + const char * m4arg; + char * m4buf; + char ** m4argv; + struct slbt_txtfile_ctx * acinc; + struct slbt_txtfile_ctx * cfgac; + struct slbt_txtfile_ctx * makam; + struct slbt_stoolie_ctx zctx; +}; + +const char * slbt_program_name(const char *); + + +int slbt_optv_init( + const struct argv_option[], + const struct argv_option **); + + +uint64_t slbt_argv_flags(uint64_t flags); + + +void slbt_argv_scan( + char ** argv, + const struct argv_option ** optv, + struct argv_ctx * ctx, + struct argv_meta * meta); + + +struct argv_meta * slbt_argv_get( + char **, + const struct argv_option **, + int flags, + int fd); + +void slbt_argv_free(struct argv_meta *); + + +void slbt_argv_usage( + int fd, + const char * header, + const struct argv_option **, + const char * mode); + + +void slbt_argv_usage_plain( + int fd, + const char * header, + const struct argv_option **, + const char * mode); + + +int slbt_driver_usage( + int fdout, + const char * program, + const char * arg, + const struct argv_option ** optv, + struct argv_meta * meta, + struct slbt_split_vector * sargv, + struct slbt_obj_list * objlistv, + int noclr); + + +int slbt_split_argv( + char ** argv, + uint64_t flags, + struct slbt_split_vector * sargv, + struct slbt_obj_list ** aobjlistv, + int fderr, + int fdcwd); + + +int slbt_init_version_info( + struct slbt_driver_ctx_impl * ictx, + struct slbt_version_info * verinfo); + + +int slbt_init_host_params( + const struct slbt_driver_ctx * dctx, + const struct slbt_common_ctx * cctx, + struct slbt_host_strs * drvhost, + struct slbt_host_params * host, + struct slbt_host_params * cfgmeta, + const char * cfgmeta_host, + const char * cfgmeta_ar, + const char * cfgmeta_as, + const char * cfgmeta_nm, + const char * cfgmeta_ranlib, + const char * cfgmeta_dlltool); + + +void slbt_free_host_params(struct slbt_host_strs * host); + + +int slbt_init_link_params(struct slbt_driver_ctx_impl * ctx); + + +void slbt_init_flavor_settings( + struct slbt_common_ctx * cctx, + const struct slbt_host_params * ahost, + struct slbt_flavor_settings * psettings); + + +int slbt_init_ldrpath( + struct slbt_common_ctx * cctx, + struct slbt_host_params * host); + + +void slbt_reset_placeholders (struct slbt_exec_ctx *); + +void slbt_disable_placeholders (struct slbt_exec_ctx *); + +int slbt_impl_get_txtfile_ctx( + const struct slbt_driver_ctx * dctx, + const char * path, + int fdsrc, + struct slbt_txtfile_ctx ** pctx); + + +static inline struct slbt_archive_ctx_impl * slbt_get_archive_ictx(const struct slbt_archive_ctx * actx) +{ + uintptr_t addr; + + if (actx) { + addr = (uintptr_t)actx - offsetof(struct slbt_archive_ctx_impl,actx); + return (struct slbt_archive_ctx_impl *)addr; + } + + return 0; +} + static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct slbt_driver_ctx * dctx) { uintptr_t addr; @@ -141,6 +389,43 @@ static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct sl return 0; } +static inline struct slbt_symlist_ctx_impl * slbt_get_symlist_ictx(const struct slbt_symlist_ctx * sctx) +{ + uintptr_t addr; + + if (sctx) { + addr = (uintptr_t)sctx - offsetof(struct slbt_symlist_ctx_impl,sctx); + return (struct slbt_symlist_ctx_impl *)addr; + } + + return 0; +} + +static inline struct slbt_stoolie_ctx_impl * slbt_get_stoolie_ictx(const struct slbt_stoolie_ctx * stctx) +{ + uintptr_t addr; + + if (stctx) { + addr = (uintptr_t)stctx - offsetof(struct slbt_stoolie_ctx_impl,zctx); + return (struct slbt_stoolie_ctx_impl *)addr; + } + + return 0; +} + +static inline void slbt_driver_set_arctx( + const struct slbt_driver_ctx * dctx, + const struct slbt_archive_ctx * arctx, + const char * arpath) +{ + struct slbt_driver_ctx_impl * ictx; + + + ictx = slbt_get_driver_ictx(dctx); + ictx->arctx = arctx; + ictx->arpath = arpath; +} + static inline char ** slbt_driver_envp(const struct slbt_driver_ctx * dctx) { struct slbt_driver_ctx_impl * ictx; @@ -151,42 +436,42 @@ static inline char ** slbt_driver_envp(const struct slbt_driver_ctx * dctx) static inline int slbt_driver_fdin(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdin; } static inline int slbt_driver_fdout(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdout; } static inline int slbt_driver_fderr(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fderr; } static inline int slbt_driver_fdlog(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdlog; } static inline int slbt_driver_fdcwd(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdcwd; } static inline int slbt_driver_fddst(const struct slbt_driver_ctx * dctx) { struct slbt_fd_ctx fdctx; - slbt_get_driver_fdctx(dctx,&fdctx); + slbt_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fddst; } diff --git a/src/internal/slibtool_errinfo_impl.c b/src/internal/slibtool_errinfo_impl.c index 5b4291b..6501d84 100644 --- a/src/internal/slibtool_errinfo_impl.c +++ b/src/internal/slibtool_errinfo_impl.c @@ -1,14 +1,15 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* 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 <slibtool/slibtool.h> #include "slibtool_driver_impl.h" #include "slibtool_errinfo_impl.h" +#include "slibtool_visibility_impl.h" -int slbt_record_error( +slbt_hidden int slbt_record_error( const struct slbt_driver_ctx * dctx, int esyscode, int elibcode, diff --git a/src/internal/slibtool_errinfo_impl.h b/src/internal/slibtool_errinfo_impl.h index 366e067..fa185c8 100644 --- a/src/internal/slibtool_errinfo_impl.h +++ b/src/internal/slibtool_errinfo_impl.h @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ diff --git a/src/internal/slibtool_lconf_impl.c b/src/internal/slibtool_lconf_impl.c index 2b893bb..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 Z. Gilboa */ +/* 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; } diff --git a/src/internal/slibtool_lconf_impl.h b/src/internal/slibtool_lconf_impl.h index d2bd44c..05c7537 100644 --- a/src/internal/slibtool_lconf_impl.h +++ b/src/internal/slibtool_lconf_impl.h @@ -8,6 +8,7 @@ struct slbt_driver_ctx; int slbt_get_lconf_flags( struct slbt_driver_ctx * dctx, const char * lconf, - uint64_t * flags); + uint64_t * flags, + bool fsilent); #endif diff --git a/src/internal/slibtool_libmeta_impl.c b/src/internal/slibtool_libmeta_impl.c index 58f582f..17e090c 100644 --- a/src/internal/slibtool_libmeta_impl.c +++ b/src/internal/slibtool_libmeta_impl.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -13,14 +13,15 @@ #include "slibtool_dprintf_impl.h" #include "slibtool_errinfo_impl.h" #include "slibtool_metafile_impl.h" +#include "slibtool_visibility_impl.h" static int slbt_create_default_library_wrapper( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, - char * arname, - char * soname, - char * soxyz, - char * solnk) + const char * arname, + const char * soname, + const char * soxyz, + const char * solnk) { int ret; int fdout; @@ -28,6 +29,7 @@ static int slbt_create_default_library_wrapper( const char * base; bool fnover; bool fvernum; + bool fspace; int current; int revision; int age; @@ -54,7 +56,8 @@ static int slbt_create_default_library_wrapper( fnover = !!(dctx->cctx->drvflags & SLBT_DRIVER_AVOID_VERSION); fvernum = !!(dctx->cctx->verinfo.vernumber); - verinfo = slbt_source_version(); + fspace = !!soname[0]; + verinfo = slbt_api_source_version(); /* wrapper header */ header = "libtool compatible library wrapper\n"; @@ -67,7 +70,7 @@ static int slbt_create_default_library_wrapper( "# [commit reference: %s]\n\n" "dlname='%s'\n" - "library_names='%s %s %s'\n" + "library_names='%s%s%s%s%s'\n" "old_library='%s'\n\n" "inherited_linker_flags='%s'\n" @@ -99,7 +102,9 @@ static int slbt_create_default_library_wrapper( /* library_names */ fnover ? solnk : soxyz, + fspace ? " " : "", fnover ? solnk : soname, + fspace ? " " : "", solnk, /* old_library */ @@ -130,16 +135,17 @@ static int slbt_create_default_library_wrapper( static int slbt_create_compatible_library_wrapper( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, - char * arname, - char * soname, - char * soxyz, - char * solnk) + const char * arname, + const char * soname, + const char * soxyz, + const char * solnk) { int ret; int fdout; const char * base; bool fnover; bool fvernum; + bool fspace; int current; int revision; int age; @@ -173,7 +179,8 @@ static int slbt_create_compatible_library_wrapper( fnover = !!(dctx->cctx->drvflags & SLBT_DRIVER_AVOID_VERSION); fvernum = !!(dctx->cctx->verinfo.vernumber); - verinfo = slbt_source_version(); + fspace = !!soname[0]; + verinfo = slbt_api_source_version(); /* wrapper content */ ret = slbt_dprintf(fdout, @@ -188,7 +195,7 @@ static int slbt_create_compatible_library_wrapper( "dlname='%s'\n\n" "# Names of this library.\n" - "library_names='%s %s %s'\n\n" + "library_names='%s%s%s%s%s'\n\n" "# The name of the static archive.\n" "old_library='%s'\n\n" @@ -233,7 +240,9 @@ static int slbt_create_compatible_library_wrapper( /* library_names */ fnover ? solnk : soxyz, + fspace ? " " : "", fnover ? solnk : soname, + fspace ? " " : "", solnk, /* old_library */ @@ -266,14 +275,24 @@ static int slbt_create_compatible_library_wrapper( return (ret < 0) ? SLBT_SYSTEM_ERROR(dctx,0) : 0; } -int slbt_create_library_wrapper( +slbt_hidden int slbt_create_library_wrapper( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, - char * arname, - char * soname, - char * soxyz, - char * solnk) + const char * arname, + const char * soname, + const char * soxyz, + const char * solnk) { + if (!arname) { + arname = ""; + } + + if (!soname) { + soname = ""; + soxyz = ""; + solnk = ""; + } + if (dctx->cctx->drvflags & SLBT_DRIVER_LEGABITS) return slbt_create_compatible_library_wrapper( dctx,ectx,arname,soxyz,soname,solnk); diff --git a/src/internal/slibtool_linkcmd_impl.h b/src/internal/slibtool_linkcmd_impl.h new file mode 100644 index 0000000..e1b384e --- /dev/null +++ b/src/internal/slibtool_linkcmd_impl.h @@ -0,0 +1,89 @@ +#ifndef SLIBTOOL_LINKCMD_IMPL_H +#define SLIBTOOL_LINKCMD_IMPL_H + +struct slbt_deps_meta { + char ** altv; + char * args; + int depscnt; + int infolen; +}; + +int slbt_get_deps_meta( + const struct slbt_driver_ctx * dctx, + char * libfilename, + int fexternal, + struct slbt_deps_meta * depsmeta); + +int slbt_exec_link_create_dep_file( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + char ** altv, + const char * libfilename, + bool farchive); + +bool slbt_adjust_object_argument( + char * arg, + bool fpic, + bool fany, + int fdcwd); + +bool slbt_adjust_wrapper_argument( + char * arg, + bool fpic, + const char * suffix); + +int slbt_adjust_linker_argument( + const struct slbt_driver_ctx * dctx, + char * arg, + char ** xarg, + bool fpic, + const char * dsosuffix, + const char * arsuffix, + struct slbt_deps_meta * depsmeta); + +int slbt_exec_link_adjust_argument_vector( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + struct slbt_deps_meta * depsmeta, + const char * cwd, + bool flibrary); + +int slbt_exec_link_finalize_argument_vector( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx); + +int slbt_exec_link_create_host_tag( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + char * deffilename); + +int slbt_exec_link_create_import_library( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + char * impfilename, + char * deffilename, + char * soname); + +int slbt_exec_link_create_archive( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + const char * arfilename, + bool fpic, + bool fdep); + +int slbt_exec_link_create_library( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + const char * dsobasename, + const char * dsofilename, + const char * relfilename, + bool fardlopen, + bool fpic); + + +int slbt_exec_link_create_executable( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + const char * exefilename); + +#endif diff --git a/src/internal/slibtool_m4fake_impl.c b/src/internal/slibtool_m4fake_impl.c new file mode 100644 index 0000000..3bab8c8 --- /dev/null +++ b/src/internal/slibtool_m4fake_impl.c @@ -0,0 +1,142 @@ +/*******************************************************************/ +/* 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 <string.h> +#include <limits.h> + +#include <slibtool/slibtool.h> +#include "slibtool_driver_impl.h" +#include "slibtool_snprintf_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_visibility_impl.h" +#include "slibtool_m4fake_impl.h" + +slbt_hidden int slbt_m4fake_expand_cmdarg( + const struct slbt_driver_ctx * dctx, + struct slbt_txtfile_ctx * sctx, + const char * cmdname, + char (*argbuf)[PATH_MAX]) +{ + const char ** pline; + size_t slen; + const char * mark; + const char * match; + const char * cap; + int fquote; + char varbuf[PATH_MAX]; + char strbuf[PATH_MAX]; + + memset(*argbuf,0,sizeof(*argbuf)); + + slen = strlen(cmdname); + pline = sctx->txtlinev; + match = 0; + + for (; !match && *pline; ) { + if (!strncmp(*pline,cmdname,slen)) { + if ((*pline)[slen] == '(') { + mark = &(*pline)[slen]; + cap = ++mark; + + for (fquote=0; !match && *cap; ) { + if (*cap == '[') + fquote++; + + else if ((*cap == ']') && fquote) + fquote--; + + else if ((*cap == ')') && !fquote) + match = cap; + + if (!match) + cap++; + } + + if (!match) + return SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_FLOW_ERROR); + } + } + + if (!match) + pline++; + } + + if (!match) + return 0; + + strncpy(strbuf,mark,cap-mark); + strbuf[cap-mark] = '\0'; + + mark = strbuf; + slen = strlen(mark); + + if ((mark[0] == '[') && (mark[--slen] == ']')) { + strcpy(*argbuf,++mark); + (*argbuf)[--slen] = '\0'; + return 0; + } + + if (slbt_snprintf( + varbuf,sizeof(varbuf), + "AC_DEFUN([%s],", + strbuf) < 0) + return SLBT_BUFFER_ERROR(dctx); + + slen = strlen(varbuf); + + for (--pline; pline >= sctx->txtlinev; pline--) { + if (!strncmp(*pline,varbuf,slen)) { + mark = &(*pline)[slen]; + cap = mark; + match = 0; + + for (fquote=0; !match && *cap; ) { + if (*cap == '[') + fquote++; + + else if ((*cap == ']') && fquote) + fquote--; + + else if ((*cap == ')') && !fquote) + match = cap; + + if (!match) + cap++; + } + + if (!match) + return SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_FLOW_ERROR); + + strncpy(strbuf,mark,cap-mark); + strbuf[cap-mark] = '\0'; + + mark = strbuf; + slen = strlen(mark); + + if ((mark[0] == '[') && (mark[--slen] == ']')) { + strcpy(*argbuf,++mark); + (*argbuf)[--slen] = '\0'; + return 0; + } + + if (slbt_snprintf( + varbuf,sizeof(varbuf), + "AC_DEFUN([%s],", + strbuf) < 0) + return SLBT_BUFFER_ERROR(dctx); + + slen = strlen(varbuf); + } + } + + strcpy(*argbuf,strbuf); + + return 0; +} diff --git a/src/internal/slibtool_m4fake_impl.h b/src/internal/slibtool_m4fake_impl.h new file mode 100644 index 0000000..8bb2b5f --- /dev/null +++ b/src/internal/slibtool_m4fake_impl.h @@ -0,0 +1,12 @@ +#ifndef SLIBTOOL_M4FAKE_IMPL_H +#define SLIBTOOL_M4FAKE_IMPL_H + +#include <slibtool/slibtool.h> + +int slbt_m4fake_expand_cmdarg( + const struct slbt_driver_ctx * dctx, + struct slbt_txtfile_ctx * sctx, + const char * cmdname, + char (*argbuf)[PATH_MAX]); + +#endif diff --git a/src/internal/slibtool_mapfile_impl.c b/src/internal/slibtool_mapfile_impl.c index 5df006b..5a4fcff 100644 --- a/src/internal/slibtool_mapfile_impl.c +++ b/src/internal/slibtool_mapfile_impl.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -15,6 +15,7 @@ #include "slibtool_errinfo_impl.h" #include "slibtool_mapfile_impl.h" +#include "slibtool_visibility_impl.h" static void slbt_munmap(void * addr, size_t size) { @@ -23,7 +24,7 @@ static void slbt_munmap(void * addr, size_t size) } } -struct slbt_map_info * slbt_map_file( +slbt_hidden struct slbt_map_info * slbt_map_file( int fdat, const char * path, uint32_t flags) @@ -82,13 +83,13 @@ struct slbt_map_info * slbt_map_file( return mapinfo; } -void slbt_unmap_file(struct slbt_map_info * mapinfo) +slbt_hidden void slbt_unmap_file(struct slbt_map_info * mapinfo) { slbt_munmap(mapinfo->addr,mapinfo->size); free(mapinfo); } -int slbt_mapped_readline( +slbt_hidden int slbt_mapped_readline( const struct slbt_driver_ctx * dctx, struct slbt_map_info * mapinfo, char * buf, diff --git a/src/internal/slibtool_metafile_impl.h b/src/internal/slibtool_metafile_impl.h index bd78b09..b415c05 100644 --- a/src/internal/slibtool_metafile_impl.h +++ b/src/internal/slibtool_metafile_impl.h @@ -10,9 +10,9 @@ int slbt_create_object_wrapper( int slbt_create_library_wrapper( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, - char * arname, - char * soname, - char * soxyz, - char * solnk); + const char * arname, + const char * soname, + const char * soxyz, + const char * solnk); #endif diff --git a/src/internal/slibtool_mkdir_impl.h b/src/internal/slibtool_mkdir_impl.h index 018f5c3..41943f1 100644 --- a/src/internal/slibtool_mkdir_impl.h +++ b/src/internal/slibtool_mkdir_impl.h @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ diff --git a/src/internal/slibtool_mkvars_impl.c b/src/internal/slibtool_mkvars_impl.c new file mode 100644 index 0000000..155036a --- /dev/null +++ b/src/internal/slibtool_mkvars_impl.c @@ -0,0 +1,245 @@ +/*******************************************************************/ +/* 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 <stdio.h> +#include <stdint.h> +#include <stdbool.h> + +#include "slibtool_mkvars_impl.h" +#include "slibtool_driver_impl.h" +#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" + +static int slbt_get_mkvars_var( + const struct slbt_driver_ctx * dctx, + 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; + char * ch; + ssize_t len; + int cint; + + /* init */ + match = 0; + len = strlen(var); + + /* search for ^var= */ + for (pline=tctx->txtlinev; !match && *pline; pline++) { + if (!strncmp(*pline,var,len)) { + if (isspace((*pline)[len]) || ((*pline)[len] == '=')) { + mark = &(*pline)[len]; + + for (; isspace(cint = *mark); ) + mark++; + + if (mark[0] != '=') + return SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_MKVARS_PARSE); + + mark++; + + for (; isspace(cint = *mark); ) + mark++; + + match = mark; + } + } + } + + /* not found? */ + if (!match) { + (*val)[0] = '\0'; + return 0; + } + + /* special case the SLIBTOOL make variable */ + if (!strcmp(var,"SLIBTOOL")) { + mark = match; + ch = *val; + + for (; *mark; ) { + if (isspace(cint = *mark)) { + *ch = '\0'; + return 0; + } + + *ch++ = *mark++; + } + } + + /* validate */ + for (mark=match; *mark; 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 SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_MKVARS_PARSE); + } + + /* all done */ + strcpy(*val,match); + + return 0; +} + +slbt_hidden int slbt_get_mkvars_flags( + struct slbt_driver_ctx * dctx, + const char * mkvars, + uint64_t * flags) +{ + struct slbt_driver_ctx_impl * ctx; + struct slbt_txtfile_ctx * confctx; + char * dash; + uint64_t optshared; + uint64_t optstatic; + char val[PATH_MAX]; + + /* driver context (ar, ranlib, cc) */ + ctx = slbt_get_driver_ictx(dctx); + + /* cache the makefile in library friendly form) */ + if (slbt_lib_get_txtfile_ctx(dctx,mkvars,&ctx->mkvarsctx) < 0) + return SLBT_NESTED_ERROR(dctx); + + confctx = ctx->mkvarsctx; + + /* scan */ + optshared = 0; + optstatic = 0; + + /* slibtool */ + if (slbt_get_mkvars_var(dctx,confctx,"SLIBTOOL",0,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + if ((dash = strrchr(val,'-'))) { + if (!strcmp(dash,"-shared")) { + optshared = SLBT_DRIVER_SHARED; + optstatic = SLBT_DRIVER_DISABLE_STATIC; + + } else if (!strcmp(dash,"-static")) { + optshared = SLBT_DRIVER_DISABLE_SHARED; + optstatic = SLBT_DRIVER_STATIC; + } else { + return SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_MKVARS_PARSE); + } + } else if (!strcmp(val,"false")) { + optshared = SLBT_DRIVER_DISABLE_SHARED; + optstatic = SLBT_DRIVER_DISABLE_STATIC; + } else { + optshared = SLBT_DRIVER_SHARED; + optstatic = SLBT_DRIVER_STATIC; + } + + *flags = optshared | optstatic; + + /* host */ + if (!ctx->cctx.host.host) { + if (slbt_get_mkvars_var(dctx,confctx,"host",0,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + 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_mkvars_var(dctx,confctx,"AR",0x20,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + 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_mkvars_var(dctx,confctx,"NM",0x20,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + 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_mkvars_var(dctx,confctx,"RANLIB",0x20,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + 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_mkvars_var(dctx,confctx,"AS",0x20,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + 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_mkvars_var(dctx,confctx,"DLLTOOL",0x20,&val) < 0) + return SLBT_NESTED_ERROR(dctx); + + if (val[0] && !(ctx->host.dlltool = strdup(val))) + return SLBT_SYSTEM_ERROR(dctx,0); + + ctx->cctx.host.dlltool = ctx->host.dlltool; + } + + + /* all done */ + return 0; +} diff --git a/src/internal/slibtool_mkvars_impl.h b/src/internal/slibtool_mkvars_impl.h new file mode 100644 index 0000000..00ebd99 --- /dev/null +++ b/src/internal/slibtool_mkvars_impl.h @@ -0,0 +1,13 @@ +#ifndef SLIBTOOL_MKVARS_IMPL_H +#define SLIBTOOL_MKVARS_IMPL_H + +#include <stdint.h> + +struct slbt_driver_ctx; + +int slbt_get_mkvars_flags( + struct slbt_driver_ctx * dctx, + const char * mkvars, + uint64_t * flags); + +#endif diff --git a/src/internal/slibtool_objlist_impl.c b/src/internal/slibtool_objlist_impl.c new file mode 100644 index 0000000..9f25529 --- /dev/null +++ b/src/internal/slibtool_objlist_impl.c @@ -0,0 +1,83 @@ +/*******************************************************************/ +/* 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 <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "slibtool_driver_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_mapfile_impl.h" +#include "slibtool_objlist_impl.h" +#include "slibtool_visibility_impl.h" + +slbt_hidden int slbt_objlist_read( + int fdcwd, + struct slbt_obj_list * objlist) +{ + struct slbt_map_info * mapinfo; + int objc; + char ** objv; + char * src; + char * dst; + char * mark; + int skip; + + /* temporarily map the object list */ + if (!(mapinfo = slbt_map_file(fdcwd,objlist->name,SLBT_MAP_INPUT))) + return -1; + + /* object list, cautionary null termination, vector null termination */ + objlist->size = mapinfo->size; + objlist->size++; + objlist->size++; + + if (!(objlist->addr = calloc(1,objlist->size))) { + slbt_unmap_file(mapinfo); + return -1; + } + + /* object list file to normalized object strings */ + objc = 0; + skip = true; + + for (src=mapinfo->addr,dst=objlist->addr; src<mapinfo->cap; src++) { + if (!*src || (*src==' ') || (*src=='\n') || (*src=='\r')) { + if (!skip) + *dst++ = 0; + + skip = true; + } else { + *dst++ = *src; + + objc += !!skip; + skip = false; + } + } + + /* object vector */ + objlist->objc = objc; + + if (!(objlist->objv = calloc(++objc,sizeof(char *)))) { + free(objlist->addr); + slbt_unmap_file(mapinfo); + return -1; + } + + for (objv=objlist->objv,mark=objlist->addr; *mark; objv++) { + *objv = mark; + mark += strlen(mark) + 1; + } + + slbt_unmap_file(mapinfo); + + return 0; +} diff --git a/src/internal/slibtool_objlist_impl.h b/src/internal/slibtool_objlist_impl.h new file mode 100644 index 0000000..cb11d07 --- /dev/null +++ b/src/internal/slibtool_objlist_impl.h @@ -0,0 +1,10 @@ +#ifndef SLIBTOOL_OBJLIST_IMPL_H +#define SLIBTOOL_OBJLIST_IMPL_H + +#include "slibtool_driver_impl.h" + +int slbt_objlist_read( + int fdcwd, + struct slbt_obj_list * objlist); + +#endif diff --git a/src/internal/slibtool_objmeta_impl.c b/src/internal/slibtool_objmeta_impl.c index 9d4902c..768cc96 100644 --- a/src/internal/slibtool_objmeta_impl.c +++ b/src/internal/slibtool_objmeta_impl.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -11,6 +11,7 @@ #include "slibtool_dprintf_impl.h" #include "slibtool_errinfo_impl.h" #include "slibtool_metafile_impl.h" +#include "slibtool_visibility_impl.h" static int slbt_create_default_object_wrapper( const struct slbt_driver_ctx * dctx, @@ -27,7 +28,7 @@ static int slbt_create_default_object_wrapper( 0644)) < 0) return SLBT_SYSTEM_ERROR(dctx,ectx->ltobjname); - verinfo = slbt_source_version(); + verinfo = slbt_api_source_version(); ret = slbt_dprintf(fdout, "# libtool compatible object wrapper\n" @@ -68,7 +69,7 @@ static int slbt_create_compatible_object_wrapper( 0644)) < 0) return SLBT_SYSTEM_ERROR(dctx, ectx->ltobjname); - verinfo = slbt_source_version(); + verinfo = slbt_api_source_version(); ret = slbt_dprintf(fdout, "# %s - a libtool object file\n" @@ -101,7 +102,7 @@ static int slbt_create_compatible_object_wrapper( return (ret < 0) ? SLBT_SYSTEM_ERROR(dctx,0) : 0; } -int slbt_create_object_wrapper( +slbt_hidden int slbt_create_object_wrapper( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx) { diff --git a/src/internal/slibtool_pecoff_impl.c b/src/internal/slibtool_pecoff_impl.c new file mode 100644 index 0000000..590fafc --- /dev/null +++ b/src/internal/slibtool_pecoff_impl.c @@ -0,0 +1,16 @@ +/*******************************************************************/ +/* 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 <string.h> + +#include "slibtool_visibility_impl.h" + +slbt_hidden int slbt_is_strong_coff_symbol(const char * sym) +{ + return strncmp(sym,"__imp_",6) + && strncmp(sym,".weak.",6) + && strncmp(sym,".refptr.",8); +} diff --git a/src/internal/slibtool_pecoff_impl.h b/src/internal/slibtool_pecoff_impl.h new file mode 100644 index 0000000..e18b5af --- /dev/null +++ b/src/internal/slibtool_pecoff_impl.h @@ -0,0 +1,6 @@ +#ifndef SLIBTOOL_PECOFF_IMPL_H +#define SLIBTOOL_PECOFF_IMPL_H + +int slbt_is_strong_coff_symbol(const char *); + +#endif diff --git a/src/internal/slibtool_readlink_impl.h b/src/internal/slibtool_readlink_impl.h index 19aafa2..378ed5c 100644 --- a/src/internal/slibtool_readlink_impl.h +++ b/src/internal/slibtool_readlink_impl.h @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ diff --git a/src/internal/slibtool_realpath_impl.c b/src/internal/slibtool_realpath_impl.c new file mode 100644 index 0000000..63fc3c4 --- /dev/null +++ b/src/internal/slibtool_realpath_impl.c @@ -0,0 +1,100 @@ +/*******************************************************************/ +/* 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 <fcntl.h> +#include <stdlib.h> +#include <limits.h> +#include <errno.h> +#include <sys/stat.h> +#include <slibtool/slibtool.h> + +#include "slibtool_driver_impl.h" +#include "slibtool_readlink_impl.h" +#include "slibtool_realpath_impl.h" +#include "slibtool_visibility_impl.h" + +#ifdef HAVE_SYS_SYSCALL_H +#include <sys/syscall.h> +#include <unistd.h> +#endif + +#ifdef _MIDIPIX_ABI +#include <sys/fs.h> +#endif + +#ifndef ENOTSUP +#define ENOTSUP EOPNOTSUPP +#endif + +slbt_hidden int slbt_realpath( + int fdat, + const char * path, + int options, + char * buf, + size_t buflen) +{ + int ret; + int fd; + int fdproc; + struct stat st; + struct stat stproc; + char procfspath[36]; + + /* common validation */ + if (!buf || (options & O_CREAT)) { + errno = EINVAL; + return -1; + } + + /* framework-based wrapper */ +#ifdef _MIDIPIX_ABI + return __fs_rpath(fdat,path,options,buf,buflen); +#endif + +#ifdef SYS___realpathat + return syscall(SYS___realpathat,fdat,path,buf,buflen,0); +#endif + + /* buflen */ + if (buflen < PATH_MAX) { + errno = ENOBUFS; + return -1; + } + + /* AT_FDCWD */ + if (fdat == AT_FDCWD) { + return realpath(path,buf) ? 0 : -1; + } + + /* /proc/self/fd */ + if ((fd = openat(fdat,path,options,0)) < 0) + return -1; + + sprintf(procfspath,"/proc/self/fd/%d",fd); + + if (slbt_readlinkat(fdat,procfspath,buf,buflen)) { + close(fd); + return -1; + } + + if ((fdproc = openat(AT_FDCWD,buf,options|O_NOFOLLOW,0)) < 0) { + close(fd); + errno = ELOOP; + return -1; + } + + ret = fstat(fd,&st) || fstat(fdproc,&stproc); + + close(fd); + close(fdproc); + + if (ret || (st.st_dev != stproc.st_dev) || (st.st_ino != stproc.st_ino)) { + errno = ENOTSUP; + return -1; + } + + return 0; +} diff --git a/src/internal/slibtool_realpath_impl.h b/src/internal/slibtool_realpath_impl.h new file mode 100644 index 0000000..01df1c1 --- /dev/null +++ b/src/internal/slibtool_realpath_impl.h @@ -0,0 +1,13 @@ +#ifndef SLIBTOOL_REALPATH_IMPL_H +#define SLIBTOOL_REALPATH_IMPL_H + +#include <stdlib.h> + +int slbt_realpath( + int fdat, + const char * path, + int options, + char * buf, + size_t buflen); + +#endif diff --git a/src/internal/slibtool_snprintf_impl.c b/src/internal/slibtool_snprintf_impl.c new file mode 100644 index 0000000..84e01f0 --- /dev/null +++ b/src/internal/slibtool_snprintf_impl.c @@ -0,0 +1,40 @@ +/*******************************************************************/ +/* 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 <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include "slibtool_snprintf_impl.h" +#include "slibtool_visibility_impl.h" + + +/*****************************************************************/ +/* snprintf() wrapper that simplifies usage via the following: */ +/* */ +/* (1) fail (return a negative result) in case the buffer is */ +/* not sufficiently large for the formatted string plus */ +/* the terminating null character. */ +/* */ +/**********************************************************/ + + +slbt_hidden int slbt_snprintf(char * buf, size_t buflen, const char * fmt, ...) +{ + va_list ap; + size_t nbytes; + + va_start(ap,fmt); + nbytes = vsnprintf(buf,buflen,fmt,ap); + va_end(ap); + + if (nbytes >= buflen) + return -1; + + return nbytes; +} diff --git a/src/internal/slibtool_snprintf_impl.h b/src/internal/slibtool_snprintf_impl.h new file mode 100644 index 0000000..87fa65a --- /dev/null +++ b/src/internal/slibtool_snprintf_impl.h @@ -0,0 +1,6 @@ +#ifndef SLIBTOOL_SNPRINTF_IMPL_H +#define SLIBTOOL_SNPRINTF_IMPL_H + +int slbt_snprintf(char * buf, size_t buflen, const char * fmt, ...); + +#endif diff --git a/src/internal/slibtool_spawn_impl.h b/src/internal/slibtool_spawn_impl.h index d6b18cb..aa4ea35 100644 --- a/src/internal/slibtool_spawn_impl.h +++ b/src/internal/slibtool_spawn_impl.h @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -30,6 +30,12 @@ #include <spawn.h> #endif +#ifdef __midipix__ +static pid_t slbt_fork(void) {return vfork();} +#else +static pid_t slbt_fork(void) {return fork();} +#endif + static inline int slbt_spawn( struct slbt_exec_ctx * ectx, bool fwait) @@ -56,6 +62,8 @@ static inline int slbt_spawn( #endif + (void)slbt_fork; + if (pid < 0) { ectx->pid = pid; ectx->exitcode = errno; diff --git a/src/internal/slibtool_stoolie_impl.h b/src/internal/slibtool_stoolie_impl.h new file mode 100644 index 0000000..43d70a5 --- /dev/null +++ b/src/internal/slibtool_stoolie_impl.h @@ -0,0 +1,15 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#ifndef SLIBTOOL_STOOLIE_IMPL_H +#define SLIBTOOL_STOOLIE_IMPL_H + +#include "argv/argv.h" +#include <slibtool/slibtool.h> + +extern const struct argv_option slbt_stoolie_options[]; + +#endif diff --git a/src/internal/slibtool_symlink_impl.c b/src/internal/slibtool_symlink_impl.c index bb38333..bb117e2 100644 --- a/src/internal/slibtool_symlink_impl.c +++ b/src/internal/slibtool_symlink_impl.c @@ -1,6 +1,6 @@ /*******************************************************************/ -/* slibtool: a skinny libtool implementation, written in C */ -/* Copyright (C) 2016--2021 Z. Gilboa */ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ @@ -13,26 +13,32 @@ #include "slibtool_errinfo_impl.h" #include "slibtool_symlink_impl.h" #include "slibtool_readlink_impl.h" +#include "slibtool_realpath_impl.h" +#include "slibtool_snprintf_impl.h" +#include "slibtool_visibility_impl.h" #define SLBT_DEV_NULL_FLAGS (SLBT_DRIVER_ALL_STATIC \ | SLBT_DRIVER_DISABLE_SHARED \ | SLBT_DRIVER_DISABLE_STATIC) -int slbt_create_symlink( +slbt_hidden int slbt_create_symlink_ex( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, + int fddst, const char * target, const char * lnkname, uint32_t options) { - int fdcwd; int fliteral; int fwrapper; int fdevnull; + size_t slen; char ** oargv; const char * slash; char * ln[5]; + char * dot; char * dotdot; + char * mark; char tmplnk [PATH_MAX]; char lnkarg [PATH_MAX]; char alnkarg[PATH_MAX]; @@ -45,18 +51,14 @@ int slbt_create_symlink( fdevnull = (options & SLBT_SYMLINK_DEVNULL); /* symlink is a placeholder? */ - if (fliteral && fdevnull) { + if (fliteral) { slash = target; - } else if ((dctx->cctx->drvflags & SLBT_DEV_NULL_FLAGS) - && !strcmp(target,"/dev/null")) { + /* .disabled .so or .a file */ + } else if (fdevnull) { slash = target; suffix = ".disabled"; - /* target is an absolute path? */ - } else if (fliteral) { - slash = target; - /* symlink target contains a dirname? */ } else if ((slash = strrchr(target,'/'))) { slash++; @@ -70,23 +72,52 @@ int slbt_create_symlink( dotdot = fwrapper ? "../" : ""; /* atarget */ - if ((size_t)snprintf(atarget,sizeof(atarget),"%s%s", - dotdot,slash) >= sizeof(atarget)) + if (slbt_snprintf(atarget,sizeof(atarget), + "%s%s",dotdot,slash) < 0) return SLBT_BUFFER_ERROR(dctx); /* tmplnk */ - if ((size_t)snprintf(tmplnk,sizeof(tmplnk),"%s.symlink.tmp", - lnkname) >= sizeof(tmplnk)) + if (slbt_snprintf(tmplnk,sizeof(tmplnk), + "%s.symlink.tmp", + lnkname) <0) return SLBT_BUFFER_ERROR(dctx); /* placeholder? */ + if (fdevnull) { + if (unlinkat(fddst,lnkname,0) && (errno != ENOENT)) + return SLBT_SYSTEM_ERROR(dctx,0); + + if ((dot = strrchr(lnkname,'.'))) { + if (!strcmp(dot,dctx->cctx->settings.dsosuffix)) { + strcpy(dot,".expsyms.a"); + + if (unlinkat(fddst,lnkname,0) && (errno != ENOENT)) + return SLBT_SYSTEM_ERROR(dctx,0); + + strcpy(dot,dctx->cctx->settings.dsosuffix); + } + } + } + if (suffix) { sprintf(alnkarg,"%s%s",lnkname,suffix); lnkname = alnkarg; } /* lnkarg */ - strcpy(lnkarg,lnkname); + if (fddst == slbt_driver_fdcwd(dctx)) { + strcpy(lnkarg,lnkname); + } else { + if (slbt_realpath(fddst,".",0,lnkarg,sizeof(lnkarg)) < 0) + return SLBT_BUFFER_ERROR(dctx); + + if ((slen = strlen(lnkarg)) + strlen(lnkname) + 1 >= PATH_MAX) + return SLBT_BUFFER_ERROR(dctx); + + mark = &lnkarg[slen]; + mark[0] = '/'; + strcpy(++mark,lnkname); + } /* ln argv (fake) */ ln[0] = "ln"; @@ -101,12 +132,12 @@ int slbt_create_symlink( /* step output */ if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) { if (dctx->cctx->mode == SLBT_MODE_LINK) { - if (slbt_output_link(dctx,ectx)) { + if (slbt_output_link(ectx)) { ectx->argv = oargv; return SLBT_NESTED_ERROR(dctx); } } else { - if (slbt_output_install(dctx,ectx)) { + if (slbt_output_install(ectx)) { ectx->argv = oargv; return SLBT_NESTED_ERROR(dctx); } @@ -116,19 +147,29 @@ int slbt_create_symlink( /* restore execution context */ ectx->argv = oargv; - /* fdcwd */ - fdcwd = slbt_driver_fdcwd(dctx); - /* create symlink */ - if (symlinkat(atarget,fdcwd,tmplnk)) + if (symlinkat(atarget,fddst,tmplnk)) return SLBT_SYSTEM_ERROR(dctx,tmplnk); - return renameat(fdcwd,tmplnk,fdcwd,lnkname) + return renameat(fddst,tmplnk,fddst,lnkname) ? SLBT_SYSTEM_ERROR(dctx,lnkname) : 0; } -int slbt_symlink_is_a_placeholder(int fdcwd, char * lnkpath) +slbt_hidden int slbt_create_symlink( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + const char * target, + const char * lnkname, + uint32_t options) +{ + return slbt_create_symlink_ex( + dctx,ectx, + slbt_driver_fdcwd(dctx), + target,lnkname,options); +} + +slbt_hidden int slbt_symlink_is_a_placeholder(int fdcwd, const char * lnkpath) { size_t len; char slink [PATH_MAX]; diff --git a/src/internal/slibtool_symlink_impl.h b/src/internal/slibtool_symlink_impl.h index fc4c708..9f968de 100644 --- a/src/internal/slibtool_symlink_impl.h +++ b/src/internal/slibtool_symlink_impl.h @@ -16,6 +16,14 @@ int slbt_create_symlink( const char * lnkname, uint32_t options); -int slbt_symlink_is_a_placeholder(int fdcwd, char * lnkpath); +int slbt_create_symlink_ex( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + int fddst, + const char * target, + const char * lnkname, + uint32_t options); + +int slbt_symlink_is_a_placeholder(int fdcwd, const char * lnkpath); #endif diff --git a/src/internal/slibtool_tmpfile_impl.c b/src/internal/slibtool_tmpfile_impl.c new file mode 100644 index 0000000..52c7317 --- /dev/null +++ b/src/internal/slibtool_tmpfile_impl.c @@ -0,0 +1,89 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#define _GNU_SOURCE +#include <time.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <inttypes.h> + +#include "slibtool_visibility_impl.h" + +#define PPRIX64 "%"PRIx64 + +/* mkostemp might be guarded by non-standard macros */ +/* unless HAVE_NO_MKOSTEMP, assume it is available */ +extern int mkstemp(char *); +extern int mkostemp(char *, int); + +/* __fs_tmpfile() atomically provides a private tmpfile */ +static int slbt_tmpfile_by_framework(void) +{ +#ifdef _MIDIPIX_ABI + extern int __fs_tmpfile(int); + return __fs_tmpfile(O_CLOEXEC); +#else + return (-1); +#endif +} + +/* O_TMPFILE atomically provides a private tmpfile */ +static int slbt_tmpfile_by_kernel(void) +{ +#ifdef O_TMPFILE + return openat(AT_FDCWD,"/tmp",O_RDWR|O_TMPFILE|O_CLOEXEC,0); +#else + return (-1); +#endif +} + +/* mk{o}stemp() provides a non-private tmpfile */ +static int slbt_mkostemp(char * tmplate) +{ + int fd; +#ifdef HAVE_NO_MKOSTEMP + if ((fd = mkstemp(tmplate)) >= 0) + fcntl(fd,F_SETFD,FD_CLOEXEC); +#else + fd = mkostemp(tmplate,O_CLOEXEC); +#endif + return fd; +} + +slbt_hidden int slbt_tmpfile(void) +{ + int fd; + void * addr; + char tmplate[128]; + + /* try with __fs_tmpfile() */ + if ((fd = slbt_tmpfile_by_framework()) >= 0) + return fd; + + /* try with O_TMPFILE */ + if ((fd = slbt_tmpfile_by_kernel()) >= 0) + return fd; + + /* fallback to mk{o}stemp */ + addr = tmplate; + memset(tmplate,0,sizeof(tmplate)); + snprintf(tmplate,sizeof(tmplate), + "/tmp/" + ".slibtool.tmpfile" + ".time."PPRIX64 + ".salt.%p" + ".pid.%d" + ".XXXXXXXXXXXX", + time(0), + addr, + getpid()); + + return slbt_mkostemp(tmplate); +} diff --git a/src/internal/slibtool_tmpfile_impl.h b/src/internal/slibtool_tmpfile_impl.h new file mode 100644 index 0000000..cd6a02b --- /dev/null +++ b/src/internal/slibtool_tmpfile_impl.h @@ -0,0 +1,6 @@ +#ifndef SLIBTOOL_TMPFILE_IMPL_H +#define SLIBTOOL_TMPFILE_IMPL_H + +int slbt_tmpfile(void); + +#endif diff --git a/src/internal/slibtool_txtline_impl.c b/src/internal/slibtool_txtline_impl.c new file mode 100644 index 0000000..4c8f2ad --- /dev/null +++ b/src/internal/slibtool_txtline_impl.c @@ -0,0 +1,67 @@ +/*******************************************************************/ +/* 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 <string.h> +#include <stdlib.h> + +#include <slibtool/slibtool.h> +#include "slibtool_visibility_impl.h" + +slbt_hidden int slbt_txtline_to_string_vector(const char * txtline, char *** pargv) +{ + int argc; + char ** argv; + const char * ch; + const char * mark; + + if (!(ch = txtline)) + return 0; + + argc = 1; + + for (; *ch == ' '; ) + ch++; + + for (; *ch; ) { + if (*ch++ == ' ') { + argc++; + + for (; (*ch == ' '); ) + ch++; + } + } + + if (argc == 1) + return 0; + + if (!(*pargv = calloc(++argc,sizeof(char *)))) + return -1; + + for (ch=txtline; (*ch == ' '); ch++) + (void)0; + + argv = *pargv; + mark = ch; + + for (; *ch; ) { + if (*ch == ' ') { + if (!(*argv++ = strndup(mark,ch-mark))) + return -1; + + for (; (*ch == ' '); ) + ch++; + + mark = ch; + } else { + ch++; + } + } + + if (!(*argv++ = strndup(mark,ch-mark))) + return -1; + + return 0; +} diff --git a/src/internal/slibtool_txtline_impl.h b/src/internal/slibtool_txtline_impl.h new file mode 100644 index 0000000..2a647b1 --- /dev/null +++ b/src/internal/slibtool_txtline_impl.h @@ -0,0 +1,8 @@ +#ifndef SLIBTOOL_TXTLINE_IMPL_H +#define SLIBTOOL_TXTLINE_IMPL_H + +#include <slibtool/slibtool.h> + +int slbt_txtline_to_string_vector(const char *, char ***); + +#endif diff --git a/src/internal/slibtool_visibility_impl.h b/src/internal/slibtool_visibility_impl.h new file mode 100644 index 0000000..2bdded0 --- /dev/null +++ b/src/internal/slibtool_visibility_impl.h @@ -0,0 +1,26 @@ +#ifndef SLIBTOOL_VISIBILITY_IMPL_H +#define SLIBTOOL_VISIBILITY_IMPL_H + +/**********************************************************************/ +/* PE targets: __dllexport suffices for the purpose of exporting only */ +/* the desired subset of global symbols; this makes the visibility */ +/* attribute not only redundant, but also tricky if not properly */ +/* supported by the toolchain. */ +/* */ +/* When targeting Midipix, __PE__, __dllexport and __dllimport are */ +/* always defined by the toolchain. Otherwise, the absnece of these */ +/* macros has been detected by sofort's ccenv.sh during ./configure, */ +/* and they have accordingly been added to CFLAGS_OS. */ +/**********************************************************************/ + +#ifdef __PE__ +#define slbt_hidden +#else +#ifdef _ATTR_VISIBILITY_HIDDEN +#define slbt_hidden _ATTR_VISIBILITY_HIDDEN +#else +#define slbt_hidden +#endif +#endif + +#endif |