diff options
Diffstat (limited to 'src/util/xmlconfig.c')
-rw-r--r-- | src/util/xmlconfig.c | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/src/util/xmlconfig.c b/src/util/xmlconfig.c index 8766bb01f0a..8269f022940 100644 --- a/src/util/xmlconfig.c +++ b/src/util/xmlconfig.c @@ -15,11 +15,11 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * */ /** * \file xmlconfig.c @@ -59,6 +59,7 @@ static inline void regfree(regex_t* r) {} #include "strndup.h" #include "u_process.h" #include "os_file.h" +#include "os_misc.h" /* For systems like Hurd */ #ifndef PATH_MAX @@ -272,7 +273,7 @@ findOption(const driOptionCache *cache, const char *name) /* this is just the starting point of the linear search for the option */ for (i = 0; i < size; ++i, hash = (hash+1) & mask) { /* if we hit an empty entry then the option is not defined (yet) */ - if (cache->info[hash].name == 0) + if (cache->info[hash].name == NULL) break; else if (!strcmp(name, cache->info[hash].name)) break; @@ -320,7 +321,7 @@ driParseOptionInfo(driOptionCache *info, /* Make the hash table big enough to fit more than the maximum number of * config options we've ever seen in a driver. */ - info->tableSize = 6; + info->tableSize = 7; info->info = calloc((size_t)1 << info->tableSize, sizeof(driOptionInfo)); info->values = calloc((size_t)1 << info->tableSize, sizeof(driOptionValue)); if (info->info == NULL || info->values == NULL) { @@ -347,11 +348,15 @@ driParseOptionInfo(driOptionCache *info, driOptionInfo *optinfo = &info->info[i]; driOptionValue *optval = &info->values[i]; - assert(!optinfo->name); /* No duplicate options in your list. */ + if (optinfo->name) { + /* Duplicate options override the value, but the type must match. */ + assert(optinfo->type == opt->info.type); + } else { + XSTRDUP(optinfo->name, name); + } optinfo->type = opt->info.type; optinfo->range = opt->info.range; - XSTRDUP(optinfo->name, name); switch (opt->info.type) { case DRI_BOOL: @@ -378,7 +383,7 @@ driParseOptionInfo(driOptionCache *info, /* Built-in default values should always be valid. */ assert(checkValue(optval, optinfo)); - char *envVal = getenv(name); + const char *envVal = os_get_option(name); if (envVal != NULL) { driOptionValue v; @@ -681,6 +686,7 @@ parseAppAttr(struct OptConfData *data, const char **attr) uint32_t i; const char *exec = NULL; const char *sha1 = NULL; + const char *exec_regexp = NULL; const char *application_name_match = NULL; const char *application_versions = NULL; driOptionInfo version_range = { @@ -690,6 +696,7 @@ parseAppAttr(struct OptConfData *data, const char **attr) 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], "executable_regexp")) exec_regexp = attr[i+1]; else if (!strcmp(attr[i], "sha1")) sha1 = attr[i+1]; else if (!strcmp(attr[i], "application_name_match")) application_name_match = attr[i+1]; @@ -699,6 +706,15 @@ parseAppAttr(struct OptConfData *data, const char **attr) } if (exec && strcmp(exec, data->execName)) { data->ignoringApp = data->inApp; + } else if (exec_regexp) { + regex_t re; + + if (regcomp(&re, exec_regexp, REG_EXTENDED|REG_NOSUB) == 0) { + if (regexec(&re, data->execName, 0, NULL, 0) == REG_NOMATCH) + data->ignoringApp = data->inApp; + regfree(&re); + } else + XML_WARNING("Invalid executable_regexp=\"%s\".", exec_regexp); } else if (sha1) { /* SHA1_DIGEST_STRING_LENGTH includes terminating null byte */ if (strlen(sha1) != (SHA1_DIGEST_STRING_LENGTH - 1)) { @@ -998,7 +1014,10 @@ scandir_filter(const struct dirent *ent) (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))) return 0; #else - if (ent->d_type != DT_REG && ent->d_type != DT_LNK) + /* Allow through unknown file types for filesystems that don't support d_type + * The full filepath isn't available here to stat the file + */ + if (ent->d_type != DT_REG && ent->d_type != DT_LNK && ent->d_type != DT_UNKNOWN) return 0; #endif @@ -1022,10 +1041,26 @@ parseConfigDir(struct OptConfData *data, const char *dirname) for (i = 0; i < count; i++) { char filename[PATH_MAX]; +#ifdef DT_REG + unsigned char d_type = entries[i]->d_type; +#endif snprintf(filename, PATH_MAX, "%s/%s", dirname, entries[i]->d_name); free(entries[i]); +#ifdef DT_REG + /* In the case of unknown d_type, ensure it is a regular file + * This can be accomplished with stat on the full filepath + */ + if (d_type == DT_UNKNOWN) { + struct stat st; + if (stat(filename, &st) != 0 || + !S_ISREG(st.st_mode)) { + continue; + } + } +#endif + parseOneConfigFile(data, filename); } @@ -1093,6 +1128,8 @@ parseStaticConfig(struct OptConfData *data) const char *appattr[] = { "name", a->name, "executable", a->executable, + "executable_regexp", a->executable_regexp, + "sha1", a->sha1, "application_name_match", a->application_name_match, "application_versions", a->application_versions, NULL @@ -1128,24 +1165,9 @@ initOptionCache(driOptionCache *cache, const driOptionCache *info) } } -#ifndef SYSCONFDIR -#define SYSCONFDIR "/etc" -#endif - -#ifndef DATADIR -#define DATADIR "/usr/share" -#endif - -static const char *datadir = DATADIR "/drirc.d"; static const char *execname; void -driInjectDataDir(const char *dir) -{ - datadir = dir; -} - -void driInjectExecName(const char *exec) { execname = exec; @@ -1160,7 +1182,12 @@ driParseConfigFiles(driOptionCache *cache, const driOptionCache *info, const char *engineName, uint32_t engineVersion) { initOptionCache(cache, info); - struct OptConfData userData; + struct OptConfData userData = {0}; + + if (!execname) + execname = os_get_option("MESA_DRICONF_EXECUTABLE_OVERRIDE"); + if (!execname) + execname = util_get_process_name(); userData.cache = cache; userData.screenNum = screenNum; @@ -1171,13 +1198,18 @@ driParseConfigFiles(driOptionCache *cache, const driOptionCache *info, userData.applicationVersion = applicationVersion; userData.engineName = engineName ? engineName : ""; userData.engineVersion = engineVersion; - userData.execName = execname ? execname : util_get_process_name(); + userData.execName = execname; #if WITH_XMLCONFIG - char *home; - - parseConfigDir(&userData, datadir); - parseOneConfigFile(&userData, SYSCONFDIR "/drirc"); + char *home, *configdir; + + /* parse from either $DRIRC_CONFIGDIR or $datadir/drirc.d */ + if ((configdir = getenv("DRIRC_CONFIGDIR"))) + parseConfigDir(&userData, configdir); + else { + parseConfigDir(&userData, DATADIR "/drirc.d"); + parseOneConfigFile(&userData, SYSCONFDIR "/drirc"); + } if ((home = getenv("HOME"))) { char filename[PATH_MAX]; |