diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c index a92d621927a..d70cf2e7c96 100644 --- a/src/util/disk_cache.c +++ b/src/util/disk_cache.c @@ -32,9 +32,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -54,6 +52,7 @@ #include "util/compiler.h" #include "disk_cache.h" +#include "disk_cache_os.h" /* Number of bits to mask off from a cache key to get an index. */ #define CACHE_INDEX_KEY_BITS 16 @@ -162,33 +161,6 @@ mkdir_if_needed(const char *path) return -1; } -/* Concatenate an existing path and a new name to form a new path. If the new - * path does not exist as a directory, create it then return the resulting - * name of the new path (ralloc'ed off of 'ctx'). - * - * Returns NULL on any error, such as: - * - * does not exist or is not a directory - * / exists but is not a directory - * / cannot be created as a directory - */ -static char * -concatenate_and_mkdir(void *ctx, const char *path, const char *name) -{ - char *new_path; - struct stat sb; - - if (stat(path, &sb) != 0 || ! S_ISDIR(sb.st_mode)) - return NULL; - - new_path = ralloc_asprintf(ctx, "%s/%s", path, name); - - if (mkdir_if_needed(new_path) == 0) - return new_path; - else - return NULL; -} - #define DRV_KEY_CPY(_dst, _src, _src_size) \ do { \ memcpy(_dst, _src, _src_size); \ @@ -201,7 +173,7 @@ disk_cache_create(const char *gpu_name, const char *driver_id, { void *local; struct disk_cache *cache = NULL; - char *path, *max_size_str; + char *max_size_str; uint64_t max_size; int fd = -1; struct stat sb; @@ -230,69 +202,9 @@ disk_cache_create(const char *gpu_name, const char *driver_id, /* Assume failure. */ cache->path_init_failed = true; - /* Determine path for cache based on the first defined name as follows: - * - * $MESA_GLSL_CACHE_DIR - * $XDG_CACHE_HOME/mesa_shader_cache - * /.cache/mesa_shader_cache - */ - path = getenv("MESA_GLSL_CACHE_DIR"); - if (path) { - if (mkdir_if_needed(path) == -1) - goto path_fail; - - path = concatenate_and_mkdir(local, path, CACHE_DIR_NAME); - if (path == NULL) - goto path_fail; - } - - if (path == NULL) { - char *xdg_cache_home = getenv("XDG_CACHE_HOME"); - - if (xdg_cache_home) { - if (mkdir_if_needed(xdg_cache_home) == -1) - goto path_fail; - - path = concatenate_and_mkdir(local, xdg_cache_home, CACHE_DIR_NAME); - if (path == NULL) - goto path_fail; - } - } - - if (path == NULL) { - char *buf; - size_t buf_size; - struct passwd pwd, *result; - - buf_size = sysconf(_SC_GETPW_R_SIZE_MAX); - if (buf_size == -1) - buf_size = 512; - - /* Loop until buf_size is large enough to query the directory */ - while (1) { - buf = ralloc_size(local, buf_size); - - getpwuid_r(getuid(), &pwd, buf, buf_size, &result); - if (result) - break; - - if (errno == ERANGE) { - ralloc_free(buf); - buf = NULL; - buf_size *= 2; - } else { - goto path_fail; - } - } - - path = concatenate_and_mkdir(local, pwd.pw_dir, ".cache"); - if (path == NULL) - goto path_fail; - - path = concatenate_and_mkdir(local, path, CACHE_DIR_NAME); - if (path == NULL) - goto path_fail; - } + char *path = disk_cache_generate_cache_dir(local); + if (!path) + goto path_fail; cache->path = ralloc_strdup(cache, path); if (cache->path == NULL) diff --git a/src/util/disk_cache_os.c b/src/util/disk_cache_os.c new file mode 100644 index 00000000000..516245b7e08 --- /dev/null +++ b/src/util/disk_cache_os.c @@ -0,0 +1,176 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifdef ENABLE_SHADER_CACHE + +#if DETECT_OS_WINDOWS +/* TODO: implement disk cache support on windows */ + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/disk_cache.h" +#include "util/disk_cache_os.h" +#include "util/ralloc.h" + +/* Create a directory named 'path' if it does not already exist. + * + * Returns: 0 if path already exists as a directory or if created. + * -1 in all other cases. + */ +static int +mkdir_if_needed(const char *path) +{ + struct stat sb; + + /* If the path exists already, then our work is done if it's a + * directory, but it's an error if it is not. + */ + if (stat(path, &sb) == 0) { + if (S_ISDIR(sb.st_mode)) { + return 0; + } else { + fprintf(stderr, "Cannot use %s for shader cache (not a directory)" + "---disabling.\n", path); + return -1; + } + } + + int ret = mkdir(path, 0755); + if (ret == 0 || (ret == -1 && errno == EEXIST)) + return 0; + + fprintf(stderr, "Failed to create %s for shader cache (%s)---disabling.\n", + path, strerror(errno)); + + return -1; +} + +/* Concatenate an existing path and a new name to form a new path. If the new + * path does not exist as a directory, create it then return the resulting + * name of the new path (ralloc'ed off of 'ctx'). + * + * Returns NULL on any error, such as: + * + * does not exist or is not a directory + * / exists but is not a directory + * / cannot be created as a directory + */ +static char * +concatenate_and_mkdir(void *ctx, const char *path, const char *name) +{ + char *new_path; + struct stat sb; + + if (stat(path, &sb) != 0 || ! S_ISDIR(sb.st_mode)) + return NULL; + + new_path = ralloc_asprintf(ctx, "%s/%s", path, name); + + if (mkdir_if_needed(new_path) == 0) + return new_path; + else + return NULL; +} + +/* Determine path for cache based on the first defined name as follows: + * + * $MESA_GLSL_CACHE_DIR + * $XDG_CACHE_HOME/mesa_shader_cache + * /.cache/mesa_shader_cache + */ +char * +disk_cache_generate_cache_dir(void *mem_ctx) +{ + char *path = getenv("MESA_GLSL_CACHE_DIR"); + if (path) { + if (mkdir_if_needed(path) == -1) + return NULL; + + path = concatenate_and_mkdir(mem_ctx, path, CACHE_DIR_NAME); + if (!path) + return NULL; + } + + if (path == NULL) { + char *xdg_cache_home = getenv("XDG_CACHE_HOME"); + + if (xdg_cache_home) { + if (mkdir_if_needed(xdg_cache_home) == -1) + return NULL; + + path = concatenate_and_mkdir(mem_ctx, xdg_cache_home, CACHE_DIR_NAME); + if (!path) + return NULL; + } + } + + if (!path) { + char *buf; + size_t buf_size; + struct passwd pwd, *result; + + buf_size = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buf_size == -1) + buf_size = 512; + + /* Loop until buf_size is large enough to query the directory */ + while (1) { + buf = ralloc_size(mem_ctx, buf_size); + + getpwuid_r(getuid(), &pwd, buf, buf_size, &result); + if (result) + break; + + if (errno == ERANGE) { + ralloc_free(buf); + buf = NULL; + buf_size *= 2; + } else { + return NULL; + } + } + + path = concatenate_and_mkdir(mem_ctx, pwd.pw_dir, ".cache"); + if (!path) + return NULL; + + path = concatenate_and_mkdir(mem_ctx, path, CACHE_DIR_NAME); + if (!path) + return NULL; + } + + return path; +} +#endif + +#endif /* ENABLE_SHADER_CACHE */ diff --git a/src/util/disk_cache_os.h b/src/util/disk_cache_os.h new file mode 100644 index 00000000000..0b7755fbacd --- /dev/null +++ b/src/util/disk_cache_os.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifndef DISK_CACHE_OS_H +#define DISK_CACHE_OS_H + +#if DETECT_OS_WINDOWS + +/* TODO: implement disk cache support on windows */ + +#else + +char * +disk_cache_generate_cache_dir(void *mem_ctx); + +#endif + +#endif /* DISK_CACHE_OS_H */ diff --git a/src/util/meson.build b/src/util/meson.build index e90f68e71d1..67f7bd7b832 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -41,6 +41,8 @@ files_mesa_util = files( 'debug.h', 'disk_cache.c', 'disk_cache.h', + 'disk_cache_os.c', + 'disk_cache_os.h', 'double.c', 'double.h', 'enum_operators.h',