| |
| |
| |
| |
| |
| |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stdbool.h> |
| #include <unistd.h> |
| #include <sys/mman.h> |
| #include <sys/stat.h> |
| |
| #include "slibtool_lconf_impl.h" |
| #include "slibtool_driver_impl.h" |
| #include "slibtool_errinfo_impl.h" |
| #include "slibtool_symlink_impl.h" |
| #include "slibtool_readlink_impl.h" |
| |
| enum slbt_lconf_opt { |
| SLBT_LCONF_OPT_UNKNOWN, |
| SLBT_LCONF_OPT_NO, |
| SLBT_LCONF_OPT_YES, |
| }; |
| |
| static void slbt_lconf_close(int fdcwd, int fdlconfdir) |
| { |
| if (fdlconfdir != fdcwd) |
| close(fdlconfdir); |
| } |
| |
| static int slbt_lconf_open( |
| struct slbt_driver_ctx * dctx, |
| const char * lconf) |
| { |
| int fdcwd; |
| int fdlconf; |
| int fdlconfdir; |
| int fdparent; |
| struct stat stcwd; |
| struct stat stparent; |
| |
| fdcwd = slbt_driver_fdcwd(dctx); |
| fdlconfdir = fdcwd; |
| |
| if (lconf) |
| return ((fdlconf = openat(fdcwd,lconf,O_RDONLY,0)) < 0) |
| ? SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_LCONF_OPEN) |
| : fdlconf; |
| |
| if (fstatat(fdlconfdir,".",&stcwd,0) < 0) |
| return SLBT_SYSTEM_ERROR(dctx); |
| |
| fdlconf = openat(fdlconfdir,"libtool",O_RDONLY,0); |
| |
| while (fdlconf < 0) { |
| fdparent = openat(fdlconfdir,"../",O_DIRECTORY,0); |
| slbt_lconf_close(fdcwd,fdlconfdir); |
| |
| if (fdparent < 0) |
| return SLBT_SYSTEM_ERROR(dctx); |
| |
| if (fstat(fdparent,&stparent) < 0) { |
| close(fdparent); |
| return SLBT_SYSTEM_ERROR(dctx); |
| } |
| |
| if (stparent.st_dev != stcwd.st_dev) { |
| close(fdparent); |
| return SLBT_CUSTOM_ERROR( |
| dctx,SLBT_ERR_LCONF_OPEN); |
| } |
| |
| fdlconfdir = fdparent; |
| fdlconf = openat(fdlconfdir,"libtool",O_RDONLY,0); |
| } |
| |
| slbt_lconf_close(fdcwd,fdlconfdir); |
| |
| return fdlconf; |
| } |
| |
| int slbt_get_lconf_flags( |
| struct slbt_driver_ctx * dctx, |
| const char * lconf, |
| uint64_t * flags) |
| { |
| int fdlconf; |
| struct stat st; |
| void * addr; |
| const char * mark; |
| const char * cap; |
| uint64_t optshared; |
| uint64_t optstatic; |
| int optlenmax; |
| int optsharedlen; |
| int optstaticlen; |
| const char * optsharedstr; |
| const char * optstaticstr; |
| |
| |
| if ((fdlconf = slbt_lconf_open(dctx,lconf)) < 0) |
| return SLBT_NESTED_ERROR(dctx); |
| |
| |
| if (fstat(fdlconf,&st) < 0) |
| return SLBT_SYSTEM_ERROR(dctx); |
| |
| addr = mmap( |
| 0,st.st_size, |
| PROT_READ,MAP_SHARED, |
| fdlconf,0); |
| |
| close(fdlconf); |
| |
| if (addr == MAP_FAILED) |
| return SLBT_CUSTOM_ERROR( |
| dctx,SLBT_ERR_LCONF_MAP); |
| |
| mark = addr; |
| cap = &mark[st.st_size]; |
| |
| |
| if (st.st_size >= (optlenmax = strlen("build_libtool_libs=yes\n"))) |
| cap -= optlenmax; |
| |
| |
| optshared = 0; |
| optstatic = 0; |
| |
| optsharedstr = "build_libtool_libs="; |
| optstaticstr = "build_old_libs="; |
| |
| optsharedlen = strlen(optsharedstr); |
| optstaticlen = strlen(optstaticstr); |
| |
| for (; mark && mark<cap; ) { |
| if (!strncmp(mark,optsharedstr,optsharedlen)) { |
| mark += optsharedlen; |
| |
| if ((mark[0]=='n') |
| && (mark[1]=='o') |
| && (mark[2]=='\n')) |
| optshared = SLBT_DRIVER_DISABLE_SHARED; |
| |
| if ((mark[0]=='y') |
| && (mark[1]=='e') |
| && (mark[2]=='s') |
| && (mark[3]=='\n')) |
| optshared = SLBT_DRIVER_SHARED; |
| |
| } if (!strncmp(mark,optstaticstr,optstaticlen)) { |
| mark += optstaticlen; |
| |
| if ((mark[0]=='n') |
| && (mark[1]=='o') |
| && (mark[2]=='\n')) |
| optstatic = SLBT_DRIVER_DISABLE_STATIC; |
| |
| if ((mark[0]=='y') |
| && (mark[1]=='e') |
| && (mark[2]=='s') |
| && (mark[3]=='\n')) |
| optstatic = SLBT_DRIVER_STATIC; |
| } |
| |
| if (optshared && optstatic) |
| mark = 0; |
| |
| else { |
| for (; (mark<cap) && (*mark!='\n'); ) |
| mark++; |
| mark++; |
| } |
| } |
| |
| munmap(addr,st.st_size); |
| |
| if (!optshared || !optstatic) |
| return SLBT_CUSTOM_ERROR( |
| dctx,SLBT_ERR_LCONF_PARSE); |
| |
| *flags = optshared | optstatic; |
| |
| return 0; |
| } |