]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/path-lookup.c
core: move flushing of generated unit files to path-lookup.c
[thirdparty/systemd.git] / src / shared / path-lookup.c
CommitLineData
84e3543e
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
84e3543e
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
84e3543e 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
84e3543e
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
cf0fbc49 20#include <errno.h>
84e3543e 21#include <stdio.h>
cf0fbc49 22#include <stdlib.h>
67445f4e 23#include <string.h>
84e3543e 24
b5efdb8a 25#include "alloc-util.h"
a8ffe6fb 26#include "install.h"
a8fbdf54
TA
27#include "log.h"
28#include "macro.h"
cd64fd56 29#include "mkdir.h"
07630cea 30#include "path-lookup.h"
cf0fbc49 31#include "path-util.h"
e4bb56c7 32#include "stat-util.h"
cf0fbc49
TA
33#include "string-util.h"
34#include "strv.h"
35#include "util.h"
84e3543e 36
205dd21e 37static int user_config_home(char **ret) {
10e87ee7 38 const char *e;
205dd21e
LP
39 char *j;
40
41 assert(ret);
10e87ee7 42
07719a21
LP
43 e = getenv("XDG_CONFIG_HOME");
44 if (e) {
205dd21e
LP
45 j = strappend(e, "/systemd/user");
46 if (!j)
10e87ee7
LP
47 return -ENOMEM;
48
10e87ee7
LP
49 } else {
50 const char *home;
51
07719a21 52 home = getenv("HOME");
205dd21e
LP
53 if (!home)
54 return -ENXIO;
55
56 j = strappend(home, "/.config/systemd/user");
57 if (!j)
58 return -ENOMEM;
10e87ee7
LP
59 }
60
205dd21e 61 *ret = j;
10e87ee7
LP
62 return 0;
63}
64
a7527131 65static int user_runtime_dir(char **ret, const char *suffix) {
718880ba 66 const char *e;
205dd21e
LP
67 char *j;
68
69 assert(ret);
a7527131 70 assert(suffix);
718880ba
SA
71
72 e = getenv("XDG_RUNTIME_DIR");
205dd21e
LP
73 if (!e)
74 return -ENXIO;
718880ba 75
a7527131 76 j = strappend(e, suffix);
205dd21e
LP
77 if (!j)
78 return -ENOMEM;
718880ba 79
205dd21e 80 *ret = j;
718880ba
SA
81 return 0;
82}
83
205dd21e 84static int user_data_home_dir(char **ret, const char *suffix) {
e801700e 85 const char *e;
205dd21e
LP
86 char *j;
87
88 assert(ret);
a7527131 89 assert(suffix);
e801700e
ZJS
90
91 /* We don't treat /etc/xdg/systemd here as the spec
92 * suggests because we assume that that is a link to
93 * /etc/systemd/ anyway. */
94
95 e = getenv("XDG_DATA_HOME");
96 if (e)
205dd21e 97 j = strappend(e, suffix);
e801700e
ZJS
98 else {
99 const char *home;
100
101 home = getenv("HOME");
205dd21e
LP
102 if (!home)
103 return -ENXIO;
104
105
106 j = strjoin(home, "/.local/share", suffix, NULL);
e801700e 107 }
205dd21e 108 if (!j)
e801700e
ZJS
109 return -ENOMEM;
110
205dd21e 111 *ret = j;
463d0d15 112 return 1;
e801700e
ZJS
113}
114
07719a21 115static char** user_dirs(
a0f84a10
LP
116 const char *persistent_config,
117 const char *runtime_config,
07719a21
LP
118 const char *generator,
119 const char *generator_early,
39591351
LP
120 const char *generator_late,
121 const char *transient) {
07719a21 122
f437d5d2 123 const char * const config_unit_paths[] = {
f437d5d2 124 USER_CONFIG_UNIT_PATH,
4bf2bbb6
LP
125 "/etc/systemd/user",
126 NULL
f437d5d2
LP
127 };
128
129 const char * const data_unit_paths[] = {
130 "/usr/local/lib/systemd/user",
131 "/usr/local/share/systemd/user",
132 USER_DATA_UNIT_PATH,
133 "/usr/lib/systemd/user",
4bf2bbb6
LP
134 "/usr/share/systemd/user",
135 NULL
f437d5d2
LP
136 };
137
e801700e 138 const char *e;
e3e45d4f 139 _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
205dd21e 140 _cleanup_free_ char *data_home = NULL;
e801700e
ZJS
141 _cleanup_free_ char **res = NULL;
142 char **tmp;
143 int r;
84e3543e
LP
144
145 /* Implement the mechanisms defined in
146 *
147 * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
148 *
149 * We look in both the config and the data dirs because we
150 * want to encourage that distributors ship their unit files
151 * as data, and allow overriding as configuration.
152 */
153
07719a21
LP
154 e = getenv("XDG_CONFIG_DIRS");
155 if (e) {
156 config_dirs = strv_split(e, ":");
157 if (!config_dirs)
e801700e 158 return NULL;
07719a21 159 }
84e3543e 160
e801700e 161 r = user_data_home_dir(&data_home, "/systemd/user");
205dd21e 162 if (r < 0 && r != -ENXIO)
e801700e 163 return NULL;
84e3543e 164
07719a21
LP
165 e = getenv("XDG_DATA_DIRS");
166 if (e)
84e3543e
LP
167 data_dirs = strv_split(e, ":");
168 else
ef3102bf 169 data_dirs = strv_new("/usr/local/share",
ef3102bf 170 "/usr/share",
ef3102bf 171 NULL);
84e3543e 172 if (!data_dirs)
e801700e 173 return NULL;
84e3543e
LP
174
175 /* Now merge everything we found. */
39591351
LP
176 if (transient)
177 if (strv_extend(&res, transient) < 0)
178 return NULL;
179
e3e45d4f 180 if (generator_early)
e801700e
ZJS
181 if (strv_extend(&res, generator_early) < 0)
182 return NULL;
07719a21 183
aa08982d 184 if (!strv_isempty(config_dirs))
e801700e
ZJS
185 if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
186 return NULL;
718880ba 187
a0f84a10
LP
188 if (strv_extend(&res, persistent_config) < 0)
189 return NULL;
190
e287086b 191 if (strv_extend_strv(&res, (char**) config_unit_paths, false) < 0)
e801700e 192 return NULL;
718880ba 193
a0f84a10 194 if (strv_extend(&res, runtime_config) < 0)
e801700e 195 return NULL;
84e3543e 196
e3e45d4f 197 if (generator)
e801700e
ZJS
198 if (strv_extend(&res, generator) < 0)
199 return NULL;
07719a21 200
e3e45d4f 201 if (data_home)
e801700e
ZJS
202 if (strv_extend(&res, data_home) < 0)
203 return NULL;
84e3543e 204
e3e45d4f 205 if (!strv_isempty(data_dirs))
e801700e
ZJS
206 if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0)
207 return NULL;
84e3543e 208
e287086b 209 if (strv_extend_strv(&res, (char**) data_unit_paths, false) < 0)
e801700e 210 return NULL;
84e3543e 211
e3e45d4f 212 if (generator_late)
e801700e
ZJS
213 if (strv_extend(&res, generator_late) < 0)
214 return NULL;
07719a21 215
0f474365 216 if (path_strv_make_absolute_cwd(res) < 0)
e801700e 217 return NULL;
84e3543e 218
e801700e
ZJS
219 tmp = res;
220 res = NULL;
221 return tmp;
222}
84e3543e 223
463d0d15
LP
224char **generator_paths(UnitFileScope scope) {
225
226 switch (scope) {
227
228 case UNIT_FILE_SYSTEM:
33e1e5a7
ZJS
229 return strv_new("/run/systemd/system-generators",
230 "/etc/systemd/system-generators",
e801700e
ZJS
231 "/usr/local/lib/systemd/system-generators",
232 SYSTEM_GENERATOR_PATH,
233 NULL);
463d0d15
LP
234
235 case UNIT_FILE_GLOBAL:
236 case UNIT_FILE_USER:
237 return strv_new("/run/systemd/user-generators",
238 "/etc/systemd/user-generators",
239 "/usr/local/lib/systemd/user-generators",
240 USER_GENERATOR_PATH,
241 NULL);
242
243 default:
244 assert_not_reached("Hmm, unexpected scope.");
245 }
84e3543e
LP
246}
247
a3c4eb07 248static int acquire_generator_dirs(
463d0d15 249 UnitFileScope scope,
a3c4eb07
LP
250 char **generator,
251 char **generator_early,
252 char **generator_late) {
253
254 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL;
255 const char *prefix;
256
257 assert(generator);
258 assert(generator_early);
259 assert(generator_late);
260
463d0d15
LP
261 switch (scope) {
262
263 case UNIT_FILE_SYSTEM:
a3c4eb07 264 prefix = "/run/systemd/";
463d0d15 265 break;
a3c4eb07 266
463d0d15
LP
267 case UNIT_FILE_USER: {
268 const char *e;
a3c4eb07
LP
269
270 e = getenv("XDG_RUNTIME_DIR");
271 if (!e)
463d0d15 272 return -ENXIO;
a3c4eb07
LP
273
274 prefix = strjoina(e, "/systemd/", NULL);
463d0d15
LP
275 break;
276 }
277
278 case UNIT_FILE_GLOBAL:
279 return -EOPNOTSUPP;
280
281 default:
282 assert_not_reached("Hmm, unexpected scope value.");
a3c4eb07
LP
283 }
284
285 x = strappend(prefix, "generator");
286 if (!x)
287 return -ENOMEM;
288
289 y = strappend(prefix, "generator.early");
290 if (!y)
291 return -ENOMEM;
292
293 z = strappend(prefix, "generator.late");
294 if (!z)
295 return -ENOMEM;
296
297 *generator = x;
298 *generator_early = y;
299 *generator_late = z;
300
301 x = y = z = NULL;
302 return 0;
303}
304
39591351 305static int acquire_transient_dir(UnitFileScope scope, char **ret) {
39591351
LP
306 assert(ret);
307
308 switch (scope) {
309
a7527131
LP
310 case UNIT_FILE_SYSTEM: {
311 char *transient;
39591351 312
a7527131
LP
313 transient = strdup("/run/systemd/transient");
314 if (!transient)
315 return -ENOMEM;
39591351 316
a7527131
LP
317 *ret = transient;
318 return 0;
39591351
LP
319 }
320
a7527131
LP
321 case UNIT_FILE_USER:
322 return user_runtime_dir(ret, "/systemd/transient");
323
39591351
LP
324 case UNIT_FILE_GLOBAL:
325 return -EOPNOTSUPP;
326
327 default:
328 assert_not_reached("Hmm, unexpected scope value.");
329 }
330
39591351
LP
331}
332
463d0d15 333static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
a0f84a10
LP
334 _cleanup_free_ char *a = NULL, *b = NULL;
335 int r;
336
337 assert(persistent);
338 assert(runtime);
339
463d0d15
LP
340 switch (scope) {
341
342 case UNIT_FILE_SYSTEM:
a0f84a10
LP
343 a = strdup(SYSTEM_CONFIG_UNIT_PATH);
344 b = strdup("/run/systemd/system");
463d0d15
LP
345 break;
346
347 case UNIT_FILE_GLOBAL:
348 a = strdup(USER_CONFIG_UNIT_PATH);
349 b = strdup("/run/systemd/user");
350 break;
a0f84a10 351
463d0d15 352 case UNIT_FILE_USER:
a0f84a10
LP
353 r = user_config_home(&a);
354 if (r < 0)
355 return r;
356
a7527131 357 r = user_runtime_dir(runtime, "/systemd/user");
a0f84a10
LP
358 if (r < 0)
359 return r;
360
361 *persistent = a;
362 a = NULL;
363
364 return 0;
a0f84a10 365
463d0d15
LP
366 default:
367 assert_not_reached("Hmm, unexpected scope value.");
a0f84a10
LP
368 }
369
370 if (!a || !b)
371 return -ENOMEM;
372
373 *persistent = a;
374 *runtime = b;
375 a = b = NULL;
376
377 return 0;
378}
379
a3c4eb07
LP
380static int patch_root_prefix(char **p, const char *root_dir) {
381 char *c;
382
383 assert(p);
384
385 if (!*p)
386 return 0;
387
a3c4eb07
LP
388 c = prefix_root(root_dir, *p);
389 if (!c)
390 return -ENOMEM;
391
392 free(*p);
393 *p = c;
394
395 return 0;
396}
397
a1453343
LP
398static int patch_root_prefix_strv(char **l, const char *root_dir) {
399 char **i;
400 int r;
401
402 if (!root_dir)
403 return 0;
404
405 STRV_FOREACH(i, l) {
406 r = patch_root_prefix(i, root_dir);
407 if (r < 0)
408 return r;
409 }
410
411 return 0;
412}
413
07719a21
LP
414int lookup_paths_init(
415 LookupPaths *p,
463d0d15 416 UnitFileScope scope,
a3c4eb07 417 const char *root_dir) {
07719a21 418
e4bb56c7
LP
419 _cleanup_free_ char
420 *root = NULL,
39591351 421 *persistent_config = NULL, *runtime_config = NULL,
e4bb56c7 422 *generator = NULL, *generator_early = NULL, *generator_late = NULL,
39591351 423 *transient = NULL;
cf7d80a5 424 bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
a3c4eb07
LP
425 char **l = NULL;
426 const char *e;
0f474365 427 int r;
84e3543e
LP
428
429 assert(p);
463d0d15
LP
430 assert(scope >= 0);
431 assert(scope < _UNIT_FILE_SCOPE_MAX);
a3c4eb07 432
e4bb56c7
LP
433 if (!isempty(root_dir) && !path_equal(root_dir, "/")) {
434 if (scope == UNIT_FILE_USER)
435 return -EINVAL;
436
437 r = is_dir(root_dir, true);
438 if (r < 0)
439 return r;
440 if (r == 0)
441 return -ENOTDIR;
442
443 root = strdup(root_dir);
444 if (!root)
445 return -ENOMEM;
446 }
447
463d0d15 448 r = acquire_config_dirs(scope, &persistent_config, &runtime_config);
205dd21e 449 if (r < 0 && r != -ENXIO)
a0f84a10
LP
450 return r;
451
463d0d15
LP
452 r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late);
453 if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
a3c4eb07 454 return r;
84e3543e 455
39591351
LP
456 r = acquire_transient_dir(scope, &transient);
457 if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
458 return r;
459
cd64fd56 460 /* First priority is whatever has been passed to us via env vars */
07719a21
LP
461 e = getenv("SYSTEMD_UNIT_PATH");
462 if (e) {
a3c4eb07
LP
463 const char *k;
464
465 k = endswith(e, ":");
466 if (k) {
467 e = strndupa(e, k - e);
cf7d80a5
ZJS
468 append = true;
469 }
470
471 /* FIXME: empty components in other places should be
472 * rejected. */
473
a3c4eb07 474 r = path_split_and_make_absolute(e, &l);
0f474365
LP
475 if (r < 0)
476 return r;
07719a21 477 } else
a3c4eb07 478 l = NULL;
84e3543e 479
a3c4eb07 480 if (!l || append) {
cf7d80a5
ZJS
481 /* Let's figure something out. */
482
a3c4eb07 483 _cleanup_strv_free_ char **add = NULL;
84e3543e 484
07719a21 485 /* For the user units we include share/ in the search
cf7d80a5
ZJS
486 * path in order to comply with the XDG basedir spec.
487 * For the system stuff we avoid such nonsense. OTOH
488 * we include /lib in the search path for the system
489 * stuff but avoid it for user stuff. */
07719a21 490
463d0d15
LP
491 switch (scope) {
492
493 case UNIT_FILE_SYSTEM:
494 add = strv_new(
495 /* If you modify this you also want to modify
496 * systemdsystemunitpath= in systemd.pc.in! */
39591351 497 STRV_IFNOTNULL(transient),
463d0d15
LP
498 STRV_IFNOTNULL(generator_early),
499 persistent_config,
5f0a41da 500 SYSTEM_CONFIG_UNIT_PATH,
463d0d15
LP
501 "/etc/systemd/system",
502 runtime_config,
503 "/run/systemd/system",
504 STRV_IFNOTNULL(generator),
505 "/usr/local/lib/systemd/system",
506 SYSTEM_DATA_UNIT_PATH,
507 "/usr/lib/systemd/system",
508#ifdef HAVE_SPLIT_USR
509 "/lib/systemd/system",
510#endif
511 STRV_IFNOTNULL(generator_late),
512 NULL);
513 break;
514
515 case UNIT_FILE_GLOBAL:
516 add = strv_new(
07719a21 517 /* If you modify this you also want to modify
cf7d80a5
ZJS
518 * systemduserunitpath= in systemd.pc.in, and
519 * the arrays in user_dirs() above! */
39591351 520 STRV_IFNOTNULL(transient),
463d0d15 521 STRV_IFNOTNULL(generator_early),
a0f84a10 522 persistent_config,
5f0a41da 523 USER_CONFIG_UNIT_PATH,
cf7d80a5 524 "/etc/systemd/user",
a0f84a10 525 runtime_config,
cf7d80a5 526 "/run/systemd/user",
463d0d15 527 STRV_IFNOTNULL(generator),
cf7d80a5
ZJS
528 "/usr/local/lib/systemd/user",
529 "/usr/local/share/systemd/user",
530 USER_DATA_UNIT_PATH,
531 "/usr/lib/systemd/user",
532 "/usr/share/systemd/user",
463d0d15 533 STRV_IFNOTNULL(generator_late),
07719a21 534 NULL);
463d0d15
LP
535 break;
536
537 case UNIT_FILE_USER:
538 add = user_dirs(persistent_config, runtime_config,
39591351
LP
539 generator, generator_early, generator_late,
540 transient);
463d0d15
LP
541 break;
542
543 default:
544 assert_not_reached("Hmm, unexpected scope?");
545 }
07719a21 546
a3c4eb07 547 if (!add)
cf7d80a5
ZJS
548 return -ENOMEM;
549
a3c4eb07
LP
550 if (l) {
551 r = strv_extend_strv(&l, add, false);
552 if (r < 0)
553 return r;
554 } else {
555 l = add;
556 add = NULL;
557 }
84e3543e
LP
558 }
559
e4bb56c7 560 r = patch_root_prefix(&persistent_config, root);
a0f84a10
LP
561 if (r < 0)
562 return r;
e4bb56c7 563 r = patch_root_prefix(&runtime_config, root);
a0f84a10
LP
564 if (r < 0)
565 return r;
566
e4bb56c7 567 r = patch_root_prefix(&generator, root);
a3c4eb07
LP
568 if (r < 0)
569 return r;
e4bb56c7 570 r = patch_root_prefix(&generator_early, root);
a3c4eb07
LP
571 if (r < 0)
572 return r;
e4bb56c7 573 r = patch_root_prefix(&generator_late, root);
a3c4eb07
LP
574 if (r < 0)
575 return r;
576
39591351
LP
577 r = patch_root_prefix(&transient, root);
578 if (r < 0)
579 return r;
580
a1453343
LP
581 r = patch_root_prefix_strv(l, root);
582 if (r < 0)
07719a21 583 return -ENOMEM;
07459bb6 584
a1453343 585 p->search_path = strv_uniq(l);
a3c4eb07
LP
586 l = NULL;
587
a0f84a10
LP
588 p->persistent_config = persistent_config;
589 p->runtime_config = runtime_config;
590 persistent_config = runtime_config = NULL;
591
a3c4eb07
LP
592 p->generator = generator;
593 p->generator_early = generator_early;
594 p->generator_late = generator_late;
595 generator = generator_early = generator_late = NULL;
84e3543e 596
39591351
LP
597 p->transient = transient;
598 transient = NULL;
599
e4bb56c7
LP
600 p->root_dir = root;
601 root = NULL;
602
84e3543e
LP
603 return 0;
604}
605
606void lookup_paths_free(LookupPaths *p) {
a3c4eb07
LP
607 if (!p)
608 return;
84e3543e 609
a3c4eb07 610 p->search_path = strv_free(p->search_path);
a0f84a10
LP
611
612 p->persistent_config = mfree(p->persistent_config);
613 p->runtime_config = mfree(p->runtime_config);
614
a3c4eb07
LP
615 p->generator = mfree(p->generator);
616 p->generator_early = mfree(p->generator_early);
617 p->generator_late = mfree(p->generator_late);
e4bb56c7 618
39591351
LP
619 p->transient = mfree(p->transient);
620
e4bb56c7 621 p->root_dir = mfree(p->root_dir);
84e3543e 622}
cd64fd56 623
a1453343
LP
624int lookup_paths_reduce(LookupPaths *p) {
625 _cleanup_free_ struct stat *stats = NULL;
626 size_t n_stats = 0, allocated = 0;
627 unsigned c = 0;
628 int r;
629
630 assert(p);
631
632 /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are
633 * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set,
634 * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into
635 * account when following symlinks. When we have no root path set this restriction does not apply however. */
636
637 if (!p->search_path)
638 return 0;
639
640 while (p->search_path[c]) {
641 struct stat st;
642 unsigned k;
643
644 if (p->root_dir)
645 r = lstat(p->search_path[c], &st);
646 else
647 r = stat(p->search_path[c], &st);
648 if (r < 0) {
649 if (errno == ENOENT)
650 goto remove_item;
651
652 /* If something we don't grok happened, let's better leave it in. */
653 log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]);
654 c++;
655 continue;
656 }
657
658 for (k = 0; k < n_stats; k++) {
659 if (stats[k].st_dev == st.st_dev &&
660 stats[k].st_ino == st.st_ino)
661 break;
662 }
663
664 if (k < n_stats) /* Is there already an entry with the same device/inode? */
665 goto remove_item;
666
667 if (!GREEDY_REALLOC(stats, allocated, n_stats+1))
668 return -ENOMEM;
669
670 stats[n_stats++] = st;
671 c++;
672 continue;
673
674 remove_item:
675 free(p->search_path[c]);
676 memmove(p->search_path + c,
677 p->search_path + c + 1,
678 (strv_length(p->search_path + c + 1) + 1) * sizeof(char*));
679 }
680
681 if (strv_isempty(p->search_path)) {
682 log_debug("Ignoring unit files.");
683 p->search_path = strv_free(p->search_path);
684 } else {
685 _cleanup_free_ char *t;
686
687 t = strv_join(p->search_path, "\n\t");
688 if (!t)
689 return -ENOMEM;
690
691 log_debug("Looking for unit files in (higher priority first):\n\t%s", t);
692 }
693
694 return 0;
695}
696
cd64fd56
LP
697int lookup_paths_mkdir_generator(LookupPaths *p) {
698 int r, q;
699
700 assert(p);
701
702 r = mkdir_p_label(p->generator, 0755);
703
704 q = mkdir_p_label(p->generator_early, 0755);
705 if (q < 0 && r >= 0)
706 r = q;
707
708 q = mkdir_p_label(p->generator_late, 0755);
709 if (q < 0 && r >= 0)
710 r = q;
711
712 return r;
713}
714
715void lookup_paths_trim_generator(LookupPaths *p) {
716 assert(p);
717
718 /* Trim empty dirs */
719
720 if (p->generator)
721 (void) rmdir(p->generator);
722
723 if (p->generator_early)
724 (void) rmdir(p->generator_early);
725
726 if (p->generator_late)
727 (void) rmdir(p->generator_late);
728}
07a78643
LP
729
730void lookup_paths_flush_generator(LookupPaths *p) {
731 assert(p);
732
733 if (p->generator)
734 (void) rm_rf(p->generator, REMOVE_ROOT);
735 if (p->generator_early)
736 (void) rm_rf(p->generator_early, REMOVE_ROOT);
737 if (p->generator_late)
738 (void) rm_rf(p->generator_late, REMOVE_ROOT);
739}