summaryrefslogtreecommitdiffhomepage
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/slbt_archive_import.c69
-rw-r--r--src/util/slbt_copy_file.c76
-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.c101
5 files changed, 448 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..5657fcc
--- /dev/null
+++ b/src/util/slbt_archive_import.c
@@ -0,0 +1,69 @@
+/*******************************************************************/
+/* slibtool: a skinny 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(
+ const struct slbt_driver_ctx * dctx,
+ 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,
+ 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_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ char * dstarchive,
+ char * srcarchive)
+{
+ 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..30d3f03
--- /dev/null
+++ b/src/util/slbt_copy_file.c
@@ -0,0 +1,76 @@
+/*******************************************************************/
+/* slibtool: a skinny 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(
+ const struct slbt_driver_ctx * dctx,
+ struct slbt_exec_ctx * ectx,
+ char * src,
+ char * dst)
+{
+ int fdcwd;
+ char ** oargv;
+ char * oprogram;
+ char * cp[4];
+ int ret;
+
+ /* fdcwd */
+ fdcwd = slbt_driver_fdcwd(dctx);
+
+ /* placeholder? */
+ if (slbt_symlink_is_a_placeholder(fdcwd,src))
+ return 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(dctx,ectx)) {
+ ectx->argv = oargv;
+ ectx->program = oprogram;
+ return SLBT_NESTED_ERROR(dctx);
+ }
+ } else {
+ if (slbt_output_install(dctx,ectx)) {
+ ectx->argv = oargv;
+ ectx->program = oprogram;
+ 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;
+ }
+
+ ectx->argv = oargv;
+ ectx->program = oprogram;
+ return ret;
+}
diff --git a/src/util/slbt_dump_machine.c b/src/util/slbt_dump_machine.c
new file mode 100644
index 0000000..bf86315
--- /dev/null
+++ b/src/util/slbt_dump_machine.c
@@ -0,0 +1,135 @@
+/*******************************************************************/
+/* slibtool: a skinny 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 = 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..ca0b06b
--- /dev/null
+++ b/src/util/slbt_map_input.c
@@ -0,0 +1,67 @@
+/*******************************************************************/
+/* slibtool: a skinny 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_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_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..3929e04
--- /dev/null
+++ b/src/util/slbt_realpath.c
@@ -0,0 +1,101 @@
+/*******************************************************************/
+/* slibtool: a skinny 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"
+
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+
+#ifdef _MIDIPIX_ABI
+#include <sys/fs.h>
+#endif
+
+#ifndef ENOTSUP
+#define ENOTSUP EOPNOTSUPP
+#endif
+
+#ifdef SYS___realpathat
+extern long syscall(int, ...);
+#endif
+
+int slbt_util_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;
+}