unit.c 91 KB
Newer Older
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Lennart Poettering's avatar
Lennart Poettering committed
2

3
4
5
6
7
8
/***
  This file is part of systemd.

  Copyright 2010 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
9
10
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
11
12
13
14
15
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
  Lesser General Public License for more details.
17

18
  You should have received a copy of the GNU Lesser General Public License
19
20
21
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

Lennart Poettering's avatar
Lennart Poettering committed
22
23
24
25
26
27
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/poll.h>
28
29
#include <stdlib.h>
#include <unistd.h>
30
#include <sys/stat.h>
Lennart Poettering's avatar
Lennart Poettering committed
31

32
33
#include "systemd/sd-id128.h"
#include "systemd/sd-messages.h"
Lennart Poettering's avatar
Lennart Poettering committed
34
35
36
37
#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
Kay Sievers's avatar
Kay Sievers committed
38
#include "path-util.h"
Lennart Poettering's avatar
Lennart Poettering committed
39
40
41
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
42
#include "unit-name.h"
43
#include "dbus-unit.h"
44
#include "special.h"
45
#include "cgroup-util.h"
46
#include "missing.h"
47
#include "cgroup-attr.h"
48
#include "mkdir.h"
49
50
#include "label.h"
#include "fileio-label.h"
51
#include "bus-errors.h"
Lennart Poettering's avatar
Lennart Poettering committed
52
53
54
55
56
57
58
59
60

const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
        [UNIT_SERVICE] = &service_vtable,
        [UNIT_TIMER] = &timer_vtable,
        [UNIT_SOCKET] = &socket_vtable,
        [UNIT_TARGET] = &target_vtable,
        [UNIT_DEVICE] = &device_vtable,
        [UNIT_MOUNT] = &mount_vtable,
        [UNIT_AUTOMOUNT] = &automount_vtable,
Maarten Lankhorst's avatar
Maarten Lankhorst committed
61
        [UNIT_SNAPSHOT] = &snapshot_vtable,
62
63
        [UNIT_SWAP] = &swap_vtable,
        [UNIT_PATH] = &path_vtable
Lennart Poettering's avatar
Lennart Poettering committed
64
65
};

66
Unit *unit_new(Manager *m, size_t size) {
Lennart Poettering's avatar
Lennart Poettering committed
67
68
69
        Unit *u;

        assert(m);
Michal Schmidt's avatar
Michal Schmidt committed
70
        assert(size >= sizeof(Unit));
Lennart Poettering's avatar
Lennart Poettering committed
71

72
73
        u = malloc0(size);
        if (!u)
Lennart Poettering's avatar
Lennart Poettering committed
74
75
                return NULL;

Michal Schmidt's avatar
Michal Schmidt committed
76
77
        u->names = set_new(string_hash_func, string_compare_func);
        if (!u->names) {
Lennart Poettering's avatar
Lennart Poettering committed
78
79
80
81
                free(u);
                return NULL;
        }

Michal Schmidt's avatar
Michal Schmidt committed
82
83
84
85
86
        u->manager = m;
        u->type = _UNIT_TYPE_INVALID;
        u->deserialized_job = _JOB_TYPE_INVALID;
        u->default_dependencies = true;
        u->unit_file_state = _UNIT_FILE_STATE_INVALID;
Lennart Poettering's avatar
Lennart Poettering committed
87
88
89
90

        return u;
}

91
92
93
94
bool unit_has_name(Unit *u, const char *name) {
        assert(u);
        assert(name);

Michal Schmidt's avatar
Michal Schmidt committed
95
        return !!set_get(u->names, (char*) name);
96
97
}

Lennart Poettering's avatar
Lennart Poettering committed
98
99
int unit_add_name(Unit *u, const char *text) {
        UnitType t;
100
        char *s, *i = NULL;
Lennart Poettering's avatar
Lennart Poettering committed
101
102
103
104
105
        int r;

        assert(u);
        assert(text);

106
        if (unit_name_is_template(text)) {
Michal Schmidt's avatar
Michal Schmidt committed
107
                if (!u->instance)
108
                        return -EINVAL;
Lennart Poettering's avatar
Lennart Poettering committed
109

Michal Schmidt's avatar
Michal Schmidt committed
110
                s = unit_name_replace_instance(text, u->instance);
111
112
        } else
                s = strdup(text);
Lennart Poettering's avatar
Lennart Poettering committed
113

114
115
        if (!s)
                return -ENOMEM;
Lennart Poettering's avatar
Lennart Poettering committed
116

117
        if (!unit_name_is_valid(s, false)) {
118
119
120
                r = -EINVAL;
                goto fail;
        }
121

122
        assert_se((t = unit_name_to_type(s)) >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
123

Michal Schmidt's avatar
Michal Schmidt committed
124
        if (u->type != _UNIT_TYPE_INVALID && t != u->type) {
125
126
127
                r = -EINVAL;
                goto fail;
        }
Lennart Poettering's avatar
Lennart Poettering committed
128

129
130
        if ((r = unit_name_to_instance(s, &i)) < 0)
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
131

132
133
        if (i && unit_vtable[t]->no_instances) {
                r = -EINVAL;
134
                goto fail;
135
        }
136

137
138
        /* Ensure that this unit is either instanced or not instanced,
         * but not both. */
