|
|
0801fe |
/*******************************************************************/
|
|
|
0801fe |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
0801fe |
/* Copyright (C) 2016--2018 Z. Gilboa */
|
|
|
0801fe |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
0801fe |
/*******************************************************************/
|
|
|
0801fe |
|
|
|
0801fe |
#include <fcntl.h>
|
|
|
0801fe |
#include <stdio.h>
|
|
|
0801fe |
#include <stdint.h>
|
|
|
0801fe |
#include <stdbool.h>
|
|
|
0801fe |
#include <unistd.h>
|
|
|
0801fe |
#include <sys/mman.h>
|
|
|
0801fe |
#include <sys/stat.h>
|
|
|
0801fe |
|
|
|
0801fe |
#include "slibtool_lconf_impl.h"
|
|
|
0801fe |
#include "slibtool_driver_impl.h"
|
|
|
0801fe |
#include "slibtool_errinfo_impl.h"
|
|
|
0801fe |
#include "slibtool_symlink_impl.h"
|
|
|
0801fe |
#include "slibtool_readlink_impl.h"
|
|
|
0801fe |
|
|
|
0801fe |
enum slbt_lconf_opt {
|
|
|
0801fe |
SLBT_LCONF_OPT_UNKNOWN,
|
|
|
0801fe |
SLBT_LCONF_OPT_NO,
|
|
|
0801fe |
SLBT_LCONF_OPT_YES,
|
|
|
0801fe |
};
|
|
|
0801fe |
|
|
|
0801fe |
static void slbt_lconf_close(int fdcwd, int fdlconfdir)
|
|
|
0801fe |
{
|
|
|
0801fe |
if (fdlconfdir != fdcwd)
|
|
|
0801fe |
close(fdlconfdir);
|
|
|
0801fe |
}
|
|
|
0801fe |
|
|
|
0801fe |
static int slbt_lconf_open(
|
|
|
0801fe |
struct slbt_driver_ctx * dctx,
|
|
|
0801fe |
const char * lconf)
|
|
|
0801fe |
{
|
|
|
0801fe |
int fdcwd;
|
|
|
0801fe |
int fdlconf;
|
|
|
0801fe |
int fdlconfdir;
|
|
|
0801fe |
int fdparent;
|
|
|
0801fe |
struct stat stcwd;
|
|
|
0801fe |
struct stat stparent;
|
|
|
0b404d |
ino_t stinode;
|
|
|
0801fe |
|
|
|
0801fe |
fdcwd = slbt_driver_fdcwd(dctx);
|
|
|
0801fe |
fdlconfdir = fdcwd;
|
|
|
0801fe |
|
|
|
d70e37 |
if (lconf && strchr(lconf,'/'))
|
|
|
0801fe |
return ((fdlconf = openat(fdcwd,lconf,O_RDONLY,0)) < 0)
|
|
|
0801fe |
? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_LCONF_OPEN)
|
|
|
0801fe |
: fdlconf;
|
|
|
0801fe |
|
|
|
0801fe |
if (fstatat(fdlconfdir,".",&stcwd,0) < 0)
|
|
|
6beda1 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
0801fe |
|
|
|
d70e37 |
lconf = lconf ? lconf : "libtool";
|
|
|
d70e37 |
fdlconf = openat(fdlconfdir,lconf,O_RDONLY,0);
|
|
|
0b404d |
stinode = stcwd.st_ino;
|
|
|
0801fe |
|
|
|
0801fe |
while (fdlconf < 0) {
|
|
|
0801fe |
fdparent = openat(fdlconfdir,"../",O_DIRECTORY,0);
|
|
|
0801fe |
slbt_lconf_close(fdcwd,fdlconfdir);
|
|
|
0801fe |
|
|
|
0801fe |
if (fdparent < 0)
|
|
|
6beda1 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
0801fe |
|
|
|
bab3d0 |
if (fstat(fdparent,&stparent) < 0) {
|
|
|
bab3d0 |
close(fdparent);
|
|
|
6beda1 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
bab3d0 |
}
|
|
|
0801fe |
|
|
|
bab3d0 |
if (stparent.st_dev != stcwd.st_dev) {
|
|
|
bab3d0 |
close(fdparent);
|
|
|
0801fe |
return SLBT_CUSTOM_ERROR(
|
|
|
0801fe |
dctx,SLBT_ERR_LCONF_OPEN);
|
|
|
bab3d0 |
}
|
|
|
0801fe |
|
|
|
0b404d |
if (stparent.st_ino == stinode) {
|
|
|
0b404d |
close(fdparent);
|
|
|
0b404d |
return SLBT_CUSTOM_ERROR(
|
|
|
0b404d |
dctx,SLBT_ERR_LCONF_OPEN);
|
|
|
0b404d |
}
|
|
|
0b404d |
|
|
|
0801fe |
fdlconfdir = fdparent;
|
|
|
d70e37 |
fdlconf = openat(fdlconfdir,lconf,O_RDONLY,0);
|
|
|
0b404d |
stinode = stparent.st_ino;
|
|
|
0801fe |
}
|
|
|
0801fe |
|
|
|
bab3d0 |
slbt_lconf_close(fdcwd,fdlconfdir);
|
|
|
bab3d0 |
|
|
|
0801fe |
return fdlconf;
|
|
|
0801fe |
}
|
|
|
0801fe |
|
|
|
0801fe |
int slbt_get_lconf_flags(
|
|
|
0801fe |
struct slbt_driver_ctx * dctx,
|
|
|
0801fe |
const char * lconf,
|
|
|
0801fe |
uint64_t * flags)
|
|
|
0801fe |
{
|
|
|
0801fe |
int fdlconf;
|
|
|
0801fe |
struct stat st;
|
|
|
0801fe |
void * addr;
|
|
|
0801fe |
const char * mark;
|
|
|
0801fe |
const char * cap;
|
|
|
0801fe |
uint64_t optshared;
|
|
|
0801fe |
uint64_t optstatic;
|
|
|
0801fe |
int optlenmax;
|
|
|
0801fe |
int optsharedlen;
|
|
|
0801fe |
int optstaticlen;
|
|
|
0801fe |
const char * optsharedstr;
|
|
|
0801fe |
const char * optstaticstr;
|
|
|
0801fe |
|
|
|
0801fe |
/* open relative libtool script */
|
|
|
0801fe |
if ((fdlconf = slbt_lconf_open(dctx,lconf)) < 0)
|
|
|
0801fe |
return SLBT_NESTED_ERROR(dctx);
|
|
|
0801fe |
|
|
|
0801fe |
/* map relative libtool script */
|
|
|
0801fe |
if (fstat(fdlconf,&st) < 0)
|
|
|
6beda1 |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
0801fe |
|
|
|
0801fe |
addr = mmap(
|
|
|
0801fe |
0,st.st_size,
|
|
|
0801fe |
PROT_READ,MAP_SHARED,
|
|
|
0801fe |
fdlconf,0);
|
|
|
0801fe |
|
|
|
0801fe |
close(fdlconf);
|
|
|
0801fe |
|
|
|
0801fe |
if (addr == MAP_FAILED)
|
|
|
0801fe |
return SLBT_CUSTOM_ERROR(
|
|
|
0801fe |
dctx,SLBT_ERR_LCONF_MAP);
|
|
|
0801fe |
|
|
|
0801fe |
mark = addr;
|
|
|
0801fe |
cap = &mark[st.st_size];
|
|
|
0801fe |
|
|
|
0801fe |
/* hard-coded options in the generated libtool precede the code */
|
|
|
0801fe |
if (st.st_size >= (optlenmax = strlen("build_libtool_libs=yes\n")))
|
|
|
0801fe |
cap -= optlenmax;
|
|
|
0801fe |
|
|
|
0801fe |
/* scan */
|
|
|
0801fe |
optshared = 0;
|
|
|
0801fe |
optstatic = 0;
|
|
|
0801fe |
|
|
|
0801fe |
optsharedstr = "build_libtool_libs=";
|
|
|
0801fe |
optstaticstr = "build_old_libs=";
|
|
|
0801fe |
|
|
|
0801fe |
optsharedlen = strlen(optsharedstr);
|
|
|
0801fe |
optstaticlen = strlen(optstaticstr);
|
|
|
0801fe |
|
|
|
0801fe |
for (; mark && mark
|
|
|
0801fe |
if (!strncmp(mark,optsharedstr,optsharedlen)) {
|
|
|
0801fe |
mark += optsharedlen;
|
|
|
0801fe |
|
|
|
0801fe |
if ((mark[0]=='n')
|
|
|
0801fe |
&& (mark[1]=='o')
|
|
|
0801fe |
&& (mark[2]=='\n'))
|
|
|
0801fe |
optshared = SLBT_DRIVER_DISABLE_SHARED;
|
|
|
0801fe |
|
|
|
0801fe |
if ((mark[0]=='y')
|
|
|
0801fe |
&& (mark[1]=='e')
|
|
|
0801fe |
&& (mark[2]=='s')
|
|
|
0801fe |
&& (mark[3]=='\n'))
|
|
|
0801fe |
optshared = SLBT_DRIVER_SHARED;
|
|
|
0801fe |
|
|
|
0801fe |
} if (!strncmp(mark,optstaticstr,optstaticlen)) {
|
|
|
0801fe |
mark += optstaticlen;
|
|
|
0801fe |
|
|
|
0801fe |
if ((mark[0]=='n')
|
|
|
0801fe |
&& (mark[1]=='o')
|
|
|
0801fe |
&& (mark[2]=='\n'))
|
|
|
0801fe |
optstatic = SLBT_DRIVER_DISABLE_STATIC;
|
|
|
0801fe |
|
|
|
0801fe |
if ((mark[0]=='y')
|
|
|
0801fe |
&& (mark[1]=='e')
|
|
|
0801fe |
&& (mark[2]=='s')
|
|
|
0801fe |
&& (mark[3]=='\n'))
|
|
|
0801fe |
optstatic = SLBT_DRIVER_STATIC;
|
|
|
0801fe |
}
|
|
|
0801fe |
|
|
|
0801fe |
if (optshared && optstatic)
|
|
|
0801fe |
mark = 0;
|
|
|
0801fe |
|
|
|
0801fe |
else {
|
|
|
0801fe |
for (; (mark
|
|
|
0801fe |
mark++;
|
|
|
0801fe |
mark++;
|
|
|
0801fe |
}
|
|
|
0801fe |
}
|
|
|
0801fe |
|
|
|
0801fe |
munmap(addr,st.st_size);
|
|
|
0801fe |
|
|
|
0801fe |
if (!optshared || !optstatic)
|
|
|
0801fe |
return SLBT_CUSTOM_ERROR(
|
|
|
0801fe |
dctx,SLBT_ERR_LCONF_PARSE);
|
|
|
0801fe |
|
|
|
0801fe |
*flags = optshared | optstatic;
|
|
|
0801fe |
|
|
|
0801fe |
return 0;
|
|
|
0801fe |
}
|