Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Internals of mount functionality.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #ifdef HAVE_KDBCONFIG_H
10 : #include "kdbconfig.h"
11 : #endif
12 :
13 : #if DEBUG && defined(HAVE_STDIO_H)
14 : #include <stdio.h>
15 : #endif
16 :
17 : #ifdef HAVE_LOCALE_H
18 : #include <locale.h>
19 : #endif
20 :
21 : #ifdef HAVE_STDLIB_H
22 : #include <stdlib.h>
23 : #endif
24 :
25 : #ifdef HAVE_STRING_H
26 : #include <string.h>
27 : #endif
28 :
29 : #ifdef HAVE_STDIO_H
30 : #include <stdio.h>
31 : #endif
32 :
33 : #include <kdbassert.h>
34 :
35 : #include "kdbinternal.h"
36 :
37 :
38 : /**
39 : * Creates a trie from a given configuration.
40 : *
41 : * The config will be deleted within this function.
42 : *
43 : * @note mountDefault is not allowed to be executed before
44 : *
45 : * @param kdb the handle to work with
46 : * @param modules the current list of loaded modules
47 : * @param config the configuration which should be used to build up the trie.
48 : * @param errorKey the key used to report warnings
49 : * @retval -1 on failure
50 : * @retval 0 on success
51 : * @ingroup mount
52 : */
53 10585 : int mountOpen (KDB * kdb, KeySet * config, KeySet * modules, Key * errorKey)
54 : {
55 : Key * root;
56 : Key * cur;
57 :
58 10585 : ksRewind (config);
59 10585 : root = ksLookupByName (config, "system/elektra/mountpoints", KDB_O_CREATE);
60 :
61 10585 : int ret = 0;
62 28329 : while ((cur = ksNext (config)) != 0)
63 : {
64 7159 : if (keyRel (root, cur) == 1)
65 : {
66 7159 : KeySet * cut = ksCut (config, cur);
67 7159 : Backend * backend = backendOpen (cut, modules, kdb->global, errorKey);
68 :
69 7159 : if (!backend)
70 : {
71 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "Could not create missing backend");
72 0 : ret = -1;
73 0 : continue;
74 : }
75 :
76 7159 : if (!backend->mountpoint)
77 : {
78 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "Backend has no mount point");
79 0 : ret = -1;
80 0 : backendClose (backend, errorKey);
81 0 : continue;
82 : }
83 :
84 7159 : if (mountBackend (kdb, backend, errorKey) == -1)
85 : {
86 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "Mounting of backend failed");
87 0 : ret = -1;
88 : /* mountBackend modified the refcounter. */
89 0 : backend->refcounter = 1;
90 0 : backendClose (backend, errorKey);
91 0 : continue;
92 : }
93 : }
94 : }
95 10585 : ksDel (config);
96 :
97 10585 : return ret;
98 : }
99 :
100 :
101 : /** Reopens the default backend and mounts the default backend if needed.
102 : *
103 : * @pre Default Backend is closed. mountOpen was executed before.
104 : *
105 : * @param kdb the handle to work with
106 : * @param modules the current list of loaded modules
107 : * @param errorKey the key used to report warnings
108 : * @retval -1 on error
109 : * @retval 0 on success
110 : * @ingroup mount
111 : */
112 10577 : int mountDefault (KDB * kdb, KeySet * modules, int inFallback, Key * errorKey)
113 : {
114 : // open the defaultBackend the first time
115 10577 : kdb->defaultBackend = backendOpenDefault (modules, kdb->global, KDB_DB_FILE, errorKey);
116 10577 : kdb->initBackend = 0;
117 :
118 10577 : if (!kdb->defaultBackend)
119 : {
120 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "Could not (re)open default backend");
121 0 : return -1;
122 : }
123 :
124 10577 : if (!inFallback)
125 : {
126 : /* Reopen the init Backend for fresh user experience (update issue) */
127 10527 : kdb->initBackend = backendOpenDefault (modules, kdb->global, KDB_DB_INIT, errorKey);
128 :
129 10527 : if (!kdb->initBackend)
130 : {
131 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "Could not (re)open init backend");
132 0 : return -1;
133 : }
134 : }
135 :
136 : Key * key = 0;
137 : Backend * backend = 0;
138 :
139 52885 : for (elektraNamespace ns = KEY_NS_FIRST; ns <= KEY_NS_LAST; ++ns)
140 : {
141 52885 : switch (ns)
142 : {
143 : case KEY_NS_SPEC:
144 10577 : key = keyNew ("spec", KEY_VALUE, "default", KEY_END);
145 10577 : backend = mountGetBackend (kdb, key);
146 10577 : if (backend != kdb->defaultBackend)
147 : {
148 : /* It does not matter that spec is not reachable anymore */
149 18 : keyDel (key);
150 : }
151 : else
152 : {
153 : /* User is reachable, so append that to split */
154 10559 : splitAppend (kdb->split, backend, key, 2);
155 : }
156 : break;
157 : case KEY_NS_DIR:
158 10577 : key = keyNew ("dir", KEY_VALUE, "default", KEY_END);
159 10577 : backend = mountGetBackend (kdb, key);
160 10577 : if (backend != kdb->defaultBackend)
161 : {
162 : /* It does not matter that dir is not reachable anymore */
163 18 : keyDel (key);
164 : }
165 : else
166 : {
167 : /* Dir is reachable, so append that to split */
168 10559 : splitAppend (kdb->split, backend, key, 2);
169 : }
170 : break;
171 : case KEY_NS_SYSTEM:
172 : /* We want system/elektra still reachable
173 : * through default backend.
174 : * First check if it is still reachable.
175 : */
176 10577 : if (inFallback)
177 : {
178 50 : key = keyNew (KDB_SYSTEM_ELEKTRA, KEY_END);
179 50 : backend = mountGetBackend (kdb, key);
180 50 : keyDel (key);
181 50 : if (backend != kdb->defaultBackend)
182 : {
183 : /* It is not reachable, mount it */
184 24 : mountBackend (kdb, kdb->defaultBackend, errorKey);
185 : /*mountBackend will set refcounter*/
186 24 : ++kdb->defaultBackend->refcounter;
187 24 : kdb->split->syncbits[kdb->split->size - 1] = 2;
188 : }
189 : else
190 : {
191 : /* Lets add the reachable default backend to split.
192 : Note that it is not possible that system/elektra has the default
193 : backend, but system has not. */
194 26 : splitAppend (kdb->split, backend, keyNew ("system", KEY_VALUE, "default", KEY_END), 2);
195 : }
196 : }
197 : else
198 : {
199 : /* We want system/elektra still reachable
200 : * through bootstrap backend. */
201 10527 : mountBackend (kdb, kdb->initBackend, errorKey);
202 : /*mountBackend will set refcounter*/
203 10527 : ++kdb->initBackend->refcounter;
204 10527 : kdb->split->syncbits[kdb->split->size - 1] = 2;
205 :
206 10527 : key = keyNew ("system", KEY_VALUE, "default", KEY_END);
207 10527 : backend = mountGetBackend (kdb, key);
208 10527 : if (backend != kdb->defaultBackend)
209 : {
210 : /* It does not matter that system is not reachable anymore */
211 2 : keyDel (key);
212 : }
213 : else
214 : {
215 : /* System is reachable, so append that to split */
216 10525 : splitAppend (kdb->split, backend, key, 2);
217 : }
218 : }
219 : break;
220 : case KEY_NS_USER:
221 10577 : key = keyNew ("user", KEY_VALUE, "default", KEY_END);
222 10577 : backend = mountGetBackend (kdb, key);
223 10577 : if (backend != kdb->defaultBackend)
224 : {
225 : /* It does not matter that user is not reachable anymore */
226 24 : keyDel (key);
227 : }
228 : else
229 : {
230 : /* User is reachable, so append that to split */
231 10553 : splitAppend (kdb->split, backend, key, 2);
232 : }
233 : break;
234 : case KEY_NS_EMPTY:
235 : case KEY_NS_PROC:
236 : case KEY_NS_NONE:
237 : case KEY_NS_META:
238 : case KEY_NS_CASCADING:
239 : break;
240 : }
241 : }
242 :
243 : return 0;
244 : }
245 :
246 31493 : KeySet * elektraMountGlobalsGetConfig (Key * cur, KeySet * global)
247 : {
248 : // putting together the plugins configuration KeySet.
249 31493 : Key * sysConfigCutKey = keyDup (cur);
250 31493 : keyAddBaseName (sysConfigCutKey, "system");
251 31493 : Key * usrConfigCutKey = keyDup (cur);
252 31493 : keyAddBaseName (usrConfigCutKey, "user");
253 31493 : KeySet * sysConfigKS = ksCut (global, sysConfigCutKey);
254 31493 : KeySet * usrConfigKS = ksCut (global, usrConfigCutKey);
255 31493 : KeySet * renamedSysConfig = elektraRenameKeys (sysConfigKS, "system");
256 31493 : KeySet * renamedUsrConfig = elektraRenameKeys (usrConfigKS, "user");
257 31493 : ksDel (sysConfigKS);
258 31493 : ksDel (usrConfigKS);
259 31493 : keyDel (usrConfigCutKey);
260 31493 : keyDel (sysConfigCutKey);
261 31493 : KeySet * config = ksNew (0, KS_END);
262 31493 : ksAppend (config, renamedSysConfig);
263 31493 : ksAppend (config, renamedUsrConfig);
264 31493 : ksDel (renamedSysConfig);
265 31493 : ksDel (renamedUsrConfig);
266 :
267 31493 : return config;
268 : }
269 :
270 126086 : Key * elektraMountGlobalsFindPlugin (KeySet * referencePlugins, Key * cur)
271 : {
272 : Key * refKey;
273 126086 : Key * searchKey = keyNew ("/", KEY_END);
274 126086 : keyAddBaseName (searchKey, keyString (cur));
275 126086 : refKey = ksLookup (referencePlugins, searchKey, 0);
276 126086 : keyDel (searchKey);
277 126086 : return refKey;
278 : }
279 :
280 : /**
281 : * Loads global plugin
282 : *
283 : * @retval -1 on failure
284 : * @retval 0 on empty plugin name (nothing configured at given position)
285 : * @retval 1 on success
286 : */
287 126086 : int elektraMountGlobalsLoadPlugin (Plugin ** plugin, KeySet * referencePlugins, Key * cur, KeySet * global, KeySet * system,
288 : KeySet * modules, Key * errorKey)
289 : {
290 126086 : Key * refKey = elektraMountGlobalsFindPlugin (referencePlugins, cur);
291 126086 : Key * openKey = keyDup (errorKey);
292 :
293 126086 : if (refKey)
294 : {
295 : // plugin already loaded, just reference it
296 94593 : *plugin = *(Plugin **) keyValue (refKey);
297 94593 : (*plugin)->refcounter += 1;
298 : }
299 : else
300 : {
301 31493 : KeySet * config = elektraMountGlobalsGetConfig (cur, global);
302 31493 : ELEKTRA_NOT_NULL (config);
303 : // config holds a newly allocated KeySet
304 31493 : const char * pluginName = keyString (cur);
305 31493 : if (!pluginName || pluginName[0] == '\0')
306 : {
307 0 : keyDel (openKey);
308 0 : ksDel (config);
309 0 : return 0;
310 : }
311 :
312 : // loading the new plugin
313 31493 : *plugin = elektraPluginOpen (pluginName, modules, config, openKey);
314 31493 : if (!(*plugin) && !elektraStrCmp (pluginName, "cache") && !ksLookupByName (system, "system/elektra/cache/enabled", 0))
315 : {
316 20970 : keyDel (openKey);
317 20970 : return 0;
318 : }
319 10523 : else if (!(*plugin))
320 : {
321 0 : ELEKTRA_ADD_INSTALLATION_WARNINGF (errorKey, "Could not load plugin '%s'", pluginName);
322 0 : keyCopyAllMeta (errorKey, openKey);
323 0 : keyDel (openKey);
324 0 : return -1;
325 : }
326 :
327 : // saving the plugin reference to avoid having to load the plugin multiple times
328 10523 : refKey = keyNew ("/", KEY_BINARY, KEY_SIZE, sizeof (Plugin *), KEY_VALUE, &(*plugin), KEY_END);
329 10523 : keyAddBaseName (refKey, keyString (cur));
330 10523 : ksAppendKey (referencePlugins, refKey);
331 10523 : keyDel (refKey);
332 : }
333 :
334 105116 : keyCopyAllMeta (errorKey, openKey);
335 105116 : keyDel (openKey);
336 105116 : return 1;
337 : }
338 :
339 10485 : KeySet * elektraDefaultGlobalConfig (KeySet * keys)
340 : {
341 10485 : KeySet * config = ksNew (
342 : 24, keyNew ("system/elektra/globalplugins", KEY_VALUE, "", KEY_END),
343 : keyNew ("system/elektra/globalplugins/postcommit", KEY_VALUE, "list", KEY_END),
344 : keyNew ("system/elektra/globalplugins/postcommit/user", KEY_VALUE, "list", KEY_END),
345 : keyNew ("system/elektra/globalplugins/postcommit/user/placements", KEY_VALUE, "", KEY_END),
346 : keyNew ("system/elektra/globalplugins/postcommit/user/placements/error", KEY_VALUE, "prerollback postrollback", KEY_END),
347 : keyNew ("system/elektra/globalplugins/postcommit/user/placements/get", KEY_VALUE,
348 : "pregetstorage procgetstorage postgetstorage", KEY_END),
349 : keyNew ("system/elektra/globalplugins/postcommit/user/placements/set", KEY_VALUE, "presetstorage precommit postcommit",
350 : KEY_END),
351 : #ifndef __MINGW32__
352 : keyNew ("system/elektra/globalplugins/postcommit/user/plugins", KEY_VALUE, "", KEY_END),
353 : keyNew ("system/elektra/globalplugins/postcommit/user/plugins/#0", KEY_VALUE, "spec", KEY_END),
354 : keyNew ("system/elektra/globalplugins/postcommit/user/plugins/#0/placements", KEY_VALUE, "spec", KEY_END),
355 : keyNew ("system/elektra/globalplugins/postcommit/user/plugins/#0/placements/get", KEY_VALUE, "postgetstorage", KEY_END),
356 : keyNew ("system/elektra/globalplugins/postcommit/user/plugins/#0/placements/set", KEY_VALUE, "presetstorage", KEY_END),
357 : #endif
358 : keyNew ("system/elektra/globalplugins/postgetcleanup", KEY_VALUE, "list", KEY_END),
359 : keyNew ("system/elektra/globalplugins/postgetstorage", KEY_VALUE, "list", KEY_END),
360 : keyNew ("system/elektra/globalplugins/postgetcache", KEY_VALUE, "", KEY_END),
361 : keyNew ("system/elektra/globalplugins/postrollback", KEY_VALUE, "list", KEY_END),
362 : keyNew ("system/elektra/globalplugins/precommit", KEY_VALUE, "list", KEY_END),
363 : keyNew ("system/elektra/globalplugins/pregetstorage", KEY_VALUE, "list", KEY_END),
364 : keyNew ("system/elektra/globalplugins/pregetcache", KEY_VALUE, "", KEY_END),
365 : keyNew ("system/elektra/globalplugins/prerollback", KEY_VALUE, "list", KEY_END),
366 : keyNew ("system/elektra/globalplugins/presetcleanup", KEY_VALUE, "list", KEY_END),
367 : keyNew ("system/elektra/globalplugins/presetstorage", KEY_VALUE, "list", KEY_END),
368 : keyNew ("system/elektra/globalplugins/procgetstorage", KEY_VALUE, "list", KEY_END), KS_END);
369 :
370 10485 : Key * cacheEnabled = ksLookupByName (keys, "system/elektra/cache/enabled", 0);
371 10485 : if (!cacheEnabled || (cacheEnabled && !elektraStrCmp (keyString (cacheEnabled), "1")))
372 : {
373 10485 : ksAppendKey (config, keyNew ("system/elektra/globalplugins/postgetcache", KEY_VALUE, "cache", KEY_END));
374 10485 : ksAppendKey (config, keyNew ("system/elektra/globalplugins/pregetcache", KEY_VALUE, "cache", KEY_END));
375 : }
376 :
377 10485 : return config;
378 : }
379 :
380 10523 : int mountGlobals (KDB * kdb, KeySet * keys, KeySet * modules, Key * errorKey)
381 : {
382 10523 : int retval = 0;
383 10523 : Key * root = ksLookupByName (keys, "system/elektra/globalplugins", 0);
384 10523 : KeySet * system = ksDup (keys);
385 10523 : if (!root)
386 : {
387 : ELEKTRA_LOG ("no global configuration, assuming spec as default");
388 10485 : KeySet * tmp = keys;
389 10485 : keys = elektraDefaultGlobalConfig (keys);
390 10485 : ksDel (tmp);
391 10485 : root = ksHead (keys);
392 : }
393 10523 : memset (kdb->globalPlugins, 0, NR_GLOBAL_POSITIONS * NR_GLOBAL_SUBPOSITIONS * sizeof (Plugin *));
394 :
395 10523 : KeySet * global = ksCut (keys, root);
396 : Key * cur;
397 10523 : KeySet * referencePlugins = ksNew (0, KS_END);
398 157655 : while ((cur = ksNext (global)) != NULL)
399 : {
400 : // the cutpoints for the plugin configs are always directly below the "root", ignore everything else
401 136609 : if (keyRel (root, cur) != 1) continue;
402 :
403 126086 : char * placement = elektraStrDup (keyBaseName (cur));
404 :
405 2395634 : for (GlobalpluginPositions i = 0; i < NR_GLOBAL_POSITIONS; ++i)
406 : {
407 2269548 : if (!elektraStrCaseCmp (placement, GlobalpluginPositionsStr[i]))
408 : {
409 : #if DEBUG && VERBOSE
410 : printf ("mounting global plugin %s to %s\n", pluginName, placement);
411 : #endif
412 : // load plugins in implicit max once placement
413 126086 : Plugin * plugin = 0;
414 126086 : int mountRet =
415 : elektraMountGlobalsLoadPlugin (&plugin, referencePlugins, cur, global, system, modules, errorKey);
416 :
417 126086 : if (mountRet == -1)
418 : retval = -1; // error loading plugin
419 126086 : else if (mountRet == 0)
420 20970 : continue; // no plugin configured here
421 : else
422 : {
423 105116 : kdb->globalPlugins[i][MAXONCE] = plugin;
424 : // set handle to global keyset
425 105116 : plugin->global = kdb->global;
426 : }
427 :
428 : // load plugins in explicit placements
429 105116 : const char * placementName = keyName (cur);
430 105116 : Key * placementKey = ksLookupByName (global, placementName, 0);
431 105116 : KeySet * subPositions = ksCut (global, placementKey);
432 : Key * curSubPosition;
433 315348 : while ((curSubPosition = ksNext (subPositions)) != NULL)
434 : {
435 105116 : if (keyRel (placementKey, curSubPosition) != 1) continue;
436 0 : const char * subPlacement = keyBaseName (curSubPosition);
437 :
438 0 : for (GlobalpluginSubPositions j = 0; j < NR_GLOBAL_SUBPOSITIONS; ++j)
439 : {
440 0 : if (j == MAXONCE) continue;
441 :
442 0 : if (!elektraStrCaseCmp (subPlacement, GlobalpluginSubPositionsStr[j]))
443 : {
444 0 : Plugin * subPlugin = 0;
445 0 : int subRet =
446 : elektraMountGlobalsLoadPlugin (&subPlugin, referencePlugins, curSubPosition,
447 : subPositions, system, modules, errorKey);
448 0 : if (subRet == -1)
449 : retval = -1; // error loading plugin
450 0 : else if (subRet == 0)
451 0 : continue; // no plugin configured here
452 : else
453 : {
454 0 : kdb->globalPlugins[i][j] = subPlugin;
455 : // set handle to global keyset
456 0 : subPlugin->global = kdb->global;
457 : }
458 : }
459 : }
460 : }
461 105116 : ksDel (subPositions);
462 : }
463 : }
464 126086 : elektraFree (placement);
465 : }
466 10523 : ksDel (global);
467 10523 : ksDel (keys);
468 10523 : ksDel (referencePlugins);
469 10523 : ksDel (system);
470 10523 : return retval;
471 : }
472 :
473 : /** Mount all module configurations.
474 : *
475 : * @param kdb the handle to work with
476 : * @param modules the current list of loaded modules
477 : * @param errorKey the key used to report warnings
478 : * @ingroup mount
479 : * @retval -1 if not rootkey was found
480 : * @retval 0 otherwise
481 : */
482 10527 : int mountModules (KDB * kdb, KeySet * modules, Key * errorKey)
483 : {
484 : Key * root;
485 : Key * cur;
486 :
487 10527 : root = ksLookupByName (modules, "system/elektra/modules", 0);
488 :
489 10527 : if (!root)
490 : {
491 0 : ELEKTRA_ADD_INSTALLATION_WARNING (errorKey, "No root key found for modules");
492 0 : return -1;
493 : }
494 :
495 10527 : KeySet * alreadyMounted = ksNew (5, KS_END);
496 10527 : ssize_t oldSize = 0;
497 :
498 68881 : while ((cur = ksNext (modules)) != 0)
499 : {
500 47827 : Backend * backend = backendOpenModules (modules, kdb->global, errorKey);
501 :
502 47827 : if (!backend)
503 : {
504 : // error already set in errorKey
505 0 : continue;
506 : }
507 :
508 47827 : ksAppendKey (alreadyMounted, backend->mountpoint);
509 47827 : if (ksGetSize (alreadyMounted) == oldSize)
510 : {
511 : // we already mounted that before
512 4816 : backendClose (backend, errorKey);
513 4816 : continue;
514 : }
515 43011 : ++oldSize;
516 43011 : mountBackend (kdb, backend, errorKey);
517 : }
518 :
519 10527 : ksDel (alreadyMounted);
520 :
521 10527 : return 0;
522 : }
523 :
524 : /** Mount the version backend
525 : *
526 : * @param kdb the handle to work with
527 : * @param errorKey the key used to report warnings
528 : * @ingroup mount
529 : * @retval 0 on success
530 : */
531 10523 : int mountVersion (KDB * kdb, Key * errorKey)
532 : {
533 10523 : Backend * backend = backendOpenVersion (kdb->global, errorKey);
534 10523 : mountBackend (kdb, backend, errorKey);
535 :
536 10523 : return 0;
537 : }
538 :
539 : /**
540 : * Mounts a backend into the trie.
541 : *
542 : * @pre user must pass correctly allocated backend
543 : * @post sets reference counter of backend
544 : *
545 : * @warning in case of init and default backends, the reference counter needs to
546 : * be modified *after* calling mountBackend.
547 : *
548 : * @param kdb the handle to work with
549 : * @param backend the backend to mount
550 : * @param errorKey the key used to report warnings
551 : * @retval -1 on failure
552 : * @retval 1 on success
553 : * @ingroup mount
554 : */
555 71248 : int mountBackend (KDB * kdb, Backend * backend, Key * errorKey ELEKTRA_UNUSED)
556 : {
557 :
558 : char * mountpoint;
559 : /* 20 is enough for any of the combinations below. */
560 71248 : mountpoint = elektraMalloc (keyGetNameSize (backend->mountpoint) + 20);
561 :
562 : /* Note that you must set the refcounter to the number of insertions
563 : into the trie */
564 :
565 71248 : if (!strcmp (keyName (backend->mountpoint), ""))
566 : {
567 : /* Default backend */
568 10553 : sprintf (mountpoint, "system/elektra/");
569 10553 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
570 10553 : splitAppend (kdb->split, backend, keyNew ("system/elektra/", KEY_VALUE, "default", KEY_END), 0);
571 10553 : backend->refcounter = 1;
572 : }
573 60695 : else if (!strcmp (keyName (backend->mountpoint), "/"))
574 : {
575 : /* Root backend */
576 28 : backend->refcounter = 0;
577 168 : for (elektraNamespace ns = KEY_NS_FIRST; ns <= KEY_NS_LAST; ++ns)
578 : {
579 140 : switch (ns)
580 : {
581 : case KEY_NS_SPEC:
582 28 : sprintf (mountpoint, "spec%s", keyName (backend->mountpoint));
583 28 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
584 28 : splitAppend (kdb->split, backend, keyNew ("spec", KEY_VALUE, "root", KEY_END), 2);
585 28 : ++backend->refcounter;
586 28 : break;
587 : case KEY_NS_DIR:
588 28 : sprintf (mountpoint, "dir%s", keyName (backend->mountpoint));
589 28 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
590 28 : splitAppend (kdb->split, backend, keyNew ("dir", KEY_VALUE, "root", KEY_END), 2);
591 28 : ++backend->refcounter;
592 28 : break;
593 : case KEY_NS_USER:
594 28 : sprintf (mountpoint, "user%s", keyName (backend->mountpoint));
595 28 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
596 28 : splitAppend (kdb->split, backend, keyNew ("user", KEY_VALUE, "root", KEY_END), 2);
597 28 : ++backend->refcounter;
598 28 : break;
599 : case KEY_NS_SYSTEM:
600 28 : sprintf (mountpoint, "system%s", keyName (backend->mountpoint));
601 28 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
602 28 : splitAppend (kdb->split, backend, keyNew ("system", KEY_VALUE, "root", KEY_END), 2);
603 28 : ++backend->refcounter;
604 28 : break;
605 : case KEY_NS_PROC:
606 : case KEY_NS_EMPTY:
607 : case KEY_NS_NONE:
608 : case KEY_NS_META:
609 : case KEY_NS_CASCADING:
610 : break;
611 : }
612 : }
613 : }
614 60667 : else if (keyName (backend->mountpoint)[0] == '/')
615 : {
616 : /* Cascading Backend */
617 2986 : backend->refcounter = 0;
618 17916 : for (elektraNamespace ns = KEY_NS_FIRST; ns <= KEY_NS_LAST; ++ns)
619 : {
620 14930 : switch (ns)
621 : {
622 : case KEY_NS_DIR:
623 2986 : sprintf (mountpoint, "dir%s/", keyName (backend->mountpoint));
624 2986 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
625 2986 : splitAppend (kdb->split, backend, keyNew (mountpoint, KEY_VALUE, keyString (backend->mountpoint), KEY_END),
626 : 2);
627 2986 : ++backend->refcounter;
628 2986 : break;
629 : case KEY_NS_USER:
630 2986 : sprintf (mountpoint, "user%s/", keyName (backend->mountpoint));
631 2986 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
632 2986 : splitAppend (kdb->split, backend, keyNew (mountpoint, KEY_VALUE, keyString (backend->mountpoint), KEY_END),
633 : 2);
634 2986 : ++backend->refcounter;
635 2986 : break;
636 : case KEY_NS_SYSTEM:
637 2986 : sprintf (mountpoint, "system%s/", keyName (backend->mountpoint));
638 2986 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
639 2986 : splitAppend (kdb->split, backend, keyNew (mountpoint, KEY_VALUE, keyString (backend->mountpoint), KEY_END),
640 : 2);
641 2986 : ++backend->refcounter;
642 2986 : break;
643 : case KEY_NS_SPEC:
644 : // excluded on purpose because mounting spec is a separate step
645 : // (see specmount)
646 : case KEY_NS_EMPTY:
647 : case KEY_NS_PROC:
648 : case KEY_NS_NONE:
649 : case KEY_NS_META:
650 : case KEY_NS_CASCADING:
651 : break;
652 : }
653 : }
654 : }
655 : else
656 : {
657 : /* Common single mounted backend */
658 57681 : sprintf (mountpoint, "%s/", keyName (backend->mountpoint));
659 57681 : kdb->trie = trieInsert (kdb->trie, mountpoint, backend);
660 57681 : splitAppend (kdb->split, backend, keyDup (backend->mountpoint), 0);
661 57681 : backend->refcounter = 1;
662 : }
663 :
664 71248 : elektraFree (mountpoint);
665 :
666 71248 : return 1;
667 : }
668 :
669 :
670 : /**
671 : * Lookup a mountpoint in a handle for a specific key.
672 : *
673 : * Will return a key representing the mountpoint or null
674 : * if there is no appropriate mountpoint e.g. its the
675 : * root mountpoint.
676 : *
677 : * @par Example:
678 : * @code
679 : Key * key = keyNew ("system/template");
680 : KDB * handle = kdbOpen();
681 : Key *mountpoint=0;
682 : mountpoint=kdbGetMountpoint(handle, key);
683 :
684 : printf("The backend I am using is %s mounted in %s\n",
685 : keyValue(mountpoint),
686 : keyName(mountpoint));
687 : kdbClose (handle);
688 : keyDel (key);
689 : * @endcode
690 : *
691 : *
692 : * @param handle is the data structure, where the mounted directories are saved.
693 : * @param where the key, that should be looked up.
694 : * @return the mountpoint associated with the key
695 : * @ingroup mount
696 : */
697 26178 : Key * mountGetMountpoint (KDB * handle, const Key * where)
698 : {
699 : Backend * backend_handle;
700 :
701 26190 : backend_handle = mountGetBackend (handle, where);
702 26190 : if (!backend_handle)
703 : {
704 : return 0;
705 : }
706 :
707 26190 : return backend_handle->mountpoint;
708 : }
709 :
710 :
711 : /**
712 : * Lookup a backend handle for a specific key.
713 : *
714 : * The required canonical name is ensured by using a key as parameter,
715 : * which will transform the key to canonical representation.
716 : *
717 : * Will return handle when no more specific KDB could be
718 : * found.
719 : *
720 : * If key is 0 or invalid the default backend will be returned.
721 : *
722 : * @param handle is the data structure, where the mounted directories are saved.
723 : * @param key the key, that should be looked up.
724 : * @return the backend handle associated with the key
725 : * @ingroup mount
726 : */
727 495744 : Backend * mountGetBackend (KDB * handle, const Key * key)
728 : {
729 495744 : if (!key || !strcmp (keyName (key), "")) return handle->defaultBackend;
730 :
731 495691 : Backend * ret = trieLookup (handle->trie, key);
732 495691 : if (!ret) return handle->defaultBackend;
733 : return ret;
734 : }
|