Michal Schmidt's avatar
Michal Schmidt committed
139
        if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
140
141
142
143
144
                r = -EINVAL;
                goto fail;
        }

        if (unit_vtable[t]->no_alias &&
Michal Schmidt's avatar
Michal Schmidt committed
145
146
            !set_isempty(u->names) &&
            !set_get(u->names, s)) {
147
148
149
150
                r = -EEXIST;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
151
        if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
152
153
154
155
                r = -E2BIG;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
156
        if ((r = set_put(u->names, s)) < 0) {
157
158
159
                if (r == -EEXIST)
                        r = 0;
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
160
161
        }

Michal Schmidt's avatar
Michal Schmidt committed
162
163
        if ((r = hashmap_put(u->manager->units, s, u)) < 0) {
                set_remove(u->names, s);
164
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
165
166
        }

Michal Schmidt's avatar
Michal Schmidt committed
167
        if (u->type == _UNIT_TYPE_INVALID) {
Lennart Poettering's avatar
Lennart Poettering committed
168

Michal Schmidt's avatar
Michal Schmidt committed
169
170
171
                u->type = t;
                u->id = s;
                u->instance = i;
172

Michal Schmidt's avatar
Michal Schmidt committed
173
                LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u);
174
175
176

                if (UNIT_VTABLE(u)->init)
                        UNIT_VTABLE(u)->init(u);
177
178
        } else
                free(i);
Lennart Poettering's avatar
Lennart Poettering committed
179

180
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
181
        return 0;
182
183
184
185
186
187

fail:
        free(s);
        free(i);

        return r;
Lennart Poettering's avatar
Lennart Poettering committed
188
189
}

