File: | lib/rpmrc.c |
Warning: | line 1734, column 6 Value stored to 'vp' is never read |
1 | #include "system.h" |
2 | |
3 | #include <stdarg.h> |
4 | #include <pthread.h> |
5 | |
6 | #if defined(__linux__1) |
7 | #include <elf.h> |
8 | #include <link.h> |
9 | #endif |
10 | |
11 | |
12 | #if HAVE_SYS_UTSNAME_H1 |
13 | #include <sys/utsname.h> |
14 | #endif |
15 | #include <ctype.h> /* XXX for /etc/rpm/platform contents */ |
16 | |
17 | #if HAVE_SYS_SYSTEMCFG_H |
18 | #include <sys/systemcfg.h> |
19 | #else |
20 | #define __power_pc()0 0 |
21 | #endif |
22 | |
23 | #ifdef HAVE_SYS_AUXV_H1 |
24 | #include <sys/auxv.h> |
25 | #endif |
26 | |
27 | #include <rpm/rpmlib.h> /* RPM_MACTABLE*, Rc-prototypes */ |
28 | #include <rpm/rpmmacro.h> |
29 | #include <rpm/rpmfileutil.h> |
30 | #include <rpm/rpmstring.h> |
31 | #include <rpm/rpmlog.h> |
32 | #include <rpm/argv.h> |
33 | |
34 | #include "rpmio/rpmlua.h" |
35 | #include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */ |
36 | #include "lib/misc.h" |
37 | #include "lib/rpmliblua.h" |
38 | #include "lib/rpmug.h" |
39 | |
40 | #include "debug.h" |
41 | |
42 | static const char * defrcfiles = NULL((void*)0); |
43 | const char * macrofiles = NULL((void*)0); |
44 | |
45 | typedef struct machCacheEntry_s { |
46 | char * name; |
47 | int count; |
48 | char ** equivs; |
49 | int visited; |
50 | } * machCacheEntry; |
51 | |
52 | typedef struct machCache_s { |
53 | machCacheEntry cache; |
54 | int size; |
55 | } * machCache; |
56 | |
57 | typedef struct machEquivInfo_s { |
58 | char * name; |
59 | int score; |
60 | } * machEquivInfo; |
61 | |
62 | typedef struct machEquivTable_s { |
63 | int count; |
64 | machEquivInfo list; |
65 | } * machEquivTable; |
66 | |
67 | struct rpmvarValue { |
68 | char * value; |
69 | /* eventually, this arch will be replaced with a generic condition */ |
70 | char * arch; |
71 | struct rpmvarValue * next; |
72 | }; |
73 | |
74 | struct rpmOption { |
75 | char * name; |
76 | int var; |
77 | int archSpecific; |
78 | int macroize; |
79 | int localize; |
80 | }; |
81 | |
82 | static struct rpmat_s { |
83 | const char *platform; |
84 | uint64_t hwcap; |
85 | } rpmat; |
86 | |
87 | typedef struct defaultEntry_s { |
88 | char * name; |
89 | char * defName; |
90 | } * defaultEntry; |
91 | |
92 | typedef struct canonEntry_s { |
93 | char * name; |
94 | char * short_name; |
95 | short num; |
96 | } * canonEntry; |
97 | |
98 | /* tags are 'key'canon, 'key'translate, 'key'compat |
99 | * |
100 | * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work |
101 | */ |
102 | typedef struct tableType_s { |
103 | char * const key; |
104 | const int hasCanon; |
105 | const int hasTranslate; |
106 | struct machEquivTable_s equiv; |
107 | struct machCache_s cache; |
108 | defaultEntry defaults; |
109 | canonEntry canons; |
110 | int defaultsLength; |
111 | int canonsLength; |
112 | } * tableType; |
113 | |
114 | /* XXX get rid of this stuff... */ |
115 | /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */ |
116 | #define RPMVAR_OPTFLAGS3 3 |
117 | #define RPMVAR_ARCHCOLOR42 42 |
118 | #define RPMVAR_INCLUDE43 43 |
119 | #define RPMVAR_MACROFILES49 49 |
120 | |
121 | #define RPMVAR_NUM55 55 /* number of RPMVAR entries */ |
122 | |
123 | /* this *must* be kept in alphabetical order */ |
124 | /* The order of the flags is archSpecific, macroize, localize */ |
125 | |
126 | static const struct rpmOption optionTable[] = { |
127 | { "archcolor", RPMVAR_ARCHCOLOR42, 1, 0, 0 }, |
128 | { "include", RPMVAR_INCLUDE43, 0, 0, 2 }, |
129 | { "macrofiles", RPMVAR_MACROFILES49, 0, 0, 1 }, |
130 | { "optflags", RPMVAR_OPTFLAGS3, 1, 1, 0 }, |
131 | }; |
132 | |
133 | static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable); |
134 | |
135 | #define OS0 0 |
136 | #define ARCH1 1 |
137 | |
138 | typedef struct rpmrcCtx_s * rpmrcCtx; |
139 | struct rpmrcCtx_s { |
140 | ARGV_t platpat; |
141 | char *current[2]; |
142 | int currTables[2]; |
143 | struct rpmvarValue values[RPMVAR_NUM55]; |
144 | struct tableType_s tables[RPM_MACHTABLE_COUNT4]; |
145 | int machDefaults; |
146 | int pathDefaults; |
147 | pthread_rwlock_t lock; |
148 | }; |
149 | |
150 | /* prototypes */ |
151 | static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn); |
152 | |
153 | static void rpmSetVarArch(rpmrcCtx ctx, |
154 | int var, const char * val, const char * arch); |
155 | |
156 | static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name); |
157 | |
158 | static void rpmRebuildTargetVars(rpmrcCtx ctx, const char **target, const char ** canontarget); |
159 | |
160 | /* Force context (lock) acquisition through a function */ |
161 | static rpmrcCtx rpmrcCtxAcquire(int write) |
162 | { |
163 | static struct rpmrcCtx_s _globalCtx = { |
164 | .lock = PTHREAD_RWLOCK_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, 0, 0 } }, |
165 | .currTables = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH }, |
166 | .tables = { |
167 | { "arch", 1, 0 }, |
168 | { "os", 1, 0 }, |
169 | { "buildarch", 0, 1 }, |
170 | { "buildos", 0, 1 } |
171 | }, |
172 | }; |
173 | rpmrcCtx ctx = &_globalCtx; |
174 | |
175 | /* XXX: errors should be handled */ |
176 | if (write) |
177 | pthread_rwlock_wrlock(&ctx->lock); |
178 | else |
179 | pthread_rwlock_rdlock(&ctx->lock); |
180 | |
181 | return ctx; |
182 | } |
183 | |
184 | /* Release context (lock) */ |
185 | static rpmrcCtx rpmrcCtxRelease(rpmrcCtx ctx) |
186 | { |
187 | pthread_rwlock_unlock(&ctx->lock); |
188 | return NULL((void*)0); |
189 | } |
190 | |
191 | static int optionCompare(const void * a, const void * b) |
192 | { |
193 | return rstrcasecmp(((const struct rpmOption *) a)->name, |
194 | ((const struct rpmOption *) b)->name); |
195 | } |
196 | |
197 | static machCacheEntry |
198 | machCacheFindEntry(const machCache cache, const char * key) |
199 | { |
200 | int i; |
201 | |
202 | for (i = 0; i < cache->size; i++) |
203 | if (rstreq(cache->cache[i].name, key)) return cache->cache + i; |
204 | |
205 | return NULL((void*)0); |
206 | } |
207 | |
208 | static int machCompatCacheAdd(char * name, const char * fn, int linenum, |
209 | machCache cache) |
210 | { |
211 | machCacheEntry entry = NULL((void*)0); |
212 | char * chptr; |
213 | char * equivs; |
214 | int delEntry = 0; |
215 | int i; |
216 | |
217 | while (*name && risspace(*name)) name++; |
218 | |
219 | chptr = name; |
220 | while (*chptr && *chptr != ':') chptr++; |
221 | if (!*chptr) { |
222 | rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n")dcgettext ("rpm", "missing second ':' at %s:%d\n", 5), fn, linenum); |
223 | return 1; |
224 | } else if (chptr == name) { |
225 | rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n")dcgettext ("rpm", "missing architecture name at %s:%d\n", 5), fn, |
226 | linenum); |
227 | return 1; |
228 | } |
229 | |
230 | while (*chptr == ':' || risspace(*chptr)) chptr--; |
231 | *(++chptr) = '\0'; |
232 | equivs = chptr + 1; |
233 | while (*equivs && risspace(*equivs)) equivs++; |
234 | if (!*equivs) { |
235 | delEntry = 1; |
236 | } |
237 | |
238 | if (cache->size) { |
239 | entry = machCacheFindEntry(cache, name); |
240 | if (entry) { |
241 | for (i = 0; i < entry->count; i++) |
242 | entry->equivs[i] = _free(entry->equivs[i])rfree((entry->equivs[i])); |
243 | entry->equivs = _free(entry->equivs)rfree((entry->equivs)); |
244 | entry->count = 0; |
245 | } |
246 | } |
247 | |
248 | if (!entry) { |
249 | cache->cache = xrealloc(cache->cache,rrealloc((cache->cache), ((cache->size + 1) * sizeof(*cache ->cache))) |
250 | (cache->size + 1) * sizeof(*cache->cache))rrealloc((cache->cache), ((cache->size + 1) * sizeof(*cache ->cache))); |
251 | entry = cache->cache + cache->size++; |
252 | entry->name = xstrdup(name)rstrdup((name)); |
253 | entry->count = 0; |
254 | entry->visited = 0; |
255 | } |
256 | |
257 | if (delEntry) return 0; |
258 | |
259 | while ((chptr = strtok(equivs, " ")) != NULL((void*)0)) { |
260 | equivs = NULL((void*)0); |
261 | if (chptr[0] == '\0') /* does strtok() return "" ever?? */ |
262 | continue; |
263 | if (entry->count) |
264 | entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)rrealloc((entry->equivs), (sizeof(*entry->equivs) * (entry ->count + 1))) |
265 | * (entry->count + 1))rrealloc((entry->equivs), (sizeof(*entry->equivs) * (entry ->count + 1))); |
266 | else |
267 | entry->equivs = xmalloc(sizeof(*entry->equivs))rmalloc((sizeof(*entry->equivs))); |
268 | |
269 | entry->equivs[entry->count] = xstrdup(chptr)rstrdup((chptr)); |
270 | entry->count++; |
271 | } |
272 | |
273 | return 0; |
274 | } |
275 | |
276 | static machEquivInfo |
277 | machEquivSearch(const machEquivTable table, const char * name) |
278 | { |
279 | int i; |
280 | |
281 | for (i = 0; i < table->count; i++) |
282 | if (!rstrcasecmp(table->list[i].name, name)) |
283 | return table->list + i; |
284 | |
285 | return NULL((void*)0); |
286 | } |
287 | |
288 | static void machAddEquiv(machEquivTable table, const char * name, |
289 | int distance) |
290 | { |
291 | machEquivInfo equiv; |
292 | |
293 | equiv = machEquivSearch(table, name); |
294 | if (!equiv) { |
295 | if (table->count) |
296 | table->list = xrealloc(table->list, (table->count + 1)rrealloc((table->list), ((table->count + 1) * sizeof(*table ->list))) |
297 | * sizeof(*table->list))rrealloc((table->list), ((table->count + 1) * sizeof(*table ->list))); |
298 | else |
299 | table->list = xmalloc(sizeof(*table->list))rmalloc((sizeof(*table->list))); |
300 | |
301 | table->list[table->count].name = xstrdup(name)rstrdup((name)); |
302 | table->list[table->count++].score = distance; |
303 | } |
304 | } |
305 | |
306 | static void machCacheEntryVisit(machCache cache, |
307 | machEquivTable table, const char * name, int distance) |
308 | { |
309 | machCacheEntry entry; |
310 | int i; |
311 | |
312 | entry = machCacheFindEntry(cache, name); |
313 | if (!entry || entry->visited) return; |
314 | |
315 | entry->visited = 1; |
316 | |
317 | for (i = 0; i < entry->count; i++) { |
318 | machAddEquiv(table, entry->equivs[i], distance); |
319 | } |
320 | |
321 | for (i = 0; i < entry->count; i++) { |
322 | machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1); |
323 | } |
324 | } |
325 | |
326 | static void machFindEquivs(machCache cache, machEquivTable table, |
327 | const char * key) |
328 | { |
329 | int i; |
330 | |
331 | for (i = 0; i < cache->size; i++) |
332 | cache->cache[i].visited = 0; |
333 | |
334 | while (table->count > 0) { |
335 | --table->count; |
336 | table->list[table->count].name = _free(table->list[table->count].name)rfree((table->list[table->count].name)); |
337 | } |
338 | table->count = 0; |
339 | table->list = _free(table->list)rfree((table->list)); |
340 | |
341 | /* |
342 | * We have a general graph built using strings instead of pointers. |
343 | * Yuck. We have to start at a point at traverse it, remembering how |
344 | * far away everything is. |
345 | */ |
346 | /* FIX: table->list may be NULL. */ |
347 | machAddEquiv(table, key, 1); |
348 | machCacheEntryVisit(cache, table, key, 2); |
349 | return; |
350 | } |
351 | |
352 | static rpmRC addCanon(canonEntry * table, int * tableLen, char * line, |
353 | const char * fn, int lineNum) |
354 | { |
355 | canonEntry t; |
356 | char *s, *s1; |
357 | const char * tname; |
358 | const char * tshort_name; |
359 | int tnum; |
360 | |
361 | (*tableLen) += 2; |
362 | *table = xrealloc(*table, sizeof(**table) * (*tableLen))rrealloc((*table), (sizeof(**table) * (*tableLen))); |
363 | |
364 | t = & ((*table)[*tableLen - 2]); |
365 | |
366 | tname = strtok(line, ": \t"); |
367 | tshort_name = strtok(NULL((void*)0), " \t"); |
368 | s = strtok(NULL((void*)0), " \t"); |
369 | if (! (tname && tshort_name && s)) { |
370 | rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n")dcgettext ("rpm", "Incomplete data line at %s:%d\n", 5), |
371 | fn, lineNum); |
372 | return RPMRC_FAIL; |
373 | } |
374 | if (strtok(NULL((void*)0), " \t")) { |
375 | rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n")dcgettext ("rpm", "Too many args in data line at %s:%d\n", 5), |
376 | fn, lineNum); |
377 | return RPMRC_FAIL; |
378 | } |
379 | |
380 | tnum = strtoul(s, &s1, 10); |
381 | if ((*s1) || (s1 == s) || (tnum == ULONG_MAX(9223372036854775807L *2UL+1UL))) { |
382 | rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n")dcgettext ("rpm", "Bad arch/os number: %s (%s:%d)\n", 5), s, |
383 | fn, lineNum); |
384 | return RPMRC_FAIL; |
385 | } |
386 | |
387 | t[0].name = xstrdup(tname)rstrdup((tname)); |
388 | t[0].short_name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup((""))); |
389 | t[0].num = tnum; |
390 | |
391 | /* From A B C entry */ |
392 | /* Add B B C entry */ |
393 | t[1].name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup((""))); |
394 | t[1].short_name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup((""))); |
395 | t[1].num = tnum; |
396 | |
397 | return RPMRC_OK; |
398 | } |
399 | |
400 | static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line, |
401 | const char * fn, int lineNum) |
402 | { |
403 | defaultEntry t; |
404 | |
405 | (*tableLen)++; |
406 | *table = xrealloc(*table, sizeof(**table) * (*tableLen))rrealloc((*table), (sizeof(**table) * (*tableLen))); |
407 | |
408 | t = & ((*table)[*tableLen - 1]); |
409 | |
410 | t->name = strtok(line, ": \t"); |
411 | t->defName = strtok(NULL((void*)0), " \t"); |
412 | if (! (t->name && t->defName)) { |
413 | rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n")dcgettext ("rpm", "Incomplete default line at %s:%d\n", 5), |
414 | fn, lineNum); |
415 | return RPMRC_FAIL; |
416 | } |
417 | if (strtok(NULL((void*)0), " \t")) { |
418 | rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n")dcgettext ("rpm", "Too many args in default line at %s:%d\n", 5), |
419 | fn, lineNum); |
420 | return RPMRC_FAIL; |
421 | } |
422 | |
423 | t->name = xstrdup(t->name)rstrdup((t->name)); |
424 | t->defName = (t->defName ? xstrdup(t->defName)rstrdup((t->defName)) : NULL((void*)0)); |
425 | |
426 | return RPMRC_OK; |
427 | } |
428 | |
429 | static canonEntry lookupInCanonTable(const char * name, |
430 | const canonEntry table, int tableLen) |
431 | { |
432 | while (tableLen) { |
433 | tableLen--; |
434 | if (!rstreq(name, table[tableLen].name)) |
435 | continue; |
436 | return &(table[tableLen]); |
437 | } |
438 | |
439 | return NULL((void*)0); |
440 | } |
441 | |
442 | static |
443 | const char * lookupInDefaultTable(const char * name, |
444 | const defaultEntry table, int tableLen) |
445 | { |
446 | while (tableLen) { |
447 | tableLen--; |
448 | if (table[tableLen].name && rstreq(name, table[tableLen].name)) |
449 | return table[tableLen].defName; |
450 | } |
451 | |
452 | return name; |
453 | } |
454 | |
455 | static void setDefaults(void) |
456 | { |
457 | const char *confdir = rpmConfigDir(); |
458 | if (!defrcfiles) { |
459 | defrcfiles = rstrscat(NULL((void*)0), confdir, "/rpmrc", ":", |
460 | confdir, "/" RPMCANONVENDOR"redhat" "/rpmrc", ":", |
461 | SYSCONFDIR"/etc" "/rpmrc", ":", |
462 | "~/.rpmrc", NULL((void*)0)); |
463 | } |
464 | |
465 | #ifndef MACROFILES |
466 | if (!macrofiles) { |
467 | macrofiles = rstrscat(NULL((void*)0), confdir, "/macros", ":", |
468 | confdir, "/macros.d/macros.*", ":", |
469 | confdir, "/platform/%{_target}/macros", ":", |
470 | confdir, "/fileattrs/*.attr", ":", |
471 | confdir, "/" RPMCANONVENDOR"redhat" "/macros", ":", |
472 | SYSCONFDIR"/etc" "/rpm/macros.*", ":", |
473 | SYSCONFDIR"/etc" "/rpm/macros", ":", |
474 | SYSCONFDIR"/etc" "/rpm/%{_target}/macros", ":", |
475 | "~/.rpmmacros", NULL((void*)0)); |
476 | } |
477 | #else |
478 | macrofiles = MACROFILES; |
479 | #endif |
480 | } |
481 | |
482 | /* FIX: se usage inconsistent, W2DO? */ |
483 | static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn) |
484 | { |
485 | char *s; |
486 | char *se, *next, *buf = NULL((void*)0), *fn; |
487 | int linenum = 0; |
488 | struct rpmOption searchOption, * option; |
489 | rpmRC rc = RPMRC_FAIL; |
490 | |
491 | fn = rpmGetPath(urlfn, NULL((void*)0)); |
492 | if (rpmioSlurp(fn, (uint8_t **) &buf, NULL((void*)0)) || buf == NULL((void*)0)) { |
493 | goto exit; |
494 | } |
495 | |
496 | next = buf; |
497 | while (*next != '\0') { |
498 | linenum++; |
499 | |
500 | s = se = next; |
501 | |
502 | /* Find end-of-line. */ |
503 | while (*se && *se != '\n') se++; |
504 | if (*se != '\0') *se++ = '\0'; |
505 | next = se; |
506 | |
507 | /* Trim leading spaces */ |
508 | while (*s && risspace(*s)) s++; |
509 | |
510 | /* We used to allow comments to begin anywhere, but not anymore. */ |
511 | if (*s == '#' || *s == '\0') continue; |
512 | |
513 | /* Find end-of-keyword. */ |
514 | se = (char *)s; |
515 | while (*se && !risspace(*se) && *se != ':') se++; |
516 | |
517 | if (risspace(*se)) { |
518 | *se++ = '\0'; |
519 | while (*se && risspace(*se) && *se != ':') se++; |
520 | } |
521 | |
522 | if (*se != ':') { |
523 | rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n")dcgettext ("rpm", "missing ':' (found 0x%02x) at %s:%d\n", 5), |
524 | (unsigned)(0xff & *se), fn, linenum); |
525 | goto exit; |
526 | } |
527 | *se++ = '\0'; /* terminate keyword or option, point to value */ |
528 | while (*se && risspace(*se)) se++; |
529 | |
530 | /* Find keyword in table */ |
531 | searchOption.name = s; |
532 | option = bsearch(&searchOption, optionTable, optionTableSize, |
533 | sizeof(optionTable[0]), optionCompare); |
534 | |
535 | if (option) { /* For configuration variables ... */ |
536 | const char *arch, *val; |
537 | |
538 | arch = val = NULL((void*)0); |
539 | if (*se == '\0') { |
540 | rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n")dcgettext ("rpm", "missing argument for %s at %s:%d\n", 5), |
541 | option->name, fn, linenum); |
542 | goto exit; |
543 | } |
544 | |
545 | if (option->var == RPMVAR_INCLUDE43) { |
546 | s = se; |
547 | while (*se && !risspace(*se)) se++; |
548 | if (*se != '\0') *se = '\0'; |
549 | |
550 | if (doReadRC(ctx, s)) { |
551 | rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n")dcgettext ("rpm", "cannot open %s at %s:%d: %m\n", 5), |
552 | s, fn, linenum); |
553 | goto exit; |
554 | } |
555 | /* XXX don't save include value as var/macro */ |
556 | continue; |
557 | } |
558 | |
559 | if (option->archSpecific) { |
560 | arch = se; |
561 | while (*se && !risspace(*se)) se++; |
562 | if (*se == '\0') { |
563 | rpmlog(RPMLOG_ERR, |
564 | _("missing architecture for %s at %s:%d\n")dcgettext ("rpm", "missing architecture for %s at %s:%d\n", 5 ), |
565 | option->name, fn, linenum); |
566 | goto exit; |
567 | } |
568 | *se++ = '\0'; |
569 | while (*se && risspace(*se)) se++; |
570 | if (*se == '\0') { |
571 | rpmlog(RPMLOG_ERR, |
572 | _("missing argument for %s at %s:%d\n")dcgettext ("rpm", "missing argument for %s at %s:%d\n", 5), |
573 | option->name, fn, linenum); |
574 | goto exit; |
575 | } |
576 | } |
577 | |
578 | val = se; |
579 | |
580 | /* Only add macros if appropriate for this arch */ |
581 | if (option->macroize && |
582 | (arch == NULL((void*)0) || rstreq(arch, ctx->current[ARCH1]))) { |
583 | char *n, *name; |
584 | n = name = xmalloc(strlen(option->name)+2)rmalloc((strlen(option->name)+2)); |
585 | if (option->localize) |
586 | *n++ = '_'; |
587 | strcpy(n, option->name); |
588 | rpmPushMacro(NULL((void*)0), name, NULL((void*)0), val, RMIL_RPMRC-11); |
589 | free(name); |
590 | } |
591 | rpmSetVarArch(ctx, option->var, val, arch); |
592 | fn = _free(fn)rfree((fn)); |
593 | |
594 | } else { /* For arch/os compatibility tables ... */ |
595 | int gotit; |
596 | int i; |
597 | |
598 | gotit = 0; |
599 | |
600 | for (i = 0; i < RPM_MACHTABLE_COUNT4; i++) { |
601 | if (rstreqn(ctx->tables[i].key, s, strlen(ctx->tables[i].key))) |
602 | break; |
603 | } |
604 | |
605 | if (i < RPM_MACHTABLE_COUNT4) { |
606 | const char *rest = s + strlen(ctx->tables[i].key); |
607 | if (*rest == '_') rest++; |
608 | |
609 | if (rstreq(rest, "compat")) { |
610 | if (machCompatCacheAdd(se, fn, linenum, |
611 | &ctx->tables[i].cache)) |
612 | goto exit; |
613 | gotit = 1; |
614 | } else if (ctx->tables[i].hasTranslate && |
615 | rstreq(rest, "translate")) { |
616 | if (addDefault(&ctx->tables[i].defaults, |
617 | &ctx->tables[i].defaultsLength, |
618 | se, fn, linenum)) |
619 | goto exit; |
620 | gotit = 1; |
621 | } else if (ctx->tables[i].hasCanon && |
622 | rstreq(rest, "canon")) { |
623 | if (addCanon(&ctx->tables[i].canons, |
624 | &ctx->tables[i].canonsLength, |
625 | se, fn, linenum)) |
626 | goto exit; |
627 | gotit = 1; |
628 | } |
629 | } |
630 | |
631 | if (!gotit) { |
632 | rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n")dcgettext ("rpm", "bad option '%s' at %s:%d\n", 5), |
633 | s, fn, linenum); |
634 | goto exit; |
635 | } |
636 | } |
637 | } |
638 | rc = RPMRC_OK; |
639 | |
640 | exit: |
641 | free(fn); |
642 | free(buf); |
643 | |
644 | return rc; |
645 | } |
646 | |
647 | |
648 | /** |
649 | */ |
650 | static rpmRC rpmPlatform(rpmrcCtx ctx, const char * platform) |
651 | { |
652 | const char *cpu = NULL((void*)0), *vendor = NULL((void*)0), *os = NULL((void*)0), *gnu = NULL((void*)0); |
653 | uint8_t * b = NULL((void*)0); |
654 | ssize_t blen = 0; |
655 | int init_platform = 0; |
656 | char * p, * pe; |
657 | rpmRC rc; |
658 | |
659 | rc = (rpmioSlurp(platform, &b, &blen) == 0) ? RPMRC_OK : RPMRC_FAIL; |
660 | |
661 | if (rc || b == NULL((void*)0) || blen <= 0) { |
662 | rc = RPMRC_FAIL; |
663 | goto exit; |
664 | } |
665 | |
666 | p = (char *)b; |
667 | for (pe = p; p && *p; p = pe) { |
668 | pe = strchr(p, '\n'); |
669 | if (pe) |
670 | *pe++ = '\0'; |
671 | |
672 | while (*p && isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) |
673 | p++; |
674 | if (*p == '\0' || *p == '#') |
675 | continue; |
676 | |
677 | if (init_platform) { |
678 | char * t = p + strlen(p); |
679 | |
680 | while (--t > p && isspace(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int) _ISspace)) |
681 | *t = '\0'; |
682 | if (t > p) { |
683 | argvAdd(&ctx->platpat, p); |
684 | } |
685 | continue; |
686 | } |
687 | |
688 | cpu = p; |
689 | vendor = "unknown"; |
690 | os = "unknown"; |
691 | gnu = NULL((void*)0); |
692 | while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace))) |
693 | p++; |
694 | if (*p != '\0') *p++ = '\0'; |
695 | |
696 | vendor = p; |
697 | while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace))) |
698 | p++; |
699 | if (*p != '-') { |
700 | if (*p != '\0') *p = '\0'; |
701 | os = vendor; |
702 | vendor = "unknown"; |
703 | } else { |
704 | if (*p != '\0') *p++ = '\0'; |
705 | |
706 | os = p; |
707 | while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace))) |
708 | p++; |
709 | if (*p == '-') { |
710 | *p++ = '\0'; |
711 | |
712 | gnu = p; |
713 | while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace))) |
714 | p++; |
715 | } |
716 | if (*p != '\0') *p = '\0'; |
717 | } |
718 | |
719 | rpmPushMacro(NULL((void*)0), "_host_cpu", NULL((void*)0), cpu, -1); |
720 | rpmPushMacro(NULL((void*)0), "_host_vendor", NULL((void*)0), vendor, -1); |
721 | rpmPushMacro(NULL((void*)0), "_host_os", NULL((void*)0), os, -1); |
722 | |
723 | char *plat = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", |
724 | (gnu && *gnu ? "-" : NULL((void*)0)), gnu, NULL((void*)0)); |
725 | argvAdd(&ctx->platpat, plat); |
726 | free(plat); |
727 | |
728 | init_platform++; |
729 | } |
730 | rc = (init_platform ? RPMRC_OK : RPMRC_FAIL); |
731 | |
732 | exit: |
733 | b = _free(b)rfree((b)); |
734 | return rc; |
735 | } |
736 | |
737 | |
738 | # if defined(__linux__1) && defined(__i386__) |
739 | #include <setjmp.h> |
740 | #include <signal.h> |
741 | |
742 | /* |
743 | * Generic CPUID function |
744 | */ |
745 | static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) |
746 | { |
747 | asm volatile ( |
748 | "pushl %%ebx \n" |
749 | "cpuid \n" |
750 | "movl %%ebx, %%esi \n" |
751 | "popl %%ebx \n" |
752 | : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) |
753 | : "a" (op)); |
754 | } |
755 | |
756 | /* |
757 | * CPUID functions returning a single datum |
758 | */ |
759 | static inline unsigned int cpuid_eax(unsigned int op) |
760 | { |
761 | unsigned int tmp, val; |
762 | cpuid(op, &val, &tmp, &tmp, &tmp); |
763 | return val; |
764 | } |
765 | |
766 | static inline unsigned int cpuid_ebx(unsigned int op) |
767 | { |
768 | unsigned int tmp, val; |
769 | cpuid(op, &tmp, &val, &tmp, &tmp); |
770 | return val; |
771 | } |
772 | |
773 | static inline unsigned int cpuid_ecx(unsigned int op) |
774 | { |
775 | unsigned int tmp, val; |
776 | cpuid(op, &tmp, &tmp, &val, &tmp); |
777 | return val; |
778 | } |
779 | |
780 | static inline unsigned int cpuid_edx(unsigned int op) |
781 | { |
782 | unsigned int tmp, val; |
783 | cpuid(op, &tmp, &tmp, &tmp, &val); |
784 | return val; |
785 | } |
786 | |
787 | static sigjmp_buf jenv; |
788 | |
789 | static inline void model3(int _unused) |
790 | { |
791 | siglongjmp(jenv, 1); |
792 | } |
793 | |
794 | static inline int RPMClass(void) |
795 | { |
796 | int cpu; |
797 | unsigned int tfms, junk, cap, capamd; |
798 | struct sigaction oldsa; |
799 | |
800 | sigaction(SIGILL4, NULL((void*)0), &oldsa); |
801 | signal(SIGILL4, model3); |
802 | |
803 | if (sigsetjmp(jenv, 1)) { |
804 | sigaction(SIGILL4, &oldsa, NULL((void*)0)); |
805 | return 3; |
806 | } |
807 | |
808 | if (cpuid_eax(0x000000000)==0) { |
809 | sigaction(SIGILL4, &oldsa, NULL((void*)0)); |
810 | return 4; |
811 | } |
812 | |
813 | cpuid(0x00000001, &tfms, &junk, &junk, &cap); |
814 | cpuid(0x80000001, &junk, &junk, &junk, &capamd); |
815 | |
816 | cpu = (tfms>>8)&15; |
817 | |
818 | if (cpu == 5 |
819 | && cpuid_ecx(0) == '68xM' |
820 | && cpuid_edx(0) == 'Teni' |
821 | && (cpuid_edx(1) & ((1<<8)|(1<<15))) == ((1<<8)|(1<<15))) { |
822 | sigaction(SIGILL4, &oldsa, NULL((void*)0)); |
823 | return 6; /* has CX8 and CMOV */ |
824 | } |
825 | |
826 | sigaction(SIGILL4, &oldsa, NULL((void*)0)); |
827 | |
828 | #define USER686 ((1<<4) | (1<<8) | (1<<15)) |
829 | /* Transmeta Crusoe CPUs say that their CPU family is "5" but they have enough features for i686. */ |
830 | if (cpu == 5 && (cap & USER686) == USER686) |
831 | return 6; |
832 | |
833 | if (cpu < 6) |
834 | return cpu; |
835 | |
836 | if (cap & (1<<15)) { |
837 | /* CMOV supported? */ |
838 | if (capamd & (1<<30)) |
839 | return 7; /* 3DNOWEXT supported */ |
840 | return 6; |
841 | } |
842 | |
843 | return 5; |
844 | } |
845 | |
846 | /* should only be called for model 6 CPU's */ |
847 | static int is_athlon(void) |
848 | { |
849 | unsigned int eax, ebx, ecx, edx; |
850 | char vendor[16]; |
851 | int i; |
852 | |
853 | cpuid (0, &eax, &ebx, &ecx, &edx); |
854 | |
855 | memset(vendor, 0, sizeof(vendor)); |
856 | |
857 | for (i=0; i<4; i++) |
858 | vendor[i] = (unsigned char) (ebx >>(8*i)); |
859 | for (i=0; i<4; i++) |
860 | vendor[4+i] = (unsigned char) (edx >>(8*i)); |
861 | for (i=0; i<4; i++) |
862 | vendor[8+i] = (unsigned char) (ecx >>(8*i)); |
863 | |
864 | if (!rstreqn(vendor, "AuthenticAMD", 12)) |
865 | return 0; |
866 | |
867 | return 1; |
868 | } |
869 | |
870 | static int is_pentium3(void) |
871 | { |
872 | unsigned int eax, ebx, ecx, edx, family, model; |
873 | char vendor[16]; |
874 | cpuid(0, &eax, &ebx, &ecx, &edx); |
875 | memset(vendor, 0, sizeof(vendor)); |
876 | *((unsigned int *)&vendor[0]) = ebx; |
877 | *((unsigned int *)&vendor[4]) = edx; |
878 | *((unsigned int *)&vendor[8]) = ecx; |
879 | if (!rstreqn(vendor, "GenuineIntel", 12)) |
880 | return 0; |
881 | cpuid(1, &eax, &ebx, &ecx, &edx); |
882 | family = (eax >> 8) & 0x0f; |
883 | model = (eax >> 4) & 0x0f; |
884 | if (family == 6) |
885 | switch (model) |
886 | { |
887 | case 7: // Pentium III, Pentium III Xeon (model 7) |
888 | case 8: // Pentium III, Pentium III Xeon, Celeron (model 8) |
889 | case 9: // Pentium M |
890 | case 10: // Pentium III Xeon (model A) |
891 | case 11: // Pentium III (model B) |
892 | return 1; |
893 | } |
894 | return 0; |
895 | } |
896 | |
897 | static int is_pentium4(void) |
898 | { |
899 | unsigned int eax, ebx, ecx, edx, family, model; |
900 | char vendor[16]; |
901 | cpuid(0, &eax, &ebx, &ecx, &edx); |
902 | memset(vendor, 0, sizeof(vendor)); |
903 | *((unsigned int *)&vendor[0]) = ebx; |
904 | *((unsigned int *)&vendor[4]) = edx; |
905 | *((unsigned int *)&vendor[8]) = ecx; |
906 | if (!rstreqn(vendor, "GenuineIntel", 12)) |
907 | return 0; |
908 | cpuid(1, &eax, &ebx, &ecx, &edx); |
909 | family = (eax >> 8) & 0x0f; |
910 | model = (eax >> 4) & 0x0f; |
911 | if (family == 15) |
912 | switch (model) |
913 | { |
914 | case 0: // Pentium 4, Pentium 4 Xeon (0.18um) |
915 | case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um) |
916 | case 2: // Pentium 4, Mobile Pentium 4-M, |
917 | // Pentium 4 Xeon, Pentium 4 Xeon MP, |
918 | // Celeron, Mobile Celron (0.13um) |
919 | case 3: // Pentium 4, Celeron (0.09um) |
920 | return 1; |
921 | } |
922 | return 0; |
923 | } |
924 | |
925 | static int is_geode(void) |
926 | { |
927 | unsigned int eax, ebx, ecx, edx, family, model; |
928 | char vendor[16]; |
929 | memset(vendor, 0, sizeof(vendor)); |
930 | |
931 | cpuid(0, &eax, &ebx, &ecx, &edx); |
932 | memset(vendor, 0, sizeof(vendor)); |
933 | *((unsigned int *)&vendor[0]) = ebx; |
934 | *((unsigned int *)&vendor[4]) = edx; |
935 | *((unsigned int *)&vendor[8]) = ecx; |
936 | if (!rstreqn(vendor, "AuthenticAMD", 12)) |
937 | return 0; |
938 | cpuid(1, &eax, &ebx, &ecx, &edx); |
939 | family = (eax >> 8) & 0x0f; |
940 | model = (eax >> 4) & 0x0f; |
941 | if (family == 5) |
942 | switch (model) |
943 | { |
944 | case 10: // Geode |
945 | return 1; |
946 | } |
947 | return 0; |
948 | } |
949 | #endif |
950 | |
951 | |
952 | #if defined(__linux__1) |
953 | /** |
954 | * Populate rpmat structure with auxv values |
955 | */ |
956 | static void read_auxv(void) |
957 | { |
958 | static int oneshot = 1; |
959 | |
960 | if (oneshot) { |
961 | #ifdef HAVE_GETAUXVAL1 |
962 | rpmat.platform = (char *) getauxval(AT_PLATFORM15); |
963 | if (!rpmat.platform) |
964 | rpmat.platform = ""; |
965 | rpmat.hwcap = getauxval(AT_HWCAP16); |
966 | #else |
967 | rpmat.platform = ""; |
968 | int fd = open("/proc/self/auxv", O_RDONLY00); |
969 | |
970 | if (fd == -1) { |
971 | rpmlog(RPMLOG_WARNING, |
972 | _("Failed to read auxiliary vector, /proc not mounted?\n")dcgettext ("rpm", "Failed to read auxiliary vector, /proc not mounted?\n" , 5)); |
973 | return; |
974 | } else { |
975 | ElfW(auxv_t)Elf64_auxv_t auxv; |
976 | while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) { |
977 | switch (auxv.a_type) |
978 | { |
979 | case AT_NULL0: |
980 | break; |
981 | case AT_PLATFORM15: |
982 | rpmat.platform = strdup((char *) auxv.a_un.a_val); |
983 | break; |
984 | case AT_HWCAP16: |
985 | rpmat.hwcap = auxv.a_un.a_val; |
986 | break; |
987 | } |
988 | } |
989 | close(fd); |
990 | } |
991 | #endif |
992 | oneshot = 0; /* only try once even if it fails */ |
993 | } |
994 | return; |
995 | } |
996 | #endif |
997 | |
998 | /** |
999 | */ |
1000 | static void defaultMachine(rpmrcCtx ctx, const char ** arch, const char ** os) |
1001 | { |
1002 | const char * const platform_path = SYSCONFDIR"/etc" "/rpm/platform"; |
1003 | static struct utsname un; |
1004 | char * chptr; |
1005 | canonEntry canon; |
1006 | int rc; |
1007 | |
1008 | #if defined(__linux__1) |
1009 | /* Populate rpmat struct with hw info */ |
1010 | read_auxv(); |
1011 | #endif |
1012 | |
1013 | while (!ctx->machDefaults) { |
1014 | if (!rpmPlatform(ctx, platform_path)) { |
1015 | char * s = rpmExpand("%{_host_cpu}", NULL((void*)0)); |
1016 | if (s) { |
1017 | rstrlcpy(un.machine, s, sizeof(un.machine)); |
1018 | free(s); |
1019 | } |
1020 | s = rpmExpand("%{_host_os}", NULL((void*)0)); |
1021 | if (s) { |
1022 | rstrlcpy(un.sysname, s, sizeof(un.sysname)); |
1023 | free(s); |
1024 | } |
1025 | ctx->machDefaults = 1; |
1026 | break; |
1027 | } |
1028 | rc = uname(&un); |
1029 | if (rc < 0) return; |
1030 | |
1031 | #if !defined(__linux__1) |
1032 | if (rstreq(un.sysname, "AIX")) { |
1033 | strcpy(un.machine, __power_pc()0 ? "ppc" : "rs6000"); |
1034 | sprintf(un.sysname,"aix%s.%s", un.version, un.release); |
1035 | } |
1036 | else if (rstreq(un.sysname, "Darwin")) { |
1037 | #if defined(__ppc__) |
1038 | strcpy(un.machine, "ppc"); |
1039 | #elif defined(__i386__) |
1040 | strcpy(un.machine, "i386"); |
1041 | #elif defined(__x86_64__1) |
1042 | strcpy(un.machine, "x86_64"); |
1043 | #else |
1044 | #warning "No architecture defined! Automatic detection may not work!" |
1045 | #endif |
1046 | } |
1047 | else if (rstreq(un.sysname, "SunOS")) { |
1048 | /* Solaris 2.x: n.x.x becomes n-3.x.x */ |
1049 | sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3, |
1050 | un.release+1+(atoi(un.release)/10)); |
1051 | |
1052 | /* Solaris on Intel hardware reports i86pc instead of i386 |
1053 | * (at least on 2.6 and 2.8) |
1054 | */ |
1055 | if (rstreq(un.machine, "i86pc")) |
1056 | sprintf(un.machine, "i386"); |
1057 | } |
1058 | else if (rstreq(un.sysname, "HP-UX")) |
1059 | /*make un.sysname look like hpux9.05 for example*/ |
1060 | sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789")); |
1061 | else if (rstreq(un.sysname, "OSF1")) |
1062 | /*make un.sysname look like osf3.2 for example*/ |
1063 | sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789")); |
1064 | #endif /* __linux__ */ |
1065 | |
1066 | /* get rid of the hyphens in the sysname */ |
1067 | for (chptr = un.machine; *chptr != '\0'; chptr++) |
1068 | if (*chptr == '/') *chptr = '-'; |
1069 | |
1070 | # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) |
1071 | /* little endian */ |
1072 | # if defined(__mips64) |
1073 | /* 64-bit */ |
1074 | # if !defined(__mips_isa_rev) || __mips_isa_rev < 6 |
1075 | /* r1-r5 */ |
1076 | strcpy(un.machine, "mips64el"); |
1077 | # else |
1078 | /* r6 */ |
1079 | strcpy(un.machine, "mips64r6el"); |
1080 | # endif |
1081 | # else |
1082 | /* 32-bit */ |
1083 | # if !defined(__mips_isa_rev) || __mips_isa_rev < 6 |
1084 | /* r1-r5 */ |
1085 | strcpy(un.machine, "mipsel"); |
1086 | # else |
1087 | /* r6 */ |
1088 | strcpy(un.machine, "mipsr6el"); |
1089 | # endif |
1090 | # endif |
1091 | # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) |
1092 | /* big endian */ |
1093 | # if defined(__mips64) |
1094 | /* 64-bit */ |
1095 | # if !defined(__mips_isa_rev) || __mips_isa_rev < 6 |
1096 | /* r1-r5 */ |
1097 | strcpy(un.machine, "mips64"); |
1098 | # else |
1099 | /* r6 */ |
1100 | strcpy(un.machine, "mips64r6"); |
1101 | # endif |
1102 | # else |
1103 | /* 32-bit */ |
1104 | # if !defined(__mips_isa_rev) || __mips_isa_rev < 6 |
1105 | /* r1-r5 */ |
1106 | strcpy(un.machine, "mips"); |
1107 | # else |
1108 | /* r6 */ |
1109 | strcpy(un.machine, "mipsr6"); |
1110 | # endif |
1111 | # endif |
1112 | # endif |
1113 | |
1114 | #if defined(__linux__1) |
1115 | /* in linux, lets rename parisc to hppa */ |
1116 | if (rstreq(un.machine, "parisc")) |
1117 | strcpy(un.machine, "hppa"); |
1118 | #endif |
1119 | |
1120 | # if defined(__hpux) && defined(_SC_CPU_VERSION) |
1121 | { |
1122 | # if !defined(CPU_PA_RISC1_2) |
1123 | # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */ |
1124 | # endif |
1125 | # if !defined(CPU_PA_RISC2_0) |
1126 | # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */ |
1127 | # endif |
1128 | int cpu_version = sysconf(_SC_CPU_VERSION); |
1129 | |
1130 | # if defined(CPU_HP_MC68020) |
1131 | if (cpu_version == CPU_HP_MC68020) |
1132 | strcpy(un.machine, "m68k"); |
1133 | # endif |
1134 | # if defined(CPU_HP_MC68030) |
1135 | if (cpu_version == CPU_HP_MC68030) |
1136 | strcpy(un.machine, "m68k"); |
1137 | # endif |
1138 | # if defined(CPU_HP_MC68040) |
1139 | if (cpu_version == CPU_HP_MC68040) |
1140 | strcpy(un.machine, "m68k"); |
1141 | # endif |
1142 | |
1143 | # if defined(CPU_PA_RISC1_0) |
1144 | if (cpu_version == CPU_PA_RISC1_0) |
1145 | strcpy(un.machine, "hppa1.0"); |
1146 | # endif |
1147 | # if defined(CPU_PA_RISC1_1) |
1148 | if (cpu_version == CPU_PA_RISC1_1) |
1149 | strcpy(un.machine, "hppa1.1"); |
1150 | # endif |
1151 | # if defined(CPU_PA_RISC1_2) |
1152 | if (cpu_version == CPU_PA_RISC1_2) |
1153 | strcpy(un.machine, "hppa1.2"); |
1154 | # endif |
1155 | # if defined(CPU_PA_RISC2_0) |
1156 | if (cpu_version == CPU_PA_RISC2_0) |
1157 | strcpy(un.machine, "hppa2.0"); |
1158 | # endif |
1159 | } |
1160 | # endif /* hpux */ |
1161 | |
1162 | # if defined(__linux__1) && defined(__sparc__) |
1163 | # if !defined(HWCAP_SPARC_BLKINIT) |
1164 | # define HWCAP_SPARC_BLKINIT 0x00000040 |
1165 | # endif |
1166 | if (rstreq(un.machine, "sparc")) { |
1167 | #define PERS_LINUX 0x00000000 |
1168 | #define PERS_LINUX_32BIT 0x00800000 |
1169 | #define PERS_LINUX32 0x00000008 |
1170 | |
1171 | extern int personality(unsigned long); |
1172 | int oldpers; |
1173 | |
1174 | oldpers = personality(PERS_LINUX_32BIT); |
1175 | if (oldpers != -1) { |
1176 | if (personality(PERS_LINUX) != -1) { |
1177 | uname(&un); |
1178 | if (rstreq(un.machine, "sparc64")) { |
1179 | strcpy(un.machine, "sparcv9"); |
1180 | oldpers = PERS_LINUX32; |
1181 | } |
1182 | } |
1183 | personality(oldpers); |
1184 | } |
1185 | |
1186 | /* This is how glibc detects Niagara so... */ |
1187 | if (rpmat.hwcap & HWCAP_SPARC_BLKINIT) { |
1188 | if (rstreq(un.machine, "sparcv9") || rstreq(un.machine, "sparc")) { |
1189 | strcpy(un.machine, "sparcv9v"); |
1190 | } else if (rstreq(un.machine, "sparc64")) { |
1191 | strcpy(un.machine, "sparc64v"); |
1192 | } |
1193 | } |
1194 | } |
1195 | # endif /* sparc*-linux */ |
1196 | |
1197 | # if defined(__linux__1) && defined(__powerpc__) |
1198 | # if __BYTE_ORDER__1234 == __ORDER_BIG_ENDIAN__4321 |
1199 | { |
1200 | int powerlvl; |
1201 | if (!rstreq(un.machine, "ppc") && |
1202 | sscanf(rpmat.platform, "power%d", &powerlvl) == 1 && |
1203 | powerlvl > 6) { |
1204 | strcpy(un.machine, "ppc64p7"); |
1205 | } |
1206 | } |
1207 | # endif /* __ORDER_BIG_ENDIAN__ */ |
1208 | # endif /* ppc64*-linux */ |
1209 | |
1210 | # if defined(__linux__1) && defined(__arm__) && defined(__ARM_PCS_VFP) |
1211 | # if !defined(HWCAP_ARM_VFP) |
1212 | # define HWCAP_ARM_VFP (1 << 6) |
1213 | # endif |
1214 | # if !defined(HWCAP_ARM_NEON) |
1215 | # define HWCAP_ARM_NEON (1 << 12) |
1216 | # endif |
1217 | # if !defined(HWCAP_ARM_VFPv3) |
1218 | # define HWCAP_ARM_VFPv3 (1 << 13) |
1219 | # endif |
1220 | if (rstreq(un.machine, "armv7l")) { |
1221 | if (rpmat.hwcap & HWCAP_ARM_VFPv3) { |
1222 | if (rpmat.hwcap & HWCAP_ARM_NEON) |
1223 | strcpy(un.machine, "armv7hnl"); |
1224 | else |
1225 | strcpy(un.machine, "armv7hl"); |
1226 | } |
1227 | } else if (rstreq(un.machine, "armv6l")) { |
1228 | if (rpmat.hwcap & HWCAP_ARM_VFP) |
1229 | strcpy(un.machine, "armv6hl"); |
1230 | } |
1231 | # endif /* arm*-linux */ |
1232 | |
1233 | # if defined(__linux__1) && defined(__riscv__) |
1234 | if (rstreq(un.machine, "riscv")) { |
1235 | if (sizeof(long) == 4) |
1236 | strcpy(un.machine, "riscv32"); |
1237 | else if (sizeof(long) == 8) |
1238 | strcpy(un.machine, "riscv64"); |
1239 | else if (sizeof(long) == 16) |
1240 | strcpy(un.machine, "riscv128"); |
1241 | } |
1242 | # endif /* riscv */ |
1243 | |
1244 | # if defined(__GNUC__4) && defined(__alpha__) |
1245 | { |
1246 | unsigned long amask, implver; |
1247 | register long v0 __asm__("$0") = -1; |
1248 | __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0)); |
1249 | amask = ~v0; |
1250 | __asm__ (".long 0x47e03d80" : "=r"(v0)); |
1251 | implver = v0; |
1252 | switch (implver) { |
1253 | case 1: |
1254 | switch (amask) { |
1255 | case 0: strcpy(un.machine, "alphaev5"); break; |
1256 | case 1: strcpy(un.machine, "alphaev56"); break; |
1257 | case 0x101: strcpy(un.machine, "alphapca56"); break; |
1258 | } |
1259 | break; |
1260 | case 2: |
1261 | switch (amask) { |
1262 | case 0x303: strcpy(un.machine, "alphaev6"); break; |
1263 | case 0x307: strcpy(un.machine, "alphaev67"); break; |
1264 | } |
1265 | break; |
1266 | } |
1267 | } |
1268 | # endif |
1269 | |
1270 | # if defined(__linux__1) && defined(__i386__) |
1271 | { |
1272 | char mclass = (char) (RPMClass() | '0'); |
1273 | |
1274 | if ((mclass == '6' && is_athlon()) || mclass == '7') |
1275 | strcpy(un.machine, "athlon"); |
1276 | else if (is_pentium4()) |
1277 | strcpy(un.machine, "pentium4"); |
1278 | else if (is_pentium3()) |
1279 | strcpy(un.machine, "pentium3"); |
1280 | else if (is_geode()) |
1281 | strcpy(un.machine, "geode"); |
1282 | else if (strchr("3456", un.machine[1]) && un.machine[1] != mclass) |
1283 | un.machine[1] = mclass; |
1284 | } |
1285 | # endif |
1286 | |
1287 | /* the uname() result goes through the arch_canon table */ |
1288 | canon = lookupInCanonTable(un.machine, |
1289 | ctx->tables[RPM_MACHTABLE_INSTARCH].canons, |
1290 | ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength); |
1291 | if (canon) |
1292 | rstrlcpy(un.machine, canon->short_name, sizeof(un.machine)); |
1293 | |
1294 | canon = lookupInCanonTable(un.sysname, |
1295 | ctx->tables[RPM_MACHTABLE_INSTOS].canons, |
1296 | ctx->tables[RPM_MACHTABLE_INSTOS].canonsLength); |
1297 | if (canon) |
1298 | rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname)); |
1299 | ctx->machDefaults = 1; |
1300 | break; |
1301 | } |
1302 | |
1303 | if (arch) *arch = un.machine; |
1304 | if (os) *os = un.sysname; |
1305 | } |
1306 | |
1307 | static |
1308 | const char * rpmGetVarArch(rpmrcCtx ctx, int var, const char * arch) |
1309 | { |
1310 | const struct rpmvarValue * next; |
1311 | |
1312 | if (arch == NULL((void*)0)) arch = ctx->current[ARCH1]; |
1313 | |
1314 | if (arch) { |
1315 | next = &ctx->values[var]; |
1316 | while (next) { |
1317 | if (next->arch && rstreq(next->arch, arch)) return next->value; |
1318 | next = next->next; |
1319 | } |
1320 | } |
1321 | |
1322 | next = ctx->values + var; |
1323 | while (next && next->arch) next = next->next; |
1324 | |
1325 | return next ? next->value : NULL((void*)0); |
1326 | } |
1327 | |
1328 | static void rpmSetVarArch(rpmrcCtx ctx, |
1329 | int var, const char * val, const char * arch) |
1330 | { |
1331 | struct rpmvarValue * next = ctx->values + var; |
1332 | |
1333 | if (next->value) { |
1334 | if (arch) { |
1335 | while (next->next) { |
1336 | if (next->arch && rstreq(next->arch, arch)) break; |
1337 | next = next->next; |
1338 | } |
1339 | } else { |
1340 | while (next->next) { |
1341 | if (!next->arch) break; |
1342 | next = next->next; |
1343 | } |
1344 | } |
1345 | |
1346 | if (next->arch && arch && rstreq(next->arch, arch)) { |
1347 | next->value = _free(next->value)rfree((next->value)); |
1348 | next->arch = _free(next->arch)rfree((next->arch)); |
1349 | } else if (next->arch || arch) { |
1350 | next->next = xmalloc(sizeof(*next->next))rmalloc((sizeof(*next->next))); |
1351 | next = next->next; |
1352 | next->value = NULL((void*)0); |
1353 | next->arch = NULL((void*)0); |
1354 | next->next = NULL((void*)0); |
1355 | } |
1356 | } |
1357 | |
1358 | next->value = _free(next->value)rfree((next->value)); |
1359 | next->value = xstrdup(val)rstrdup((val)); |
1360 | next->arch = (arch ? xstrdup(arch)rstrdup((arch)) : NULL((void*)0)); |
1361 | } |
1362 | |
1363 | static void rpmSetTables(rpmrcCtx ctx, int archTable, int osTable) |
1364 | { |
1365 | const char * arch, * os; |
1366 | |
1367 | defaultMachine(ctx, &arch, &os); |
1368 | |
1369 | if (ctx->currTables[ARCH1] != archTable) { |
1370 | ctx->currTables[ARCH1] = archTable; |
1371 | rebuildCompatTables(ctx, ARCH1, arch); |
1372 | } |
1373 | |
1374 | if (ctx->currTables[OS0] != osTable) { |
1375 | ctx->currTables[OS0] = osTable; |
1376 | rebuildCompatTables(ctx, OS0, os); |
1377 | } |
1378 | } |
1379 | |
1380 | /** \ingroup rpmrc |
1381 | * Set current arch/os names. |
1382 | * NULL as argument is set to the default value (munged uname()) |
1383 | * pushed through a translation table (if appropriate). |
1384 | * @deprecated Use addMacro to set _target_* macros. |
1385 | * @todo Eliminate |
1386 | * |
1387 | * @param ctx rpmrc context |
1388 | * @param arch arch name (or NULL) |
1389 | * @param os os name (or NULL) |
1390 | * */ |
1391 | |
1392 | static void rpmSetMachine(rpmrcCtx ctx, const char * arch, const char * os) |
1393 | { |
1394 | const char * host_cpu, * host_os; |
1395 | |
1396 | defaultMachine(ctx, &host_cpu, &host_os); |
1397 | |
1398 | if (arch == NULL((void*)0)) { |
1399 | arch = host_cpu; |
1400 | if (ctx->tables[ctx->currTables[ARCH1]].hasTranslate) |
1401 | arch = lookupInDefaultTable(arch, |
1402 | ctx->tables[ctx->currTables[ARCH1]].defaults, |
1403 | ctx->tables[ctx->currTables[ARCH1]].defaultsLength); |
1404 | } |
1405 | if (arch == NULL((void*)0)) return; /* XXX can't happen */ |
1406 | |
1407 | if (os == NULL((void*)0)) { |
1408 | os = host_os; |
1409 | if (ctx->tables[ctx->currTables[OS0]].hasTranslate) |
1410 | os = lookupInDefaultTable(os, |
1411 | ctx->tables[ctx->currTables[OS0]].defaults, |
1412 | ctx->tables[ctx->currTables[OS0]].defaultsLength); |
1413 | } |
1414 | if (os == NULL((void*)0)) return; /* XXX can't happen */ |
1415 | |
1416 | if (!ctx->current[ARCH1] || !rstreq(arch, ctx->current[ARCH1])) { |
1417 | ctx->current[ARCH1] = _free(ctx->current[ARCH])rfree((ctx->current[1])); |
1418 | ctx->current[ARCH1] = xstrdup(arch)rstrdup((arch)); |
1419 | rebuildCompatTables(ctx, ARCH1, host_cpu); |
1420 | } |
1421 | |
1422 | if (!ctx->current[OS0] || !rstreq(os, ctx->current[OS0])) { |
1423 | char * t = xstrdup(os)rstrdup((os)); |
1424 | ctx->current[OS0] = _free(ctx->current[OS])rfree((ctx->current[0])); |
1425 | /* |
1426 | * XXX Capitalizing the 'L' is needed to insure that old |
1427 | * XXX os-from-uname (e.g. "Linux") is compatible with the new |
1428 | * XXX os-from-platform (e.g "linux" from "sparc-*-linux"). |
1429 | * XXX A copy of this string is embedded in headers and is |
1430 | * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore-> |
1431 | * XXX to verify correct arch/os from headers. |
1432 | */ |
1433 | if (rstreq(t, "linux")) |
1434 | *t = 'L'; |
1435 | ctx->current[OS0] = t; |
1436 | |
1437 | rebuildCompatTables(ctx, OS0, host_os); |
1438 | } |
1439 | } |
1440 | |
1441 | static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name) |
1442 | { |
1443 | machFindEquivs(&ctx->tables[ctx->currTables[type]].cache, |
1444 | &ctx->tables[ctx->currTables[type]].equiv, |
1445 | name); |
1446 | } |
1447 | |
1448 | static void getMachineInfo(rpmrcCtx ctx, |
1449 | int type, const char ** name, int * num) |
1450 | { |
1451 | canonEntry canon; |
1452 | int which = ctx->currTables[type]; |
1453 | |
1454 | /* use the normal canon tables, even if we're looking up build stuff */ |
1455 | if (which >= 2) which -= 2; |
1456 | |
1457 | canon = lookupInCanonTable(ctx->current[type], |
1458 | ctx->tables[which].canons, |
1459 | ctx->tables[which].canonsLength); |
1460 | |
1461 | if (canon) { |
1462 | if (num) *num = canon->num; |
1463 | if (name) *name = canon->short_name; |
1464 | } else { |
1465 | if (num) *num = 255; |
1466 | if (name) *name = ctx->current[type]; |
1467 | |
1468 | if (ctx->tables[ctx->currTables[type]].hasCanon) { |
1469 | rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n")dcgettext ("rpm", "Unknown system: %s\n", 5), |
1470 | ctx->current[type]); |
1471 | rpmlog(RPMLOG_WARNING, _("Please contact %s\n")dcgettext ("rpm", "Please contact %s\n", 5), PACKAGE_BUGREPORT"rpm-maint@lists.rpm.org"); |
1472 | } |
1473 | } |
1474 | } |
1475 | |
1476 | static void rpmRebuildTargetVars(rpmrcCtx ctx, |
1477 | const char ** target, const char ** canontarget) |
1478 | { |
1479 | |
1480 | char *ca = NULL((void*)0), *co = NULL((void*)0), *ct = NULL((void*)0); |
1481 | int x; |
1482 | |
1483 | /* Rebuild the compat table to recalculate the current target arch. */ |
1484 | |
1485 | rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0)); |
1486 | rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS); |
1487 | rpmSetTables(ctx, RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS); |
1488 | |
1489 | if (target && *target) { |
1490 | char *c; |
1491 | /* Set arch and os from specified build target */ |
1492 | ca = xstrdup(*target)rstrdup((*target)); |
1493 | if ((c = strchr(ca, '-')) != NULL((void*)0)) { |
1494 | *c++ = '\0'; |
1495 | |
1496 | if ((co = strrchr(c, '-')) == NULL((void*)0)) { |
1497 | co = c; |
1498 | } else { |
1499 | if (!rstrcasecmp(co, "-gnu")) |
1500 | *co = '\0'; |
1501 | if ((co = strrchr(c, '-')) == NULL((void*)0)) |
1502 | co = c; |
1503 | else |
1504 | co++; |
1505 | } |
1506 | if (co != NULL((void*)0)) co = xstrdup(co)rstrdup((co)); |
1507 | } |
1508 | } else { |
1509 | const char *a = NULL((void*)0); |
1510 | const char *o = NULL((void*)0); |
1511 | /* Set build target from rpm arch and os */ |
1512 | getMachineInfo(ctx, ARCH1, &a, NULL((void*)0)); |
1513 | ca = (a) ? xstrdup(a)rstrdup((a)) : NULL((void*)0); |
1514 | getMachineInfo(ctx, OS0, &o, NULL((void*)0)); |
1515 | co = (o) ? xstrdup(o)rstrdup((o)) : NULL((void*)0); |
1516 | } |
1517 | |
1518 | /* If still not set, Set target arch/os from default uname(2) values */ |
1519 | if (ca == NULL((void*)0)) { |
1520 | const char *a = NULL((void*)0); |
1521 | defaultMachine(ctx, &a, NULL((void*)0)); |
1522 | ca = xstrdup(a ? a : "(arch)")rstrdup((a ? a : "(arch)")); |
1523 | } |
1524 | for (x = 0; ca[x] != '\0'; x++) |
1525 | ca[x] = rtolower(ca[x]); |
1526 | |
1527 | if (co == NULL((void*)0)) { |
1528 | const char *o = NULL((void*)0); |
1529 | defaultMachine(ctx, NULL((void*)0), &o); |
1530 | co = xstrdup(o ? o : "(os)")rstrdup((o ? o : "(os)")); |
1531 | } |
1532 | for (x = 0; co[x] != '\0'; x++) |
1533 | co[x] = rtolower(co[x]); |
1534 | |
1535 | /* XXX For now, set canonical target to arch-os */ |
1536 | if (ct == NULL((void*)0)) { |
1537 | rasprintf(&ct, "%s-%s", ca, co); |
1538 | } |
1539 | |
1540 | /* |
1541 | * XXX All this macro pokery/jiggery could be achieved by doing a delayed |
1542 | * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES); |
1543 | */ |
1544 | rpmPopMacro(NULL((void*)0), "_target"); |
1545 | rpmPushMacro(NULL((void*)0), "_target", NULL((void*)0), ct, RMIL_RPMRC-11); |
1546 | rpmPopMacro(NULL((void*)0), "_target_cpu"); |
1547 | rpmPushMacro(NULL((void*)0), "_target_cpu", NULL((void*)0), ca, RMIL_RPMRC-11); |
1548 | rpmPopMacro(NULL((void*)0), "_target_os"); |
1549 | rpmPushMacro(NULL((void*)0), "_target_os", NULL((void*)0), co, RMIL_RPMRC-11); |
1550 | /* |
1551 | * XXX Make sure that per-arch optflags is initialized correctly. |
1552 | */ |
1553 | { const char *optflags = rpmGetVarArch(ctx, RPMVAR_OPTFLAGS3, ca); |
1554 | if (optflags != NULL((void*)0)) { |
1555 | rpmPopMacro(NULL((void*)0), "optflags"); |
1556 | rpmPushMacro(NULL((void*)0), "optflags", NULL((void*)0), optflags, RMIL_RPMRC-11); |
1557 | } |
1558 | } |
1559 | |
1560 | if (canontarget) |
1561 | *canontarget = ct; |
1562 | else |
1563 | free(ct); |
1564 | free(ca); |
1565 | free(co); |
1566 | } |
1567 | |
1568 | /** \ingroup rpmrc |
1569 | * Read rpmrc (and macro) configuration file(s). |
1570 | * @param ctx rpmrc context |
1571 | * @param rcfiles colon separated files to read (NULL uses default) |
1572 | * @return RPMRC_OK on success |
1573 | */ |
1574 | static rpmRC rpmReadRC(rpmrcCtx ctx, const char * rcfiles) |
1575 | { |
1576 | ARGV_t p, globs = NULL((void*)0), files = NULL((void*)0); |
1577 | rpmRC rc = RPMRC_FAIL; |
1578 | |
1579 | if (!ctx->pathDefaults) { |
1580 | setDefaults(); |
1581 | ctx->pathDefaults = 1; |
1582 | } |
1583 | |
1584 | if (rcfiles == NULL((void*)0)) |
1585 | rcfiles = defrcfiles; |
1586 | |
1587 | /* Expand any globs in rcfiles. Missing files are ok here. */ |
1588 | argvSplit(&globs, rcfiles, ":"); |
1589 | for (p = globs; *p; p++) { |
1590 | ARGV_t av = NULL((void*)0); |
1591 | if (rpmGlob(*p, NULL((void*)0), &av) == 0) { |
1592 | argvAppend(&files, av); |
1593 | argvFree(av); |
1594 | } |
1595 | } |
1596 | argvFree(globs); |
1597 | |
1598 | /* Read each file in rcfiles. */ |
1599 | for (p = files; p && *p; p++) { |
1600 | /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */ |
1601 | if (access(*p, R_OK4) != 0) { |
1602 | if (rcfiles == defrcfiles && p != files) |
1603 | continue; |
1604 | rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n")dcgettext ("rpm", "Unable to open %s for reading: %m.\n", 5), *p); |
1605 | goto exit; |
1606 | break; |
1607 | } else { |
1608 | rc = doReadRC(ctx, *p); |
1609 | } |
1610 | } |
1611 | rc = RPMRC_OK; |
1612 | rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0)); /* XXX WTFO? Why bother? */ |
1613 | |
1614 | exit: |
1615 | argvFree(files); |
1616 | return rc; |
1617 | } |
1618 | |
1619 | static void register_atexit(void) |
1620 | { |
1621 | if (atexit(rpmAtExit) != 0) |
1622 | rpmlog(RPMLOG_WARNING, _("failed to register exit handler")dcgettext ("rpm", "failed to register exit handler", 5)); |
1623 | } |
1624 | |
1625 | /* External interfaces */ |
1626 | |
1627 | int rpmReadConfigFiles(const char * file, const char * target) |
1628 | { |
1629 | static pthread_once_t atexit_registered = PTHREAD_ONCE_INIT0; |
1630 | int rc = -1; /* assume failure */ |
1631 | rpmrcCtx ctx = rpmrcCtxAcquire(1); |
1632 | |
1633 | pthread_once(&atexit_registered, register_atexit); |
1634 | |
1635 | /* Force preloading of dlopen()'ed libraries in case we go chrooting */ |
1636 | if (rpmugInit()) |
1637 | goto exit; |
1638 | |
1639 | if (rpmInitCrypto()) |
1640 | goto exit; |
1641 | |
1642 | /* Preset target macros */ |
1643 | /* FIX: target can be NULL */ |
1644 | rpmRebuildTargetVars(ctx, &target, NULL((void*)0)); |
1645 | |
1646 | /* Read the files */ |
1647 | if (rpmReadRC(ctx, file)) |
1648 | goto exit; |
1649 | |
1650 | if (macrofiles != NULL((void*)0)) { |
1651 | char *mf = rpmGetPath(macrofiles, NULL((void*)0)); |
1652 | rpmInitMacros(NULL((void*)0), mf); |
1653 | _free(mf)rfree((mf)); |
1654 | } |
1655 | |
1656 | /* Reset target macros */ |
1657 | rpmRebuildTargetVars(ctx, &target, NULL((void*)0)); |
1658 | |
1659 | /* Finally set target platform */ |
1660 | { char *cpu = rpmExpand("%{_target_cpu}", NULL((void*)0)); |
1661 | char *os = rpmExpand("%{_target_os}", NULL((void*)0)); |
1662 | rpmSetMachine(ctx, cpu, os); |
1663 | free(cpu); |
1664 | free(os); |
1665 | } |
1666 | |
1667 | #ifdef WITH_LUA1 |
1668 | /* Force Lua state initialization */ |
1669 | rpmLuaInit(); |
1670 | #endif |
1671 | rc = 0; |
1672 | |
1673 | exit: |
1674 | rpmrcCtxRelease(ctx); |
1675 | return rc; |
1676 | } |
1677 | |
1678 | void rpmFreeRpmrc(void) |
1679 | { |
1680 | rpmrcCtx ctx = rpmrcCtxAcquire(1); |
1681 | int i, j, k; |
1682 | |
1683 | ctx->platpat = argvFree(ctx->platpat); |
1684 | |
1685 | for (i = 0; i < RPM_MACHTABLE_COUNT4; i++) { |
1686 | tableType t; |
1687 | t = ctx->tables + i; |
1688 | if (t->equiv.list) { |
1689 | for (j = 0; j < t->equiv.count; j++) |
1690 | t->equiv.list[j].name = _free(t->equiv.list[j].name)rfree((t->equiv.list[j].name)); |
1691 | t->equiv.list = _free(t->equiv.list)rfree((t->equiv.list)); |
1692 | t->equiv.count = 0; |
1693 | } |
1694 | if (t->cache.cache) { |
1695 | for (j = 0; j < t->cache.size; j++) { |
1696 | machCacheEntry e; |
1697 | e = t->cache.cache + j; |
1698 | if (e == NULL((void*)0)) |
1699 | continue; |
1700 | e->name = _free(e->name)rfree((e->name)); |
1701 | if (e->equivs) { |
1702 | for (k = 0; k < e->count; k++) |
1703 | e->equivs[k] = _free(e->equivs[k])rfree((e->equivs[k])); |
1704 | e->equivs = _free(e->equivs)rfree((e->equivs)); |
1705 | } |
1706 | } |
1707 | t->cache.cache = _free(t->cache.cache)rfree((t->cache.cache)); |
1708 | t->cache.size = 0; |
1709 | } |
1710 | if (t->defaults) { |
1711 | for (j = 0; j < t->defaultsLength; j++) { |
1712 | t->defaults[j].name = _free(t->defaults[j].name)rfree((t->defaults[j].name)); |
1713 | t->defaults[j].defName = _free(t->defaults[j].defName)rfree((t->defaults[j].defName)); |
1714 | } |
1715 | t->defaults = _free(t->defaults)rfree((t->defaults)); |
1716 | t->defaultsLength = 0; |
1717 | } |
1718 | if (t->canons) { |
1719 | for (j = 0; j < t->canonsLength; j++) { |
1720 | t->canons[j].name = _free(t->canons[j].name)rfree((t->canons[j].name)); |
1721 | t->canons[j].short_name = _free(t->canons[j].short_name)rfree((t->canons[j].short_name)); |
1722 | } |
1723 | t->canons = _free(t->canons)rfree((t->canons)); |
1724 | t->canonsLength = 0; |
1725 | } |
1726 | } |
1727 | |
1728 | for (i = 0; i < RPMVAR_NUM55; i++) { |
1729 | struct rpmvarValue * vp; |
1730 | while ((vp = ctx->values[i].next) != NULL((void*)0)) { |
1731 | ctx->values[i].next = vp->next; |
1732 | vp->value = _free(vp->value)rfree((vp->value)); |
1733 | vp->arch = _free(vp->arch)rfree((vp->arch)); |
1734 | vp = _free(vp)rfree((vp)); |
Value stored to 'vp' is never read | |
1735 | } |
1736 | ctx->values[i].value = _free(ctx->values[i].value)rfree((ctx->values[i].value)); |
1737 | ctx->values[i].arch = _free(ctx->values[i].arch)rfree((ctx->values[i].arch)); |
1738 | } |
1739 | ctx->current[OS0] = _free(ctx->current[OS])rfree((ctx->current[0])); |
1740 | ctx->current[ARCH1] = _free(ctx->current[ARCH])rfree((ctx->current[1])); |
1741 | ctx->machDefaults = 0; |
1742 | ctx->pathDefaults = 0; |
1743 | |
1744 | /* XXX doesn't really belong here but... */ |
1745 | rpmFreeCrypto(); |
1746 | #ifdef WITH_LUA1 |
1747 | rpmLuaFree(); |
1748 | #endif |
1749 | |
1750 | rpmrcCtxRelease(ctx); |
1751 | return; |
1752 | } |
1753 | |
1754 | int rpmShowRC(FILE * fp) |
1755 | { |
1756 | /* Write-context necessary as this calls rpmSetTables(), ugh */ |
1757 | rpmrcCtx ctx = rpmrcCtxAcquire(1); |
1758 | const struct rpmOption *opt; |
1759 | rpmds ds = NULL((void*)0); |
1760 | int i; |
1761 | machEquivTable equivTable; |
1762 | |
1763 | /* the caller may set the build arch which should be printed here */ |
1764 | fprintf(fp, "ARCHITECTURE AND OS:\n"); |
1765 | fprintf(fp, "build arch : %s\n", ctx->current[ARCH1]); |
1766 | |
1767 | fprintf(fp, "compatible build archs:"); |
1768 | equivTable = &ctx->tables[RPM_MACHTABLE_BUILDARCH].equiv; |
1769 | for (i = 0; i < equivTable->count; i++) |
1770 | fprintf(fp," %s", equivTable->list[i].name); |
1771 | fprintf(fp, "\n"); |
1772 | |
1773 | fprintf(fp, "build os : %s\n", ctx->current[OS0]); |
1774 | |
1775 | fprintf(fp, "compatible build os's :"); |
1776 | equivTable = &ctx->tables[RPM_MACHTABLE_BUILDOS].equiv; |
1777 | for (i = 0; i < equivTable->count; i++) |
1778 | fprintf(fp," %s", equivTable->list[i].name); |
1779 | fprintf(fp, "\n"); |
1780 | |
1781 | rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS); |
1782 | rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0)); /* XXX WTFO? Why bother? */ |
1783 | |
1784 | fprintf(fp, "install arch : %s\n", ctx->current[ARCH1]); |
1785 | fprintf(fp, "install os : %s\n", ctx->current[OS0]); |
1786 | |
1787 | fprintf(fp, "compatible archs :"); |
1788 | equivTable = &ctx->tables[RPM_MACHTABLE_INSTARCH].equiv; |
1789 | for (i = 0; i < equivTable->count; i++) |
1790 | fprintf(fp," %s", equivTable->list[i].name); |
1791 | fprintf(fp, "\n"); |
1792 | |
1793 | fprintf(fp, "compatible os's :"); |
1794 | equivTable = &ctx->tables[RPM_MACHTABLE_INSTOS].equiv; |
1795 | for (i = 0; i < equivTable->count; i++) |
1796 | fprintf(fp," %s", equivTable->list[i].name); |
1797 | fprintf(fp, "\n"); |
1798 | |
1799 | fprintf(fp, "\nRPMRC VALUES:\n"); |
1800 | for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) { |
1801 | const char *s = rpmGetVarArch(ctx, opt->var, NULL((void*)0)); |
1802 | if (s != NULL((void*)0) || rpmIsVerbose()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_INFO)) ))) |
1803 | fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)"); |
1804 | } |
1805 | fprintf(fp, "\n"); |
1806 | |
1807 | fprintf(fp, "Features supported by rpmlib:\n"); |
1808 | rpmdsRpmlib(&ds, NULL((void*)0)); |
1809 | ds = rpmdsInit(ds); |
1810 | while (rpmdsNext(ds) >= 0) { |
1811 | const char * DNEVR = rpmdsDNEVR(ds); |
1812 | if (DNEVR != NULL((void*)0)) |
1813 | fprintf(fp, " %s\n", DNEVR+2); |
1814 | } |
1815 | ds = rpmdsFree(ds); |
1816 | fprintf(fp, "\n"); |
1817 | |
1818 | fprintf(fp, "Macro path: %s\n", macrofiles); |
1819 | fprintf(fp, "\n"); |
1820 | |
1821 | rpmDumpMacroTable(NULL((void*)0), fp); |
1822 | |
1823 | /* XXX: Move this earlier eventually... */ |
1824 | rpmrcCtxRelease(ctx); |
1825 | |
1826 | return 0; |
1827 | } |
1828 | |
1829 | int rpmMachineScore(int type, const char * name) |
1830 | { |
1831 | int score = 0; |
1832 | if (name) { |
1833 | rpmrcCtx ctx = rpmrcCtxAcquire(0); |
1834 | machEquivInfo info = machEquivSearch(&ctx->tables[type].equiv, name); |
1835 | if (info) |
1836 | score = info->score; |
1837 | rpmrcCtxRelease(ctx); |
1838 | } |
1839 | return score; |
1840 | } |
1841 | |
1842 | int rpmIsKnownArch(const char *name) |
1843 | { |
1844 | rpmrcCtx ctx = rpmrcCtxAcquire(0); |
1845 | canonEntry canon = lookupInCanonTable(name, |
1846 | ctx->tables[RPM_MACHTABLE_INSTARCH].canons, |
1847 | ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength); |
1848 | int known = (canon != NULL((void*)0) || rstreq(name, "noarch")); |
1849 | rpmrcCtxRelease(ctx); |
1850 | return known; |
1851 | } |
1852 | |
1853 | void rpmGetArchInfo(const char ** name, int * num) |
1854 | { |
1855 | rpmrcCtx ctx = rpmrcCtxAcquire(0); |
1856 | getMachineInfo(ctx, ARCH1, name, num); |
1857 | rpmrcCtxRelease(ctx); |
1858 | } |
1859 | |
1860 | int rpmGetArchColor(const char *arch) |
1861 | { |
1862 | rpmrcCtx ctx = rpmrcCtxAcquire(0); |
1863 | const char *color; |
1864 | char *e; |
1865 | int color_i = -1; /* assume failure */ |
1866 | |
1867 | arch = lookupInDefaultTable(arch, |
1868 | ctx->tables[ctx->currTables[ARCH1]].defaults, |
1869 | ctx->tables[ctx->currTables[ARCH1]].defaultsLength); |
1870 | color = rpmGetVarArch(ctx, RPMVAR_ARCHCOLOR42, arch); |
1871 | if (color) { |
1872 | color_i = strtol(color, &e, 10); |
1873 | if (!(e && *e == '\0')) { |
1874 | color_i = -1; |
1875 | } |
1876 | } |
1877 | rpmrcCtxRelease(ctx); |
1878 | |
1879 | return color_i; |
1880 | } |
1881 | |
1882 | void rpmGetOsInfo(const char ** name, int * num) |
1883 | { |
1884 | rpmrcCtx ctx = rpmrcCtxAcquire(0); |
1885 | getMachineInfo(ctx, OS0, name, num); |
1886 | rpmrcCtxRelease(ctx); |
1887 | } |
1888 |