X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Futil%2Fxmlconfig.c;h=4ddad79e8bdebf983d175f1056c028191ee02777;hb=d76abe98cf15226f25d93e76e383715061ada6f4;hp=d3f47ecda0c1738d9d050d9bae1d27df349df82d;hpb=601093f95ddf6b49a79baa91dc51d4f163dfc8de;p=mesa.git diff --git a/src/util/xmlconfig.c b/src/util/xmlconfig.c index d3f47ecda0c..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,82 +40,28 @@ #include #include #include +#include +#include +#include +#include "strndup.h" #include "xmlconfig.h" +#include "u_process.h" +#include "os_file.h" -#undef GET_PROGRAM_NAME - -#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__) -# if !defined(__GLIBC__) || (__GLIBC__ < 2) -/* These aren't declared in any libc5 header */ -extern char *program_invocation_name, *program_invocation_short_name; -# endif -# define GET_PROGRAM_NAME() program_invocation_short_name -#elif defined(__CYGWIN__) -# define GET_PROGRAM_NAME() program_invocation_short_name -#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) -# include -# if (__FreeBSD_version >= 440000) -# include -# define GET_PROGRAM_NAME() getprogname() -# endif -#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) -# include -# define GET_PROGRAM_NAME() getprogname() -#elif defined(__DragonFly__) -# include -# define GET_PROGRAM_NAME() getprogname() -#elif defined(__APPLE__) -# include -# define GET_PROGRAM_NAME() getprogname() -#elif defined(__sun) -/* Solaris has getexecname() which returns the full path - return just - the basename to match BSD getprogname() */ -# include -# include - -static const char * -__getProgramName() -{ - static const char *progname; - - if (progname == NULL) { - const char *e = getexecname(); - if (e != NULL) { - /* Have to make a copy since getexecname can return a readonly - string, but basename expects to be able to modify its arg. */ - char *n = strdup(e); - if (n != NULL) { - progname = basename(n); - } - } - } - return progname; -} - -# define GET_PROGRAM_NAME() __getProgramName() +/* For systems like Hurd */ +#ifndef PATH_MAX +#define PATH_MAX 4096 #endif -#if !defined(GET_PROGRAM_NAME) -# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID) -/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. - * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's - * used as a last resort, if there is no documented facility available. */ -static const char * -__getProgramName() +static bool +be_verbose(void) { - extern const char *__progname; - char * arg = strrchr(__progname, '/'); - if (arg) - return arg+1; - else - return __progname; + const char *s = getenv("MESA_DEBUG"); + if (!s) + return true; + + return strstr(s, "silent") == NULL; } -# define GET_PROGRAM_NAME() __getProgramName() -# else -# define GET_PROGRAM_NAME() "" -# warning "Per application configuration won't work with your OS version." -# endif -#endif /** \brief Find an option in an option cache with the name as key */ static uint32_t @@ -466,11 +416,11 @@ __driUtilMessage(const char *f, ...) (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser)); \ } while (0) -#define XML_WARNING(msg,args...) do { \ +#define XML_WARNING(msg, ...) do { \ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ - args); \ + ##__VA_ARGS__); \ } while (0) /** \brief Output an error message. */ #define XML_ERROR1(msg) do { \ @@ -478,11 +428,11 @@ __driUtilMessage(const char *f, ...) (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser)); \ } while (0) -#define XML_ERROR(msg,args...) do { \ +#define XML_ERROR(msg, ...) do { \ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ - args); \ + ##__VA_ARGS__); \ } while (0) /** \brief Output a fatal error message and abort. */ #define XML_FATAL1(msg) do { \ @@ -492,12 +442,12 @@ __driUtilMessage(const char *f, ...) (int) XML_GetCurrentColumnNumber(data->parser)); \ abort();\ } while (0) -#define XML_FATAL(msg,args...) do { \ +#define XML_FATAL(msg, ...) do { \ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ data->name, \ (int) XML_GetCurrentLineNumber(data->parser), \ (int) XML_GetCurrentColumnNumber(data->parser), \ - args); \ + ##__VA_ARGS__); \ abort();\ } while (0) @@ -609,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)) @@ -761,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; @@ -771,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", }; @@ -785,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)) @@ -802,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. */ @@ -837,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); } } @@ -874,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 ("