190
int unit_choose_id(Unit *u, const char *name) {
191
192
        char *s, *t = NULL, *i;
        int r;
193
194
195
196

        assert(u);
        assert(name);

197
198
        if (unit_name_is_template(name)) {

Michal Schmidt's avatar
Michal Schmidt committed
199
                if (!u->instance)
200
201
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
202
                if (!(t = unit_name_replace_instance(name, u->instance)))
203
204
205
206
207
                        return -ENOMEM;

                name = t;
        }

208
        /* Selects one of the names of this unit as the id */
Michal Schmidt's avatar
Michal Schmidt committed
209
        s = set_get(u->names, (char*) name);
210
        free(t);
211

212
        if (!s)
213
214
                return -ENOENT;

215
216
217
        if ((r = unit_name_to_instance(s, &i)) < 0)
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
218
        u->id = s;
219

Michal Schmidt's avatar
Michal Schmidt committed
220
221
        free(u->instance);
        u->instance = i;
222

223
        unit_add_to_dbus_queue(u);
224

225
226
227
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
228
229
230
231
232
233
234
235
int unit_set_description(Unit *u, const char *description) {
        char *s;

        assert(u);

        if (!(s = strdup(description)))
                return -ENOMEM;

Michal Schmidt's avatar
Michal Schmidt committed
236
237
        free(u->description);
        u->description = s;
238
239

        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
240
241
242
        return 0;
}

243
244
245
bool unit_check_gc(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
246
        if (u->load_state == UNIT_STUB)
247
248
                return true;

249
250
251
        if (UNIT_VTABLE(u)->no_gc)
                return true;

Michal Schmidt's avatar
Michal Schmidt committed
252
        if (u->no_gc)
253
254
                return true;

Michal Schmidt's avatar
Michal Schmidt committed
255
        if (u->job)
256
257
                return true;

258
259
260
        if (u->nop_job)
                return true;

261
262
263
        if (unit_active_state(u) != UNIT_INACTIVE)
                return true;

264
265
266
        if (u->refs)
                return true;

267
268
269
270
271
272
273
        if (UNIT_VTABLE(u)->check_gc)
                if (UNIT_VTABLE(u)->check_gc(u))
                        return true;

        return false;
}

Lennart Poettering's avatar
Lennart Poettering committed
274
275
void unit_add_to_load_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
276
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
277

Michal Schmidt's avatar
Michal Schmidt committed
278
        if (u->load_state != UNIT_STUB || u->in_load_queue)
Lennart Poettering's avatar
Lennart Poettering committed
279
280
                return;

Michal Schmidt's avatar
Michal Schmidt committed
281
282
        LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u);
        u->in_load_queue = true;
Lennart Poettering's avatar
Lennart Poettering committed
283
284
}

285
286
287
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
288
        if (u->in_cleanup_queue)
289
290
                return;

Michal Schmidt's avatar
Michal Schmidt committed
291
292
        LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
        u->in_cleanup_queue = true;
293
294
}

295
296
297
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
298
        if (u->in_gc_queue || u->in_cleanup_queue)
299
300
301
302
303
                return;

        if (unit_check_gc(u))
                return;

Michal Schmidt's avatar
Michal Schmidt committed
304
305
        LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
        u->in_gc_queue = true;
306

Michal Schmidt's avatar
Michal Schmidt committed
307
        u->manager->n_in_gc_queue ++;
308

Michal Schmidt's avatar
Michal Schmidt committed
309
310
        if (u->manager->gc_queue_timestamp <= 0)
                u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
311
312
}

313
314
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
315
        assert(u->type != _UNIT_TYPE_INVALID);
316

Michal Schmidt's avatar
Michal Schmidt committed
317
        if (u->load_state == UNIT_STUB || u->in_dbus_queue)
318
319
                return;

320
        /* Shortcut things if nobody cares */
Michal Schmidt's avatar
Michal Schmidt committed
321
322
        if (!bus_has_subscriber(u->manager)) {
                u->sent_dbus_new_signal = true;
323
324
325
                return;
        }

Michal Schmidt's avatar
Michal Schmidt committed
326
327
        LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
        u->in_dbus_queue = true;
328
329
}

Lennart Poettering's avatar
Lennart Poettering committed
330
331
332
333
334
335
336
337
338
339
340
341
342
static void bidi_set_free(Unit *u, Set *s) {
        Iterator i;
        Unit *other;

        assert(u);

        /* Frees the set and makes sure we are dropped from the
         * inverse pointers */

        SET_FOREACH(other, s, i) {
                UnitDependency d;

                for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
Michal Schmidt's avatar
Michal Schmidt committed
343
                        set_remove(other->dependencies[d], u);
344
345

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
346
347
348
349
350
351
352
353
354
355
356
357
        }

        set_free(s);
}

