|
|
6529aa |
/*******************************************************************/
|
|
|
6529aa |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
49181b |
/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
|
|
|
6529aa |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
6529aa |
/*******************************************************************/
|
|
|
6529aa |
|
|
|
6529aa |
#include <stdio.h>
|
|
|
6529aa |
#include <string.h>
|
|
|
6529aa |
#include <stdbool.h>
|
|
|
6529aa |
#include <unistd.h>
|
|
|
6529aa |
|
|
|
b8d3bb |
#include "slibtool_driver_impl.h"
|
|
|
d56ead |
#include "slibtool_errinfo_impl.h"
|
|
|
6529aa |
#include "slibtool_symlink_impl.h"
|
|
|
2baf1c |
#include "slibtool_readlink_impl.h"
|
|
|
19022e |
#include "slibtool_snprintf_impl.h"
|
|
|
4b56de |
#include "slibtool_visibility_impl.h"
|
|
|
6529aa |
|
|
|
ec5e56 |
#define SLBT_DEV_NULL_FLAGS (SLBT_DRIVER_ALL_STATIC \
|
|
|
ec5e56 |
| SLBT_DRIVER_DISABLE_SHARED \
|
|
|
ec5e56 |
| SLBT_DRIVER_DISABLE_STATIC)
|
|
|
d1e257 |
|
|
|
4b56de |
slbt_hidden int slbt_create_symlink(
|
|
|
6529aa |
const struct slbt_driver_ctx * dctx,
|
|
|
6529aa |
struct slbt_exec_ctx * ectx,
|
|
|
6529aa |
const char * target,
|
|
|
e0a045 |
const char * lnkname,
|
|
|
cc0827 |
uint32_t options)
|
|
|
6529aa |
{
|
|
|
b8d3bb |
int fdcwd;
|
|
|
cc0827 |
int fliteral;
|
|
|
cc0827 |
int fwrapper;
|
|
|
c7981c |
int fdevnull;
|
|
|
660491 |
char ** oargv;
|
|
|
6529aa |
const char * slash;
|
|
|
6529aa |
char * ln[5];
|
|
|
9c46bd |
char * dot;
|
|
|
6529aa |
char * dotdot;
|
|
|
6529aa |
char tmplnk [PATH_MAX];
|
|
|
e0a045 |
char lnkarg [PATH_MAX];
|
|
|
2baf1c |
char alnkarg[PATH_MAX];
|
|
|
6529aa |
char atarget[PATH_MAX];
|
|
|
2baf1c |
char * suffix = 0;
|
|
|
6529aa |
|
|
|
cc0827 |
/* options */
|
|
|
cc0827 |
fliteral = (options & SLBT_SYMLINK_LITERAL);
|
|
|
cc0827 |
fwrapper = (options & SLBT_SYMLINK_WRAPPER);
|
|
|
c7981c |
fdevnull = (options & SLBT_SYMLINK_DEVNULL);
|
|
|
cc0827 |
|
|
|
2baf1c |
/* symlink is a placeholder? */
|
|
|
93e38b |
if (fliteral) {
|
|
|
c7981c |
slash = target;
|
|
|
c7981c |
|
|
|
93e38b |
/* .disabled .so or .a file */
|
|
|
93e38b |
} else if (fdevnull) {
|
|
|
2baf1c |
slash = target;
|
|
|
2baf1c |
suffix = ".disabled";
|
|
|
2baf1c |
|
|
|
2baf1c |
/* symlink target contains a dirname? */
|
|
|
2baf1c |
} else if ((slash = strrchr(target,'/'))) {
|
|
|
6529aa |
slash++;
|
|
|
2baf1c |
|
|
|
2baf1c |
/* symlink target is a basename */
|
|
|
2baf1c |
} else {
|
|
|
6529aa |
slash = target;
|
|
|
2baf1c |
}
|
|
|
6529aa |
|
|
|
2baf1c |
/* .la wrapper? */
|
|
|
cc0827 |
dotdot = fwrapper ? "../" : "";
|
|
|
6529aa |
|
|
|
2baf1c |
/* atarget */
|
|
|
19022e |
if (slbt_snprintf(atarget,sizeof(atarget),
|
|
|
19022e |
"%s%s",dotdot,slash) < 0)
|
|
|
d56ead |
return SLBT_BUFFER_ERROR(dctx);
|
|
|
6529aa |
|
|
|
6529aa |
/* tmplnk */
|
|
|
19022e |
if (slbt_snprintf(tmplnk,sizeof(tmplnk),
|
|
|
19022e |
"%s.symlink.tmp",
|
|
|
19022e |
lnkname) <0)
|
|
|
d56ead |
return SLBT_BUFFER_ERROR(dctx);
|
|
|
6529aa |
|
|
|
a06474 |
/* fdcwd */
|
|
|
a06474 |
fdcwd = slbt_driver_fdcwd(dctx);
|
|
|
a06474 |
|
|
|
2baf1c |
/* placeholder? */
|
|
|
9c46bd |
if (fdevnull) {
|
|
|
a06474 |
if (unlinkat(fdcwd,lnkname,0) && (errno != ENOENT))
|
|
|
a06474 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
a06474 |
|
|
|
9c46bd |
if ((dot = strrchr(lnkname,'.'))) {
|
|
|
9c46bd |
if (!strcmp(dot,dctx->cctx->settings.dsosuffix)) {
|
|
|
9c46bd |
strcpy(dot,".expsyms.a");
|
|
|
9c46bd |
|
|
|
9c46bd |
if (unlinkat(fdcwd,lnkname,0) && (errno != ENOENT))
|
|
|
9c46bd |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
9c46bd |
|
|
|
9c46bd |
strcpy(dot,dctx->cctx->settings.dsosuffix);
|
|
|
9c46bd |
}
|
|
|
9c46bd |
}
|
|
|
9c46bd |
}
|
|
|
9c46bd |
|
|
|
2baf1c |
if (suffix) {
|
|
|
2baf1c |
sprintf(alnkarg,"%s%s",lnkname,suffix);
|
|
|
2baf1c |
lnkname = alnkarg;
|
|
|
2baf1c |
}
|
|
|
2baf1c |
|
|
|
e0a045 |
/* lnkarg */
|
|
|
e0a045 |
strcpy(lnkarg,lnkname);
|
|
|
e0a045 |
|
|
|
6529aa |
/* ln argv (fake) */
|
|
|
6529aa |
ln[0] = "ln";
|
|
|
6529aa |
ln[1] = "-s";
|
|
|
6529aa |
ln[2] = atarget;
|
|
|
e0a045 |
ln[3] = lnkarg;
|
|
|
6529aa |
ln[4] = 0;
|
|
|
660491 |
|
|
|
660491 |
oargv = ectx->argv;
|
|
|
6529aa |
ectx->argv = ln;
|
|
|
6529aa |
|
|
|
6529aa |
/* step output */
|
|
|
dc77cb |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT)) {
|
|
|
5e1c21 |
if (dctx->cctx->mode == SLBT_MODE_LINK) {
|
|
|
33a569 |
if (slbt_output_link(ectx)) {
|
|
|
660491 |
ectx->argv = oargv;
|
|
|
d56ead |
return SLBT_NESTED_ERROR(dctx);
|
|
|
660491 |
}
|
|
|
5e1c21 |
} else {
|
|
|
33a569 |
if (slbt_output_install(ectx)) {
|
|
|
660491 |
ectx->argv = oargv;
|
|
|
d56ead |
return SLBT_NESTED_ERROR(dctx);
|
|
|
660491 |
}
|
|
|
5e1c21 |
}
|
|
|
dc77cb |
}
|
|
|
dc77cb |
|
|
|
660491 |
/* restore execution context */
|
|
|
660491 |
ectx->argv = oargv;
|
|
|
660491 |
|
|
|
6529aa |
/* create symlink */
|
|
|
b8d3bb |
if (symlinkat(atarget,fdcwd,tmplnk))
|
|
|
6beda1 |
return SLBT_SYSTEM_ERROR(dctx,tmplnk);
|
|
|
6529aa |
|
|
|
d586fc |
return renameat(fdcwd,tmplnk,fdcwd,lnkname)
|
|
|
6beda1 |
? SLBT_SYSTEM_ERROR(dctx,lnkname)
|
|
|
d56ead |
: 0;
|
|
|
6529aa |
}
|
|
|
2baf1c |
|
|
|
fc7ad9 |
slbt_hidden int slbt_symlink_is_a_placeholder(int fdcwd, const char * lnkpath)
|
|
|
2baf1c |
{
|
|
|
2baf1c |
size_t len;
|
|
|
2baf1c |
char slink [PATH_MAX];
|
|
|
2baf1c |
char target[PATH_MAX];
|
|
|
2baf1c |
const char suffix[] = ".disabled";
|
|
|
2baf1c |
|
|
|
2baf1c |
if ((sizeof(slink)-sizeof(suffix)) < (len=strlen(lnkpath)))
|
|
|
2baf1c |
return 0;
|
|
|
2baf1c |
|
|
|
2baf1c |
memcpy(slink,lnkpath,len);
|
|
|
2baf1c |
memcpy(&slink[len],suffix,sizeof(suffix));
|
|
|
2baf1c |
|
|
|
c81d16 |
return (!slbt_readlinkat(fdcwd,slink,target,sizeof(target)))
|
|
|
2baf1c |
&& (!strcmp(target,"/dev/null"));
|
|
|
2baf1c |
}
|