diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 16d2caae5..51fa0facb 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -111,6 +111,7 @@ set(UTIL_SOURCE_FILES util/u_distortion_mesh.h util/u_documentation.h util/u_file.c + util/u_file.cpp util/u_file.h util/u_format.c util/u_format.h diff --git a/src/xrt/auxiliary/util/u_file.c b/src/xrt/auxiliary/util/u_file.c index d711f5676..b40295860 100644 --- a/src/xrt/auxiliary/util/u_file.c +++ b/src/xrt/auxiliary/util/u_file.c @@ -104,6 +104,8 @@ u_file_open_file_in_config_dir(const char *filename, const char *mode) return fopen(file_str, mode); } +#endif + char * u_file_read_content(FILE *file) { @@ -128,5 +130,3 @@ u_file_read_content(FILE *file) return buffer; } - -#endif diff --git a/src/xrt/auxiliary/util/u_file.cpp b/src/xrt/auxiliary/util/u_file.cpp new file mode 100644 index 000000000..4a2054fce --- /dev/null +++ b/src/xrt/auxiliary/util/u_file.cpp @@ -0,0 +1,94 @@ +// Copyright 2019-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Very simple file opening functions, mostly using std::filesystem for portability. + * @author Ryan Pavlik + * @author Jakob Bornecrantz + * @author Pete Black + * @ingroup aux_util + */ + +#include "xrt/xrt_config_os.h" +#include "util/u_file.h" + +#ifndef XRT_OS_LINUX + +#include +#include +#include +#include + +#if __cplusplus >= 201703L +#include +namespace fs = std::filesystem; +#else +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#include +namespace fs = std::experimental::filesystem; +#endif + +static inline fs::path +get_config_path() +{ +#ifdef XRT_OS_WINDOWS + auto local_app_data = fs::path{getenv("LOCALAPPDATA")}; + return local_app_data / "monado"; +#else + + const char *xdg_home = getenv("XDG_CONFIG_HOME"); + const char *home = getenv("HOME"); + if (xdg_home != NULL) { + return fs::path(xdg_home) / "monado"; + } + if (home != NULL) { + return fs::path(home) / "monado"; + } + return {}; +#endif +} +ssize_t +u_file_get_config_dir(char *out_path, size_t out_path_size) +{ + auto config_path = get_config_path(); + if (config_path.empty()) { + return -1; + } + auto config_path_string = config_path.string(); + return snprintf(out_path, out_path_size, "%s", config_path_string.c_str()); +} + +ssize_t +u_file_get_path_in_config_dir(const char *filename, char *out_path, size_t out_path_size) +{ + auto config_path = get_config_path(); + if (config_path.empty()) { + return -1; + } + auto path_string = (config_path / filename).string(); + return snprintf(out_path, out_path_size, "%s", path_string.c_str()); +} + +FILE * +u_file_open_file_in_config_dir(const char *filename, const char *mode) +{ + auto config_path = get_config_path(); + if (config_path.empty()) { + return NULL; + } + + auto file_path_string = (config_path / filename).string(); + FILE *file = fopen(file_path_string.c_str(), mode); + if (file != NULL) { + return file; + } + + // Try creating the path. + auto directory = (config_path / filename).parent_path(); + fs::create_directories(directory); + + // Do not report error. + return fopen(file_path_string.c_str(), mode); +} + +#endif