unit.c 85.9 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
                        _cleanup_free_ char *v = NULL;
753

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

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
771

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

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

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

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

        assert(u);

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

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

        assert(u);

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);

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

870
871
872
        return 0;
}

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

        assert(u);

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

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

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

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

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

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

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

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

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

                r = -EINVAL;
                goto fail;
        }

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

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

        return 0;

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

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

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

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

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

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

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

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

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