unit.c 80.8 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"
Lennart Poettering's avatar
Lennart Poettering committed
48
49
50
51
52
53
54
55
56

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

62
Unit *unit_new(Manager *m, size_t size) {
Lennart Poettering's avatar
Lennart Poettering committed
63
64
65
        Unit *u;

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

68
69
        u = malloc0(size);
        if (!u)
Lennart Poettering's avatar
Lennart Poettering committed
70
71
                return NULL;

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

Michal Schmidt's avatar
Michal Schmidt committed
78
79
80
81
82
        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
83
84
85
86

        return u;
}

87
88
89
90
bool unit_has_name(Unit *u, const char *name) {
        assert(u);
        assert(name);

Michal Schmidt's avatar
Michal Schmidt committed
91
        return !!set_get(u->names, (char*) name);
92
93
}

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

        assert(u);
        assert(text);

102
        if (unit_name_is_template(text)) {
Michal Schmidt's avatar
Michal Schmidt committed
103
                if (!u->instance)
104
                        return -EINVAL;
Lennart Poettering's avatar
Lennart Poettering committed
105

Michal Schmidt's avatar
Michal Schmidt committed
106
                s = unit_name_replace_instance(text, u->instance);
107
108
        } else
                s = strdup(text);
Lennart Poettering's avatar
Lennart Poettering committed
109

110
111
        if (!s)
                return -ENOMEM;
Lennart Poettering's avatar
Lennart Poettering committed
112

113
        if (!unit_name_is_valid(s, false)) {
114
115
116
                r = -EINVAL;
                goto fail;
        }
117

118
        assert_se((t = unit_name_to_type(s)) >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
119

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

125
126
        if ((r = unit_name_to_instance(s, &i)) < 0)
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
127

128
129
        if (i && unit_vtable[t]->no_instances) {
                r = -EINVAL;
130
                goto fail;
131
        }
132

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

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
165
166
167
                u->type = t;
                u->id = s;
                u->instance = i;
168

Michal Schmidt's avatar
Michal Schmidt committed
169
                LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u);
170
171
172

                if (UNIT_VTABLE(u)->init)
                        UNIT_VTABLE(u)->init(u);
173
174
        } else
                free(i);
Lennart Poettering's avatar
Lennart Poettering committed
175

176
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
177
        return 0;
178
179
180
181
182
183

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

        return r;
Lennart Poettering's avatar
Lennart Poettering committed
184
185
}

186
int unit_choose_id(Unit *u, const char *name) {
187
188
        char *s, *t = NULL, *i;
        int r;
189
190
191
192

        assert(u);
        assert(name);

193
194
        if (unit_name_is_template(name)) {

Michal Schmidt's avatar
Michal Schmidt committed
195
                if (!u->instance)
196
197
                        return -EINVAL;

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

                name = t;
        }

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

208
        if (!s)
209
210
                return -ENOENT;

211
212
213
        if ((r = unit_name_to_instance(s, &i)) < 0)
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
214
        u->id = s;
215

Michal Schmidt's avatar
Michal Schmidt committed
216
217
        free(u->instance);
        u->instance = i;
218

219
        unit_add_to_dbus_queue(u);
220

221
222
223
        return 0;
}

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

        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
236
237
238
        return 0;
}

239
240
241
bool unit_check_gc(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
242
        if (u->load_state == UNIT_STUB)
243
244
                return true;

245
246
247
        if (UNIT_VTABLE(u)->no_gc)
                return true;

Michal Schmidt's avatar
Michal Schmidt committed
248
        if (u->no_gc)
249
250
                return true;

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

254
255
256
        if (u->nop_job)
                return true;

257
258
259
        if (unit_active_state(u) != UNIT_INACTIVE)
                return true;

260
261
262
        if (u->refs)
                return true;

263
264
265
266
267
268
269
        if (UNIT_VTABLE(u)->check_gc)
                if (UNIT_VTABLE(u)->check_gc(u))
                        return true;

        return false;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
274
        if (u->load_state != UNIT_STUB || u->in_load_queue)
Lennart Poettering's avatar
Lennart Poettering committed
275
276
                return;

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

281
282
283
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
284
        if (u->in_cleanup_queue)
285
286
                return;

Michal Schmidt's avatar
Michal Schmidt committed
287
288
        LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
        u->in_cleanup_queue = true;
289
290
}

