diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/slbt_archive_import.c | 71 | ||||
-rw-r--r-- | src/util/slbt_copy_file.c | 96 | ||||
-rw-r--r-- | src/util/slbt_create_mapfile.c | 132 | ||||
-rw-r--r-- | src/util/slbt_create_symfile.c | 84 | ||||
-rw-r--r-- | src/util/slbt_dump_machine.c | 135 | ||||
-rw-r--r-- | src/util/slbt_map_input.c | 67 | ||||
-rw-r--r-- | src/util/slbt_realpath.c | 18 |
7 files changed, 603 insertions, 0 deletions
diff --git a/src/util/slbt_archive_import.c b/src/util/slbt_archive_import.c new file mode 100644 index 0000000..11b68de --- /dev/null +++ b/src/util/slbt_archive_import.c @@ -0,0 +1,71 @@ +/*******************************************************************/ +/* 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_symlink_impl.h" +#include "slibtool_errinfo_impl.h" + +/* legacy fallback, no longer in use */ +extern int slbt_util_import_archive_mri( + struct slbt_exec_ctx * ectx, + char * dstarchive, + char * srcarchive); + +/* use slibtool's in-memory archive merging facility */ +static int slbt_util_import_archive_impl( + const struct slbt_driver_ctx * dctx, + const struct slbt_exec_ctx * ectx, + char * dstarchive, + char * srcarchive) +{ + int ret; + struct slbt_archive_ctx * arctxv[3] = {0,0,0}; + struct slbt_archive_ctx * arctx; + + (void)ectx; + + if (slbt_ar_get_archive_ctx(dctx,dstarchive,&arctxv[0]) < 0) + return SLBT_NESTED_ERROR(dctx); + + if (slbt_ar_get_archive_ctx(dctx,srcarchive,&arctxv[1]) < 0) { + slbt_ar_free_archive_ctx(arctxv[0]); + return SLBT_NESTED_ERROR(dctx); + } + + ret = slbt_ar_merge_archives(arctxv,&arctx); + + slbt_ar_free_archive_ctx(arctxv[0]); + slbt_ar_free_archive_ctx(arctxv[1]); + + if (ret == 0) { + ret = slbt_ar_store_archive(arctx,dstarchive,0644); + slbt_ar_free_archive_ctx(arctx); + } + + return (ret < 0) ? SLBT_NESTED_ERROR(dctx) : 0; +} + + +int slbt_util_import_archive( + const struct slbt_exec_ctx * ectx, + char * dstarchive, + char * srcarchive) +{ + const struct slbt_driver_ctx * dctx; + + dctx = (slbt_get_exec_ictx(ectx))->dctx; + + if (slbt_symlink_is_a_placeholder( + slbt_driver_fdcwd(dctx), + srcarchive)) + return 0; + + return slbt_util_import_archive_impl( + dctx,ectx, + dstarchive, + srcarchive); +} diff --git a/src/util/slbt_copy_file.c b/src/util/slbt_copy_file.c new file mode 100644 index 0000000..23d8cc3 --- /dev/null +++ b/src/util/slbt_copy_file.c @@ -0,0 +1,96 @@ +/*******************************************************************/ +/* 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_spawn_impl.h" +#include "slibtool_symlink_impl.h" +#include "slibtool_errinfo_impl.h" + +int slbt_util_copy_file( + struct slbt_exec_ctx * ectx, + const char * from, + const char * to) +{ + int ret; + int fdcwd; + char ** oargv; + char * oprogram; + char * src; + char * dst; + char * cp[4]; + + const struct slbt_driver_ctx * dctx; + + /* driver context */ + dctx = (slbt_get_exec_ictx(ectx))->dctx; + + /* fdcwd */ + fdcwd = slbt_driver_fdcwd(dctx); + + /* placeholder? */ + if (slbt_symlink_is_a_placeholder(fdcwd,from)) + return 0; + + /* until we perform an in-memory copy ... */ + if (!(src = strdup(from))) + return SLBT_SYSTEM_ERROR(dctx,0); + + if (!(dst = strdup(to))) { + free(src); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + /* cp argv */ + cp[0] = "cp"; + cp[1] = src; + cp[2] = dst; + cp[3] = 0; + + /* alternate argument vector */ + oprogram = ectx->program; + oargv = ectx->argv; + ectx->argv = cp; + ectx->program = "cp"; + + /* step output */ + if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) { + if (dctx->cctx->mode == SLBT_MODE_LINK) { + if (slbt_output_link(ectx)) { + ectx->argv = oargv; + ectx->program = oprogram; + free(src); free(dst); + return SLBT_NESTED_ERROR(dctx); + } + } else { + if (slbt_output_install(ectx)) { + ectx->argv = oargv; + ectx->program = oprogram; + free(src); free(dst); + return SLBT_NESTED_ERROR(dctx); + } + } + } + + /* cp spawn */ + if ((slbt_spawn(ectx,true) < 0) && (ectx->pid < 0)) { + ret = SLBT_SPAWN_ERROR(dctx); + + } else if (ectx->exitcode) { + ret = SLBT_CUSTOM_ERROR( + dctx, + SLBT_ERR_COPY_ERROR); + } else { + ret = 0; + } + + free(src); + free(dst); + + ectx->argv = oargv; + ectx->program = oprogram; + return ret; +} diff --git a/src/util/slbt_create_mapfile.c b/src/util/slbt_create_mapfile.c new file mode 100644 index 0000000..8c03920 --- /dev/null +++ b/src/util/slbt_create_mapfile.c @@ -0,0 +1,132 @@ +/*******************************************************************/ +/* 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 <time.h> +#include <locale.h> +#include <regex.h> +#include <inttypes.h> +#include <slibtool/slibtool.h> +#include <slibtool/slibtool_output.h> +#include "slibtool_driver_impl.h" +#include "slibtool_dprintf_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_pecoff_impl.h" +#include "slibtool_ar_impl.h" + +/****************************************************/ +/* Generate a linker version script (aka mapfile) */ +/* that could be passed to the host linker. */ +/* */ +/* Since the provided symbol list is host-neautral, */ +/* prepend symbol names with an underscore whenever */ +/* necessary. */ +/****************************************************/ + +static int slbt_util_output_mapfile_impl( + const struct slbt_driver_ctx * dctx, + const struct slbt_symlist_ctx * sctx, + int fdout) +{ + bool fcoff; + bool fmach; + const char * dot; + const char * mark; + const char ** symv; + const char ** symstrv; + char strbuf[4096]; + + fcoff = slbt_host_objfmt_is_coff(dctx); + fmach = slbt_host_objfmt_is_macho(dctx); + + if (fcoff) { + if (slbt_dprintf(fdout,"EXPORTS\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else if (fmach) { + if (slbt_dprintf(fdout,"# export_list, underscores prepended\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + if (slbt_dprintf(fdout,"{\n" "\t" "global:\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } + + symstrv = sctx->symstrv; + + for (symv=symstrv; *symv; symv++) { + if (fcoff && slbt_is_strong_coff_symbol(*symv)) { + if (slbt_dprintf(fdout,"%s\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + } else if (fcoff && !strncmp(*symv,".weak.",6)) { + mark = &(*symv)[6]; + dot = strchr(mark,'.'); + + strncpy(strbuf,mark,dot-mark); + strbuf[dot-mark] = '\0'; + + if (slbt_dprintf(fdout," %s = %s\n",strbuf,++dot) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + } else if (fmach) { + if (slbt_dprintf(fdout,"_%s\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + } else { + if (slbt_dprintf(fdout,"\t\t%s;\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + if (!fcoff && !fmach) + if (slbt_dprintf(fdout,"\n\t" "local:\n" "\t\t*;\n" "};\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + return 0; +} + + +static int slbt_util_create_mapfile_impl( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + int ret; + const struct slbt_driver_ctx * dctx; + struct slbt_fd_ctx fdctx; + int fdout; + + dctx = (slbt_get_symlist_ictx(sctx))->dctx; + + if (slbt_lib_get_driver_fdctx(dctx,&fdctx) < 0) + return SLBT_NESTED_ERROR(dctx); + + if (path) { + if ((fdout = openat( + fdctx.fdcwd,path, + O_WRONLY|O_CREAT|O_TRUNC, + mode)) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + fdout = fdctx.fdout; + } + + ret = slbt_util_output_mapfile_impl( + dctx,sctx,fdout); + + if (path) { + close(fdout); + } + + return ret; +} + + +int slbt_util_create_mapfile( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + return slbt_util_create_mapfile_impl(sctx,path,mode); +} diff --git a/src/util/slbt_create_symfile.c b/src/util/slbt_create_symfile.c new file mode 100644 index 0000000..8c9b4be --- /dev/null +++ b/src/util/slbt_create_symfile.c @@ -0,0 +1,84 @@ +/*******************************************************************/ +/* 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 <time.h> +#include <locale.h> +#include <regex.h> +#include <inttypes.h> +#include <slibtool/slibtool.h> +#include <slibtool/slibtool_output.h> +#include "slibtool_driver_impl.h" +#include "slibtool_dprintf_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_pecoff_impl.h" +#include "slibtool_ar_impl.h" + +/********************************************************/ +/* Clone a symbol list that could be used by a build */ +/* system for code generation or any other purpose. */ +/********************************************************/ + +static int slbt_util_output_symfile_impl( + const struct slbt_driver_ctx * dctx, + const struct slbt_symlist_ctx * sctx, + int fdout) +{ + const char ** symv; + const char ** symstrv; + + symstrv = sctx->symstrv; + + for (symv=symstrv; *symv; symv++) + if (slbt_dprintf(fdout,"%s\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + return 0; +} + + +static int slbt_util_create_symfile_impl( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + int ret; + const struct slbt_driver_ctx * dctx; + struct slbt_fd_ctx fdctx; + int fdout; + + dctx = (slbt_get_symlist_ictx(sctx))->dctx; + + if (slbt_lib_get_driver_fdctx(dctx,&fdctx) < 0) + return SLBT_NESTED_ERROR(dctx); + + if (path) { + if ((fdout = openat( + fdctx.fdcwd,path, + O_WRONLY|O_CREAT|O_TRUNC, + mode)) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + fdout = fdctx.fdout; + } + + ret = slbt_util_output_symfile_impl( + dctx,sctx,fdout); + + if (path) { + close(fdout); + } + + return ret; +} + + +int slbt_util_create_symfile( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + return slbt_util_create_symfile_impl(sctx,path,mode); +} diff --git a/src/util/slbt_dump_machine.c b/src/util/slbt_dump_machine.c new file mode 100644 index 0000000..1b42211 --- /dev/null +++ b/src/util/slbt_dump_machine.c @@ -0,0 +1,135 @@ +/*******************************************************************/ +/* 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 <limits.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/wait.h> + +#include <slibtool/slibtool.h> +#include "slibtool_spawn_impl.h" +#include "slibtool_snprintf_impl.h" + +static void slbt_util_dump_machine_child( + char * program, + int fd[2]) +{ + char * compiler; + char * argv[3]; + + close(fd[0]); + + if ((compiler = strrchr(program,'/'))) + compiler++; + else + compiler = program; + + argv[0] = compiler; + argv[1] = "-dumpmachine"; + argv[2] = 0; + + if ((fd[0] = openat(AT_FDCWD,"/dev/null",O_RDONLY,0)) >= 0) + if (dup2(fd[0],0) == 0) + if (dup2(fd[1],1) == 1) + execvp(program,argv); + + _exit(EXIT_FAILURE); +} + +int slbt_util_dump_machine( + const char * compiler, + char * machine, + size_t buflen) +{ + ssize_t ret; + pid_t pid; + pid_t rpid; + int code; + int fd[2]; + char * mark; + char program[PATH_MAX]; + + /* setup */ + if (!machine || !buflen || !--buflen) { + errno = EINVAL; + return -1; + } + + if (slbt_snprintf(program,sizeof(program), + "%s",compiler) < 0) + return -1; + + /* fork */ + if (pipe(fd)) + return -1; + + if ((pid = slbt_fork()) < 0) { + close(fd[0]); + close(fd[1]); + return -1; + } + + /* child */ + if (pid == 0) + slbt_util_dump_machine_child( + program, + fd); + + /* parent */ + close(fd[1]); + + mark = machine; + + for (; buflen; ) { + ret = read(fd[0],mark,buflen); + + while ((ret < 0) && (errno == EINTR)) + ret = read(fd[0],mark,buflen); + + if (ret > 0) { + buflen -= ret; + mark += ret; + + } else if (ret == 0) { + close(fd[0]); + buflen = 0; + + } else { + close(fd[0]); + return -1; + } + } + + /* execve verification */ + rpid = waitpid( + pid, + &code, + 0); + + if ((rpid != pid) || code) { + errno = ESTALE; + return -1; + } + + /* newline verification */ + if ((mark == machine) || (*--mark != '\n')) { + errno = ERANGE; + return -1; + } + + *mark = 0; + + /* portbld <--> unknown synonym? */ + if ((mark = strstr(machine,"-portbld-"))) + memcpy(mark,"-unknown",8); + + /* all done */ + return 0; +} diff --git a/src/util/slbt_map_input.c b/src/util/slbt_map_input.c new file mode 100644 index 0000000..d99b4ba --- /dev/null +++ b/src/util/slbt_map_input.c @@ -0,0 +1,67 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <slibtool/slibtool.h> +#include "slibtool_driver_impl.h" +#include "slibtool_errinfo_impl.h" + +int slbt_fs_map_input( + const struct slbt_driver_ctx * dctx, + int fd, + const char * path, + int prot, + struct slbt_input * map) +{ + int ret; + struct stat st; + bool fnew; + int fdcwd; + + fdcwd = slbt_driver_fdcwd(dctx); + + if ((fnew = (fd < 0))) + fd = openat(fdcwd,path,O_RDONLY | O_CLOEXEC); + + if (fd < 0) + return SLBT_SYSTEM_ERROR(dctx,path); + + if ((ret = fstat(fd,&st) < 0) && fnew) + close(fd); + + else if ((st.st_size == 0) && fnew) + close(fd); + + if (ret < 0) + return SLBT_SYSTEM_ERROR(dctx,path); + + if (st.st_size == 0) { + map->size = 0; + map->addr = 0; + } else { + map->size = st.st_size; + map->addr = mmap(0,map->size,prot,MAP_PRIVATE,fd,0); + } + + if (fnew) + close(fd); + + return (map->addr == MAP_FAILED) + ? SLBT_SYSTEM_ERROR(dctx,path) + : 0; +} + +int slbt_fs_unmap_input(struct slbt_input * map) +{ + return map->size ? munmap(map->addr,map->size) : 0; +} diff --git a/src/util/slbt_realpath.c b/src/util/slbt_realpath.c new file mode 100644 index 0000000..823f3a0 --- /dev/null +++ b/src/util/slbt_realpath.c @@ -0,0 +1,18 @@ +/*******************************************************************/ +/* 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_realpath_impl.h" + +int slbt_util_real_path( + int fdat, + const char * path, + int options, + char * buf, + size_t buflen) +{ + return slbt_realpath(fdat,path,options,buf,buflen); +} |