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