X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Futil%2Fxmlconfig.c;h=4ddad79e8bdebf983d175f1056c028191ee02777;hb=ae7759eb210dfaa111c36845283ba113d9c09966;hp=ba657294c1c4812b45916d0bd3cc83064f8ea1ba;hpb=17f49950da91137366910183f616d15b8bbf580c;p=mesa.git diff --git a/src/util/xmlconfig.c b/src/util/xmlconfig.c index ba657294c1c..4ddad79e8bd 100644 --- a/src/util/xmlconfig.c +++ b/src/util/xmlconfig.c @@ -27,8 +27,12 @@ * \author Felix Kuehling */ +#include #include +#include +#include #include +#include #include #include #include @@ -36,9 +40,28 @@ #include #include #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 @@ -536,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)) @@ -688,6 +713,9 @@ struct OptConfData { driOptionCache *cache; int screenNum; const char *driverName, *execName; + const char *kernelDriverName; + const char *engineName; + uint32_t engineVersion; uint32_t ignoringDevice; uint32_t ignoringApp; uint32_t inDriConf; @@ -698,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", }; @@ -712,14 +741,17 @@ static void parseDeviceAttr(struct OptConfData *data, const XML_Char **attr) { uint32_t i; - const XML_Char *driver = NULL, *screen = NULL; + const XML_Char *driver = NULL, *screen = NULL, *kernel = NULL; for (i = 0; attr[i]; i += 2) { if (!strcmp (attr[i], "driver")) driver = attr[i+1]; else if (!strcmp (attr[i], "screen")) screen = attr[i+1]; + else if (!strcmp (attr[i], "kernel_driver")) kernel = attr[i+1]; else XML_WARNING("unknown device attribute: %s.", attr[i]); } if (driver && strcmp (driver, data->driverName)) data->ignoringDevice = data->inDevice; + else if (kernel && (!data->kernelDriverName || strcmp (kernel, data->kernelDriverName))) + data->ignoringDevice = data->inDevice; else if (screen) { driOptionValue screenNum; if (!parseValue (&screenNum, DRI_INT, screen)) @@ -729,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. */ @@ -764,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); } } @@ -801,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 ("