diff options
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | project/headers.mk | 1 | ||||
-rw-r--r-- | project/tree.mk | 1 | ||||
-rw-r--r-- | src/internal/slibtool_linkcmd_impl.h | 24 | ||||
-rw-r--r-- | src/logic/linkcmd/slbt_linkcmd_deps.c | 329 | ||||
-rw-r--r-- | src/logic/slbt_exec_link.c | 316 |
6 files changed, 357 insertions, 315 deletions
diff --git a/project/common.mk b/project/common.mk index 8ebd33d..971173d 100644 --- a/project/common.mk +++ b/project/common.mk @@ -28,6 +28,7 @@ API_SRCS = \ src/logic/slbt_exec_install.c \ src/logic/slbt_exec_link.c \ src/logic/slbt_exec_uninstall.c \ + src/logic/linkcmd/slbt_linkcmd_deps.c \ src/output/slbt_output_config.c \ src/output/slbt_output_error.c \ src/output/slbt_output_exec.c \ diff --git a/project/headers.mk b/project/headers.mk index f847b60..bb2628f 100644 --- a/project/headers.mk +++ b/project/headers.mk @@ -12,6 +12,7 @@ INTERNAL_HEADERS = \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_errinfo_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_install_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_lconf_impl.h \ + $(PROJECT_DIR)/src/internal/$(PACKAGE)_linkcmd_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_mapfile_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_metafile_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_mkdir_impl.h \ diff --git a/project/tree.mk b/project/tree.mk index 978e313..c06d62c 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -9,4 +9,5 @@ tree.tag: mkdir -p src/output mkdir -p src/skin mkdir -p src/arbits/output + mkdir -p src/logic/linkcmd touch tree.tag diff --git a/src/internal/slibtool_linkcmd_impl.h b/src/internal/slibtool_linkcmd_impl.h new file mode 100644 index 0000000..c2598f3 --- /dev/null +++ b/src/internal/slibtool_linkcmd_impl.h @@ -0,0 +1,24 @@ +#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); + +#endif diff --git a/src/logic/linkcmd/slbt_linkcmd_deps.c b/src/logic/linkcmd/slbt_linkcmd_deps.c new file mode 100644 index 0000000..2b50ff8 --- /dev/null +++ b/src/logic/linkcmd/slbt_linkcmd_deps.c @@ -0,0 +1,329 @@ +/*******************************************************************/ +/* slibtool: a skinny libtool implementation, written in C */ +/* Copyright (C) 2016--2021 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/stat.h> + +#include <slibtool/slibtool.h> +#include "slibtool_driver_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_linkcmd_impl.h" +#include "slibtool_mapfile_impl.h" +#include "slibtool_metafile_impl.h" +#include "slibtool_snprintf_impl.h" + +int slbt_get_deps_meta( + const struct slbt_driver_ctx * dctx, + char * libfilename, + int fexternal, + struct slbt_deps_meta * depsmeta) +{ + int fdcwd; + char * ch; + char * cap; + char * base; + size_t libexlen; + struct stat st; + struct slbt_map_info * mapinfo; + char depfile[PATH_MAX]; + + /* fdcwd */ + fdcwd = slbt_driver_fdcwd(dctx); + + /* -rpath */ + if (slbt_snprintf(depfile,sizeof(depfile), + "%s.slibtool.rpath", + libfilename) < 0) + return SLBT_BUFFER_ERROR(dctx); + + /* -Wl,%s */ + if (!fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) { + depsmeta->infolen += st.st_size + 4; + depsmeta->infolen++; + } + + /* .deps */ + if (slbt_snprintf(depfile,sizeof(depfile), + "%s.slibtool.deps", + libfilename) < 0) + return SLBT_BUFFER_ERROR(dctx); + + /* mapinfo */ + if (!(mapinfo = slbt_map_file(fdcwd,depfile,SLBT_MAP_INPUT))) + return (fexternal && (errno == ENOENT)) + ? 0 : SLBT_SYSTEM_ERROR(dctx,depfile); + + /* copied length */ + depsmeta->infolen += mapinfo->size; + depsmeta->infolen++; + + /* libexlen */ + libexlen = (base = strrchr(libfilename,'/')) + ? strlen(depfile) + 2 + (base - libfilename) + : strlen(depfile) + 2; + + /* iterate */ + ch = mapinfo->addr; + cap = mapinfo->cap; + + for (; ch<cap; ) { + if (*ch++ == '\n') { + depsmeta->infolen += libexlen; + depsmeta->depscnt++; + } + } + + slbt_unmap_file(mapinfo); + + return 0; +} + + +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) +{ + int ret; + int deps; + int slen; + int fdcwd; + char ** parg; + char * popt; + char * plib; + char * path; + char * mark; + char * base; + size_t size; + char deplib [PATH_MAX]; + bool is_reladir; + char reladir[PATH_MAX]; + char depfile[PATH_MAX]; + struct stat st; + int ldepth; + int fdyndep; + struct slbt_map_info * mapinfo; + + /* fdcwd */ + fdcwd = slbt_driver_fdcwd(dctx); + + /* depfile */ + if (slbt_snprintf(depfile,sizeof(depfile), + "%s.slibtool.deps", + libfilename) < 0) + return SLBT_BUFFER_ERROR(dctx); + + /* deps */ + if ((deps = openat(fdcwd,depfile,O_RDWR|O_CREAT|O_TRUNC,0644)) < 0) + return SLBT_SYSTEM_ERROR(dctx,depfile); + + /* iterate */ + for (parg=altv; *parg; parg++) { + popt = 0; + plib = 0; + path = 0; + mapinfo = 0; + + if (!strncmp(*parg,"-l",2)) { + popt = *parg; + plib = popt + 2; + + } else if (!strncmp(*parg,"-L",2)) { + popt = *parg; + path = popt + 2; + + } else if (!strncmp(*parg,"-f",2)) { + (void)0; + + } else if ((popt = strrchr(*parg,'.')) && !strcmp(popt,".la")) { + /* import dependency list */ + if ((base = strrchr(*parg,'/'))) + base++; + else + base = *parg; + + /* [relative .la directory] */ + if (base > *parg) { + slen = slbt_snprintf( + reladir, + sizeof(reladir), + "%s",*parg); + + if (slen < 0) { + close(deps); + return SLBT_BUFFER_ERROR(dctx); + } + + is_reladir = true; + reladir[base - *parg - 1] = 0; + } else { + is_reladir = false; + reladir[0] = '.'; + reladir[1] = 0; + } + + + /* dynamic library dependency? */ + strcpy(depfile,*parg); + mark = depfile + (base - *parg); + size = sizeof(depfile) - (base - *parg); + slen = slbt_snprintf(mark,size,".libs/%s",base); + + if (slen < 0) { + close(deps); + return SLBT_BUFFER_ERROR(dctx); + } + + mark = strrchr(mark,'.'); + strcpy(mark,dctx->cctx->settings.dsosuffix); + + fdyndep = !fstatat(fdcwd,depfile,&st,0); + + /* [-L... as needed] */ + if (fdyndep && (ectx->ldirdepth >= 0)) { + if (slbt_dprintf(deps,"-L") < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + for (ldepth=ectx->ldirdepth; ldepth; ldepth--) { + if (slbt_dprintf(deps,"../") < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + if (slbt_dprintf(deps,"%s%s.libs\n", + (is_reladir ? reladir : ""), + (is_reladir ? "/" : "")) < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + /* -ldeplib */ + if (fdyndep) { + *popt = 0; + mark = base; + mark += strlen(dctx->cctx->settings.dsoprefix); + + if (slbt_dprintf(deps,"-l%s\n",mark) < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + *popt = '.'; + } + + /* [open dependency list] */ + strcpy(depfile,*parg); + mark = depfile + (base - *parg); + size = sizeof(depfile) - (base - *parg); + slen = slbt_snprintf(mark,size,".libs/%s",base); + + if (slen < 0) { + close(deps); + return SLBT_BUFFER_ERROR(dctx); + } + + mapinfo = 0; + + mark = strrchr(mark,'.'); + size = sizeof(depfile) - (mark - depfile); + + if (!farchive) { + slen = slbt_snprintf(mark,size, + "%s.slibtool.deps", + dctx->cctx->settings.dsosuffix); + + if (slen < 0) { + close(deps); + return SLBT_BUFFER_ERROR(dctx); + } + + mapinfo = slbt_map_file( + fdcwd,depfile, + SLBT_MAP_INPUT); + + if (!mapinfo && (errno != ENOENT)) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + if (!mapinfo) { + slen = slbt_snprintf(mark,size, + ".a.slibtool.deps"); + + if (slen < 0) { + close(deps); + return SLBT_BUFFER_ERROR(dctx); + } + + mapinfo = slbt_map_file( + fdcwd,depfile, + SLBT_MAP_INPUT); + + if (!mapinfo) { + strcpy(mark,".a.disabled"); + + if (fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,depfile); + } + } + } + + /* [-l... as needed] */ + while (mapinfo && (mapinfo->mark < mapinfo->cap)) { + ret = slbt_mapped_readline( + dctx,mapinfo, + deplib,sizeof(deplib)); + + if (ret) { + close(deps); + return SLBT_NESTED_ERROR(dctx); + } + + ret = ((deplib[0] == '-') + && (deplib[1] == 'L') + && (deplib[2] != '/')) + ? slbt_dprintf( + deps,"-L%s/%s", + reladir,&deplib[2]) + : slbt_dprintf( + deps,"%s", + deplib); + + if (ret < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + if (mapinfo) + slbt_unmap_file(mapinfo); + } + + if (plib && (slbt_dprintf(deps,"-l%s\n",plib) < 0)) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + if (path && (slbt_dprintf(deps,"-L%s\n",path) < 0)) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + return 0; +} diff --git a/src/logic/slbt_exec_link.c b/src/logic/slbt_exec_link.c index 6eb9e8d..cacbe44 100644 --- a/src/logic/slbt_exec_link.c +++ b/src/logic/slbt_exec_link.c @@ -19,19 +19,13 @@ #include "slibtool_driver_impl.h" #include "slibtool_dprintf_impl.h" #include "slibtool_errinfo_impl.h" +#include "slibtool_linkcmd_impl.h" #include "slibtool_mapfile_impl.h" #include "slibtool_metafile_impl.h" #include "slibtool_readlink_impl.h" #include "slibtool_snprintf_impl.h" #include "slibtool_symlink_impl.h" -struct slbt_deps_meta { - char ** altv; - char * args; - int depscnt; - int infolen; -}; - /*******************************************************************/ /* */ /* -o <ltlib> switches input result */ @@ -83,72 +77,6 @@ static int slbt_exec_link_exit( return ret; } -static int slbt_get_deps_meta( - const struct slbt_driver_ctx * dctx, - char * libfilename, - int fexternal, - struct slbt_deps_meta * depsmeta) -{ - int fdcwd; - char * ch; - char * cap; - char * base; - size_t libexlen; - struct stat st; - struct slbt_map_info * mapinfo; - char depfile[PATH_MAX]; - - /* fdcwd */ - fdcwd = slbt_driver_fdcwd(dctx); - - /* -rpath */ - if (slbt_snprintf(depfile,sizeof(depfile), - "%s.slibtool.rpath", - libfilename) < 0) - return SLBT_BUFFER_ERROR(dctx); - - /* -Wl,%s */ - if (!fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) { - depsmeta->infolen += st.st_size + 4; - depsmeta->infolen++; - } - - /* .deps */ - if (slbt_snprintf(depfile,sizeof(depfile), - "%s.slibtool.deps", - libfilename) < 0) - return SLBT_BUFFER_ERROR(dctx); - - /* mapinfo */ - if (!(mapinfo = slbt_map_file(fdcwd,depfile,SLBT_MAP_INPUT))) - return (fexternal && (errno == ENOENT)) - ? 0 : SLBT_SYSTEM_ERROR(dctx,depfile); - - /* copied length */ - depsmeta->infolen += mapinfo->size; - depsmeta->infolen++; - - /* libexlen */ - libexlen = (base = strrchr(libfilename,'/')) - ? strlen(depfile) + 2 + (base - libfilename) - : strlen(depfile) + 2; - - /* iterate */ - ch = mapinfo->addr; - cap = mapinfo->cap; - - for (; ch<cap; ) { - if (*ch++ == '\n') { - depsmeta->infolen += libexlen; - depsmeta->depscnt++; - } - } - - slbt_unmap_file(mapinfo); - - return 0; -} - static bool slbt_adjust_object_argument( char * arg, bool fpic, @@ -895,248 +823,6 @@ static int slbt_exec_link_remove_file( return SLBT_SYSTEM_ERROR(dctx,0); } -static 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) -{ - int ret; - int deps; - int slen; - int fdcwd; - char ** parg; - char * popt; - char * plib; - char * path; - char * mark; - char * base; - size_t size; - char deplib [PATH_MAX]; - bool is_reladir; - char reladir[PATH_MAX]; - char depfile[PATH_MAX]; - struct stat st; - int ldepth; - int fdyndep; - struct slbt_map_info * mapinfo; - - /* fdcwd */ - fdcwd = slbt_driver_fdcwd(dctx); - - /* depfile */ - if (slbt_snprintf(depfile,sizeof(depfile), - "%s.slibtool.deps", - libfilename) < 0) - return SLBT_BUFFER_ERROR(dctx); - - /* deps */ - if ((deps = openat(fdcwd,depfile,O_RDWR|O_CREAT|O_TRUNC,0644)) < 0) - return SLBT_SYSTEM_ERROR(dctx,depfile); - - /* iterate */ - for (parg=altv; *parg; parg++) { - popt = 0; - plib = 0; - path = 0; - mapinfo = 0; - - if (!strncmp(*parg,"-l",2)) { - popt = *parg; - plib = popt + 2; - - } else if (!strncmp(*parg,"-L",2)) { - popt = *parg; - path = popt + 2; - - } else if (!strncmp(*parg,"-f",2)) { - (void)0; - - } else if ((popt = strrchr(*parg,'.')) && !strcmp(popt,".la")) { - /* import dependency list */ - if ((base = strrchr(*parg,'/'))) - base++; - else - base = *parg; - - /* [relative .la directory] */ - if (base > *parg) { - slen = slbt_snprintf( - reladir, - sizeof(reladir), - "%s",*parg); - - if (slen < 0) { - close(deps); - return SLBT_BUFFER_ERROR(dctx); - } - - is_reladir = true; - reladir[base - *parg - 1] = 0; - } else { - is_reladir = false; - reladir[0] = '.'; - reladir[1] = 0; - } - - - /* dynamic library dependency? */ - strcpy(depfile,*parg); - mark = depfile + (base - *parg); - size = sizeof(depfile) - (base - *parg); - slen = slbt_snprintf(mark,size,".libs/%s",base); - - if (slen < 0) { - close(deps); - return SLBT_BUFFER_ERROR(dctx); - } - - mark = strrchr(mark,'.'); - strcpy(mark,dctx->cctx->settings.dsosuffix); - - fdyndep = !fstatat(fdcwd,depfile,&st,0); - - /* [-L... as needed] */ - if (fdyndep && (ectx->ldirdepth >= 0)) { - if (slbt_dprintf(deps,"-L") < 0) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - - for (ldepth=ectx->ldirdepth; ldepth; ldepth--) { - if (slbt_dprintf(deps,"../") < 0) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - } - - if (slbt_dprintf(deps,"%s%s.libs\n", - (is_reladir ? reladir : ""), - (is_reladir ? "/" : "")) < 0) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - } - - /* -ldeplib */ - if (fdyndep) { - *popt = 0; - mark = base; - mark += strlen(dctx->cctx->settings.dsoprefix); - - if (slbt_dprintf(deps,"-l%s\n",mark) < 0) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - - *popt = '.'; - } - - /* [open dependency list] */ - strcpy(depfile,*parg); - mark = depfile + (base - *parg); - size = sizeof(depfile) - (base - *parg); - slen = slbt_snprintf(mark,size,".libs/%s",base); - - if (slen < 0) { - close(deps); - return SLBT_BUFFER_ERROR(dctx); - } - - mapinfo = 0; - - mark = strrchr(mark,'.'); - size = sizeof(depfile) - (mark - depfile); - - if (!farchive) { - slen = slbt_snprintf(mark,size, - "%s.slibtool.deps", - dctx->cctx->settings.dsosuffix); - - if (slen < 0) { - close(deps); - return SLBT_BUFFER_ERROR(dctx); - } - - mapinfo = slbt_map_file( - fdcwd,depfile, - SLBT_MAP_INPUT); - - if (!mapinfo && (errno != ENOENT)) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - } - - if (!mapinfo) { - slen = slbt_snprintf(mark,size, - ".a.slibtool.deps"); - - if (slen < 0) { - close(deps); - return SLBT_BUFFER_ERROR(dctx); - } - - mapinfo = slbt_map_file( - fdcwd,depfile, - SLBT_MAP_INPUT); - - if (!mapinfo) { - strcpy(mark,".a.disabled"); - - if (fstatat(fdcwd,depfile,&st,AT_SYMLINK_NOFOLLOW)) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,depfile); - } - } - } - - /* [-l... as needed] */ - while (mapinfo && (mapinfo->mark < mapinfo->cap)) { - ret = slbt_mapped_readline( - dctx,mapinfo, - deplib,sizeof(deplib)); - - if (ret) { - close(deps); - return SLBT_NESTED_ERROR(dctx); - } - - ret = ((deplib[0] == '-') - && (deplib[1] == 'L') - && (deplib[2] != '/')) - ? slbt_dprintf( - deps,"-L%s/%s", - reladir,&deplib[2]) - : slbt_dprintf( - deps,"%s", - deplib); - - if (ret < 0) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - } - - if (mapinfo) - slbt_unmap_file(mapinfo); - } - - if (plib && (slbt_dprintf(deps,"-l%s\n",plib) < 0)) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - - if (path && (slbt_dprintf(deps,"-L%s\n",path) < 0)) { - close(deps); - return SLBT_SYSTEM_ERROR(dctx,0); - } - } - - return 0; -} - static int slbt_exec_link_create_host_tag( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, |