void unit_free(Unit *u) {
        UnitDependency d;
        Iterator i;
        char *t;

        assert(u);

358
359
        bus_unit_send_removed_signal(u);

Michal Schmidt's avatar
Michal Schmidt committed
360
        if (u->load_state != UNIT_STUB)
361
362
363
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

Michal Schmidt's avatar
Michal Schmidt committed
364
365
        SET_FOREACH(t, u->names, i)
                hashmap_remove_value(u->manager->units, t, u);
Lennart Poettering's avatar
Lennart Poettering committed
366

Michal Schmidt's avatar
Michal Schmidt committed
367
368
369
370
371
        if (u->job) {
                Job *j = u->job;
                job_uninstall(j);
                job_free(j);
        }
372

373
374
375
376
377
378
        if (u->nop_job) {
                Job *j = u->nop_job;
                job_uninstall(j);
                job_free(j);
        }

379
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
Michal Schmidt's avatar
Michal Schmidt committed
380
                bidi_set_free(u, u->dependencies[d]);
381

382
383
384
385
386
        if (u->requires_mounts_for) {
                LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
                strv_free(u->requires_mounts_for);
        }

Michal Schmidt's avatar
Michal Schmidt committed
387
388
        if (u->type != _UNIT_TYPE_INVALID)
                LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
Lennart Poettering's avatar
Lennart Poettering committed
389

Michal Schmidt's avatar
Michal Schmidt committed
390
391
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
392

Michal Schmidt's avatar
Michal Schmidt committed
393
394
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
395

Michal Schmidt's avatar
Michal Schmidt committed
396
397
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
398

Michal Schmidt's avatar
Michal Schmidt committed
399
400
401
        if (u->in_gc_queue) {
                LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
                u->manager->n_in_gc_queue--;
402
403
        }

Michal Schmidt's avatar
Michal Schmidt committed
404
405
        cgroup_bonding_free_list(u->cgroup_bondings, u->manager->n_reloading <= 0);
        cgroup_attribute_free_list(u->cgroup_attributes);
Lennart Poettering's avatar
Lennart Poettering committed
406

Michal Schmidt's avatar
Michal Schmidt committed
407
        free(u->description);
408
        strv_free(u->documentation);
Michal Schmidt's avatar
Michal Schmidt committed
409
        free(u->fragment_path);
410
        free(u->source_path);
411
        strv_free(u->dropin_paths);
Michal Schmidt's avatar
Michal Schmidt committed
412
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
413

Michal Schmidt's avatar
Michal Schmidt committed
414
        set_free_free(u->names);
Lennart Poettering's avatar
Lennart Poettering committed
415

Michal Schmidt's avatar
Michal Schmidt committed
416
        condition_free_list(u->conditions);
417

Michal Schmidt's avatar
Michal Schmidt committed
418
419
        while (u->refs)
                unit_ref_unset(u->refs);
420

Lennart Poettering's avatar
Lennart Poettering committed
421
422
423
424
425
426
        free(u);
}

UnitActiveState unit_active_state(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
427
        if (u->load_state == UNIT_MERGED)
428
429
430
431
                return unit_active_state(unit_follow_merge(u));

        /* After a reload it might happen that a unit is not correctly
         * loaded but still has a process around. That's why we won't
432
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
433
434
435
436

        return UNIT_VTABLE(u)->active_state(u);
}

437
438
439
440
441
442
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

        return UNIT_VTABLE(u)->sub_state_to_string(u);
}

443
444
445
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
446

447
448
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
449
450

        if (*s)
451
452
453
454
455
456
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
457

458
459
460
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
461

462
463
464
        assert(u);
        assert(other);

Michal Schmidt's avatar
Michal Schmidt committed
465
        complete_move(&u->names, &other->names);
466

Michal Schmidt's avatar
Michal Schmidt committed
467
468
469
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
470

Michal Schmidt's avatar
Michal Schmidt committed
471
472
        SET_FOREACH(t, u->names, i)
                assert_se(hashmap_replace(u->manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
473
474
}

475
476
477
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
478
        int r;
479
480
481
482
483

        assert(u);
        assert(other);
        assert(d < _UNIT_DEPENDENCY_MAX);

484
        /* Fix backwards pointers */
Michal Schmidt's avatar
Michal Schmidt committed
485
        SET_FOREACH(back, other->dependencies[d], i) {
486
487
488
                UnitDependency k;

                for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
Michal Schmidt's avatar
Michal Schmidt committed
489
                        if ((r = set_remove_and_put(back->dependencies[k], other, u)) < 0) {
490
491

                                if (r == -EEXIST)
Michal Schmidt's avatar
Michal Schmidt committed
492
                                        set_remove(back->dependencies[k], other);
493
494
495
496
497
                                else
                                        assert(r == -ENOENT);
                        }
        }

Michal Schmidt's avatar
Michal Schmidt committed
498
        complete_move(&u->dependencies[d], &other->dependencies[d]);
499

Michal Schmidt's avatar
Michal Schmidt committed
500
501
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
502
503
504
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
505
506
507
508
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
509
510
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
511

512
513
        other = unit_follow_merge(other);

514
515
516
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
517
        if (u->type != other->type)
518
519
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
520
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
521
522
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
523
524
        if (other->load_state != UNIT_STUB &&
            other->load_state != UNIT_ERROR)
525
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
526

Michal Schmidt's avatar
Michal Schmidt committed
527
        if (other->job)
528
529
                return -EEXIST;

530
531
532
        if (other->nop_job)
                return -EEXIST;

533
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
534
535
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
536
        /* Merge names */
537
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
538

539
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
540
541
        while (other->refs)
                unit_ref_set(other->refs, u);
542

Lennart Poettering's avatar
Lennart Poettering committed
543
544
        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
545
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
546

Michal Schmidt's avatar
Michal Schmidt committed
547
548
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
549

550
551
        /* If there is still some data attached to the other node, we
         * don't need it anymore, and can free it. */
Michal Schmidt's avatar
Michal Schmidt committed
552
        if (other->load_state != UNIT_STUB)
553
554
555
556
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
557
558
559
560
561
562
563
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
564
565
        int r;
        char *s = NULL;
566
567
568
569

        assert(u);
        assert(name);

570
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
571
                if (!u->instance)
572
573
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
574
                if (!(s = unit_name_replace_instance(name, u->instance)))
575
576
577
578
579
                        return -ENOMEM;

                name = s;
        }

