X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Futil%2Fxmlconfig.c;h=4ddad79e8bdebf983d175f1056c028191ee02777;hb=772b15ad3227e08bb4e18932ac9ecf4c29271160;hp=5d218eeb927fc19f14f906e0abf3a8a0634b61da;hpb=91cc6fcbb050423823ff4262cf860a34d20f504e;p=mesa.git diff --git a/src/util/xmlconfig.c b/src/util/xmlconfig.c index 5d218eeb927..4ddad79e8bd 100644 --- a/src/util/xmlconfig.c +++ b/src/util/xmlconfig.c @@ -29,7 +29,10 @@ #include #include +#include +#include #include +#include #include #include #include @@ -39,14 +42,27 @@ #include #include #include +#include +#include "strndup.h" #include "xmlconfig.h" #include "u_process.h" +#include "os_file.h" /* For systems like Hurd */ #ifndef PATH_MAX #define PATH_MAX 4096 #endif +static bool +be_verbose(void) +{ + const char *s = getenv("MESA_DEBUG"); + if (!s) + return true; + + return strstr(s, "silent") == NULL; +} + /** \brief Find an option in an option cache with the name as key */ static uint32_t findOption(const driOptionCache *cache, const char *name) @@ -543,9 +559,11 @@ parseOptInfoAttr(struct OptInfoData *data, const XML_Char **attr) defaultVal = getenv (cache->info[opt].name); if (defaultVal != NULL) { /* don't use XML_WARNING, we want the user to see this! */ - fprintf (stderr, - "ATTENTION: default value of option %s overridden by environment.\n", - cache->info[opt].name); + if (be_verbose()) { + fprintf(stderr, + "ATTENTION: default value of option %s overridden by environment.\n", + cache->info[opt].name); + } } else defaultVal = attrVal[OA_DEFAULT]; if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal)) @@ -696,6 +714,8 @@ struct OptConfData { int screenNum; const char *driverName, *execName; const char *kernelDriverName; + const char *engineName; + uint32_t engineVersion; uint32_t ignoringDevice; uint32_t ignoringApp; uint32_t inDriConf; @@ -706,12 +726,13 @@ struct OptConfData { /** \brief Elements in configuration files. */ enum OptConfElem { - OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT + OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_ENGINE, OC_OPTION, OC_COUNT }; static const XML_Char *OptConfElems[] = { [OC_APPLICATION] = "application", [OC_DEVICE] = "device", [OC_DRICONF] = "driconf", + [OC_ENGINE] = "engine", [OC_OPTION] = "option", }; @@ -740,19 +761,94 @@ parseDeviceAttr(struct OptConfData *data, const XML_Char **attr) } } +static bool +valueInRanges(const driOptionInfo *info, uint32_t value) +{ + uint32_t i; + + for (i = 0; i < info->nRanges; i++) { + if (info->ranges[i].start._int <= value && + info->ranges[i].end._int >= value) + return true; + } + + return false; +} + /** \brief Parse attributes of an application element. */ static void parseAppAttr(struct OptConfData *data, const XML_Char **attr) { uint32_t i; const XML_Char *exec = NULL; + const XML_Char *sha1 = NULL; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "name")) /* not needed here */; else if (!strcmp (attr[i], "executable")) exec = attr[i+1]; + else if (!strcmp (attr[i], "sha1")) sha1 = attr[i+1]; else XML_WARNING("unknown application attribute: %s.", attr[i]); } - if (exec && strcmp (exec, data->execName)) + if (exec && strcmp (exec, data->execName)) { data->ignoringApp = data->inApp; + } else if (sha1) { + /* SHA1_DIGEST_STRING_LENGTH includes terminating null byte */ + if (strlen(sha1) != (SHA1_DIGEST_STRING_LENGTH - 1)) { + XML_WARNING("Incorrect sha1 application attribute"); + data->ignoringApp = data->inApp; + } else { + size_t len; + char* content; + char path[PATH_MAX]; + if (util_get_process_exec_path(path, ARRAY_SIZE(path)) > 0 && + (content = os_read_file(path, &len))) { + uint8_t sha1x[SHA1_DIGEST_LENGTH]; + char sha1s[SHA1_DIGEST_STRING_LENGTH]; + _mesa_sha1_compute(content, len, sha1x); + _mesa_sha1_format((char*) sha1s, sha1x); + free(content); + + if (strcmp(sha1, sha1s)) { + data->ignoringApp = data->inApp; + } + } else { + data->ignoringApp = data->inApp; + } + } + } +} + +/** \brief Parse attributes of an application element. */ +static void +parseEngineAttr(struct OptConfData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *engine_name_match = NULL, *engine_versions = NULL; + driOptionInfo version_ranges = { + .type = DRI_INT, + }; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "name")) /* not needed here */; + else if (!strcmp (attr[i], "engine_name_match")) engine_name_match = attr[i+1]; + else if (!strcmp (attr[i], "engine_versions")) engine_versions = attr[i+1]; + else XML_WARNING("unknown application attribute: %s.", attr[i]); + } + if (engine_name_match) { + regex_t re; + + if (regcomp (&re, engine_name_match, REG_EXTENDED|REG_NOSUB) == 0) { + if (regexec (&re, data->engineName, 0, NULL, 0) == REG_NOMATCH) + data->ignoringApp = data->inApp; + regfree (&re); + } else + XML_WARNING ("Invalid engine_name_match=\"%s\".", engine_name_match); + } + if (engine_versions) { + if (parseRanges (&version_ranges, engine_versions) && + !valueInRanges (&version_ranges, data->engineVersion)) + data->ignoringApp = data->inApp; + } + + free(version_ranges.ranges); } /** \brief Parse attributes of an option element. */ @@ -775,11 +871,14 @@ parseOptConfAttr(struct OptConfData *data, const XML_Char **attr) /* don't use XML_WARNING, drirc defines options for all drivers, * but not all drivers support them */ return; - else if (getenv (cache->info[opt].name)) + else if (getenv (cache->info[opt].name)) { /* don't use XML_WARNING, we want the user to see this! */ - fprintf (stderr, "ATTENTION: option value of option %s ignored.\n", - cache->info[opt].name); - else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) + if (be_verbose()) { + fprintf(stderr, + "ATTENTION: option value of option %s ignored.\n", + cache->info[opt].name); + } + } else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) XML_WARNING ("illegal option value: %s.", value); } } @@ -812,11 +911,20 @@ optConfStartElem(void *userData, const XML_Char *name, if (!data->inDevice) XML_WARNING1 (" should be inside ."); if (data->inApp) - XML_WARNING1 ("nested elements."); + XML_WARNING1 ("nested or elements."); data->inApp++; if (!data->ignoringDevice && !data->ignoringApp) parseAppAttr (data, attr); break; + case OC_ENGINE: + if (!data->inDevice) + XML_WARNING1 (" should be inside ."); + if (data->inApp) + XML_WARNING1 ("nested or elements."); + data->inApp++; + if (!data->ignoringDevice && !data->ignoringApp) + parseEngineAttr (data, attr); + break; case OC_OPTION: if (!data->inApp) XML_WARNING1 ("