4 #if defined(__linux__) && defined(__powerpc__)
8 #include <ctype.h> /* XXX for /etc/rpm/platform contents */
10 #if HAVE_SYS_SYSTEMCFG_H
11 #include <sys/systemcfg.h>
13 #define __power_pc() 0
16 #include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */
17 #include <rpm/rpmlib.h>
18 #include <rpm/rpmmacro.h>
19 #include <rpm/rpmfileutil.h>
20 #include <rpm/rpmstring.h>
21 #include "rpmio/rpmlua.h"
23 #include <rpm/rpmlog.h>
26 static const char *defrcfiles =
28 ":" RPMCONFIGDIR "/" RPMCANONVENDOR "/rpmrc"
29 ":" SYSCONFDIR "/rpmrc"
32 const char * macrofiles =
34 RPMCONFIGDIR "/macros"
35 ":" RPMCONFIGDIR "/%{_target}/macros"
36 ":" SYSCONFDIR "/rpm/macros.*"
37 ":" SYSCONFDIR "/rpm/macros"
38 ":" SYSCONFDIR "/rpm/%{_target}/macros"
44 static const char * platform = SYSCONFDIR "/rpm/platform";
45 static char ** platpat = NULL;
46 static int nplatpat = 0;
48 typedef char * cptr_t;
50 typedef struct machCacheEntry_s {
57 typedef struct machCache_s {
62 typedef struct machEquivInfo_s {
67 typedef struct machEquivTable_s {
74 /* eventually, this arch will be replaced with a generic condition */
76 struct rpmvarValue * next;
86 struct rpmOptionValue * value;
89 typedef struct defaultEntry_s {
94 typedef struct canonEntry_s {
100 /* tags are 'key'canon, 'key'translate, 'key'compat
102 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
104 typedef struct tableType_s {
107 const int hasTranslate;
108 struct machEquivTable_s equiv;
109 struct machCache_s cache;
110 defaultEntry defaults;
116 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
119 { "buildarch", 0, 1 },
123 /* XXX get rid of this stuff... */
124 /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
125 #define RPMVAR_OPTFLAGS 3
126 #define RPMVAR_INCLUDE 43
127 #define RPMVAR_MACROFILES 49
129 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
131 /* this *must* be kept in alphabetical order */
132 /* The order of the flags is archSpecific, required, macroize, localize */
134 static struct rpmOption optionTable[] = {
135 { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
136 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
137 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
140 static size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
145 static cptr_t current[2];
147 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
149 static struct rpmvarValue values[RPMVAR_NUM];
151 static int defaultsInitialized = 0;
154 static rpmRC doReadRC( FD_t fd, const char * urlfn);
156 static void rpmSetVarArch(int var, const char * val,
159 static void rebuildCompatTables(int type, const char * name);
161 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
163 static int optionCompare(const void * a, const void * b)
165 return xstrcasecmp(((const struct rpmOption *) a)->name,
166 ((const struct rpmOption *) b)->name);
169 static machCacheEntry
170 machCacheFindEntry(const machCache cache, const char * key)
174 for (i = 0; i < cache->size; i++)
175 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
180 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
183 machCacheEntry entry = NULL;
189 while (*name && xisspace(*name)) name++;
192 while (*chptr && *chptr != ':') chptr++;
194 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n"), fn, linenum);
196 } else if (chptr == name) {
197 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n"), fn,
202 while (*chptr == ':' || xisspace(*chptr)) chptr--;
205 while (*equivs && xisspace(*equivs)) equivs++;
211 entry = machCacheFindEntry(cache, name);
213 for (i = 0; i < entry->count; i++)
214 entry->equivs[i] = _free(entry->equivs[i]);
215 entry->equivs = _free(entry->equivs);
221 cache->cache = xrealloc(cache->cache,
222 (cache->size + 1) * sizeof(*cache->cache));
223 entry = cache->cache + cache->size++;
224 entry->name = xstrdup(name);
229 if (delEntry) return 0;
231 while ((chptr = strtok(equivs, " ")) != NULL) {
233 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
236 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
237 * (entry->count + 1));
239 entry->equivs = xmalloc(sizeof(*entry->equivs));
241 entry->equivs[entry->count] = xstrdup(chptr);
249 machEquivSearch(const machEquivTable table, const char * name)
253 for (i = 0; i < table->count; i++)
254 if (!xstrcasecmp(table->list[i].name, name))
255 return table->list + i;
260 static void machAddEquiv(machEquivTable table, const char * name,
265 equiv = machEquivSearch(table, name);
268 table->list = xrealloc(table->list, (table->count + 1)
269 * sizeof(*table->list));
271 table->list = xmalloc(sizeof(*table->list));
273 table->list[table->count].name = xstrdup(name);
274 table->list[table->count++].score = distance;
278 static void machCacheEntryVisit(machCache cache,
279 machEquivTable table, const char * name, int distance)
281 machCacheEntry entry;
284 entry = machCacheFindEntry(cache, name);
285 if (!entry || entry->visited) return;
289 for (i = 0; i < entry->count; i++) {
290 machAddEquiv(table, entry->equivs[i], distance);
293 for (i = 0; i < entry->count; i++) {
294 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
298 static void machFindEquivs(machCache cache, machEquivTable table,
303 for (i = 0; i < cache->size; i++)
304 cache->cache[i].visited = 0;
306 while (table->count > 0) {
308 table->list[table->count].name = _free(table->list[table->count].name);
311 table->list = _free(table->list);
314 * We have a general graph built using strings instead of pointers.
315 * Yuck. We have to start at a point at traverse it, remembering how
316 * far away everything is.
318 /* FIX: table->list may be NULL. */
319 machAddEquiv(table, key, 1);
320 machCacheEntryVisit(cache, table, key, 2);
324 static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
325 const char * fn, int lineNum)
330 const char * tshort_name;
334 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
336 t = & ((*table)[*tableLen - 2]);
338 tname = strtok(line, ": \t");
339 tshort_name = strtok(NULL, " \t");
340 s = strtok(NULL, " \t");
341 if (! (tname && tshort_name && s)) {
342 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n"),
346 if (strtok(NULL, " \t")) {
347 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n"),
352 /* LCL: s != NULL here. */
353 tnum = strtoul(s, &s1, 10);
354 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
355 rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n"), s,
360 t[0].name = xstrdup(tname);
361 t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
364 /* From A B C entry */
365 /* Add B B C entry */
366 t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
367 t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
373 static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line,
374 const char * fn, int lineNum)
379 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
381 t = & ((*table)[*tableLen - 1]);
383 t->name = strtok(line, ": \t");
384 t->defName = strtok(NULL, " \t");
385 if (! (t->name && t->defName)) {
386 rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n"),
390 if (strtok(NULL, " \t")) {
391 rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n"),
396 t->name = xstrdup(t->name);
397 t->defName = (t->defName ? xstrdup(t->defName) : NULL);
402 static canonEntry lookupInCanonTable(const char * name,
403 const canonEntry table, int tableLen)
407 if (strcmp(name, table[tableLen].name))
409 return &(table[tableLen]);
416 const char * lookupInDefaultTable(const char * name,
417 const defaultEntry table, int tableLen)
421 if (table[tableLen].name && !strcmp(name, table[tableLen].name))
422 return table[tableLen].defName;
428 static void addMacroDefault(const char * macroname, const char * val,
433 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
436 static void setPathDefault(const char * macroname, const char * subdir)
439 if (macroname != NULL) {
440 #define _TOPDIRMACRO "%{_topdir}/"
441 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
442 strcpy(body, _TOPDIRMACRO);
443 strcat(body, subdir);
444 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
449 static const char * prescriptenviron = "\n\
450 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
451 RPM_BUILD_DIR=\"%{_builddir}\"\n\
452 RPM_OPT_FLAGS=\"%{optflags}\"\n\
453 RPM_ARCH=\"%{_arch}\"\n\
455 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
456 RPM_DOC_DIR=\"%{_docdir}\"\n\
457 export RPM_DOC_DIR\n\
458 RPM_PACKAGE_NAME=\"%{name}\"\n\
459 RPM_PACKAGE_VERSION=\"%{version}\"\n\
460 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
461 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
462 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
463 export RPM_BUILD_ROOT\n}\
466 static void setDefaults(void)
469 addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
470 addMacro(NULL, "_var", NULL, LOCALSTATEDIR, RMIL_DEFAULT);
472 addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
474 addMacroDefault("_topdir",
475 "/usr/src/packages", "%{_usrsrc}/packages");
476 addMacroDefault("_tmppath",
477 LOCALSTATEDIR "/tmp", "%{_var}/tmp");
478 addMacroDefault("_dbpath",
479 LOCALSTATEDIR "/lib/rpm", "%{_var}/lib/rpm");
480 addMacroDefault("_defaultdocdir",
481 "/usr/doc", "%{_usr}/doc");
483 addMacroDefault("_rpmfilename",
484 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
486 addMacroDefault("optflags",
488 addMacroDefault("sigtype",
490 addMacroDefault("_buildshell",
493 setPathDefault("_builddir", "BUILD");
494 setPathDefault("_rpmdir", "RPMS");
495 setPathDefault("_srcrpmdir", "SRPMS");
496 setPathDefault("_sourcedir", "SOURCES");
497 setPathDefault("_specdir", "SPECS");
501 /* FIX: se usage inconsistent, W2DO? */
502 static rpmRC doReadRC( FD_t fd, const char * urlfn)
507 struct rpmOption searchOption, * option;
510 /* XXX really need rc = Slurp(fd, const char * filename, char ** buf) */
511 { off_t size = fdSize(fd);
512 size_t nb = (size >= 0 ? size : (8*BUFSIZ - 2));
517 next = alloca(nb + 2);
519 rc = Fread(next, sizeof(*next), nb, fd);
520 if (Ferror(fd) || (size > 0 && rc != nb)) { /* XXX Feof(fd) */
521 rpmlog(RPMLOG_ERR, _("Failed to read %s: %s.\n"), urlfn,
532 while (*next != '\0') {
537 /* Find end-of-line. */
538 while (*se && *se != '\n') se++;
539 if (*se != '\0') *se++ = '\0';
542 /* Trim leading spaces */
543 while (*s && xisspace(*s)) s++;
545 /* We used to allow comments to begin anywhere, but not anymore. */
546 if (*s == '#' || *s == '\0') continue;
548 /* Find end-of-keyword. */
550 while (*se && !xisspace(*se) && *se != ':') se++;
554 while (*se && xisspace(*se) && *se != ':') se++;
558 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n"),
559 (unsigned)(0xff & *se), urlfn, linenum);
562 *se++ = '\0'; /* terminate keyword or option, point to value */
563 while (*se && xisspace(*se)) se++;
565 /* Find keyword in table */
566 searchOption.name = s;
567 option = bsearch(&searchOption, optionTable, optionTableSize,
568 sizeof(optionTable[0]), optionCompare);
570 if (option) { /* For configuration variables ... */
571 const char *arch, *val;
574 arch = val = fn = NULL;
576 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n"),
577 option->name, urlfn, linenum);
581 switch (option->var) {
586 while (*se && !xisspace(*se)) se++;
587 if (*se != '\0') *se++ = '\0';
589 rpmRebuildTargetVars(NULL, NULL);
591 fn = rpmGetPath(s, NULL);
592 if (fn == NULL || *fn == '\0') {
593 rpmlog(RPMLOG_ERR, _("%s expansion failed at %s:%d \"%s\"\n"),
594 option->name, urlfn, linenum, s);
599 fdinc = Fopen(fn, "r.fpio");
600 if (fdinc == NULL || Ferror(fdinc)) {
601 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %s\n"),
602 fn, urlfn, linenum, Fstrerror(fdinc));
605 rc = doReadRC(fdinc, fn);
609 continue; /* XXX don't save include value as var/macro */
615 if (option->archSpecific) {
617 while (*se && !xisspace(*se)) se++;
620 _("missing architecture for %s at %s:%d\n"),
621 option->name, urlfn, linenum);
625 while (*se && xisspace(*se)) se++;
628 _("missing argument for %s at %s:%d\n"),
629 option->name, urlfn, linenum);
636 /* Only add macros if appropriate for this arch */
637 if (option->macroize &&
638 (arch == NULL || !strcmp(arch, current[ARCH]))) {
640 n = name = xmalloc(strlen(option->name)+2);
641 if (option->localize)
643 strcpy(n, option->name);
644 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
647 rpmSetVarArch(option->var, val, arch);
650 } else { /* For arch/os compatibilty tables ... */
656 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
657 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
661 if (i < RPM_MACHTABLE_COUNT) {
662 const char *rest = s + strlen(tables[i].key);
663 if (*rest == '_') rest++;
665 if (!strcmp(rest, "compat")) {
666 if (machCompatCacheAdd(se, urlfn, linenum,
670 } else if (tables[i].hasTranslate &&
671 !strcmp(rest, "translate")) {
672 if (addDefault(&tables[i].defaults,
673 &tables[i].defaultsLength,
677 } else if (tables[i].hasCanon &&
678 !strcmp(rest, "canon")) {
679 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
687 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n"),
699 static rpmRC rpmPlatform(const char * platform)
701 const char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
704 int init_platform = 0;
708 rc = rpmioSlurp(platform, &b, &blen);
710 if (rc || b == NULL || blen <= 0) {
716 for (pe = p; p && *p; p = pe) {
717 pe = strchr(p, '\n');
721 while (*p && isspace(*p))
723 if (*p == '\0' || *p == '#')
727 char * t = p + strlen(p);
729 while (--t > p && isspace(*t))
732 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
733 platpat[nplatpat] = xstrdup(p);
735 platpat[nplatpat] = NULL;
744 while (*p && !(*p == '-' || isspace(*p)))
746 if (*p != '\0') *p++ = '\0';
749 while (*p && !(*p == '-' || isspace(*p)))
752 if (*p != '\0') *p++ = '\0';
756 if (*p != '\0') *p++ = '\0';
759 while (*p && !(*p == '-' || isspace(*p)))
765 while (*p && !(*p == '-' || isspace(*p)))
768 if (*p != '\0') *p++ = '\0';
771 addMacro(NULL, "_host_cpu", NULL, cpu, -1);
772 addMacro(NULL, "_host_vendor", NULL, vendor, -1);
773 addMacro(NULL, "_host_os", NULL, os, -1);
775 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
776 platpat[nplatpat] = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", (gnu && *gnu ? "-" : NULL), gnu, NULL);
778 platpat[nplatpat] = NULL;
782 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
790 # if defined(__linux__) && defined(__i386__)
795 * Generic CPUID function
797 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
802 "movl %%ebx, %%esi \n"
804 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
809 * CPUID functions returning a single datum
811 static inline unsigned int cpuid_eax(unsigned int op)
813 unsigned int tmp, val;
814 cpuid(op, &val, &tmp, &tmp, &tmp);
818 static inline unsigned int cpuid_ebx(unsigned int op)
820 unsigned int tmp, val;
821 cpuid(op, &tmp, &val, &tmp, &tmp);
825 static inline unsigned int cpuid_ecx(unsigned int op)
827 unsigned int tmp, val;
828 cpuid(op, &tmp, &tmp, &val, &tmp);
832 static inline unsigned int cpuid_edx(unsigned int op)
834 unsigned int tmp, val;
835 cpuid(op, &tmp, &tmp, &tmp, &val);
839 static sigjmp_buf jenv;
841 static inline void model3(int _unused)
846 static inline int RPMClass(void)
849 unsigned int tfms, junk, cap, capamd;
850 struct sigaction oldsa;
852 sigaction(SIGILL, NULL, &oldsa);
853 signal(SIGILL, model3);
855 if (sigsetjmp(jenv, 1)) {
856 sigaction(SIGILL, &oldsa, NULL);
860 if (cpuid_eax(0x000000000)==0) {
861 sigaction(SIGILL, &oldsa, NULL);
865 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
866 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
870 sigaction(SIGILL, &oldsa, NULL);
876 /* CMOV supported? */
877 if (capamd & (1<<30))
878 return 7; /* 3DNOWEXT supported */
885 /* should only be called for model 6 CPU's */
886 static int is_athlon(void)
888 unsigned int eax, ebx, ecx, edx;
892 cpuid (0, &eax, &ebx, &ecx, &edx);
894 /* If you care about space, you can just check ebx, ecx and edx directly
895 instead of forming a string first and then doing a strcmp */
896 memset(vendor, 0, sizeof(vendor));
899 vendor[i] = (unsigned char) (ebx >>(8*i));
901 vendor[4+i] = (unsigned char) (edx >>(8*i));
903 vendor[8+i] = (unsigned char) (ecx >>(8*i));
905 if (strncmp(vendor, "AuthenticAMD", 12) != 0)
911 static int is_pentium3()
913 unsigned int eax, ebx, ecx, edx, family, model;
915 cpuid(0, &eax, &ebx, &ecx, &edx);
916 memset(vendor, 0, sizeof(vendor));
917 *((unsigned int *)&vendor[0]) = ebx;
918 *((unsigned int *)&vendor[4]) = edx;
919 *((unsigned int *)&vendor[8]) = ecx;
920 if (strncmp(vendor, "GenuineIntel", 12) != 0)
922 cpuid(1, &eax, &ebx, &ecx, &edx);
923 family = (eax >> 8) & 0x0f;
924 model = (eax >> 4) & 0x0f;
928 case 7: // Pentium III, Pentium III Xeon (model 7)
929 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
932 Intel recently announced its new technology for mobile platforms,
933 named Centrino, and presents it as a big advance in mobile PCs.
934 One of the main part of Centrino consists in a brand new CPU,
935 the Pentium M, codenamed Banias, that we'll study in this review.
936 A particularity of this CPU is that it was designed for mobile platform
937 exclusively, unlike previous mobile CPU (Pentium III-M, Pentium 4-M)
938 that share the same micro-architecture as their desktop counterparts.
939 The Pentium M introduces a new micro-architecture, adapted for mobility
940 constraints, and that is halfway between the Pentium III and the Pentium 4.
941 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
943 case 10: // Pentium III Xeon (model A)
944 case 11: // Pentium III (model B)
950 static int is_pentium4()
952 unsigned int eax, ebx, ecx, edx, family, model;
954 cpuid(0, &eax, &ebx, &ecx, &edx);
955 memset(vendor, 0, sizeof(vendor));
956 *((unsigned int *)&vendor[0]) = ebx;
957 *((unsigned int *)&vendor[4]) = edx;
958 *((unsigned int *)&vendor[8]) = ecx;
959 if (strncmp(vendor, "GenuineIntel", 12) != 0)
961 cpuid(1, &eax, &ebx, &ecx, &edx);
962 family = (eax >> 8) & 0x0f;
963 model = (eax >> 4) & 0x0f;
967 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
968 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
969 case 2: // Pentium 4, Mobile Pentium 4-M,
970 // Pentium 4 Xeon, Pentium 4 Xeon MP,
971 // Celeron, Mobile Celron (0.13um)
972 case 3: // Pentium 4, Celeron (0.09um)
978 static int is_geode()
980 unsigned int eax, ebx, ecx, edx, family, model;
982 /* If you care about space, you can just check ebx, ecx and edx directly
983 instead of forming a string first and then doing a strcmp */
984 memset(vendor, 0, sizeof(vendor));
986 cpuid(0, &eax, &ebx, &ecx, &edx);
987 memset(vendor, 0, sizeof(vendor));
988 *((unsigned int *)&vendor[0]) = ebx;
989 *((unsigned int *)&vendor[4]) = edx;
990 *((unsigned int *)&vendor[8]) = ecx;
991 if (strncmp(vendor, "AuthenticAMD", 12) != 0)
993 cpuid(1, &eax, &ebx, &ecx, &edx);
994 family = (eax >> 8) & 0x0f;
995 model = (eax >> 4) & 0x0f;
1006 #if defined(__linux__) && defined(__powerpc__)
1007 static jmp_buf mfspr_jmpbuf;
1009 static void mfspr_ill(int notused)
1011 longjmp(mfspr_jmpbuf, -1);
1017 static void defaultMachine(const char ** arch,
1020 static struct utsname un;
1021 static int gotDefaults = 0;
1026 while (!gotDefaults) {
1027 if (!rpmPlatform(platform)) {
1029 s = rpmExpand("%{_host_cpu}", NULL);
1031 strncpy(un.machine, s, sizeof(un.machine));
1032 un.machine[sizeof(un.machine)-1] = '\0';
1035 s = rpmExpand("%{_host_os}", NULL);
1037 strncpy(un.sysname, s, sizeof(un.sysname));
1038 un.sysname[sizeof(un.sysname)-1] = '\0';
1047 #if !defined(__linux__)
1049 /* USUALLY un.sysname on sinix does start with the word "SINIX"
1050 * let's be absolutely sure
1052 strncpy(un.sysname, "SINIX", sizeof(un.sysname));
1054 if (!strcmp(un.sysname, "AIX")) {
1055 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
1056 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
1058 else if(!strcmp(un.sysname, "Darwin")) {
1060 strcpy(un.machine, "ppc");
1061 #else ifdef __i386__
1062 strcpy(un.machine, "i386");
1065 else if (!strcmp(un.sysname, "SunOS")) {
1066 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
1069 (un.release[fd] != 0 && (fd < sizeof(un.release)));
1071 if (!xisdigit(un.release[fd]) && (un.release[fd] != '.')) {
1076 sprintf(un.sysname,"sunos%s",un.release);
1079 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
1080 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1081 un.release+1+(atoi(un.release)/10));
1083 /* Solaris on Intel hardware reports i86pc instead of i386
1084 * (at least on 2.6 and 2.8)
1086 if (!strcmp(un.machine, "i86pc"))
1087 sprintf(un.machine, "i386");
1089 else if (!strcmp(un.sysname, "HP-UX"))
1090 /*make un.sysname look like hpux9.05 for example*/
1091 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1092 else if (!strcmp(un.sysname, "OSF1"))
1093 /*make un.sysname look like osf3.2 for example*/
1094 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1095 else if (!strncmp(un.sysname, "IP", 2))
1096 un.sysname[2] = '\0';
1097 else if (!strncmp(un.sysname, "SINIX", 5)) {
1098 sprintf(un.sysname, "sinix%s",un.release);
1099 if (!strncmp(un.machine, "RM", 2))
1100 sprintf(un.machine, "mips");
1102 else if ((!strncmp(un.machine, "34", 2) ||
1103 !strncmp(un.machine, "33", 2)) && \
1104 !strncmp(un.release, "4.0", 3))
1106 /* we are on ncr-sysv4 */
1107 char * prelid = NULL;
1108 FD_t fd = Fopen("/etc/.relid", "r.fdio");
1110 if (fd != NULL && !Ferror(fd)) {
1111 chptr = xcalloc(1, 256);
1112 { int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
1114 /* example: "112393 RELEASE 020200 Version 01 OS" */
1116 if ((prelid = strstr(chptr, "RELEASE "))){
1117 prelid += strlen("RELEASE ")+1;
1118 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
1123 chptr = _free (chptr);
1125 if (!gotit) /* parsing /etc/.relid file failed? */
1126 strcpy(un.sysname,"ncr-sysv4");
1127 /* wrong, just for now, find out how to look for i586 later*/
1128 strcpy(un.machine,"i486");
1130 #endif /* __linux__ */
1132 /* get rid of the hyphens in the sysname */
1133 for (chptr = un.machine; *chptr != '\0'; chptr++)
1134 if (*chptr == '/') *chptr = '-';
1136 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1138 strcpy(un.machine, "mipsel");
1139 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1141 strcpy(un.machine, "mips");
1144 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1146 # if !defined(CPU_PA_RISC1_2)
1147 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1149 # if !defined(CPU_PA_RISC2_0)
1150 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1152 int cpu_version = sysconf(_SC_CPU_VERSION);
1154 # if defined(CPU_HP_MC68020)
1155 if (cpu_version == CPU_HP_MC68020)
1156 strcpy(un.machine, "m68k");
1158 # if defined(CPU_HP_MC68030)
1159 if (cpu_version == CPU_HP_MC68030)
1160 strcpy(un.machine, "m68k");
1162 # if defined(CPU_HP_MC68040)
1163 if (cpu_version == CPU_HP_MC68040)
1164 strcpy(un.machine, "m68k");
1167 # if defined(CPU_PA_RISC1_0)
1168 if (cpu_version == CPU_PA_RISC1_0)
1169 strcpy(un.machine, "hppa1.0");
1171 # if defined(CPU_PA_RISC1_1)
1172 if (cpu_version == CPU_PA_RISC1_1)
1173 strcpy(un.machine, "hppa1.1");
1175 # if defined(CPU_PA_RISC1_2)
1176 if (cpu_version == CPU_PA_RISC1_2)
1177 strcpy(un.machine, "hppa1.2");
1179 # if defined(CPU_PA_RISC2_0)
1180 if (cpu_version == CPU_PA_RISC2_0)
1181 strcpy(un.machine, "hppa2.0");
1186 # if defined(__linux__) && defined(__sparc__)
1187 if (!strcmp(un.machine, "sparc")) {
1188 #define PERS_LINUX 0x00000000
1189 #define PERS_LINUX_32BIT 0x00800000
1190 #define PERS_LINUX32 0x00000008
1192 extern int personality(unsigned long);
1195 oldpers = personality(PERS_LINUX_32BIT);
1196 if (oldpers != -1) {
1197 if (personality(PERS_LINUX) != -1) {
1199 if (! strcmp(un.machine, "sparc64")) {
1200 strcpy(un.machine, "sparcv9");
1201 oldpers = PERS_LINUX32;
1204 personality(oldpers);
1207 # endif /* sparc*-linux */
1209 # if defined(__GNUC__) && defined(__alpha__)
1211 unsigned long amask, implver;
1212 register long v0 __asm__("$0") = -1;
1213 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1215 __asm__ (".long 0x47e03d80" : "=r"(v0));
1220 case 0: strcpy(un.machine, "alphaev5"); break;
1221 case 1: strcpy(un.machine, "alphaev56"); break;
1222 case 0x101: strcpy(un.machine, "alphapca56"); break;
1227 case 0x303: strcpy(un.machine, "alphaev6"); break;
1228 case 0x307: strcpy(un.machine, "alphaev67"); break;
1235 # if defined(__linux__) && defined(__i386__)
1237 char class = (char) (RPMClass() | '0');
1239 if ((class == '6' && is_athlon()) || class == '7')
1240 strcpy(un.machine, "athlon");
1241 else if (is_pentium4())
1242 strcpy(un.machine, "pentium4");
1243 else if (is_pentium3())
1244 strcpy(un.machine, "pentium3");
1245 else if (is_geode())
1246 strcpy(un.machine, "geode");
1247 else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
1248 un.machine[1] = class;
1252 /* the uname() result goes through the arch_canon table */
1253 canon = lookupInCanonTable(un.machine,
1254 tables[RPM_MACHTABLE_INSTARCH].canons,
1255 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1257 strcpy(un.machine, canon->short_name);
1259 canon = lookupInCanonTable(un.sysname,
1260 tables[RPM_MACHTABLE_INSTOS].canons,
1261 tables[RPM_MACHTABLE_INSTOS].canonsLength);
1263 strcpy(un.sysname, canon->short_name);
1268 if (arch) *arch = un.machine;
1269 if (os) *os = un.sysname;
1273 const char * rpmGetVarArch(int var, const char * arch)
1275 const struct rpmvarValue * next;
1277 if (arch == NULL) arch = current[ARCH];
1280 next = &values[var];
1282 if (next->arch && !strcmp(next->arch, arch)) return next->value;
1287 next = values + var;
1288 while (next && next->arch) next = next->next;
1290 return next ? next->value : NULL;
1293 static const char *rpmGetVar(int var)
1295 return rpmGetVarArch(var, NULL);
1298 static void rpmSetVarArch(int var, const char * val, const char * arch)
1300 struct rpmvarValue * next = values + var;
1304 while (next->next) {
1305 if (next->arch && !strcmp(next->arch, arch)) break;
1309 while (next->next) {
1310 if (!next->arch) break;
1315 if (next->arch && arch && !strcmp(next->arch, arch)) {
1316 next->value = _free(next->value);
1317 next->arch = _free(next->arch);
1318 } else if (next->arch || arch) {
1319 next->next = xmalloc(sizeof(*next->next));
1327 next->value = _free(next->value);
1328 next->value = xstrdup(val);
1329 next->arch = (arch ? xstrdup(arch) : NULL);
1332 void rpmSetTables(int archTable, int osTable)
1334 const char * arch, * os;
1336 defaultMachine(&arch, &os);
1338 if (currTables[ARCH] != archTable) {
1339 currTables[ARCH] = archTable;
1340 rebuildCompatTables(ARCH, arch);
1343 if (currTables[OS] != osTable) {
1344 currTables[OS] = osTable;
1345 rebuildCompatTables(OS, os);
1349 int rpmMachineScore(int type, const char * name)
1351 machEquivInfo info = machEquivSearch(&tables[type].equiv, name);
1352 return (info != NULL ? info->score : 0);
1356 * Set current arch/os names.
1357 * NULL as argument is set to the default value (munged uname())
1358 * pushed through a translation table (if appropriate).
1359 * @deprecated Use addMacro to set _target_* macros.
1362 * @param arch arch name (or NULL)
1363 * @param os os name (or NULL)
1366 static void rpmSetMachine(const char * arch, const char * os)
1368 const char * host_cpu, * host_os;
1370 defaultMachine(&host_cpu, &host_os);
1374 if (tables[currTables[ARCH]].hasTranslate)
1375 arch = lookupInDefaultTable(arch,
1376 tables[currTables[ARCH]].defaults,
1377 tables[currTables[ARCH]].defaultsLength);
1379 if (arch == NULL) return; /* XXX can't happen */
1383 if (tables[currTables[OS]].hasTranslate)
1384 os = lookupInDefaultTable(os,
1385 tables[currTables[OS]].defaults,
1386 tables[currTables[OS]].defaultsLength);
1388 if (os == NULL) return; /* XXX can't happen */
1390 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1391 current[ARCH] = _free(current[ARCH]);
1392 current[ARCH] = xstrdup(arch);
1393 rebuildCompatTables(ARCH, host_cpu);
1396 if (!current[OS] || strcmp(os, current[OS])) {
1397 char * t = xstrdup(os);
1398 current[OS] = _free(current[OS]);
1400 * XXX Capitalizing the 'L' is needed to insure that old
1401 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1402 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1403 * XXX A copy of this string is embedded in headers and is
1404 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1405 * XXX to verify correct arch/os from headers.
1407 if (!strcmp(t, "linux"))
1411 rebuildCompatTables(OS, host_os);
1415 static void rebuildCompatTables(int type, const char * name)
1417 machFindEquivs(&tables[currTables[type]].cache,
1418 &tables[currTables[type]].equiv,
1422 static void getMachineInfo(int type, const char ** name,
1426 int which = currTables[type];
1428 /* use the normal canon tables, even if we're looking up build stuff */
1429 if (which >= 2) which -= 2;
1431 canon = lookupInCanonTable(current[type],
1432 tables[which].canons,
1433 tables[which].canonsLength);
1436 if (num) *num = canon->num;
1437 if (name) *name = canon->short_name;
1439 if (num) *num = 255;
1440 if (name) *name = current[type];
1442 if (tables[currTables[type]].hasCanon) {
1443 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n"), current[type]);
1444 rpmlog(RPMLOG_WARNING, _("Please contact %s\n"), PACKAGE_BUGREPORT);
1449 void rpmGetArchInfo(const char ** name, int * num)
1451 getMachineInfo(ARCH, name, num);
1454 void rpmGetOsInfo(const char ** name, int * num)
1456 getMachineInfo(OS, name, num);
1459 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
1462 char *ca = NULL, *co = NULL, *ct = NULL;
1465 /* Rebuild the compat table to recalculate the current target arch. */
1467 rpmSetMachine(NULL, NULL);
1468 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1469 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1471 if (target && *target) {
1473 /* Set arch and os from specified build target */
1474 ca = xstrdup(*target);
1475 if ((c = strchr(ca, '-')) != NULL) {
1478 if ((co = strrchr(c, '-')) == NULL) {
1481 if (!xstrcasecmp(co, "-gnu"))
1483 if ((co = strrchr(c, '-')) == NULL)
1488 if (co != NULL) co = xstrdup(co);
1491 const char *a = NULL;
1492 const char *o = NULL;
1493 /* Set build target from rpm arch and os */
1494 rpmGetArchInfo(&a, NULL);
1495 ca = (a) ? xstrdup(a) : NULL;
1496 rpmGetOsInfo(&o, NULL);
1497 co = (o) ? xstrdup(o) : NULL;
1500 /* If still not set, Set target arch/os from default uname(2) values */
1502 const char *a = NULL;
1503 defaultMachine(&a, NULL);
1504 ca = (a) ? xstrdup(a) : NULL;
1506 for (x = 0; ca[x] != '\0'; x++)
1507 ca[x] = xtolower(ca[x]);
1510 const char *o = NULL;
1511 defaultMachine(NULL, &o);
1512 co = (o) ? xstrdup(o) : NULL;
1514 for (x = 0; co[x] != '\0'; x++)
1515 co[x] = xtolower(co[x]);
1517 /* XXX For now, set canonical target to arch-os */
1519 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
1520 sprintf(ct, "%s-%s", ca, co);
1524 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1525 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1527 delMacro(NULL, "_target");
1528 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1529 delMacro(NULL, "_target_cpu");
1530 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1531 delMacro(NULL, "_target_os");
1532 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1534 * XXX Make sure that per-arch optflags is initialized correctly.
1536 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1537 if (optflags != NULL) {
1538 delMacro(NULL, "optflags");
1539 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1551 void rpmFreeRpmrc(void)
1556 for (i = 0; i < nplatpat; i++)
1557 platpat[i] = _free(platpat[i]);
1558 platpat = _free(platpat);
1561 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1564 if (t->equiv.list) {
1565 for (j = 0; j < t->equiv.count; j++)
1566 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1567 t->equiv.list = _free(t->equiv.list);
1570 if (t->cache.cache) {
1571 for (j = 0; j < t->cache.size; j++) {
1573 e = t->cache.cache + j;
1576 e->name = _free(e->name);
1578 for (k = 0; k < e->count; k++)
1579 e->equivs[k] = _free(e->equivs[k]);
1580 e->equivs = _free(e->equivs);
1583 t->cache.cache = _free(t->cache.cache);
1587 for (j = 0; j < t->defaultsLength; j++) {
1588 t->defaults[j].name = _free(t->defaults[j].name);
1589 t->defaults[j].defName = _free(t->defaults[j].defName);
1591 t->defaults = _free(t->defaults);
1592 t->defaultsLength = 0;
1595 for (j = 0; j < t->canonsLength; j++) {
1596 t->canons[j].name = _free(t->canons[j].name);
1597 t->canons[j].short_name = _free(t->canons[j].short_name);
1599 t->canons = _free(t->canons);
1600 t->canonsLength = 0;
1604 for (i = 0; i < RPMVAR_NUM; i++) {
1605 struct rpmvarValue * vp;
1606 while ((vp = values[i].next) != NULL) {
1607 values[i].next = vp->next;
1608 vp->value = _free(vp->value);
1609 vp->arch = _free(vp->arch);
1612 values[i].value = _free(values[i].value);
1613 values[i].arch = _free(values[i].arch);
1615 current[OS] = _free(current[OS]);
1616 current[ARCH] = _free(current[ARCH]);
1617 defaultsInitialized = 0;
1618 /* FIX: platpat/current may be NULL */
1620 /* XXX doesn't really belong here but... */
1627 * Read rpmrc (and macro) configuration file(s).
1628 * @param rcfiles colon separated files to read (NULL uses default)
1629 * @return RPMRC_OK on success
1631 static rpmRC rpmReadRC(const char * rcfiles)
1633 char *myrcfiles, *r, *re;
1636 if (!defaultsInitialized) {
1638 defaultsInitialized = 1;
1641 if (rcfiles == NULL)
1642 rcfiles = defrcfiles;
1644 /* Read each file in rcfiles. */
1646 for (r = myrcfiles = xstrdup(rcfiles); r && *r != '\0'; r = re) {
1650 /* Get pointer to rest of files */
1651 for (re = r; (re = strchr(re, ':')) != NULL; re++) {
1652 if (!(re[1] == '/' && re[2] == '/'))
1655 if (re && *re == ':')
1660 /* Expand ~/ to $HOME/ */
1662 if (r[0] == '~' && r[1] == '/') {
1663 const char * home = getenv("HOME");
1665 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1666 if (rcfiles == defrcfiles && myrcfiles != r)
1668 rpmlog(RPMLOG_ERR, _("Cannot expand %s\n"), r);
1672 if (strlen(home) > (sizeof(fn) - strlen(r))) {
1673 rpmlog(RPMLOG_ERR, _("Cannot read %s, HOME is too large.\n"),
1681 strncat(fn, r, sizeof(fn) - (strlen(fn) + 1));
1682 fn[sizeof(fn)-1] = '\0';
1684 /* Read another rcfile */
1685 fd = Fopen(fn, "r.fpio");
1686 if (fd == NULL || Ferror(fd)) {
1687 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1688 if (rcfiles == defrcfiles && myrcfiles != r)
1690 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %s.\n"),
1695 rc = doReadRC(fd, fn);
1699 myrcfiles = _free(myrcfiles);
1703 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1708 int rpmReadConfigFiles(const char * file, const char * target)
1711 /* Reset umask to its default umask(2) value. */
1714 /* Initialize crypto engine as early as possible */
1715 if (rpmInitCrypto() < 0) {
1719 /* Preset target macros */
1720 /* FIX: target can be NULL */
1721 rpmRebuildTargetVars(&target, NULL);
1723 /* Read the files */
1724 if (rpmReadRC(file)) return -1;
1726 if (macrofiles != NULL) {
1727 char *mf = rpmGetPath(macrofiles, NULL);
1728 rpmInitMacros(NULL, mf);
1732 /* Reset target macros */
1733 rpmRebuildTargetVars(&target, NULL);
1735 /* Finally set target platform */
1736 { char *cpu = rpmExpand("%{_target_cpu}", NULL);
1737 char *os = rpmExpand("%{_target_os}", NULL);
1738 rpmSetMachine(cpu, os);
1743 /* Force Lua state initialization */
1745 (void)rpmluaGetPrintBuffer(NULL);
1751 int rpmShowRC(FILE * fp)
1753 struct rpmOption *opt;
1755 machEquivTable equivTable;
1757 /* the caller may set the build arch which should be printed here */
1758 fprintf(fp, "ARCHITECTURE AND OS:\n");
1759 fprintf(fp, "build arch : %s\n", current[ARCH]);
1761 fprintf(fp, "compatible build archs:");
1762 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1763 for (i = 0; i < equivTable->count; i++)
1764 fprintf(fp," %s", equivTable->list[i].name);
1767 fprintf(fp, "build os : %s\n", current[OS]);
1769 fprintf(fp, "compatible build os's :");
1770 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1771 for (i = 0; i < equivTable->count; i++)
1772 fprintf(fp," %s", equivTable->list[i].name);
1775 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1776 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1778 fprintf(fp, "install arch : %s\n", current[ARCH]);
1779 fprintf(fp, "install os : %s\n", current[OS]);
1781 fprintf(fp, "compatible archs :");
1782 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1783 for (i = 0; i < equivTable->count; i++)
1784 fprintf(fp," %s", equivTable->list[i].name);
1787 fprintf(fp, "compatible os's :");
1788 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1789 for (i = 0; i < equivTable->count; i++)
1790 fprintf(fp," %s", equivTable->list[i].name);
1793 fprintf(fp, "\nRPMRC VALUES:\n");
1794 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1795 const char *s = rpmGetVar(opt->var);
1796 if (s != NULL || rpmIsVerbose())
1797 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1801 fprintf(fp, "Features supported by rpmlib:\n");
1802 rpmShowRpmlibProvides(fp);
1805 rpmDumpMacroTable(NULL, fp);