Pharos 0.7.23
Modern Web Framework & Web App Hosting Service.
Loading...
Searching...
No Matches
native_app_config.c
Go to the documentation of this file.
1/**
2 * @file
3 * @brief Loads app-local runtime configuration and resolves app-relative override paths from local config and manifest data.
4 */
5
6#include "native_app_config.h"
7
9#include "native_support.h"
10
11#include <stdlib.h>
12#include <string.h>
13
14#ifdef _WIN32
15#define pharos_app_config_strdup _strdup
16#else
17#define pharos_app_config_strdup strdup
18#endif
19
20char *resolve_conf_relative_path_native(const char *conf_path, const char *raw_value) {
21 char *conf_dir;
22 char *resolved;
23 if (raw_value == NULL || raw_value[0] == '\0') {
24 return pharos_app_config_strdup("");
25 }
26#ifdef _WIN32
27 if ((strlen(raw_value) > 2 && raw_value[1] == ':') || raw_value[0] == '\\' || raw_value[0] == '/') {
28 return pharos_app_config_strdup(raw_value);
29 }
30#else
31 if (raw_value[0] == '/') {
32 return pharos_app_config_strdup(raw_value);
33 }
34#endif
35 conf_dir = path_dirname(conf_path);
36 if (conf_dir == NULL) {
37 return NULL;
38 }
39 resolved = path_join(conf_dir, raw_value);
40 free(conf_dir);
41 return resolved;
42}
43
44char *app_local_conf_path_native(const char *app_root) {
45 char *path = path_join(app_root, "app.conf");
46 if (path != NULL && path_exists(path)) {
47 return path;
48 }
49 free(path);
50 path = path_join(app_root, "pharos.conf");
51 if (path == NULL) {
52 return NULL;
53 }
54 if (!path_exists(path)) {
55 free(path);
56 return NULL;
57 }
58 return path;
59}
60
61
62
63static char *resolve_conf_value_key_native(const char *conf_path, const char *key, const char *value) {
64 if (value == NULL) {
65 return NULL;
66 }
67 if (streq(key, "app_dir") || streq(key, "build_dir") || streq(key, "state_dir") || streq(key, "state_path") || streq(key, "log_path") || streq(key, "socket_path") || streq(key, "error_report_path")) {
68 return resolve_conf_relative_path_native(conf_path, value);
69 }
70 return pharos_app_config_strdup(value);
71}
72
73static char *duplicate_config_field_native(const AppLocalConfigNative *config, size_t offset) {
74 const char *const *field;
75 if (config == NULL) {
76 return NULL;
77 }
78 field = (const char *const *)((const char *)config + offset);
79 if (field == NULL || *field == NULL) {
80 return NULL;
81 }
82 return pharos_app_config_strdup(*field);
83}
84
85char *app_local_conf_value_native(const char *app_root, const char *key) {
86 static const struct {
87 const char *key;
88 size_t offset;
89 } key_map[] = {
90 { "build_dir", offsetof(AppLocalConfigNative, build_dir) },
91 { "state_dir", offsetof(AppLocalConfigNative, state_dir) },
92 { "state_path", offsetof(AppLocalConfigNative, state_path) },
93 { "base_path", offsetof(AppLocalConfigNative, base_path) },
94 { "log_path", offsetof(AppLocalConfigNative, log_path) },
95 { "socket_path", offsetof(AppLocalConfigNative, socket_path) },
96 { "error_report_path", offsetof(AppLocalConfigNative, error_report_path) },
97 { "debug", offsetof(AppLocalConfigNative, debug) },
98 { "conf_path", offsetof(AppLocalConfigNative, conf_path) }
99 };
101 char *value = NULL;
102 size_t index;
103 if (key != NULL && streq(key, "app_dir")) {
104 return NULL;
105 }
106 if (load_app_local_config_native(app_root, &config) != 0) {
107 return NULL;
108 }
109 for (index = 0; index < sizeof(key_map) / sizeof(key_map[0]); index++) {
110 if (!streq(key, key_map[index].key)) {
111 continue;
112 }
113 value = duplicate_config_field_native(&config, key_map[index].offset);
114 break;
115 }
117 return value;
118}
119
120int load_app_local_config_native(const char *app_root, AppLocalConfigNative *config) {
121 char *conf_path;
122 char *conf_text = NULL;
123 char *manifest_path = NULL;
124 char *manifest_text = NULL;
125
126 if (config == NULL) {
127 return -1;
128 }
129 memset(config, 0, sizeof(*config));
130 if (app_root == NULL || app_root[0] == '\0') {
131 return -1;
132 }
133 conf_path = app_local_conf_path_native(app_root);
134 if (conf_path != NULL) {
135 conf_text = read_file_text(conf_path);
136 config->conf_path = conf_path;
137 }
138 manifest_path = path_join(app_root, "pharos.app.json");
139 if (manifest_path != NULL && path_exists(manifest_path)) {
140 manifest_text = read_file_text(manifest_path);
141 }
142 free(manifest_path);
143 if (config->conf_path != NULL && conf_text != NULL) {
144 char *raw;
145 raw = conf_lookup_value_in_text(conf_text, "build_dir");
146 config->build_dir = resolve_conf_value_key_native(config->conf_path, "build_dir", raw);
147 free(raw);
148 raw = conf_lookup_value_in_text(conf_text, "state_dir");
149 config->state_dir = resolve_conf_value_key_native(config->conf_path, "state_dir", raw);
150 free(raw);
151 raw = conf_lookup_value_in_text(conf_text, "state_path");
152 config->state_path = resolve_conf_value_key_native(config->conf_path, "state_path", raw);
153 free(raw);
154 raw = conf_lookup_value_in_text(conf_text, "base_path");
155 config->base_path = resolve_conf_value_key_native(config->conf_path, "base_path", raw);
156 free(raw);
157 raw = conf_lookup_value_in_text(conf_text, "log_path");
158 config->log_path = resolve_conf_value_key_native(config->conf_path, "log_path", raw);
159 free(raw);
160 raw = conf_lookup_value_in_text(conf_text, "socket_path");
161 config->socket_path = resolve_conf_value_key_native(config->conf_path, "socket_path", raw);
162 free(raw);
163 raw = conf_lookup_value_in_text(conf_text, "error_report_path");
164 config->error_report_path = resolve_conf_value_key_native(config->conf_path, "error_report_path", raw);
165 free(raw);
166 raw = conf_lookup_value_in_text(conf_text, "debug");
167 config->debug = resolve_conf_value_key_native(config->conf_path, "debug", raw);
168 free(raw);
169 }
170 if (manifest_text != NULL) {
171 config->manifest_build_artifact_dir = json_find_string_in_section(manifest_text, "runtime", "build_artifact_dir");
172 config->manifest_state_path = json_find_string_in_section(manifest_text, "runtime", "state_path");
173 config->manifest_base_path = json_find_string_in_section(manifest_text, "runtime", "base_path");
174 }
175 free(conf_text);
176 free(manifest_text);
177 return 0;
178}
179
181 if (config == NULL) {
182 return;
183 }
184 free(config->conf_path);
185 free(config->build_dir);
186 free(config->state_dir);
187 free(config->state_path);
188 free(config->base_path);
189 free(config->log_path);
190 free(config->socket_path);
191 free(config->error_report_path);
192 free(config->debug);
193 free(config->manifest_build_artifact_dir);
194 free(config->manifest_state_path);
195 free(config->manifest_base_path);
196 memset(config, 0, sizeof(*config));
197}
198
199char *normalize_base_path_native(const char *raw_value) {
200 char *copy;
201 char *trimmed;
202 size_t len;
203 if (raw_value == NULL || raw_value[0] == '\0' || streq(raw_value, "/") || streq(raw_value, "null")) {
204 return pharos_app_config_strdup("");
205 }
206 copy = pharos_app_config_strdup(raw_value);
207 if (copy == NULL) {
208 return NULL;
209 }
210 trimmed = copy;
211 while (*trimmed == '/') {
212 trimmed++;
213 }
214 len = strlen(trimmed);
215 while (len > 0 && trimmed[len - 1] == '/') {
216 trimmed[--len] = '\0';
217 }
218 if (len == 0) {
219 free(copy);
220 return pharos_app_config_strdup("");
221 }
222 {
223 char *normalized = (char *)malloc(len + 2);
224 if (normalized == NULL) {
225 free(copy);
226 return NULL;
227 }
228 normalized[0] = '/';
229 memcpy(normalized + 1, trimmed, len + 1);
230 free(copy);
231 return normalized;
232 }
233}
void free_app_local_config_native(AppLocalConfigNative *config)
Releases heap-owned fields in an app-local configuration record.
char * app_local_conf_path_native(const char *app_root)
Builds the path to an app-local runtime configuration file.
static char * resolve_conf_value_key_native(const char *conf_path, const char *key, const char *value)
char * app_local_conf_value_native(const char *app_root, const char *key)
Looks up one key from the app-local runtime configuration.
static char * duplicate_config_field_native(const AppLocalConfigNative *config, size_t offset)
char * resolve_conf_relative_path_native(const char *conf_path, const char *raw_value)
Resolves a config value relative to the directory that owns a config file.
char * normalize_base_path_native(const char *raw_value)
Normalizes a configured app base path into Pharos runtime form.
#define pharos_app_config_strdup
int load_app_local_config_native(const char *app_root, AppLocalConfigNative *config)
Loads app-local configuration and manifest-derived path hints into a config record.
Declares app-local runtime configuration helpers and the app-local configuration record.
char * conf_lookup_value_in_text(const char *text, const char *key)
Looks up one key from Pharos conf-format text.
char * json_find_string_in_section(const char *text, const char *section, const char *key)
Finds a JSON string value for a key inside a named section object.
Declares lightweight JSON and conf value lookup helpers.
char * path_join(const char *left, const char *right)
Joins two path segments using the native path separator.
int streq(const char *a, const char *b)
Tests whether two strings are exactly equal.
char * path_dirname(const char *path)
Returns the parent directory component of a path.
char * read_file_text(const char *path)
Reads an entire file into a newly allocated text buffer.
int path_exists(const char *path)
Tests whether a filesystem path currently exists.
Declares shared low-level support helpers used across the Pharos native runtime.
App-local configuration values loaded from app-local config and manifest authority fields.
const char size_t len
Definition yyjson.h:8364