Michal Schmidt's avatar
Michal Schmidt committed
580
        if (!(other = manager_get_unit(u->manager, name)))
581
582
583
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
584

585
586
        free(s);
        return r;
587
588
589
590
591
}

Unit* unit_follow_merge(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
592
593
        while (u->load_state == UNIT_MERGED)
                assert_se(u = u->merged_into);
594
595
596
597
598
599
600
601
602
603

        return u;
}

int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
        int r;

        assert(u);
        assert(c);

604
605
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
606
            c->std_output != EXEC_OUTPUT_JOURNAL &&
607
608
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
609
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
610
            c->std_error != EXEC_OUTPUT_KMSG &&
611
            c->std_error != EXEC_OUTPUT_SYSLOG &&
612
            c->std_error != EXEC_OUTPUT_JOURNAL &&
613
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
614
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
615
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
616
617
618
619
620
                return 0;

        /* If syslog or kernel logging is requested, make sure our own
         * logging daemon is run first. */

621
622
623
        if (u->manager->running_as == SYSTEMD_SYSTEM) {
                r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true);
                if (r < 0)
624
                        return r;
625
        }
626

Lennart Poettering's avatar
Lennart Poettering committed
627
628
629
630
631
632
        return 0;
}

const char *unit_description(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
633
634
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
635

Michal Schmidt's avatar
Michal Schmidt committed
636
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
637
638
639
}

