diff options
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | project/tree.mk | 1 | ||||
-rw-r--r-- | src/fallback/slbt_archive_import_mri.c | 163 | ||||
-rw-r--r-- | src/helper/slbt_archive_import.c | 154 |
4 files changed, 174 insertions, 145 deletions
diff --git a/project/common.mk b/project/common.mk index b22c1b7..40c0fa4 100644 --- a/project/common.mk +++ b/project/common.mk @@ -9,6 +9,7 @@ API_SRCS = \ src/arbits/output/slbt_ar_output_members.c \ src/driver/slbt_amain.c \ src/driver/slbt_driver_ctx.c \ + src/fallback/slbt_archive_import_mri.c \ src/helper/slbt_archive_import.c \ src/helper/slbt_copy_file.c \ src/helper/slbt_dump_machine.c \ diff --git a/project/tree.mk b/project/tree.mk index f147466..978e313 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -2,6 +2,7 @@ tree.tag: mkdir -p src mkdir -p src/arbits mkdir -p src/driver + mkdir -p src/fallback mkdir -p src/helper mkdir -p src/internal mkdir -p src/logic diff --git a/src/fallback/slbt_archive_import_mri.c b/src/fallback/slbt_archive_import_mri.c new file mode 100644 index 0000000..fb880c2 --- /dev/null +++ b/src/fallback/slbt_archive_import_mri.c @@ -0,0 +1,163 @@ +/*******************************************************************/ +/* 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 <fcntl.h> +#include <stdio.h> +#include <limits.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/wait.h> + +#include <slibtool/slibtool.h> +#include "slibtool_driver_impl.h" +#include "slibtool_spawn_impl.h" +#include "slibtool_dprintf_impl.h" +#include "slibtool_symlink_impl.h" +#include "slibtool_readlink_impl.h" +#include "slibtool_errinfo_impl.h" + +static char * slbt_mri_argument( + int fdat, + char * arg, + char * buf) +{ + int i; + char * lnk; + char * target; + char mricwd[PATH_MAX]; + char dstbuf[PATH_MAX]; + + if ((!(strchr(arg,'+'))) && (!(strchr(arg,'-')))) + return arg; + + if (arg[0] == '/') + target = arg; + else { + if (slbt_realpath(fdat,".",O_DIRECTORY,mricwd,sizeof(mricwd))) + return 0; + + if ((size_t)snprintf(dstbuf,sizeof(dstbuf),"%s/%s", + mricwd,arg) >= sizeof(dstbuf)) + return 0; + + target = dstbuf; + } + + for (i=0,lnk=0; i<1024 && !lnk; i++) { + if (!(tmpnam(buf))) + return 0; + + if (!(symlinkat(target,fdat,buf))) + lnk = buf; + } + + return lnk; +} + +static void slbt_archive_import_child( + char * program, + int fd[2]) +{ + char * argv[3]; + + argv[0] = program; + argv[1] = "-M"; + argv[2] = 0; + + close(fd[1]); + + if (dup2(fd[0],0) == 0) + execvp(program,argv); + + _exit(EXIT_FAILURE); +} + +int slbt_archive_import_mri( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + char * dstarchive, + char * srcarchive) +{ + int fdcwd; + pid_t pid; + pid_t rpid; + int fd[2]; + char * dst; + char * src; + char * fmt; + char mridst [L_tmpnam]; + char mrisrc [L_tmpnam]; + char program[PATH_MAX]; + + /* fdcwd */ + fdcwd = slbt_driver_fdcwd(dctx); + + /* not needed? */ + if (slbt_symlink_is_a_placeholder(fdcwd,srcarchive)) + return 0; + + /* program */ + if ((size_t)snprintf(program,sizeof(program), + "%s", + dctx->cctx->host.ar) + >= sizeof(program)) + return SLBT_BUFFER_ERROR(dctx); + + /* fork */ + if (pipe(fd)) + return SLBT_SYSTEM_ERROR(dctx,0); + + if ((pid = fork()) < 0) { + close(fd[0]); + close(fd[1]); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + /* child */ + if (pid == 0) + slbt_archive_import_child( + program, + fd); + + /* parent */ + close(fd[0]); + + ectx->pid = pid; + + dst = slbt_mri_argument(fdcwd,dstarchive,mridst); + src = slbt_mri_argument(fdcwd,srcarchive,mrisrc); + + if (!dst || !src) + return SLBT_SYSTEM_ERROR(dctx,0); + + fmt = "OPEN %s\n" + "ADDLIB %s\n" + "SAVE\n" + "END\n"; + + if (slbt_dprintf(fd[1],fmt,dst,src) < 0) { + close(fd[1]); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + close(fd[1]); + + rpid = waitpid( + pid, + &ectx->exitcode, + 0); + + if (dst == mridst) + unlinkat(fdcwd,dst,0); + + if (src == mrisrc) + unlinkat(fdcwd,src,0); + + return (rpid == pid) && (ectx->exitcode == 0) + ? 0 : SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_ARCHIVE_IMPORT); +} diff --git a/src/helper/slbt_archive_import.c b/src/helper/slbt_archive_import.c index e8ea5aa..620ac3b 100644 --- a/src/helper/slbt_archive_import.c +++ b/src/helper/slbt_archive_import.c @@ -4,78 +4,15 @@ /* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ /*******************************************************************/ -#include <fcntl.h> -#include <stdio.h> -#include <limits.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <stdbool.h> -#include <sys/wait.h> - #include <slibtool/slibtool.h> #include "slibtool_driver_impl.h" -#include "slibtool_spawn_impl.h" -#include "slibtool_dprintf_impl.h" -#include "slibtool_symlink_impl.h" -#include "slibtool_readlink_impl.h" #include "slibtool_errinfo_impl.h" -static char * slbt_mri_argument( - int fdat, - char * arg, - char * buf) -{ - int i; - char * lnk; - char * target; - char mricwd[PATH_MAX]; - char dstbuf[PATH_MAX]; - - if ((!(strchr(arg,'+'))) && (!(strchr(arg,'-')))) - return arg; - - if (arg[0] == '/') - target = arg; - else { - if (slbt_realpath(fdat,".",O_DIRECTORY,mricwd,sizeof(mricwd))) - return 0; - - if ((size_t)snprintf(dstbuf,sizeof(dstbuf),"%s/%s", - mricwd,arg) >= sizeof(dstbuf)) - return 0; - - target = dstbuf; - } - - for (i=0,lnk=0; i<1024 && !lnk; i++) { - if (!(tmpnam(buf))) - return 0; - - if (!(symlinkat(target,fdat,buf))) - lnk = buf; - } - - return lnk; -} - -static void slbt_archive_import_child( - char * program, - int fd[2]) -{ - char * argv[3]; - - argv[0] = program; - argv[1] = "-M"; - argv[2] = 0; - - close(fd[1]); - - if (dup2(fd[0],0) == 0) - execvp(program,argv); - - _exit(EXIT_FAILURE); -} +extern int slbt_archive_import_mri( + const struct slbt_driver_ctx * dctx, + struct slbt_exec_ctx * ectx, + char * dstarchive, + char * srcarchive); int slbt_archive_import( const struct slbt_driver_ctx * dctx, @@ -83,81 +20,8 @@ int slbt_archive_import( char * dstarchive, char * srcarchive) { - int fdcwd; - pid_t pid; - pid_t rpid; - int fd[2]; - char * dst; - char * src; - char * fmt; - char mridst [L_tmpnam]; - char mrisrc [L_tmpnam]; - char program[PATH_MAX]; - - /* fdcwd */ - fdcwd = slbt_driver_fdcwd(dctx); - - /* not needed? */ - if (slbt_symlink_is_a_placeholder(fdcwd,srcarchive)) - return 0; - - /* program */ - if ((size_t)snprintf(program,sizeof(program), - "%s", - dctx->cctx->host.ar) - >= sizeof(program)) - return SLBT_BUFFER_ERROR(dctx); - - /* fork */ - if (pipe(fd)) - return SLBT_SYSTEM_ERROR(dctx,0); - - if ((pid = fork()) < 0) { - close(fd[0]); - close(fd[1]); - return SLBT_SYSTEM_ERROR(dctx,0); - } - - /* child */ - if (pid == 0) - slbt_archive_import_child( - program, - fd); - - /* parent */ - close(fd[0]); - - ectx->pid = pid; - - dst = slbt_mri_argument(fdcwd,dstarchive,mridst); - src = slbt_mri_argument(fdcwd,srcarchive,mrisrc); - - if (!dst || !src) - return SLBT_SYSTEM_ERROR(dctx,0); - - fmt = "OPEN %s\n" - "ADDLIB %s\n" - "SAVE\n" - "END\n"; - - if (slbt_dprintf(fd[1],fmt,dst,src) < 0) { - close(fd[1]); - return SLBT_SYSTEM_ERROR(dctx,0); - } - - close(fd[1]); - - rpid = waitpid( - pid, - &ectx->exitcode, - 0); - - if (dst == mridst) - unlinkat(fdcwd,dst,0); - - if (src == mrisrc) - unlinkat(fdcwd,src,0); - - return (rpid == pid) && (ectx->exitcode == 0) - ? 0 : SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_ARCHIVE_IMPORT); + return slbt_archive_import_mri( + dctx,ectx, + dstarchive, + srcarchive); } |