diff --git a/Makefile.am b/Makefile.am index e690362..e6620b1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,12 +49,12 @@ sbin_PROGRAMS = bin/bumblebeed bin_PROGRAMS = bin/optirun bin_optirun_SOURCES = src/module.c src/bbconfig.c src/bblogger.c src/bbrun.c \ - src/bbsocket.c src/driver.c src/optirun.c src/bbsocketclient.c + src/bbsocket.c src/driver.c src/optirun.c src/bbsocketclient.c src/findpathwild.c bin_optirun_LDADD = ${glib_LIBS} -lrt bin_bumblebeed_SOURCES = src/pci.c src/bbconfig.c src/bblogger.c src/bbrun.c \ src/bbsocket.c src/module.c src/bbsecondary.c src/switch/switching.c \ src/switch/sw_bbswitch.c src/switch/sw_switcheroo.c \ - src/driver.c src/bumblebeed.c + src/driver.c src/bumblebeed.c src/findpathwild.c bin_bumblebeed_LDADD = ${x11_LIBS} ${libbsd_LIBS} ${glib_LIBS} -lrt dist_doc_DATA = $(relnotes) README.markdown diff --git a/src/bbconfig.c b/src/bbconfig.c index 1dff5e0..15b9548 100644 --- a/src/bbconfig.c +++ b/src/bbconfig.c @@ -1,4 +1,7 @@ /* + * Copyright (c) 2017, The Bumblebee Project + * Author: Stefan Helmert (TheTesla) + * * Copyright (c) 2011-2013, The Bumblebee Project * Author: Joaquín Ignacio Aramendía samsagax@gmail.com * Author: Jaron Viëtor AKA "Thulinma" @@ -34,6 +37,7 @@ #include "bbconfig.h" #include "bblogger.h" #include "module.h" +#include "findpathwild.h" /* config values for PM methods, edit bb_pm_method in bbconfig.h as well! */ const char *bb_pm_method_string[PM_METHODS_COUNT] = { @@ -380,7 +384,10 @@ GKeyFile *bbconfig_parse_conf(void) { } key = "PrimusLibraryPath"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { - free_and_set_value(&bb_config.primus_ld_path, g_key_file_get_string(bbcfg, section, key, NULL)); + char* primusLibraryPath; + primusLibraryPath = malloc(MAX_STR_LEN); + findPathListWild(primusLibraryPath, g_key_file_get_string(bbcfg, section, key, NULL)); + free_and_set_value(&bb_config.primus_ld_path, primusLibraryPath); } key = "VGLTransport"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { @@ -423,7 +430,10 @@ GKeyFile *bbconfig_parse_conf(void) { } key = "XorgConfDir"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { - free_and_set_value(&bb_config.x_conf_dir, g_key_file_get_string(bbcfg, section, key, NULL)); + char* xorgConfDir; + xorgConfDir = malloc(MAX_STR_LEN); + findPathListWild(xorgConfDir, g_key_file_get_string(bbcfg, section, key, NULL)); + free_and_set_value(&bb_config.x_conf_dir, xorgConfDir); } return bbcfg; } @@ -453,18 +463,31 @@ void bbconfig_parse_conf_driver(GKeyFile *bbcfg, char *driver) { /* if KernelDriver is empty, the default behavior is to copy Driver which * is done in driver_detect() */ if (*module_name) { - free_and_set_value(&bb_config.module_name, module_name); + char* kernelDriver; + kernelDriver = malloc(MAX_STR_LEN); + if(findDriverWild(kernelDriver, module_name)) { + free_and_set_value(&bb_config.module_name, kernelDriver); + } else { + free_and_set_value(&bb_config.module_name, module_name); + } } else { g_free(module_name); } } key = "LibraryPath"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { - free_and_set_value(&bb_config.ld_path, g_key_file_get_string(bbcfg, section, key, NULL)); + char* libraryPath; + libraryPath = malloc(MAX_STR_LEN); + findPathListWild(libraryPath, g_key_file_get_string(bbcfg, section, key, NULL)); + free_and_set_value(&bb_config.ld_path, libraryPath); + } key = "XorgModulePath"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { - free_and_set_value(&bb_config.mod_path, g_key_file_get_string(bbcfg, section, key, NULL)); + char* xorgModulePath; + xorgModulePath = malloc(MAX_STR_LEN); + findPathListWildDelim(xorgModulePath, g_key_file_get_string(bbcfg, section, key, NULL), ','); + free_and_set_value(&bb_config.mod_path, xorgModulePath); } key = "PMMethod"; if (g_key_file_has_key(bbcfg, section, key, NULL)) { diff --git a/src/findpathwild.c b/src/findpathwild.c new file mode 100644 index 0000000..c169c6f --- /dev/null +++ b/src/findpathwild.c @@ -0,0 +1,203 @@ +/*********************************************************************** + + Copyright (c) 2017 Stefan Helmert + + ***********************************************************************/ + +#include "findpathwild.h" +#include +#include +#include +#include +#include +#include +#include + + +char* getRootPath(char *rootPath, char *wildPath) +{ + char c; + c = 1; + unsigned pidxend = 0; + for(int i=0; c && i < MAX_STR_LEN; i++){ + c = wildPath[i]; + rootPath[i] = c; + if('/' == c){ + pidxend = i; + } + if('?' == c){ + rootPath[pidxend] = 0; + return &wildPath[pidxend+1]; // may be dangerous, bacause reduces maximum string length + } + } + return ""; +} + +char* splitStr(char* str, char delim) +{ + char c; + c = 1; + for(int i=0; c && i < MAX_STR_LEN; i++){ + c = str[i]; + if(delim == c){ + str[i] = 0; + return &str[i+1]; + } + + } + return ""; +} + +int cmpStrWild(char* inputStr, char* wildStr) +{ + char ci, cw; + ci = 1; + cw = 1; + for(int i = 0; ci && cw && i < MAX_STR_LEN; i++){ + ci = inputStr[i]; + cw = wildStr[i]; + if(ci == cw) continue; + if('?' == cw) continue; + return 0; + } + if(0 == ci && 0 == cw) return 1; + return 0; +} + +char* findPathWild(char* foundPath, char* wildPath) +{ + DIR *dir; + struct dirent *ent; + char found[MAX_STR_LEN]; + char rootPath[MAX_STR_LEN]; + char currentLabel[MAX_STR_LEN]; + char* pathEnd; + int cmpResult; + + + if('/' == wildPath[strlen(wildPath) -1]){ + wildPath[strlen(wildPath) -1] = 0; + } + + pathEnd = getRootPath(rootPath, wildPath); + strncpy(currentLabel, pathEnd, MAX_STR_LEN - 1); + pathEnd = splitStr(currentLabel, '/'); + strncat(rootPath, "/", MAX_STR_LEN - strlen(rootPath) - 1); + // structur: /root/Path / currentLabel / p?th/E?d/ + // | rootPath | currentLabel | pathEnd + + if ((dir = opendir (rootPath)) != NULL) { // acceppt only if path exists + if(0 == currentLabel[0]) { // no currentLabel means end of path reached + strncpy(foundPath, rootPath, MAX_STR_LEN - 1); + closedir (dir); + return foundPath; // means the path is found in deepest recursion + } + while ((ent = readdir (dir)) != NULL) { // go through all dirs in rootPath + cmpResult = cmpStrWild(ent->d_name, currentLabel); // check if wildcard matches + if(cmpResult) { // found match - next recursion step, process inner directory wildcards + strncpy(found, rootPath, MAX_STR_LEN - 1); + strncat(found, ent->d_name, MAX_STR_LEN - strlen(found) - 1); + strncat(found, "/", MAX_STR_LEN - strlen(found) - 1); + strncat(found, pathEnd, MAX_STR_LEN - strlen(found) - 1); + if(findPathWild(foundPath, found) != NULL) { + closedir (dir); + return foundPath; + } + } + } + closedir (dir); + return NULL; + } else { + return NULL; + } +} + + +char* findPathListWildDelim(char* foundPathList, char* wildPathList, char delim) +{ + char lWildPathList[MAX_STR_LEN] = ""; + char foundPath[MAX_STR_LEN] = ""; + char* nextStr; + char* wildPath; + char delimStr[2]; + delimStr[0] = delim; + delimStr[1] = 0; + foundPathList[0] = 0; + strncpy(lWildPathList, wildPathList, MAX_STR_LEN - 1); + wildPath = lWildPathList; + while(1){ + nextStr = splitStr(wildPath, delim); + + if(0 == wildPath[0]) { + return foundPathList; + } + + if(findPathWild(foundPath, wildPath)){ + if(0 != foundPathList[0]) { + strncat(foundPathList, delimStr, MAX_STR_LEN - strlen(foundPathList) - 1); + } + strncat(foundPathList, foundPath, MAX_STR_LEN - strlen(foundPathList) - 1); + } + wildPath = nextStr; + } + return NULL; +} + +char* findPathListWild(char* foundPathList, char* wildPathList) +{ + return findPathListWildDelim(foundPathList, wildPathList, ':'); +} + +char* findFileWild(char* foundDriver, char* fileNameWild, char* rootPath) +{ + DIR *dir; + struct dirent *ent; + char recursePath[MAX_STR_LEN]; + char* ret; + if ((dir = opendir (rootPath)) != NULL) { + while ((ent = readdir (dir)) != NULL) { + if(0 == strcmp(ent->d_name, ".")) continue; + if(0 == strcmp(ent->d_name, "..")) continue; + strncpy(recursePath, rootPath, MAX_STR_LEN - 1); + strncat(recursePath, "/", MAX_STR_LEN - strlen(recursePath) - 1); + strncat(recursePath, ent->d_name, MAX_STR_LEN - strlen(recursePath) - 1); + if(NULL != (ret = findFileWild(foundDriver, fileNameWild, recursePath))) { + return ret; + } + + } + closedir (dir); + return NULL; + } else { // can't open dir (is file or dir has not the right permissions) + struct stat s; + stat(rootPath, &s); + if(S_ISREG(s.st_mode)) { // is a file + if(cmpStrWild(basename(rootPath), fileNameWild)) { + strncpy(foundDriver, basename(rootPath), MAX_STR_LEN - 1); + return rootPath; + } + } + return NULL; + } +} + +char* findDriverWild(char* foundDriver, char* driverNameWild) +{ + struct utsname unameData; + char rootPath[MAX_STR_LEN]; + char wild[MAX_STR_LEN]; + char* ret; + if(uname(&unameData)) { + return NULL; + } + strncpy(rootPath, "/lib/modules/", MAX_STR_LEN - 1); + strncat(rootPath, unameData.release, MAX_STR_LEN - strlen(rootPath) - 1); + strncpy(wild, driverNameWild, MAX_STR_LEN - 1); + strncat(wild, ".ko", MAX_STR_LEN - strlen(wild) - 1); + ret = findFileWild(foundDriver, wild, rootPath); + foundDriver[strlen(foundDriver) - 3] = 0; + return ret; +} + + + diff --git a/src/findpathwild.h b/src/findpathwild.h new file mode 100644 index 0000000..9de61df --- /dev/null +++ b/src/findpathwild.h @@ -0,0 +1,22 @@ +/*********************************************************************** + + Copyright (c) 2017 Stefan Helmert + + ***********************************************************************/ + + +#define MAX_STR_LEN 512 + +char* getRootPath(char *rootPath, char *wildPath); +char* splitStr(char* str, char delim); +int cmpStrWild(char* inputStr, char* wildStr); +char* findPathWild(char* foundPath, char* wildPath); +char* findPathListWildDelim(char* foundPathList, char* wildPathList, char delim); +char* findPathListWild(char* foundPathList, char* wildPathList); +char* findFileWild(char* foundDriver, char* fileNameWild, char* rootPath); +char* findDriverWild(char* foundDriver, char* driverNameWild); + + + + + diff --git a/test/bumblebee.conf b/test/bumblebee.conf new file mode 100644 index 0000000..30243d8 --- /dev/null +++ b/test/bumblebee.conf @@ -0,0 +1,69 @@ +# Configuration file for Bumblebee. Values should **not** be put between quotes + +## Server options. Any change made in this section will need a server restart +# to take effect. +[bumblebeed] +# The secondary Xorg server DISPLAY number +VirtualDisplay=:8 +# Should the unused Xorg server be kept running? Set this to true if waiting +# for X to be ready is too long and don't need power management at all. +KeepUnusedXServer=false +# The name of the Bumbleblee server group name (GID name) +ServerGroup=bumblebee +# Card power state at exit. Set to false if the card shoud be ON when Bumblebee +# server exits. +TurnCardOffAtExit=false +# The default behavior of '-f' option on optirun. If set to "true", '-f' will +# be ignored. +NoEcoModeOverride=false +# The Driver used by Bumblebee server. If this value is not set (or empty), +# auto-detection is performed. The available drivers are nvidia and nouveau +# (See also the driver-specific sections below) +Driver = nvidia +# Directory with a dummy config file to pass as a -configdir to secondary X +XorgConfDir=/etc/bumblebee/xorg.conf.d + +## Client options. Will take effect on the next optirun executed. +[optirun] +# Acceleration/ rendering bridge, possible values are auto, virtualgl and +# primus. +Bridge=auto +# The method used for VirtualGL to transport frames between X servers. +# Possible values are proxy, jpeg, rgb, xv and yuv. +VGLTransport=proxy +# List of paths which are searched for the primus libGL.so.1 when using +# the primus bridge +PrimusLibraryPath=/usr/lib/x86_64-linux-gnu/primus:/usr/lib/i386-linux-gnu/primus +# Should the program run under optirun even if Bumblebee server or nvidia card +# is not available? +AllowFallbackToIGC=false + + +# Driver-specific settings are grouped under [driver-NAME]. The sections are +# parsed if the Driver setting in [bumblebeed] is set to NAME (or if auto- +# detection resolves to NAME). +# PMMethod: method to use for saving power by disabling the nvidia card, valid +# values are: auto - automatically detect which PM method to use +# bbswitch - new in BB 3, recommended if available +# switcheroo - vga_switcheroo method, use at your own risk +# none - disable PM completely +# https://github.com/Bumblebee-Project/Bumblebee/wiki/Comparison-of-PM-methods + +## Section with nvidia driver specific options, only parsed if Driver=nvidia +[driver-nvidia] +# Module name to load, defaults to Driver if empty or unset +KernelDriver = nvidia_??? +PMMethod=auto +# colon-separated path to the nvidia libraries +LibraryPath = /usr/lib/nvidia-???:/usr/lib32/nvidia-??? +# comma-separated path of the directory containing nvidia_drv.so and the +# default Xorg modules path +XorgModulePath = /usr/lib/nvidia-???/xorg,/usr/lib/xorg/modules +XorgConfFile=/etc/bumblebee/xorg.conf.nvidia + +## Section with nouveau driver specific options, only parsed if Driver=nouveau +[driver-nouveau] +KernelDriver=nouveau +PMMethod=auto +XorgConfFile=/etc/bumblebee/xorg.conf.nouveau +