| 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 |