summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/slbt_archive_import.c71
-rw-r--r--src/util/slbt_copy_file.c96
-rw-r--r--src/util/slbt_create_mapfile.c132
-rw-r--r--src/util/slbt_create_symfile.c84
-rw-r--r--src/util/slbt_dump_machine.c135
-rw-r--r--src/util/slbt_map_input.c67
-rw-r--r--src/util/slbt_realpath.c18
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);
+}