unit.c 88 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);
Michal Schmidt's avatar
Michal Schmidt committed
411
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
412

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

511
512
        other = unit_follow_merge(other);

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

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

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

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

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

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

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

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

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

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

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

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

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

        return 0;
}

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

        assert(u);
        assert(name);

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

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

                name = s;
        }

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

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

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

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

        return u;
}

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

        assert(u);
        assert(c);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

755
756
                        if (a->semantics && a->semantics->map_write)
                                a->semantics->map_write(a->semantics, a->value, &v);
757

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
772

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

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

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

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

        assert(u);

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

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

        assert(u);

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);

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

871
872
873
        return 0;
}

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

        assert(u);

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

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

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

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

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

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

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

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

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

                r = -EINVAL;
                goto fail;
        }

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

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

        return 0;

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

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

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

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

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

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

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