void unit_dump(Unit *u, FILE *f, const char *prefix) {
640
        char *t, **j;
Lennart Poettering's avatar
Lennart Poettering committed
641
642
        UnitDependency d;
        Iterator i;
643
644
        char *p2;
        const char *prefix2;
645
646
647
648
        char
                timestamp1[FORMAT_TIMESTAMP_MAX],
                timestamp2[FORMAT_TIMESTAMP_MAX],
                timestamp3[FORMAT_TIMESTAMP_MAX],
649
650
                timestamp4[FORMAT_TIMESTAMP_MAX],
                timespan[FORMAT_TIMESPAN_MAX];
651
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
652
653

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
654
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
655
656
657

        if (!prefix)
                prefix = "";
658
659
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
660
661

        fprintf(f,
662
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
663
                "%s\tDescription: %s\n"
664
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
665
                "%s\tUnit Load State: %s\n"
666
                "%s\tUnit Active State: %s\n"
667
                "%s\tInactive Exit Timestamp: %s\n"
668
                "%s\tActive Enter Timestamp: %s\n"
669
                "%s\tActive Exit Timestamp: %s\n"
670
                "%s\tInactive Enter Timestamp: %s\n"
671
672
                "%s\tGC Check Good: %s\n"
                "%s\tNeed Daemon Reload: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
673
                prefix, u->id,
Lennart Poettering's avatar
Lennart Poettering committed
674
                prefix, unit_description(u),
Michal Schmidt's avatar
Michal Schmidt committed
675
676
                prefix, strna(u->instance),
                prefix, unit_load_state_to_string(u->load_state),
677
                prefix, unit_active_state_to_string(unit_active_state(u)),
Michal Schmidt's avatar
Michal Schmidt committed
678
679
680
681
                prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
                prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
682
683
                prefix, yes_no(unit_check_gc(u)),
                prefix, yes_no(unit_need_daemon_reload(u)));
684

Michal Schmidt's avatar
Michal Schmidt committed
685
        SET_FOREACH(t, u->names, i)
Lennart Poettering's avatar
Lennart Poettering committed
686
687
                fprintf(f, "%s\tName: %s\n", prefix, t);

688
689
690
        STRV_FOREACH(j, u->documentation)
                fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);

691
        if ((following = unit_following(u)))
Michal Schmidt's avatar
Michal Schmidt committed
692
                fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
693

Michal Schmidt's avatar
Michal Schmidt committed
694
695
        if (u->fragment_path)
                fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
696

697
698
699
        if (u->source_path)
                fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);

700
        STRV_FOREACH(j, u->dropin_paths)
701
                fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
702

Michal Schmidt's avatar
Michal Schmidt committed
703
        if (u->job_timeout > 0)
704
                fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
705

Michal Schmidt's avatar
Michal Schmidt committed
706
        condition_dump_list(u->conditions, f, prefix);
707

Michal Schmidt's avatar
Michal Schmidt committed
708
        if (dual_timestamp_is_set(&u->condition_timestamp))
709
710
711
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
712
713
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
714

Lennart Poettering's avatar
Lennart Poettering committed
715
716
717
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
718
719
                SET_FOREACH(other, u->dependencies[d], i)
                        fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
Lennart Poettering's avatar
Lennart Poettering committed
720
721
        }

722
723
724
725
726
727
728
729
730
731
        if (!strv_isempty(u->requires_mounts_for)) {
                fprintf(f,
                        "%s\tRequiresMountsFor:", prefix);

                STRV_FOREACH(j, u->requires_mounts_for)
                        fprintf(f, " %s", *j);

                fputs("\n", f);
        }

Michal Schmidt's avatar
Michal Schmidt committed
732
        if (u->load_state == UNIT_LOADED) {
733
734
735
                CGroupBonding *b;
                CGroupAttribute *a;

736
                fprintf(f,
737
                        "%s\tStopWhenUnneeded: %s\n"
738
739
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
740
                        "%s\tDefaultDependencies: %s\n"
741
                        "%s\tOnFailureIsolate: %s\n"
742
743
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
744
745
746
747
748
749
750
751
752
                        prefix, yes_no(u->stop_when_unneeded),
                        prefix, yes_no(u->refuse_manual_start),
                        prefix, yes_no(u->refuse_manual_stop),
                        prefix, yes_no(u->default_dependencies),
                        prefix, yes_no(u->on_failure_isolate),
                        prefix, yes_no(u->ignore_on_isolate),
                        prefix, yes_no(u->ignore_on_snapshot));

                LIST_FOREACH(by_unit, b, u->cgroup_bondings)
753
754
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
755

Michal Schmidt's avatar
Michal Schmidt committed
756
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
757
                        _cleanup_free_ char *v = NULL;
758

759
760
                        if (a->semantics && a->semantics->map_write)
                                a->semantics->map_write(a->semantics, a->value, &v);
761

762
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
763
764
                                prefix, a->controller, a->name, v ? v : a->value);
                }
765

766
767
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
768

Michal Schmidt's avatar
Michal Schmidt committed
769
        } else if (u->load_state == UNIT_MERGED)
770
771
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
772
773
774
                        prefix, u->merged_into->id);
        else if (u->load_state == UNIT_ERROR)
                fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
