The open source OpenXR runtime
1// Copyright 2019-2021, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Very simple file opening functions, mostly using std::filesystem for portability.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @author Pete Black <pblack@collabora.com>
9 * @ingroup aux_util
10 */
11
12#include "xrt/xrt_config_os.h"
13#include "util/u_file.h"
14
15#ifndef XRT_OS_LINUX
16
17#include <errno.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#if __cplusplus >= 201703L
23#include <filesystem>
24namespace fs = std::filesystem;
25#else
26#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
27#include <experimental/filesystem>
28namespace fs = std::experimental::filesystem;
29#endif
30
31static inline fs::path
32get_config_path()
33{
34#ifdef XRT_OS_WINDOWS
35 char *buffer = nullptr;
36 errno_t ret = _dupenv_s(&buffer, nullptr, "LOCALAPPDATA");
37 if (ret != 0) {
38 return {};
39 }
40
41 auto local_app_data = fs::path{buffer};
42 free(buffer);
43
44 return local_app_data / "monado";
45#else
46 const char *xdg_home = getenv("XDG_CONFIG_HOME");
47 const char *home = getenv("HOME");
48 if (xdg_home != NULL) {
49 return fs::path(xdg_home) / "monado";
50 }
51 if (home != NULL) {
52 return fs::path(home) / "monado";
53 }
54 return {};
55#endif
56}
57
58int
59u_file_get_config_dir(char *out_path, size_t out_path_size)
60{
61 auto config_path = get_config_path();
62 if (config_path.empty()) {
63 return -1;
64 }
65 auto config_path_string = config_path.string();
66 return snprintf(out_path, out_path_size, "%s", config_path_string.c_str());
67}
68
69int
70u_file_get_path_in_config_dir(const char *filename, char *out_path, size_t out_path_size)
71{
72 auto config_path = get_config_path();
73 if (config_path.empty()) {
74 return -1;
75 }
76 auto path_string = (config_path / filename).string();
77 return snprintf(out_path, out_path_size, "%s", path_string.c_str());
78}
79
80FILE *
81u_file_open_file_in_config_dir(const char *filename, const char *mode)
82{
83 auto config_path = get_config_path();
84 if (config_path.empty()) {
85 return NULL;
86 }
87
88 auto file_path_string = (config_path / filename).string();
89 FILE *file = nullptr;
90 errno_t ret = fopen_s(&file, file_path_string.c_str(), mode);
91 if (ret == 0) {
92 return file;
93 }
94
95 // Try creating the path.
96 auto directory = (config_path / filename).parent_path();
97 fs::create_directories(directory);
98
99 // Do not report error.
100 ret = fopen_s(&file, file_path_string.c_str(), mode);
101 if (ret == 0) {
102 return file;
103 }
104
105 return nullptr;
106}
107
108#endif // XRT_OS_LINUX