291
292
293
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
294
        if (u->in_gc_queue || u->in_cleanup_queue)
295
296
297
298
299
                return;

        if (unit_check_gc(u))
                return;

Michal Schmidt's avatar
Michal Schmidt committed
300
301
        LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
        u->in_gc_queue = true;
302

Michal Schmidt's avatar
Michal Schmidt committed
303
        u->manager->n_in_gc_queue ++;
304

Michal Schmidt's avatar
Michal Schmidt committed
305
306
        if (u->manager->gc_queue_timestamp <= 0)
                u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
307
308
}

309
310
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
311
        assert(u->type != _UNIT_TYPE_INVALID);
312

Michal Schmidt's avatar
Michal Schmidt committed
313
        if (u->load_state == UNIT_STUB || u->in_dbus_queue)
314
315
                return;

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

Michal Schmidt's avatar
Michal Schmidt committed
322
323
        LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
        u->in_dbus_queue = true;
324
325
}

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

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
342
343
344
345
346
347
348
349
350
351
352
353
        }

        set_free(s);
}

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

        assert(u);

354
355
        bus_unit_send_removed_signal(u);

Michal Schmidt's avatar
Michal Schmidt committed
356
        if (u->load_state != UNIT_STUB)
357
358
359
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

Michal Schmidt's avatar
Michal Schmidt committed
360
361
        SET_FOREACH(t, u->names, i)
                hashmap_remove_value(u->manager->units, t, u);
Lennart Poettering's avatar
Lennart Poettering committed
362

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

369
370
371
372
373
374
        if (u->nop_job) {
                Job *j = u->nop_job;
                job_uninstall(j);
                job_free(j);
        }

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

378
379
380
381
382
        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
383
384
        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
385

Michal Schmidt's avatar
Michal Schmidt committed
386
387
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
388

Michal Schmidt's avatar
Michal Schmidt committed
389
390
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
391

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

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

Michal Schmidt's avatar
Michal Schmidt committed
400
401
        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
402

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

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

Michal Schmidt's avatar
Michal Schmidt committed
411
        condition_free_list(u->conditions);
412

Michal Schmidt's avatar
Michal Schmidt committed
413
414
        while (u->refs)
                unit_ref_unset(u->refs);
415

Lennart Poettering's avatar
Lennart Poettering committed
416
417
418
419
420
421
        free(u);
}

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

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

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

432
433
434
435
436
437
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

438
439
440
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
441

442
443
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
444
445

        if (*s)
446
447
448
449
450
451
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
452

453
454
455
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
456

457
458
459
        assert(u);
        assert(other);

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

Michal Schmidt's avatar
Michal Schmidt committed
462
463
464
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
465

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

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

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

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
495
496
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
497
498
499
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
500
501
502
503
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
504
505
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
506

507
508
        other = unit_follow_merge(other);

509
510
511
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
512
        if (u->type != other->type)
513
514
                return -EINVAL;

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

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

Michal Schmidt's avatar
Michal Schmidt committed
522
        if (other->job)
523
524
                return -EEXIST;

525
526
527
        if (other->nop_job)
                return -EEXIST;

528
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
529
530
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
531
        /* Merge names */
532
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
533

534
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
535
536
        while (other->refs)
                unit_ref_set(other->refs, u);
537

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

Michal Schmidt's avatar
Michal Schmidt committed
542
543
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
544

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

        unit_add_to_dbus_queue(u);
