1*906afcb8SAndy Fiddaman /*********************************************************************** 2*906afcb8SAndy Fiddaman * * 3*906afcb8SAndy Fiddaman * This software is part of the ast package * 4*906afcb8SAndy Fiddaman * Copyright (c) 1997-2012 AT&T Intellectual Property * 5*906afcb8SAndy Fiddaman * and is licensed under the * 6*906afcb8SAndy Fiddaman * Eclipse Public License, Version 1.0 * 7*906afcb8SAndy Fiddaman * by AT&T Intellectual Property * 8*906afcb8SAndy Fiddaman * * 9*906afcb8SAndy Fiddaman * A copy of the License is available at * 10*906afcb8SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html * 11*906afcb8SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12*906afcb8SAndy Fiddaman * * 13*906afcb8SAndy Fiddaman * Information and Software Systems Research * 14*906afcb8SAndy Fiddaman * AT&T Research * 15*906afcb8SAndy Fiddaman * Florham Park NJ * 16*906afcb8SAndy Fiddaman * * 17*906afcb8SAndy Fiddaman * Glenn Fowler <gsf@research.att.com> * 18*906afcb8SAndy Fiddaman * * 19*906afcb8SAndy Fiddaman ***********************************************************************/ 20*906afcb8SAndy Fiddaman #pragma prototyped 21*906afcb8SAndy Fiddaman /* 22*906afcb8SAndy Fiddaman * Glenn Fowler 23*906afcb8SAndy Fiddaman * AT&T Research 24*906afcb8SAndy Fiddaman */ 25*906afcb8SAndy Fiddaman 26*906afcb8SAndy Fiddaman #define _DLLINFO_PRIVATE_ \ 27*906afcb8SAndy Fiddaman char* sib[3]; \ 28*906afcb8SAndy Fiddaman char sibbuf[64]; \ 29*906afcb8SAndy Fiddaman char envbuf[64]; 30*906afcb8SAndy Fiddaman 31*906afcb8SAndy Fiddaman #define _DLLSCAN_PRIVATE_ \ 32*906afcb8SAndy Fiddaman Dllent_t entry; \ 33*906afcb8SAndy Fiddaman Uniq_t* uniq; \ 34*906afcb8SAndy Fiddaman int flags; \ 35*906afcb8SAndy Fiddaman Vmalloc_t* vm; \ 36*906afcb8SAndy Fiddaman Dt_t* dict; \ 37*906afcb8SAndy Fiddaman Dtdisc_t disc; \ 38*906afcb8SAndy Fiddaman FTS* fts; \ 39*906afcb8SAndy Fiddaman FTSENT* ent; \ 40*906afcb8SAndy Fiddaman Sfio_t* tmp; \ 41*906afcb8SAndy Fiddaman char** sb; \ 42*906afcb8SAndy Fiddaman char** sp; \ 43*906afcb8SAndy Fiddaman char* pb; \ 44*906afcb8SAndy Fiddaman char* pp; \ 45*906afcb8SAndy Fiddaman char* pe; \ 46*906afcb8SAndy Fiddaman int off; \ 47*906afcb8SAndy Fiddaman int prelen; \ 48*906afcb8SAndy Fiddaman int suflen; \ 49*906afcb8SAndy Fiddaman char** lib; \ 50*906afcb8SAndy Fiddaman char nam[64]; \ 51*906afcb8SAndy Fiddaman char pat[64]; \ 52*906afcb8SAndy Fiddaman char buf[64]; 53*906afcb8SAndy Fiddaman 54*906afcb8SAndy Fiddaman #define DLL_MATCH_DONE 0x8000 55*906afcb8SAndy Fiddaman #define DLL_MATCH_NAME 0x4000 56*906afcb8SAndy Fiddaman #define DLL_MATCH_VERSION 0x2000 57*906afcb8SAndy Fiddaman 58*906afcb8SAndy Fiddaman #include <ast.h> 59*906afcb8SAndy Fiddaman #include <cdt.h> 60*906afcb8SAndy Fiddaman #include <ctype.h> 61*906afcb8SAndy Fiddaman #include <error.h> 62*906afcb8SAndy Fiddaman #include <fts.h> 63*906afcb8SAndy Fiddaman #include <vmalloc.h> 64*906afcb8SAndy Fiddaman 65*906afcb8SAndy Fiddaman typedef struct Uniq_s 66*906afcb8SAndy Fiddaman { 67*906afcb8SAndy Fiddaman Dtlink_t link; 68*906afcb8SAndy Fiddaman char name[1]; 69*906afcb8SAndy Fiddaman } Uniq_t; 70*906afcb8SAndy Fiddaman 71*906afcb8SAndy Fiddaman #include <dlldefs.h> 72*906afcb8SAndy Fiddaman 73*906afcb8SAndy Fiddaman static char bin[] = "bin"; 74*906afcb8SAndy Fiddaman static char lib[] = "lib"; 75*906afcb8SAndy Fiddaman 76*906afcb8SAndy Fiddaman /* 77*906afcb8SAndy Fiddaman * we need a sibling dir in PATH to search for dlls 78*906afcb8SAndy Fiddaman * the confstr LIBPATH provides the local info 79*906afcb8SAndy Fiddaman * 80*906afcb8SAndy Fiddaman * <sibling-dir>[:<env-var>[:<host-pattern>]][,...] 81*906afcb8SAndy Fiddaman * 82*906afcb8SAndy Fiddaman * if <host-pattern> is present then it must match confstr HOSTTYPE 83*906afcb8SAndy Fiddaman */ 84*906afcb8SAndy Fiddaman 85*906afcb8SAndy Fiddaman Dllinfo_t* 86*906afcb8SAndy Fiddaman dllinfo(void) 87*906afcb8SAndy Fiddaman { 88*906afcb8SAndy Fiddaman register char* s; 89*906afcb8SAndy Fiddaman register char* h; 90*906afcb8SAndy Fiddaman char* d; 91*906afcb8SAndy Fiddaman char* v; 92*906afcb8SAndy Fiddaman char* p; 93*906afcb8SAndy Fiddaman int dn; 94*906afcb8SAndy Fiddaman int vn; 95*906afcb8SAndy Fiddaman int pn; 96*906afcb8SAndy Fiddaman char pat[256]; 97*906afcb8SAndy Fiddaman 98*906afcb8SAndy Fiddaman static Dllinfo_t info; 99*906afcb8SAndy Fiddaman 100*906afcb8SAndy Fiddaman if (!info.sibling) 101*906afcb8SAndy Fiddaman { 102*906afcb8SAndy Fiddaman info.sibling = info.sib; 103*906afcb8SAndy Fiddaman if (*(s = astconf("LIBPATH", NiL, NiL))) 104*906afcb8SAndy Fiddaman { 105*906afcb8SAndy Fiddaman while (*s == ':' || *s == ',') 106*906afcb8SAndy Fiddaman s++; 107*906afcb8SAndy Fiddaman if (*s) 108*906afcb8SAndy Fiddaman { 109*906afcb8SAndy Fiddaman h = 0; 110*906afcb8SAndy Fiddaman for (;;) 111*906afcb8SAndy Fiddaman { 112*906afcb8SAndy Fiddaman for (d = s; *s && *s != ':' && *s != ','; s++); 113*906afcb8SAndy Fiddaman if (!(dn = s - d)) 114*906afcb8SAndy Fiddaman d = 0; 115*906afcb8SAndy Fiddaman if (*s == ':') 116*906afcb8SAndy Fiddaman { 117*906afcb8SAndy Fiddaman for (v = ++s; *s && *s != ':' && *s != ','; s++); 118*906afcb8SAndy Fiddaman if (!(vn = s - v)) 119*906afcb8SAndy Fiddaman v = 0; 120*906afcb8SAndy Fiddaman if (*s == ':') 121*906afcb8SAndy Fiddaman { 122*906afcb8SAndy Fiddaman for (p = ++s; *s && *s != ':' && *s != ','; s++); 123*906afcb8SAndy Fiddaman if (!(pn = s - p)) 124*906afcb8SAndy Fiddaman p = 0; 125*906afcb8SAndy Fiddaman } 126*906afcb8SAndy Fiddaman else 127*906afcb8SAndy Fiddaman p = 0; 128*906afcb8SAndy Fiddaman } 129*906afcb8SAndy Fiddaman else 130*906afcb8SAndy Fiddaman { 131*906afcb8SAndy Fiddaman v = 0; 132*906afcb8SAndy Fiddaman p = 0; 133*906afcb8SAndy Fiddaman } 134*906afcb8SAndy Fiddaman while (*s && *s++ != ','); 135*906afcb8SAndy Fiddaman if (!*s || !p || !h && !*(h = astconf("HOSTTYPE", NiL, NiL))) 136*906afcb8SAndy Fiddaman break; 137*906afcb8SAndy Fiddaman if (pn >= sizeof(pat)) 138*906afcb8SAndy Fiddaman pn = sizeof(pat) - 1; 139*906afcb8SAndy Fiddaman memcpy(pat, p, pn); 140*906afcb8SAndy Fiddaman pat[pn] = 0; 141*906afcb8SAndy Fiddaman if (strmatch(h, pat)) 142*906afcb8SAndy Fiddaman break; 143*906afcb8SAndy Fiddaman } 144*906afcb8SAndy Fiddaman if (d && dn < sizeof(info.sibbuf)) 145*906afcb8SAndy Fiddaman { 146*906afcb8SAndy Fiddaman memcpy(info.sibbuf, d, dn); 147*906afcb8SAndy Fiddaman info.sibling[0] = info.sibbuf; 148*906afcb8SAndy Fiddaman } 149*906afcb8SAndy Fiddaman if (v && vn < sizeof(info.envbuf)) 150*906afcb8SAndy Fiddaman { 151*906afcb8SAndy Fiddaman memcpy(info.envbuf, v, vn); 152*906afcb8SAndy Fiddaman info.env = info.envbuf; 153*906afcb8SAndy Fiddaman } 154*906afcb8SAndy Fiddaman } 155*906afcb8SAndy Fiddaman } 156*906afcb8SAndy Fiddaman if (!info.sibling[0] || streq(info.sibling[0], bin)) 157*906afcb8SAndy Fiddaman info.sibling[0] = bin; 158*906afcb8SAndy Fiddaman if (!streq(info.sibling[0], lib)) 159*906afcb8SAndy Fiddaman info.sibling[1] = lib; 160*906afcb8SAndy Fiddaman if (!info.env) 161*906afcb8SAndy Fiddaman info.env = "LD_LIBRARY_PATH"; 162*906afcb8SAndy Fiddaman info.prefix = astconf("LIBPREFIX", NiL, NiL); 163*906afcb8SAndy Fiddaman info.suffix = astconf("LIBSUFFIX", NiL, NiL); 164*906afcb8SAndy Fiddaman if (streq(info.suffix, ".dll")) 165*906afcb8SAndy Fiddaman info.flags |= DLL_INFO_PREVER; 166*906afcb8SAndy Fiddaman else 167*906afcb8SAndy Fiddaman info.flags |= DLL_INFO_DOTVER; 168*906afcb8SAndy Fiddaman } 169*906afcb8SAndy Fiddaman return &info; 170*906afcb8SAndy Fiddaman } 171*906afcb8SAndy Fiddaman 172*906afcb8SAndy Fiddaman /* 173*906afcb8SAndy Fiddaman * fts version sort order 174*906afcb8SAndy Fiddaman * higher versions appear first 175*906afcb8SAndy Fiddaman */ 176*906afcb8SAndy Fiddaman 177*906afcb8SAndy Fiddaman static int 178*906afcb8SAndy Fiddaman vercmp(FTSENT* const* ap, FTSENT* const* bp) 179*906afcb8SAndy Fiddaman { 180*906afcb8SAndy Fiddaman register unsigned char* a = (unsigned char*)(*ap)->fts_name; 181*906afcb8SAndy Fiddaman register unsigned char* b = (unsigned char*)(*bp)->fts_name; 182*906afcb8SAndy Fiddaman register int n; 183*906afcb8SAndy Fiddaman register int m; 184*906afcb8SAndy Fiddaman char* e; 185*906afcb8SAndy Fiddaman 186*906afcb8SAndy Fiddaman for (;;) 187*906afcb8SAndy Fiddaman { 188*906afcb8SAndy Fiddaman if (isdigit(*a) && isdigit(*b)) 189*906afcb8SAndy Fiddaman { 190*906afcb8SAndy Fiddaman m = strtol((char*)a, &e, 10); 191*906afcb8SAndy Fiddaman a = (unsigned char*)e; 192*906afcb8SAndy Fiddaman n = strtol((char*)b, &e, 10); 193*906afcb8SAndy Fiddaman b = (unsigned char*)e; 194*906afcb8SAndy Fiddaman if (n -= m) 195*906afcb8SAndy Fiddaman return n; 196*906afcb8SAndy Fiddaman } 197*906afcb8SAndy Fiddaman if (n = *a - *b) 198*906afcb8SAndy Fiddaman return n; 199*906afcb8SAndy Fiddaman if (!*a++) 200*906afcb8SAndy Fiddaman return *b ? 0 : -1; 201*906afcb8SAndy Fiddaman if (!*b++) 202*906afcb8SAndy Fiddaman return 1; 203*906afcb8SAndy Fiddaman } 204*906afcb8SAndy Fiddaman /*NOTREACHED*/ 205*906afcb8SAndy Fiddaman } 206*906afcb8SAndy Fiddaman 207*906afcb8SAndy Fiddaman /* 208*906afcb8SAndy Fiddaman * open a scan stream 209*906afcb8SAndy Fiddaman */ 210*906afcb8SAndy Fiddaman 211*906afcb8SAndy Fiddaman Dllscan_t* 212*906afcb8SAndy Fiddaman dllsopen(const char* lib, const char* name, const char* version) 213*906afcb8SAndy Fiddaman { 214*906afcb8SAndy Fiddaman register char* s; 215*906afcb8SAndy Fiddaman register char* t; 216*906afcb8SAndy Fiddaman Dllscan_t* scan; 217*906afcb8SAndy Fiddaman Dllinfo_t* info; 218*906afcb8SAndy Fiddaman Vmalloc_t* vm; 219*906afcb8SAndy Fiddaman int i; 220*906afcb8SAndy Fiddaman int j; 221*906afcb8SAndy Fiddaman int k; 222*906afcb8SAndy Fiddaman char buf[32]; 223*906afcb8SAndy Fiddaman 224*906afcb8SAndy Fiddaman if (!(vm = vmopen(Vmdcheap, Vmlast, 0))) 225*906afcb8SAndy Fiddaman return 0; 226*906afcb8SAndy Fiddaman if (lib && *lib && (*lib != '-' || *(lib + 1))) 227*906afcb8SAndy Fiddaman { 228*906afcb8SAndy Fiddaman /* 229*906afcb8SAndy Fiddaman * grab the local part of the library id 230*906afcb8SAndy Fiddaman */ 231*906afcb8SAndy Fiddaman 232*906afcb8SAndy Fiddaman if (s = strrchr(lib, ':')) 233*906afcb8SAndy Fiddaman lib = (const char*)(s + 1); 234*906afcb8SAndy Fiddaman i = 2 * sizeof(char**) + strlen(lib) + 5; 235*906afcb8SAndy Fiddaman } 236*906afcb8SAndy Fiddaman else 237*906afcb8SAndy Fiddaman { 238*906afcb8SAndy Fiddaman lib = 0; 239*906afcb8SAndy Fiddaman i = 0; 240*906afcb8SAndy Fiddaman } 241*906afcb8SAndy Fiddaman if (version && (!*version || *version == '-' && !*(version + 1))) 242*906afcb8SAndy Fiddaman version = 0; 243*906afcb8SAndy Fiddaman if (!(scan = vmnewof(vm, 0, Dllscan_t, 1, i)) || !(scan->tmp = sfstropen())) 244*906afcb8SAndy Fiddaman { 245*906afcb8SAndy Fiddaman vmclose(vm); 246*906afcb8SAndy Fiddaman return 0; 247*906afcb8SAndy Fiddaman } 248*906afcb8SAndy Fiddaman scan->vm = vm; 249*906afcb8SAndy Fiddaman info = dllinfo(); 250*906afcb8SAndy Fiddaman scan->flags = info->flags; 251*906afcb8SAndy Fiddaman if (lib) 252*906afcb8SAndy Fiddaman { 253*906afcb8SAndy Fiddaman scan->lib = (char**)(scan + 1); 254*906afcb8SAndy Fiddaman s = *scan->lib = (char*)(scan->lib + 2); 255*906afcb8SAndy Fiddaman sfsprintf(s, i, "lib/%s", lib); 256*906afcb8SAndy Fiddaman if (!version && streq(info->suffix, ".dylib")) 257*906afcb8SAndy Fiddaman version = "0.0"; 258*906afcb8SAndy Fiddaman } 259*906afcb8SAndy Fiddaman if (!name || !*name || *name == '-' && !*(name + 1)) 260*906afcb8SAndy Fiddaman { 261*906afcb8SAndy Fiddaman name = (const char*)"?*"; 262*906afcb8SAndy Fiddaman scan->flags |= DLL_MATCH_NAME; 263*906afcb8SAndy Fiddaman } 264*906afcb8SAndy Fiddaman else if (t = strrchr(name, '/')) 265*906afcb8SAndy Fiddaman { 266*906afcb8SAndy Fiddaman if (!(scan->pb = vmnewof(vm, 0, char, t - (char*)name, 2))) 267*906afcb8SAndy Fiddaman goto bad; 268*906afcb8SAndy Fiddaman memcpy(scan->pb, name, t - (char*)name); 269*906afcb8SAndy Fiddaman name = (const char*)(t + 1); 270*906afcb8SAndy Fiddaman } 271*906afcb8SAndy Fiddaman if (name) 272*906afcb8SAndy Fiddaman { 273*906afcb8SAndy Fiddaman i = strlen(name); 274*906afcb8SAndy Fiddaman j = strlen(info->prefix); 275*906afcb8SAndy Fiddaman if (!j || i > j && strneq(name, info->prefix, j)) 276*906afcb8SAndy Fiddaman { 277*906afcb8SAndy Fiddaman k = strlen(info->suffix); 278*906afcb8SAndy Fiddaman if (i > k && streq(name + i - k, info->suffix)) 279*906afcb8SAndy Fiddaman { 280*906afcb8SAndy Fiddaman i -= j + k; 281*906afcb8SAndy Fiddaman if (!(t = vmnewof(vm, 0, char, i, 1))) 282*906afcb8SAndy Fiddaman goto bad; 283*906afcb8SAndy Fiddaman memcpy(t, name + j, i); 284*906afcb8SAndy Fiddaman t[i] = 0; 285*906afcb8SAndy Fiddaman name = (const char*)t; 286*906afcb8SAndy Fiddaman } 287*906afcb8SAndy Fiddaman } 288*906afcb8SAndy Fiddaman if (!version) 289*906afcb8SAndy Fiddaman for (t = (char*)name; *t; t++) 290*906afcb8SAndy Fiddaman if ((*t == '-' || *t == '.' || *t == '?') && isdigit(*(t + 1))) 291*906afcb8SAndy Fiddaman { 292*906afcb8SAndy Fiddaman if (*t != '-') 293*906afcb8SAndy Fiddaman scan->flags |= DLL_MATCH_VERSION; 294*906afcb8SAndy Fiddaman version = t + 1; 295*906afcb8SAndy Fiddaman if (!(s = vmnewof(vm, 0, char, t - (char*)name, 1))) 296*906afcb8SAndy Fiddaman goto bad; 297*906afcb8SAndy Fiddaman memcpy(s, name, t - (char*)name); 298*906afcb8SAndy Fiddaman name = (const char*)s; 299*906afcb8SAndy Fiddaman break; 300*906afcb8SAndy Fiddaman } 301*906afcb8SAndy Fiddaman } 302*906afcb8SAndy Fiddaman if (!version) 303*906afcb8SAndy Fiddaman { 304*906afcb8SAndy Fiddaman scan->flags |= DLL_MATCH_VERSION; 305*906afcb8SAndy Fiddaman sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s", info->prefix, name, info->suffix); 306*906afcb8SAndy Fiddaman } 307*906afcb8SAndy Fiddaman else if (scan->flags & DLL_INFO_PREVER) 308*906afcb8SAndy Fiddaman { 309*906afcb8SAndy Fiddaman sfprintf(scan->tmp, "%s%s", info->prefix, name); 310*906afcb8SAndy Fiddaman for (s = (char*)version; *s; s++) 311*906afcb8SAndy Fiddaman if (isdigit(*s)) 312*906afcb8SAndy Fiddaman sfputc(scan->tmp, *s); 313*906afcb8SAndy Fiddaman sfprintf(scan->tmp, "%s", info->suffix); 314*906afcb8SAndy Fiddaman if (!(s = sfstruse(scan->tmp))) 315*906afcb8SAndy Fiddaman goto bad; 316*906afcb8SAndy Fiddaman sfsprintf(scan->nam, sizeof(scan->nam), "%s", s); 317*906afcb8SAndy Fiddaman } 318*906afcb8SAndy Fiddaman else 319*906afcb8SAndy Fiddaman sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s.%s", info->prefix, name, info->suffix, version); 320*906afcb8SAndy Fiddaman if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION)) 321*906afcb8SAndy Fiddaman { 322*906afcb8SAndy Fiddaman if (scan->flags & DLL_INFO_PREVER) 323*906afcb8SAndy Fiddaman { 324*906afcb8SAndy Fiddaman if (!version) 325*906afcb8SAndy Fiddaman version = "*([0-9_])"; 326*906afcb8SAndy Fiddaman else 327*906afcb8SAndy Fiddaman { 328*906afcb8SAndy Fiddaman t = buf; 329*906afcb8SAndy Fiddaman for (s = (char*)version; *s; s++) 330*906afcb8SAndy Fiddaman if (isdigit(*s) && t < &buf[sizeof(buf)-1]) 331*906afcb8SAndy Fiddaman *t++ = *s; 332*906afcb8SAndy Fiddaman *t = 0; 333*906afcb8SAndy Fiddaman version = (const char*)buf; 334*906afcb8SAndy Fiddaman } 335*906afcb8SAndy Fiddaman sfsprintf(scan->pat, sizeof(scan->pat), "%s%s%s%s", info->prefix, name, version, info->suffix); 336*906afcb8SAndy Fiddaman } 337*906afcb8SAndy Fiddaman else if (version) 338*906afcb8SAndy Fiddaman sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(%s([-.])%s%s|%s.%s)", info->prefix, name, strchr(version, '.') ? "@" : "?", version, info->suffix, info->suffix, version); 339*906afcb8SAndy Fiddaman else 340*906afcb8SAndy Fiddaman { 341*906afcb8SAndy Fiddaman version = "*([0-9.])"; 342*906afcb8SAndy Fiddaman sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(?([-.])%s%s|%s%s)", info->prefix, name, version, info->suffix, info->suffix, version); 343*906afcb8SAndy Fiddaman } 344*906afcb8SAndy Fiddaman } 345*906afcb8SAndy Fiddaman scan->sp = scan->sb = (scan->lib ? scan->lib : info->sibling); 346*906afcb8SAndy Fiddaman scan->prelen = strlen(info->prefix); 347*906afcb8SAndy Fiddaman scan->suflen = strlen(info->suffix); 348*906afcb8SAndy Fiddaman return scan; 349*906afcb8SAndy Fiddaman bad: 350*906afcb8SAndy Fiddaman dllsclose(scan); 351*906afcb8SAndy Fiddaman return 0; 352*906afcb8SAndy Fiddaman } 353*906afcb8SAndy Fiddaman 354*906afcb8SAndy Fiddaman /* 355*906afcb8SAndy Fiddaman * close a scan stream 356*906afcb8SAndy Fiddaman */ 357*906afcb8SAndy Fiddaman 358*906afcb8SAndy Fiddaman int 359*906afcb8SAndy Fiddaman dllsclose(Dllscan_t* scan) 360*906afcb8SAndy Fiddaman { 361*906afcb8SAndy Fiddaman if (!scan) 362*906afcb8SAndy Fiddaman return -1; 363*906afcb8SAndy Fiddaman if (scan->fts) 364*906afcb8SAndy Fiddaman fts_close(scan->fts); 365*906afcb8SAndy Fiddaman if (scan->dict) 366*906afcb8SAndy Fiddaman dtclose(scan->dict); 367*906afcb8SAndy Fiddaman if (scan->tmp) 368*906afcb8SAndy Fiddaman sfclose(scan->tmp); 369*906afcb8SAndy Fiddaman if (scan->vm) 370*906afcb8SAndy Fiddaman vmclose(scan->vm); 371*906afcb8SAndy Fiddaman return 0; 372*906afcb8SAndy Fiddaman } 373*906afcb8SAndy Fiddaman 374*906afcb8SAndy Fiddaman /* 375*906afcb8SAndy Fiddaman * return the next scan stream entry 376*906afcb8SAndy Fiddaman */ 377*906afcb8SAndy Fiddaman 378*906afcb8SAndy Fiddaman Dllent_t* 379*906afcb8SAndy Fiddaman dllsread(register Dllscan_t* scan) 380*906afcb8SAndy Fiddaman { 381*906afcb8SAndy Fiddaman register char* p; 382*906afcb8SAndy Fiddaman register char* b; 383*906afcb8SAndy Fiddaman register char* t; 384*906afcb8SAndy Fiddaman register Uniq_t* u; 385*906afcb8SAndy Fiddaman register int n; 386*906afcb8SAndy Fiddaman register int m; 387*906afcb8SAndy Fiddaman 388*906afcb8SAndy Fiddaman if (scan->flags & DLL_MATCH_DONE) 389*906afcb8SAndy Fiddaman return 0; 390*906afcb8SAndy Fiddaman again: 391*906afcb8SAndy Fiddaman do 392*906afcb8SAndy Fiddaman { 393*906afcb8SAndy Fiddaman while (!scan->ent || !(scan->ent = scan->ent->fts_link)) 394*906afcb8SAndy Fiddaman { 395*906afcb8SAndy Fiddaman if (scan->fts) 396*906afcb8SAndy Fiddaman { 397*906afcb8SAndy Fiddaman fts_close(scan->fts); 398*906afcb8SAndy Fiddaman scan->fts = 0; 399*906afcb8SAndy Fiddaman } 400*906afcb8SAndy Fiddaman if (!scan->pb) 401*906afcb8SAndy Fiddaman scan->pb = pathbin(); 402*906afcb8SAndy Fiddaman else if (!*scan->sp) 403*906afcb8SAndy Fiddaman { 404*906afcb8SAndy Fiddaman scan->sp = scan->sb; 405*906afcb8SAndy Fiddaman if (!*scan->pe++) 406*906afcb8SAndy Fiddaman return 0; 407*906afcb8SAndy Fiddaman scan->pb = scan->pe; 408*906afcb8SAndy Fiddaman } 409*906afcb8SAndy Fiddaman for (p = scan->pp = scan->pb; *p && *p != ':'; p++) 410*906afcb8SAndy Fiddaman if (*p == '/') 411*906afcb8SAndy Fiddaman scan->pp = p; 412*906afcb8SAndy Fiddaman scan->pe = p; 413*906afcb8SAndy Fiddaman if (*scan->sp == bin) 414*906afcb8SAndy Fiddaman scan->off = sfprintf(scan->tmp, "%-.*s", scan->pe - scan->pb, scan->pb); 415*906afcb8SAndy Fiddaman else 416*906afcb8SAndy Fiddaman scan->off = sfprintf(scan->tmp, "%-.*s/%s", scan->pp - scan->pb, scan->pb, *scan->sp); 417*906afcb8SAndy Fiddaman scan->sp++; 418*906afcb8SAndy Fiddaman if (!(scan->flags & DLL_MATCH_NAME)) 419*906afcb8SAndy Fiddaman { 420*906afcb8SAndy Fiddaman sfprintf(scan->tmp, "/%s", scan->nam); 421*906afcb8SAndy Fiddaman if (!(p = sfstruse(scan->tmp))) 422*906afcb8SAndy Fiddaman return 0; 423*906afcb8SAndy Fiddaman if (!eaccess(p, R_OK)) 424*906afcb8SAndy Fiddaman { 425*906afcb8SAndy Fiddaman b = scan->nam; 426*906afcb8SAndy Fiddaman goto found; 427*906afcb8SAndy Fiddaman } 428*906afcb8SAndy Fiddaman if (errno != ENOENT) 429*906afcb8SAndy Fiddaman continue; 430*906afcb8SAndy Fiddaman } 431*906afcb8SAndy Fiddaman if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION)) 432*906afcb8SAndy Fiddaman { 433*906afcb8SAndy Fiddaman sfstrseek(scan->tmp, scan->off, SEEK_SET); 434*906afcb8SAndy Fiddaman if (!(t = sfstruse(scan->tmp))) 435*906afcb8SAndy Fiddaman return 0; 436*906afcb8SAndy Fiddaman if ((scan->fts = fts_open((char**)t, FTS_LOGICAL|FTS_NOPOSTORDER|FTS_ONEPATH, vercmp)) && (scan->ent = fts_read(scan->fts)) && (scan->ent = fts_children(scan->fts, FTS_NOSTAT))) 437*906afcb8SAndy Fiddaman break; 438*906afcb8SAndy Fiddaman } 439*906afcb8SAndy Fiddaman } 440*906afcb8SAndy Fiddaman } while (!strmatch(scan->ent->fts_name, scan->pat)); 441*906afcb8SAndy Fiddaman b = scan->ent->fts_name; 442*906afcb8SAndy Fiddaman sfstrseek(scan->tmp, scan->off, SEEK_SET); 443*906afcb8SAndy Fiddaman sfprintf(scan->tmp, "/%s", b); 444*906afcb8SAndy Fiddaman if (!(p = sfstruse(scan->tmp))) 445*906afcb8SAndy Fiddaman return 0; 446*906afcb8SAndy Fiddaman found: 447*906afcb8SAndy Fiddaman b = scan->buf + sfsprintf(scan->buf, sizeof(scan->buf), "%s", b + scan->prelen); 448*906afcb8SAndy Fiddaman if (!(scan->flags & DLL_INFO_PREVER)) 449*906afcb8SAndy Fiddaman while (b > scan->buf) 450*906afcb8SAndy Fiddaman { 451*906afcb8SAndy Fiddaman if (!isdigit(*(b - 1)) && *(b - 1) != '.') 452*906afcb8SAndy Fiddaman break; 453*906afcb8SAndy Fiddaman b--; 454*906afcb8SAndy Fiddaman } 455*906afcb8SAndy Fiddaman b -= scan->suflen; 456*906afcb8SAndy Fiddaman if (b > (scan->buf + 2) && (*(b - 1) == 'g' || *(b - 1) == 'O') && *(b - 2) == '-') 457*906afcb8SAndy Fiddaman b -= 2; 458*906afcb8SAndy Fiddaman n = m = 0; 459*906afcb8SAndy Fiddaman for (t = b; t > scan->buf; t--) 460*906afcb8SAndy Fiddaman if (isdigit(*(t - 1))) 461*906afcb8SAndy Fiddaman n = 1; 462*906afcb8SAndy Fiddaman else if (*(t - 1) != m) 463*906afcb8SAndy Fiddaman { 464*906afcb8SAndy Fiddaman if (*(t - 1) == '.' || *(t - 1) == '-' || *(t - 1) == '_') 465*906afcb8SAndy Fiddaman { 466*906afcb8SAndy Fiddaman n = 1; 467*906afcb8SAndy Fiddaman if (m) 468*906afcb8SAndy Fiddaman { 469*906afcb8SAndy Fiddaman m = -1; 470*906afcb8SAndy Fiddaman t--; 471*906afcb8SAndy Fiddaman break; 472*906afcb8SAndy Fiddaman } 473*906afcb8SAndy Fiddaman m = *(t - 1); 474*906afcb8SAndy Fiddaman } 475*906afcb8SAndy Fiddaman else 476*906afcb8SAndy Fiddaman break; 477*906afcb8SAndy Fiddaman } 478*906afcb8SAndy Fiddaman if (n) 479*906afcb8SAndy Fiddaman { 480*906afcb8SAndy Fiddaman if (isdigit(t[0]) && isdigit(t[1]) && !isdigit(t[2])) 481*906afcb8SAndy Fiddaman n = (t[0] - '0') * 10 + (t[1] - '0'); 482*906afcb8SAndy Fiddaman else if (isdigit(t[1]) && isdigit(t[2]) && !isdigit(t[3])) 483*906afcb8SAndy Fiddaman n = (t[1] - '0') * 10 + (t[2] - '0'); 484*906afcb8SAndy Fiddaman else 485*906afcb8SAndy Fiddaman n = 0; 486*906afcb8SAndy Fiddaman if (n && !(n & (n - 1))) 487*906afcb8SAndy Fiddaman { 488*906afcb8SAndy Fiddaman if (!isdigit(t[0])) 489*906afcb8SAndy Fiddaman t++; 490*906afcb8SAndy Fiddaman m = *(t += 2); 491*906afcb8SAndy Fiddaman } 492*906afcb8SAndy Fiddaman if (m || (scan->flags & DLL_INFO_PREVER)) 493*906afcb8SAndy Fiddaman b = t; 494*906afcb8SAndy Fiddaman } 495*906afcb8SAndy Fiddaman *b = 0; 496*906afcb8SAndy Fiddaman if (!*(b = scan->buf)) 497*906afcb8SAndy Fiddaman goto again; 498*906afcb8SAndy Fiddaman if (scan->uniq) 499*906afcb8SAndy Fiddaman { 500*906afcb8SAndy Fiddaman if (!scan->dict) 501*906afcb8SAndy Fiddaman { 502*906afcb8SAndy Fiddaman scan->disc.key = offsetof(Uniq_t, name); 503*906afcb8SAndy Fiddaman scan->disc.size = 0; 504*906afcb8SAndy Fiddaman scan->disc.link = offsetof(Uniq_t, link); 505*906afcb8SAndy Fiddaman if (!(scan->dict = dtopen(&scan->disc, Dtset))) 506*906afcb8SAndy Fiddaman return 0; 507*906afcb8SAndy Fiddaman dtinsert(scan->dict, scan->uniq); 508*906afcb8SAndy Fiddaman } 509*906afcb8SAndy Fiddaman if (dtmatch(scan->dict, b)) 510*906afcb8SAndy Fiddaman goto again; 511*906afcb8SAndy Fiddaman if (!(u = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b)))) 512*906afcb8SAndy Fiddaman return 0; 513*906afcb8SAndy Fiddaman strcpy(u->name, b); 514*906afcb8SAndy Fiddaman dtinsert(scan->dict, u); 515*906afcb8SAndy Fiddaman } 516*906afcb8SAndy Fiddaman else if (!(scan->flags & DLL_MATCH_NAME)) 517*906afcb8SAndy Fiddaman scan->flags |= DLL_MATCH_DONE; 518*906afcb8SAndy Fiddaman else if (!(scan->uniq = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b)))) 519*906afcb8SAndy Fiddaman return 0; 520*906afcb8SAndy Fiddaman else 521*906afcb8SAndy Fiddaman strcpy(scan->uniq->name, b); 522*906afcb8SAndy Fiddaman scan->entry.name = b; 523*906afcb8SAndy Fiddaman scan->entry.path = p; 524*906afcb8SAndy Fiddaman errorf("dll", NiL, -1, "dllsread: %s bound to %s", b, p); 525*906afcb8SAndy Fiddaman return &scan->entry; 526*906afcb8SAndy Fiddaman } 527