unit.c 84.7 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"
Lennart Poettering's avatar
Lennart Poettering committed
51
52
53
54
55
56
57
58
59

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
60
        [UNIT_SNAPSHOT] = &snapshot_vtable,
61
62
        [UNIT_SWAP] = &swap_vtable,
        [UNIT_PATH] = &path_vtable
Lennart Poettering's avatar
Lennart Poettering committed
63
64
};

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
81
82
83
84
85
        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
86
87
88
89

        return u;
}

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

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

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

        assert(u);
        assert(text);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);
        assert(name);

196
197
        if (unit_name_is_template(name)) {

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

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

                name = t;
        }

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

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

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

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

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

222
        unit_add_to_dbus_queue(u);
223

224
225
226
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
227
228
229
230
231
232
233
234
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
235
236
        free(u->description);
        u->description = s;
237
238

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

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

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

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

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

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

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

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

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

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

        return false;
}

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

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

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

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

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

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

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

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

        if (unit_check_gc(u))
                return;

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

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

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

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

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
329
330
331
332
333
334
335
336
337
338
339
340
341
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
342
                        set_remove(other->dependencies[d], u);
343
344

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

        set_free(s);
}

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

        assert(u);

357
358
        bus_unit_send_removed_signal(u);

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

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

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

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

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

381
382
383
384
385
        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
386
387
        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
388

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
403
404
        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
405

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

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

Michal Schmidt's avatar
Michal Schmidt committed
414
        condition_free_list(u->conditions);
415

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
425
        if (u->load_state == UNIT_MERGED)
426
427
428
429
                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
430
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
431
432
433
434

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

435
436
437
438
439
440
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

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

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

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

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

460
461
462
        assert(u);
        assert(other);

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

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

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

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

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

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

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

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

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

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

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

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

510
511
        other = unit_follow_merge(other);

512
513
514
        if (other == u)
                return 0;

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

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

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

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

528
529
530
        if (other->nop_job)
                return -EEXIST;

531
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
532
533
                return -EEXIST;

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

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

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

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

548
549
        /* 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
550
        if (other->load_state != UNIT_STUB)
551
552
553
554
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
555
556
557
558
559
560
561
        unit_add_to_cleanup_queue(other);

        return 0;
}

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

        assert(u);
        assert(name);

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

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

                name = s;
        }

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

583
584
        free(s);
        return r;
585
586
587
588
589
}

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

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

        return u;
}

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

        assert(u);
        assert(c);

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
625
626
627
628
629
630
        return 0;
}

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

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

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

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

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

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

        fprintf(f,
660
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
661
                "%s\tDescription: %s\n"
662
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
663
                "%s\tUnit Load State: %s\n"
664
                "%s\tUnit Active State: %s\n"
665
                "%s\tInactive Exit Timestamp: %s\n"
666
                "%s\tActive Enter Timestamp: %s\n"
667
                "%s\tActive Exit Timestamp: %s\n"
668
                "%s\tInactive Enter Timestamp: %s\n"
669
670
                "%s\tGC Check Good: %s\n"
                "%s\tNeed Daemon Reload: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
671
                prefix, u->id,
Lennart Poettering's avatar
Lennart Poettering committed
672
                prefix, unit_description(u),
Michal Schmidt's avatar
Michal Schmidt committed
673
674
                prefix, strna(u->instance),
                prefix, unit_load_state_to_string(u->load_state),
675
                prefix, unit_active_state_to_string(unit_active_state(u)),
Michal Schmidt's avatar
Michal Schmidt committed
676
677
678
679
                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)),
680
681
                prefix, yes_no(unit_check_gc(u)),
                prefix, yes_no(unit_need_daemon_reload(u)));
682

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

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

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
703
        if (dual_timestamp_is_set(&u->condition_timestamp))
704
705
706
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
707
708
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
709

Lennart Poettering's avatar
Lennart Poettering committed
710
711
712
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
713
714
                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
715
716
        }

717
718
719
720
721
722
723
724
725
726
        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
727
        if (u->load_state == UNIT_LOADED) {
728
729
730
                CGroupBonding *b;
                CGroupAttribute *a;

731
                fprintf(f,
732
                        "%s\tStopWhenUnneeded: %s\n"
733
734
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
735
                        "%s\tDefaultDependencies: %s\n"
736
                        "%s\tOnFailureIsolate: %s\n"
737
738
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
739
740
741
742
743
744
745
746
747
                        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)
748
749
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
750

Michal Schmidt's avatar
Michal Schmidt committed
751
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
752
753
754
755
756
                        char *v = NULL;

                        if (a->map_callback)
                                a->map_callback(a->controller, a->name, a->value, &v);

757
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
758
759
760
761
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
762

763
764
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
765

Michal Schmidt's avatar
Michal Schmidt committed
766
        } else if (u->load_state == UNIT_MERGED)
767
768
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
769
770
771
                        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));
772

Lennart Poettering's avatar
Lennart Poettering committed
773

Michal Schmidt's avatar
Michal Schmidt committed
774
775
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
776

777
778
779
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

780
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
781
782
783
}

/* Common implementation for multiple backends */
784
int unit_load_fragment_and_dropin(Unit *u) {
785
786
787
788
789
        int r;

        assert(u);

        /* Load a .service file */
790
        if ((r = unit_load_fragment(u)) < 0)
791
792
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
793
        if (u->load_state == UNIT_STUB)
794
795
796
797
798
799
800
801
802
803
                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 */
804
int unit_load_fragment_and_dropin_optional(Unit *u) {
805
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
806
807
808

        assert(u);

809
810
811
812
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
816
817
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
818

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

823
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
824
825
}

826
int unit_add_default_target_dependency(Unit *u, Unit *target) {
827
828
829
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
830
        if (target->type != UNIT_TARGET)
831
832
                return 0;

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

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

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

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

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

860
        Unit *target;
861
862
        Iterator i;
        int r;
863
        unsigned k;
864
865
866

        assert(u);

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

872
873
874
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
875
876
877
878
879
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
880
881
882
        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
883
884
        }

Michal Schmidt's avatar
Michal Schmidt committed
885
        if (u->type == _UNIT_TYPE_INVALID)
886
887
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
888
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
889
890
                return 0;

891
892
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
893
                        goto fail;
894

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

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

905
906
907
908
909
910
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

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

                log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
Michal Schmidt's avatar
Michal Schmidt committed
915
                          u->id);
916
917
918
919
920

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
921
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
922
923

        unit_add_to_dbus_queue(unit_follow_merge(u));
924
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
925
926
927
928

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
929
930
        u->load_state = UNIT_ERROR;
        u->load_error = r;
931
        unit_add_to_dbus_queue(u);
932
        unit_add_to_gc_queue(u);
933

Michal Schmidt's avatar
Michal Schmidt committed
934
        log_debug("Failed to load configuration for %s: %s", u->id, strerror(-r));
935

Lennart Poettering's avatar
Lennart Poettering committed
936
937
938
        return r;
}

939
940
941
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
942
943
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
944

Michal Schmidt's avatar
Michal Schmidt committed
945
        return u->condition_result;
946
947
}

948
static const char* unit_get_status_message_format(Unit *u, JobType t) {
949
        const UnitStatusMessageFormats *format_table;
950
951
952
953
954
955
956

        assert(u);
        assert(t >= 0);
        assert(t < _JOB_TYPE_MAX);

        if (t != JOB_START && t != JOB_STOP)
                return NULL;
957
958
959

        format_table = &UNIT_VTABLE(u)->status_message_formats;
        if (!format_table)
960
961