552
553
554
555
556
557
558
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
559
560
        int r;
        char *s = NULL;
561
562
563
564

        assert(u);
        assert(name);

565
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
566
                if (!u->instance)
567
568
                        return -EINVAL;

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

                name = s;
        }

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

580
581
        free(s);
        return r;
582
583
584
585
586
}

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

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

        return u;
}

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

        assert(u);
        assert(c);

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

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

616
        if (u->manager->running_as == SYSTEMD_SYSTEM)
617
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
618
619
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
620
621
622
623
624
625
        return 0;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
626
627
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
628

Michal Schmidt's avatar
Michal Schmidt committed
629
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
630
631
632
}

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

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
647
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
648
649
650

        if (!prefix)
                prefix = "";
651
652
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
653
654

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

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

681
682
683
        STRV_FOREACH(j, u->documentation)
                fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);

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

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

690
691
692
        if (u->source_path)
                fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);

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

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

Michal Schmidt's avatar
Michal Schmidt committed
698
        if (dual_timestamp_is_set(&u->condition_timestamp))
699
700
701
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
702
703
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
704

Lennart Poettering's avatar
Lennart Poettering committed
705
706
707
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
708
709
                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
710
711
        }

712
713
714
715
716
717
718
719
720
721
        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
722
        if (u->load_state == UNIT_LOADED) {
723
724
725
                CGroupBonding *b;
                CGroupAttribute *a;

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

Michal Schmidt's avatar
Michal Schmidt committed
746
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
747
748
749
750
751
                        char *v = NULL;

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

752
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
753
754
755
756
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
757

758
759
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
760

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

Lennart Poettering's avatar
Lennart Poettering committed
768

Michal Schmidt's avatar
Michal Schmidt committed
769
770
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
771

772
773
774
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

775
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
776
777
778
}

/* Common implementation for multiple backends */
779
int unit_load_fragment_and_dropin(Unit *u) {
780
781
782
783
784
        int r;

        assert(u);

        /* Load a .service file */
785
        if ((r = unit_load_fragment(u)) < 0)
786
787
                return r;

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

        assert(u);

804
805
806
807
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
811
812
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
813

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

818
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
819
820
}

821
int unit_add_default_target_dependency(Unit *u, Unit *target) {
822
823
824
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
825
        if (target->type != UNIT_TARGET)
826
827
                return 0;

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

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

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

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

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

855
        Unit *target;
856
857
        Iterator i;
        int r;
858
        unsigned k;
859
860
861

        assert(u);

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

867
868
869
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
870
871
872
873
874
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
875
876
877
        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
878
879
        }

Michal Schmidt's avatar
Michal Schmidt committed
880
        if (u->type == _UNIT_TYPE_INVALID)
881
882
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
883
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
884
885
                return 0;

886
887
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
888
                        goto fail;
889

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

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

900
901
902
903
904
905
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

Michal Schmidt's avatar
Michal Schmidt committed
906
907
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
908
909

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

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
916
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
917
918

        unit_add_to_dbus_queue(unit_follow_merge(u));
919
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
920
921
922
923

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
924
925
        u->load_state = UNIT_ERROR;
        u->load_error = r;
926
        unit_add_to_dbus_queue(u);
927
        unit_add_to_gc_queue(u);
928

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

Lennart Poettering's avatar
Lennart Poettering committed
931
932
933
        return r;
}

934
935
936
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
937
938
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
939

Michal Schmidt's avatar
Michal Schmidt committed
940
        return u->condition_result;
941
942
}

943
static const char* unit_get_status_message_format(Unit *u, JobType t) {
944
        const UnitStatusMessageFormats *format_table;
945
946
947
948
949
950
951

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

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

        format_table = &UNIT_VTABLE(u)->status_message_formats;
        if (!format_table)
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
                return NULL;

        return format_table->starting_stopping[t == JOB_STOP];
}

static const <