775

Lennart Poettering's avatar
Lennart Poettering committed
776

Michal Schmidt's avatar
Michal Schmidt committed
777
778
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
779

780
781
782
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

783
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
784
785
786
}

/* Common implementation for multiple backends */
787
int unit_load_fragment_and_dropin(Unit *u) {
788
789
790
791
792
        int r;

        assert(u);

        /* Load a .service file */
793
        if ((r = unit_load_fragment(u)) < 0)
794
795
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
796
        if (u->load_state == UNIT_STUB)
797
798
799
800
801
802
803
804
805
806
                return -ENOENT;

        /* Load drop-in directory data */
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
                return r;

        return 0;
}

/* Common implementation for multiple backends */
807
int unit_load_fragment_and_dropin_optional(Unit *u) {
808
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
809
810
811

        assert(u);

812
813
814
815
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

        /* Load a .service file */
816
        if ((r = unit_load_fragment(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
817
818
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
819
820
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
821

Lennart Poettering's avatar
Lennart Poettering committed
822
        /* Load drop-in directory data */
823
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
824
825
                return r;

826
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
827
828
}

829
int unit_add_default_target_dependency(Unit *u, Unit *target) {
830
831
832
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
833
        if (target->type != UNIT_TARGET)
834
835
                return 0;

Harald Hoyer's avatar
Harald Hoyer committed
836
        /* Only add the dependency if both units are loaded, so that
837
         * that loop check below is reliable */
Michal Schmidt's avatar
Michal Schmidt committed
838
839
        if (u->load_state != UNIT_LOADED ||
            target->load_state != UNIT_LOADED)
840
841
                return 0;

842
843
        /* If either side wants no automatic dependencies, then let's
         * skip this */
Michal Schmidt's avatar
Michal Schmidt committed
844
845
        if (!u->default_dependencies ||
            !target->default_dependencies)
846
847
                return 0;

848
        /* Don't create loops */
Michal Schmidt's avatar
Michal Schmidt committed
849
        if (set_get(target->dependencies[UNIT_BEFORE], u))
850
851
852
853
854
855
                return 0;

        return unit_add_dependency(target, UNIT_AFTER, u, true);
}

static int unit_add_default_dependencies(Unit *u) {
856
857
858
859
860
861
862
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

863
        Unit *target;
864
865
        Iterator i;
        int r;
866
        unsigned k;
867
868
869

        assert(u);

870
        for (k = 0; k < ELEMENTSOF(deps); k++)
Michal Schmidt's avatar
Michal Schmidt committed
871
                SET_FOREACH(target, u->dependencies[deps[k]], i)
872
873
                        if ((r = unit_add_default_target_dependency(u, target)) < 0)
                                return r;
874

875
876
877
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
878
879
880
881
882
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
883
884
885
        if (u->in_load_queue) {
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
                u->in_load_queue = false;
Lennart Poettering's avatar
Lennart Poettering committed
886
887
        }

Michal Schmidt's avatar
Michal Schmidt committed
888
        if (u->type == _UNIT_TYPE_INVALID)
889
890
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
891
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
892
893
                return 0;

894
895
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
896
                        goto fail;
897

Michal Schmidt's avatar
Michal Schmidt committed
898
        if (u->load_state == UNIT_STUB) {
899
900
901
902
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
903
904
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
905
906
907
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

908
909
910
911
912
913
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

Michal Schmidt's avatar
Michal Schmidt committed
914
915
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
916

917
918
                log_error_unit(u->id,
                               "More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.", u->id);
919
920
921
922
923

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
924
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
925
926

        unit_add_to_dbus_queue(unit_follow_merge(u));
927
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
928
929
930
931

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
932
933
        u->load_state = UNIT_ERROR;
        u->load_error = r;
934
        unit_add_to_dbus_queue(u);
935
        unit_add_to_gc_queue(u);
936

937
938
        log_debug_unit(u->id, "Failed to load configuration for %s: %s",
                       u->id, strerror(-r));
939

Lennart Poettering's avatar
Lennart Poettering committed
940
941
942
        return r;
}

943
944
945
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
946
947
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);