Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include "resolver.h"
10 :
11 : #include <errno.h>
12 : #include <kdbhelper.h>
13 : #include <kdbtypes.h>
14 : #include <libgen.h>
15 : #include <pwd.h>
16 : #include <stdbool.h>
17 : #include <stdio.h>
18 : #include <stdlib.h>
19 : #include <string.h>
20 : #include <sys/time.h>
21 : #include <sys/types.h>
22 : #include <unistd.h>
23 :
24 :
25 : #define POSTFIX_SIZE 50
26 :
27 :
28 : /**
29 : * Check if supplied filename is ok.
30 : *
31 : * This symbol is exported and used during mounting.
32 : *
33 : * @retval 1 on success (Relative path)
34 : * @retval 0 on success (Absolute path)
35 : * @retval -1 on a non-valid file
36 : */
37 726 : int ELEKTRA_PLUGIN_FUNCTION (checkFile) (const char * filename)
38 : {
39 726 : if (!filename) return -1;
40 726 : if (filename[0] == '0') return -1;
41 :
42 726 : size_t size = strlen (filename);
43 726 : char * buffer = elektraMalloc (size + sizeof ("system/"));
44 726 : strcpy (buffer, "system/");
45 726 : strcat (buffer, filename);
46 :
47 : /* Because of the outbreak bugs these tests are not enough */
48 726 : Key * check = keyNew (buffer, KEY_END);
49 726 : if (!strcmp (keyName (check), "")) goto error;
50 726 : if (!strcmp (keyName (check), "system")) goto error;
51 716 : keyDel (check);
52 716 : elektraFree (buffer);
53 :
54 : /* Be strict, don't allow any .., even if it would be ok sometimes */
55 716 : if (strstr (filename, "..") != 0) return -1;
56 :
57 704 : if (filename[0] == '/') return 0;
58 :
59 582 : return 1;
60 :
61 : error:
62 10 : keyDel (check);
63 10 : elektraFree (buffer);
64 10 : return -1;
65 : }
66 :
67 159117 : static void elektraGenTempFilename (ElektraResolved * handle, ElektraResolveTempfile tmpDir)
68 : {
69 159117 : char * tmpFile = NULL;
70 159117 : size_t len = 0;
71 159117 : size_t tmpFilenameSize = 0;
72 159117 : if (tmpDir == ELEKTRA_RESOLVER_TEMPFILE_SAMEDIR)
73 : {
74 159117 : tmpFilenameSize = strlen (handle->fullPath) + POSTFIX_SIZE;
75 159117 : tmpFile = elektraCalloc (tmpFilenameSize);
76 159117 : len = sprintf (tmpFile, "%s", handle->fullPath);
77 : }
78 0 : else if (tmpDir == ELEKTRA_RESOLVER_TEMPFILE_TMPDIR)
79 : {
80 0 : tmpFilenameSize = sizeof ("/tmp/") + strlen (handle->fullPath) + POSTFIX_SIZE;
81 0 : tmpFile = elektraCalloc (tmpFilenameSize);
82 0 : len = sprintf (tmpFile, "/tmp/%s", handle->fullPath);
83 : }
84 :
85 : struct timeval tv;
86 159117 : memset (&tv, 0, sizeof (struct timeval));
87 159117 : gettimeofday (&tv, 0);
88 159117 : snprintf (tmpFile + len, POSTFIX_SIZE - 1, ".%d:%ld." ELEKTRA_TIME_USEC_F ".tmp", getpid (), tv.tv_sec, tv.tv_usec);
89 159117 : handle->tmpFile = tmpFile;
90 159117 : }
91 :
92 159133 : static void elektraResolveFinishByFilename (ElektraResolved * handle, ElektraResolveTempfile tmpDir)
93 : {
94 159133 : size_t filenameSize = strlen (handle->fullPath);
95 159133 : char * dir = elektraMalloc (filenameSize);
96 159133 : char * dup = elektraStrDup (handle->fullPath);
97 159133 : strcpy (dir, dirname (dup));
98 159133 : elektraFree (dup);
99 159133 : handle->dirname = dir;
100 :
101 159133 : switch (tmpDir)
102 : {
103 : case ELEKTRA_RESOLVER_TEMPFILE_NONE:
104 : return;
105 : case ELEKTRA_RESOLVER_TEMPFILE_SAMEDIR:
106 159117 : elektraGenTempFilename (handle, tmpDir);
107 159117 : return;
108 : case ELEKTRA_RESOLVER_TEMPFILE_TMPDIR:
109 0 : elektraGenTempFilename (handle, tmpDir);
110 0 : return;
111 : }
112 : }
113 :
114 39809 : static void elektraResolveUsingHome (ElektraResolved * handle, const char * home, short addPostfix)
115 : {
116 39809 : Key * canonify = keyNew ("user", KEY_END);
117 39809 : keyAddName (canonify, home);
118 :
119 39809 : size_t dirnameSize = keyGetNameSize (canonify) + sizeof ("/" KDB_DB_USER);
120 39809 : char * dir = elektraMalloc (dirnameSize);
121 :
122 39809 : strcpy (dir, keyName (canonify) + 4); // cut user, leave slash
123 39809 : if (addPostfix && handle->relPath[0] != '/')
124 : {
125 39498 : strcat (dir, "/" KDB_DB_USER);
126 : }
127 39809 : handle->dirname = dir;
128 39809 : keyDel (canonify);
129 39809 : }
130 :
131 1028 : static char * elektraResolvePasswd (Key * warningsKey)
132 : {
133 1028 : ssize_t bufSize = sysconf (_SC_GETPW_R_SIZE_MAX);
134 1028 : if (bufSize == -1) bufSize = 16384; // man 3 getpwuid
135 :
136 1028 : char * buf = elektraMalloc (bufSize);
137 1028 : if (!buf) return NULL;
138 : struct passwd pwd;
139 : struct passwd * result;
140 :
141 1028 : int s = getpwuid_r (getuid (), &pwd, buf, bufSize, &result);
142 1028 : if (result == NULL)
143 : {
144 0 : elektraFree (buf);
145 0 : if (s != 0)
146 : {
147 0 : ELEKTRA_ADD_INSTALLATION_WARNINGF (warningsKey, "Could not retrieve from passwd using getpwuid_r. Reason: %s",
148 : strerror (s));
149 : }
150 : return NULL;
151 : }
152 1028 : char * resolved = elektraStrDup (pwd.pw_dir);
153 1028 : elektraFree (buf);
154 1028 : return resolved;
155 : }
156 :
157 1028 : static int elektraResolveUserPasswd (ElektraResolved * handle, Key * warningsKey)
158 : {
159 1028 : char * dir = elektraResolvePasswd (warningsKey);
160 1028 : if (!dir) return 0;
161 1028 : elektraResolveUsingHome (handle, dir, 1);
162 1028 : elektraFree (dir);
163 1028 : return 1;
164 : }
165 :
166 0 : static int elektraResolveSystemPasswd (ElektraResolved * handle, Key * warningsKey)
167 : {
168 0 : char * dir = elektraResolvePasswd (warningsKey);
169 0 : if (!dir) return -1;
170 0 : size_t filenameSize = elektraStrLen (dir) + elektraStrLen (handle->relPath) - 1;
171 0 : char * resolved = elektraMalloc (filenameSize);
172 0 : snprintf (resolved, filenameSize, "%s/%s", dir, handle->relPath + 2);
173 0 : elektraFree (dir);
174 0 : handle->fullPath = resolved;
175 : return 0;
176 : }
177 :
178 23 : static int elektraResolveUserXDGHome (ElektraResolved * handle, Key * warningsKey)
179 : {
180 23 : const char * home = getenv ("XDG_CONFIG_HOME");
181 :
182 23 : if (!home || !strcmp (home, ""))
183 : {
184 : return 0;
185 : }
186 :
187 23 : if (home[0] != '/')
188 : {
189 0 : ELEKTRA_ADD_VALIDATION_SYNTACTIC_WARNINGF (warningsKey,
190 : "XDG_CONFIG_HOME contains a path that is "
191 : "not absolute (violates XDG specification) and thus "
192 : "it was skipped: %s",
193 : home);
194 0 : return 0;
195 : }
196 23 : elektraResolveUsingHome (handle, home, 0);
197 23 : return 1;
198 : }
199 :
200 39784 : static int elektraResolveEnvHome (ElektraResolved * handle, Key * warningsKey)
201 : {
202 39784 : const char * home = getenv ("HOME");
203 :
204 39784 : if (!home || !strcmp (home, ""))
205 : {
206 : return 0;
207 : }
208 :
209 38758 : if (home[0] != '/')
210 : {
211 0 : ELEKTRA_ADD_VALIDATION_SYNTACTIC_WARNINGF (warningsKey,
212 : "HOME contains a path that is "
213 : "not absolute and thus "
214 : "it was skipped: %s",
215 : home);
216 0 : return 0;
217 : }
218 38758 : elektraResolveUsingHome (handle, home, 1);
219 38758 : return 1;
220 : }
221 :
222 190 : static int elektraResolveEnvUser (ElektraResolved * handle)
223 : {
224 190 : const char * user = getenv ("USER");
225 :
226 190 : if (!user || !strcmp (user, ""))
227 : {
228 : return 0;
229 : }
230 :
231 17 : Key * canonify = keyNew ("user", KEY_END);
232 17 : keyAddName (canonify, user);
233 17 : size_t homeSize = sizeof (KDB_DB_HOME "/") + keyGetNameSize (canonify) + sizeof ("/" KDB_DB_USER);
234 :
235 17 : char * homeBuf = elektraMalloc (homeSize);
236 17 : strcpy (homeBuf, KDB_DB_HOME "/");
237 17 : strcat (homeBuf, keyName (canonify) + 5); // cut user/
238 17 : if (handle->relPath[0] != '/')
239 : {
240 17 : strcat (homeBuf, "/" KDB_DB_USER);
241 : }
242 17 : keyDel (canonify);
243 17 : handle->dirname = homeBuf;
244 : return 1;
245 : }
246 :
247 641 : static int elektraResolveUserBuildin (ElektraResolved * handle)
248 : {
249 641 : size_t homeSize = sizeof (KDB_DB_HOME "/") + sizeof ("/" KDB_DB_USER);
250 :
251 641 : char * homeBuf = elektraMalloc (homeSize);
252 641 : snprintf (homeBuf, homeSize, "%s", KDB_DB_HOME);
253 641 : if (handle->relPath[0] != '/')
254 : {
255 633 : strcat (homeBuf, "/" KDB_DB_USER);
256 : }
257 641 : handle->dirname = homeBuf;
258 641 : return 1;
259 : }
260 :
261 41666 : static int elektraResolveUser (char variant, ElektraResolved * handle, Key * warningsKey)
262 : {
263 41666 : switch (variant)
264 : {
265 : case 'p':
266 1028 : return elektraResolveUserPasswd (handle, warningsKey);
267 : case 'x':
268 23 : return elektraResolveUserXDGHome (handle, warningsKey);
269 : case 'h':
270 39784 : return elektraResolveEnvHome (handle, warningsKey);
271 : case 'u':
272 190 : return elektraResolveEnvUser (handle);
273 : case 'b':
274 641 : return elektraResolveUserBuildin (handle);
275 : }
276 : return -1;
277 : }
278 :
279 40467 : static void elektraResolveFinishByDirname (ElektraResolved * handle, ElektraResolveTempfile tmpDir)
280 : {
281 40467 : size_t filenameSize = elektraStrLen (handle->relPath) + elektraStrLen (handle->dirname);
282 40467 : char * filename = elektraMalloc (filenameSize);
283 40467 : strcpy (filename, handle->dirname);
284 40467 : if (handle->relPath[0] != '/')
285 : {
286 40171 : strcat (filename, "/");
287 : }
288 40467 : strcat (filename, handle->relPath);
289 40467 : elektraFree (handle->dirname);
290 40467 : handle->fullPath = filename;
291 40467 : elektraResolveFinishByFilename (handle, tmpDir);
292 40467 : }
293 :
294 40467 : static int elektraResolveMapperUser (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
295 : {
296 40467 : int finished = 0;
297 : size_t i;
298 82133 : for (i = 0; !finished && i < sizeof (ELEKTRA_VARIANT_USER); ++i)
299 : {
300 41666 : finished = elektraResolveUser (ELEKTRA_VARIANT_USER[i], handle, warningsKey);
301 : }
302 40467 : if (finished == -1)
303 : {
304 0 : ELEKTRA_ADD_PLUGIN_MISBEHAVIOR_WARNINGF (warningsKey, "User resolver failed at step %zu, the configuration is: %s", i,
305 : ELEKTRA_VARIANT_USER);
306 0 : return -1;
307 : }
308 :
309 40467 : if (!(handle->dirname))
310 : {
311 0 : ELEKTRA_ADD_INSTALLATION_WARNINGF (warningsKey, "No resolver set the user dirname, the configuration is: %s",
312 : ELEKTRA_VARIANT_USER);
313 0 : return -1;
314 : }
315 :
316 40467 : elektraResolveFinishByDirname (handle, tmpDir);
317 :
318 40467 : return finished;
319 : }
320 :
321 38519 : static int elektraResolveSystemBuildin (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
322 : {
323 38519 : size_t filenameSize = sizeof (KDB_DB_SYSTEM) + elektraStrLen (handle->relPath) + sizeof ("/");
324 38519 : char * resolved = NULL;
325 : if (KDB_DB_SYSTEM[0] == '~')
326 : {
327 : char * resolvedPath = elektraMalloc (filenameSize);
328 : strcpy (resolvedPath, KDB_DB_SYSTEM);
329 : strcat (resolvedPath, "/");
330 : strcat (resolvedPath, handle->relPath);
331 : char * oldPath = handle->relPath;
332 : handle->relPath = resolvedPath;
333 : elektraResolveSystemPasswd (handle, warningsKey);
334 : elektraFree (resolvedPath);
335 : handle->relPath = oldPath;
336 : }
337 : else
338 : {
339 38519 : resolved = elektraMalloc (filenameSize);
340 38519 : strcpy (resolved, KDB_DB_SYSTEM);
341 38519 : strcat (resolved, "/");
342 38519 : strcat (resolved, handle->relPath);
343 38519 : handle->fullPath = resolved;
344 : }
345 38519 : elektraResolveFinishByFilename (handle, tmpDir);
346 38519 : return 1;
347 : }
348 :
349 275 : static void elektraResolveSystemXDGHelper (char ** filename, const char * path, const char * result)
350 : {
351 275 : size_t configDirSize = elektraStrLen (result);
352 275 : size_t pathSize = elektraStrLen (path);
353 275 : size_t filenameSize = configDirSize + pathSize + sizeof ("/") + 1;
354 :
355 275 : elektraRealloc ((void **) filename, filenameSize);
356 275 : strcpy (*filename, result);
357 275 : strcat (*filename, "/");
358 275 : strcat (*filename, path);
359 275 : }
360 :
361 241 : static int elektraResolveSystemXDG (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
362 : {
363 241 : const char * configDir = getenv ("XDG_CONFIG_DIRS");
364 241 : const char * defaultDir = "/etc/xdg";
365 241 : char * filename = NULL;
366 241 : if (!configDir || !strcmp (configDir, ""))
367 : {
368 197 : elektraResolveSystemXDGHelper (&filename, handle->relPath, defaultDir);
369 197 : handle->fullPath = filename;
370 197 : elektraResolveFinishByFilename (handle, tmpDir);
371 197 : return 1;
372 : }
373 :
374 44 : char * saveptr = 0;
375 44 : char * str = elektraStrDup (configDir);
376 88 : char * result = strtok_r (str, ":", &saveptr);
377 : struct stat buf;
378 44 : int errnoSave = errno;
379 44 : int success = 0;
380 166 : while (result)
381 : {
382 78 : if (result[0] != '/')
383 : {
384 0 : ELEKTRA_ADD_VALIDATION_SYNTACTIC_WARNINGF (warningsKey,
385 : "XDG_CONFIG_DIRS contains a path that is "
386 : "not absolute (violates XDG specification) and thus "
387 : "it was skipped: %s",
388 : result);
389 :
390 0 : result = strtok_r (0, ":", &saveptr);
391 0 : continue;
392 : }
393 :
394 78 : success = 1; // at least once we got a valid path
395 :
396 78 : elektraResolveSystemXDGHelper (&filename, handle->relPath, result);
397 :
398 156 : if (stat (filename, &buf) == 0)
399 : {
400 : // we found a file!
401 : break;
402 : }
403 :
404 : result = strtok_r (0, ":", &saveptr);
405 : }
406 44 : elektraFree (str);
407 44 : errno = errnoSave;
408 :
409 44 : if (!success)
410 : {
411 0 : elektraResolveSystemXDGHelper (&filename, handle->relPath, defaultDir);
412 : }
413 44 : handle->fullPath = filename;
414 44 : elektraResolveFinishByFilename (handle, tmpDir);
415 44 : return 1;
416 : }
417 :
418 : /**
419 : * @retval 0 if variant did not have a result
420 : * @retval 1 on success
421 : */
422 39703 : static int elektraResolveSystem (char variant, ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
423 : {
424 : // hardcoded path wins against variants for now
425 39703 : if (handle->relPath[0] == '/')
426 : {
427 : /* Use absolute path */
428 943 : handle->fullPath = elektraStrDup (handle->relPath);
429 943 : elektraResolveFinishByFilename (handle, tmpDir);
430 943 : return 1;
431 : }
432 38760 : if (handle->relPath[0] == '~')
433 : {
434 0 : if (elektraResolveSystemPasswd (handle, warningsKey) == -1)
435 : {
436 : return -1;
437 : }
438 0 : elektraResolveFinishByFilename (handle, tmpDir);
439 0 : return 1;
440 : }
441 38760 : switch (variant)
442 : {
443 : case 'x':
444 241 : return elektraResolveSystemXDG (handle, tmpDir, warningsKey);
445 : case 'b':
446 38519 : return elektraResolveSystemBuildin (handle, tmpDir, warningsKey);
447 : // TODO: also document in doc/COMPILE.md
448 : }
449 : return -1;
450 : }
451 39703 : static int elektraResolveMapperSystem (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
452 : {
453 39703 : int finished = 0;
454 : size_t i;
455 79406 : for (i = 0; !finished && i < sizeof (ELEKTRA_VARIANT_SYSTEM); ++i)
456 : {
457 39703 : finished = elektraResolveSystem (ELEKTRA_VARIANT_SYSTEM[i], handle, tmpDir, warningsKey);
458 : }
459 39703 : if (finished == -1)
460 : {
461 0 : ELEKTRA_ADD_INSTALLATION_WARNINGF (warningsKey, "No resolver set the user dirname, the configuration is: %s",
462 : ELEKTRA_VARIANT_USER);
463 0 : return -1;
464 : }
465 :
466 39703 : if (!(handle->fullPath))
467 : {
468 0 : ELEKTRA_ADD_INSTALLATION_WARNINGF (warningsKey, "No resolver set the system dirname, the configuration is: %s",
469 : ELEKTRA_VARIANT_SYSTEM);
470 0 : return -1;
471 : }
472 :
473 : return finished;
474 : }
475 :
476 : /**
477 : * @return freshly allocated buffer with current working directory
478 : *
479 : * @param warningsKey where warnings are added
480 : */
481 38870 : static char * elektraGetCwd (Key * warningsKey)
482 : {
483 38870 : int size = 4096;
484 38870 : char * cwd = elektraMalloc (size);
485 38870 : if (cwd == NULL)
486 : {
487 0 : ELEKTRA_ADD_OUT_OF_MEMORY_WARNING (warningsKey, "Could not alloc for getcwd, defaulting to /");
488 0 : return 0;
489 : }
490 :
491 : char * ret = NULL;
492 77740 : while (ret == NULL)
493 : {
494 38870 : ret = getcwd (cwd, size);
495 :
496 38870 : if (ret == NULL)
497 : {
498 0 : if (errno != ERANGE)
499 : {
500 : // give up, we cannot handle the problem
501 0 : elektraFree (cwd);
502 0 : ELEKTRA_ADD_RESOURCE_WARNINGF (warningsKey, "Method 'getcwd()' failed. Defaulting to /. Reason: %s",
503 : strerror (errno));
504 0 : return 0;
505 : }
506 :
507 : // try to double the space
508 0 : size *= 2;
509 0 : elektraRealloc ((void **) &cwd, size);
510 0 : if (cwd == NULL)
511 : {
512 0 : ELEKTRA_ADD_OUT_OF_MEMORY_WARNINGF (warningsKey,
513 : "Could not realloc for `getcwd()` size %d, defaulting to /", size);
514 0 : return 0;
515 : }
516 : }
517 : }
518 :
519 : return ret;
520 : }
521 :
522 :
523 40093 : static int elektraResolveSpec (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey ELEKTRA_UNUSED)
524 : {
525 40093 : size_t filenameSize = sizeof (KDB_DB_SPEC) + strlen (handle->relPath) + sizeof ("/") + 1;
526 40093 : if (handle->relPath[0] == '/')
527 : {
528 304 : char * filename = NULL;
529 304 : filename = elektraMalloc (filenameSize);
530 304 : strcpy (filename, handle->relPath);
531 304 : handle->fullPath = filename;
532 : }
533 39789 : else if (handle->relPath[0] == '~')
534 : {
535 0 : if (elektraResolveSystemPasswd (handle, warningsKey) == -1)
536 : {
537 : return -1;
538 : }
539 : }
540 : else if (KDB_DB_SPEC[0] == '~')
541 : {
542 : char * oldPath = handle->relPath;
543 : char * path = elektraMalloc (filenameSize);
544 : strcpy (path, KDB_DB_SPEC);
545 : strcat (path, "/");
546 : strcat (path, handle->relPath);
547 : handle->relPath = path;
548 : elektraResolveSystemPasswd (handle, warningsKey);
549 : elektraFree (path);
550 : handle->relPath = oldPath;
551 : }
552 : else
553 : {
554 39789 : char * path = elektraMalloc (filenameSize);
555 39789 : strcpy (path, KDB_DB_SPEC);
556 39789 : strcat (path, "/");
557 39789 : strcat (path, handle->relPath);
558 39789 : handle->fullPath = path;
559 : }
560 :
561 40093 : elektraResolveFinishByFilename (handle, tmpDir);
562 40093 : return 1;
563 : }
564 :
565 :
566 38870 : static int elektraResolveDir (ElektraResolved * handle, ElektraResolveTempfile tmpDir, Key * warningsKey)
567 : {
568 38870 : char * cwd = elektraGetCwd (warningsKey);
569 38870 : if (!cwd)
570 : {
571 0 : cwd = elektraStrDup ("/");
572 : }
573 38870 : char * dn = elektraStrDup (cwd);
574 38870 : char * dnOrig = dn;
575 :
576 : char * filename;
577 :
578 : while (true)
579 214334 : {
580 : // now put together the filename
581 253204 : filename = handle->relPath[0] == '/' ? elektraFormat ("%s%s", dn, handle->relPath) :
582 : elektraFormat ("%s/" KDB_DB_DIR "/%s", dn, handle->relPath);
583 :
584 : struct stat buf;
585 253204 : if (stat (filename, &buf) == 0)
586 : {
587 : // we found a file!
588 : break;
589 : }
590 :
591 252914 : if (!strcmp (dn, "/"))
592 : {
593 : // we reached the end, filename not useful anymore
594 : break;
595 : }
596 :
597 214334 : elektraFree (filename);
598 214334 : dn = dirname (dn);
599 : }
600 :
601 38870 : if (!strcmp (dn, "/"))
602 : {
603 : // nothing found, so we use most specific
604 38820 : elektraFree (filename);
605 38820 : filename = handle->relPath[0] == '/' ? elektraFormat ("%s%s", cwd, handle->relPath) :
606 : elektraFormat ("%s/" KDB_DB_DIR "/%s", cwd, handle->relPath);
607 : }
608 :
609 38870 : elektraFree (cwd);
610 38870 : elektraFree (dnOrig);
611 38870 : handle->fullPath = filename;
612 38870 : elektraResolveFinishByFilename (handle, tmpDir);
613 38870 : return 1;
614 : }
615 :
616 159133 : void ELEKTRA_PLUGIN_FUNCTION (freeHandle) (ElektraResolved * handle)
617 : {
618 159133 : if (!handle) return;
619 159133 : if (handle->relPath != NULL) elektraFree (handle->relPath);
620 159133 : if (handle->dirname != NULL) elektraFree (handle->dirname);
621 159133 : if (handle->fullPath != NULL) elektraFree (handle->fullPath);
622 159133 : if (handle->tmpFile != NULL) elektraFree (handle->tmpFile);
623 159133 : elektraFree (handle);
624 159133 : handle = NULL;
625 : }
626 :
627 159133 : ElektraResolved * ELEKTRA_PLUGIN_FUNCTION (filename) (elektraNamespace namespace, const char * path, ElektraResolveTempfile tmpDir,
628 : Key * warningsKey)
629 : {
630 :
631 159133 : ElektraResolved * handle = elektraCalloc (sizeof (ElektraResolved));
632 159133 : handle->relPath = elektraStrDup (path);
633 :
634 159133 : int rc = 0;
635 :
636 159133 : switch (namespace)
637 : {
638 : case KEY_NS_SPEC:
639 40093 : rc = elektraResolveSpec (handle, tmpDir, warningsKey);
640 40093 : break;
641 : case KEY_NS_DIR:
642 38870 : rc = elektraResolveDir (handle, tmpDir, warningsKey);
643 38870 : break;
644 : case KEY_NS_USER:
645 40467 : rc = elektraResolveMapperUser (handle, tmpDir, warningsKey);
646 40467 : break;
647 : case KEY_NS_SYSTEM:
648 39703 : rc = elektraResolveMapperSystem (handle, tmpDir, warningsKey);
649 39703 : break;
650 : case KEY_NS_PROC:
651 0 : ELEKTRA_ADD_INTERFACE_WARNING (warningsKey, "Resolver was not able to resolve a filename. Tried to resolve proc");
652 0 : rc = -1;
653 0 : break;
654 : case KEY_NS_EMPTY:
655 0 : ELEKTRA_ADD_INTERFACE_WARNING (warningsKey, "Resolver was not able to resolve a filename. Tried to resolve empty");
656 0 : rc = -1;
657 0 : break;
658 : case KEY_NS_NONE:
659 0 : ELEKTRA_ADD_INTERFACE_WARNING (warningsKey, "Resolver was not able to resolve a filename. Tried to resolve none");
660 0 : rc = -1;
661 0 : break;
662 : case KEY_NS_META:
663 0 : ELEKTRA_ADD_INTERFACE_WARNING (warningsKey, "Resolver was not able to resolve a filename. Tried to resolve meta");
664 0 : rc = -1;
665 0 : break;
666 : case KEY_NS_CASCADING:
667 0 : ELEKTRA_ADD_INTERFACE_WARNING (warningsKey, "Resolver was not able to resolve a filename. Tried to resolve cascading");
668 0 : rc = -1;
669 0 : break;
670 : }
671 159133 : if (rc == -1)
672 : {
673 0 : ELEKTRA_PLUGIN_FUNCTION (freeHandle) (handle);
674 0 : return NULL;
675 : }
676 : return handle;
677 : }
|