unit.c 81 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
34
35

#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
Kay Sievers's avatar
Kay Sievers committed
36
#include "path-util.h"
Lennart Poettering's avatar
Lennart Poettering committed
37
38
39
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
40
41
#include "unit-name.h"
#include "specifier.h"
42
#include "dbus-unit.h"
43
#include "special.h"
44
#include "cgroup-util.h"
45
#include "missing.h"
46
#include "cgroup-attr.h"
Lennart Poettering's avatar
Lennart Poettering committed
47
48
49
50
51
52
53
54
55

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

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

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

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

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

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

        return u;
}

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

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

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

        assert(u);
        assert(text);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);
        assert(name);

192
193
        if (unit_name_is_template(name)) {

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

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

                name = t;
        }

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

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

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

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

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

218
        unit_add_to_dbus_queue(u);
219

220
221
222
        return 0;
}

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

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

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

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

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

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

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

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

256
257
258
259
260
261
262
263
264
265
        if (unit_active_state(u) != UNIT_INACTIVE)
                return true;

        if (UNIT_VTABLE(u)->check_gc)
                if (UNIT_VTABLE(u)->check_gc(u))
                        return true;

        return false;
}

Lennart Poettering's avatar
Lennart Poettering committed
266
267
void unit_add_to_load_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
268
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
269

Michal Schmidt's avatar
Michal Schmidt committed
270
        if (u->load_state != UNIT_STUB || u->in_load_queue)
Lennart Poettering's avatar
Lennart Poettering committed
271
272
                return;

Michal Schmidt's avatar
Michal Schmidt committed
273
274
        LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u);
        u->in_load_queue = true;
Lennart Poettering's avatar
Lennart Poettering committed
275
276
}

277
278
279
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
280
        if (u->in_cleanup_queue)
281
282
                return;

Michal Schmidt's avatar
Michal Schmidt committed
283
284
        LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
        u->in_cleanup_queue = true;
285
286
}

287
288
289
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
290
        if (u->in_gc_queue || u->in_cleanup_queue)
291
292
293
294
295
                return;

        if (unit_check_gc(u))
                return;

Michal Schmidt's avatar
Michal Schmidt committed
296
297
        LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
        u->in_gc_queue = true;
298

Michal Schmidt's avatar
Michal Schmidt committed
299
        u->manager->n_in_gc_queue ++;
300

Michal Schmidt's avatar
Michal Schmidt committed
301
302
        if (u->manager->gc_queue_timestamp <= 0)
                u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
303
304
}

305
306
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
307
        assert(u->type != _UNIT_TYPE_INVALID);
308

Michal Schmidt's avatar
Michal Schmidt committed
309
        if (u->load_state == UNIT_STUB || u->in_dbus_queue)
310
311
                return;

312
        /* Shortcut things if nobody cares */
Michal Schmidt's avatar
Michal Schmidt committed
313
314
        if (!bus_has_subscriber(u->manager)) {
                u->sent_dbus_new_signal = true;
315
316
317
                return;
        }

Michal Schmidt's avatar
Michal Schmidt committed
318
319
        LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
        u->in_dbus_queue = true;
320
321
}

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

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
338
339
340
341
342
343
344
345
346
347
348
349
        }

        set_free(s);
}

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

        assert(u);

350
351
        bus_unit_send_removed_signal(u);

Michal Schmidt's avatar
Michal Schmidt committed
352
        if (u->load_state != UNIT_STUB)
353
354
355
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

Michal Schmidt's avatar
Michal Schmidt committed
356
357
        SET_FOREACH(t, u->names, i)
                hashmap_remove_value(u->manager->units, t, u);
Lennart Poettering's avatar
Lennart Poettering committed
358

Michal Schmidt's avatar
Michal Schmidt committed
359
360
361
362
363
        if (u->job) {
                Job *j = u->job;
                job_uninstall(j);
                job_free(j);
        }
364

365
366
367
368
369
370
        if (u->nop_job) {
                Job *j = u->nop_job;
                job_uninstall(j);
                job_free(j);
        }

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

374
375
376
377
378
        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
379
380
        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
381

Michal Schmidt's avatar
Michal Schmidt committed
382
383
        if (u->in_load_queue)
                LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
Lennart Poettering's avatar
Lennart Poettering committed
384

Michal Schmidt's avatar
Michal Schmidt committed
385
386
        if (u->in_dbus_queue)
                LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
387

Michal Schmidt's avatar
Michal Schmidt committed
388
389
        if (u->in_cleanup_queue)
                LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
390

Michal Schmidt's avatar
Michal Schmidt committed
391
392
393
        if (u->in_gc_queue) {
                LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
                u->manager->n_in_gc_queue--;
394
395
        }

Michal Schmidt's avatar
Michal Schmidt committed
396
397
        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
398

Michal Schmidt's avatar
Michal Schmidt committed
399
        free(u->description);
400
        strv_free(u->documentation);
Michal Schmidt's avatar
Michal Schmidt committed
401
402
        free(u->fragment_path);
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
403

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

Michal Schmidt's avatar
Michal Schmidt committed
406
        condition_free_list(u->conditions);
407

Michal Schmidt's avatar
Michal Schmidt committed
408
409
        while (u->refs)
                unit_ref_unset(u->refs);
410

Lennart Poettering's avatar
Lennart Poettering committed
411
412
413
414
415
416
        free(u);
}

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

Michal Schmidt's avatar
Michal Schmidt committed
417
        if (u->load_state == UNIT_MERGED)
418
419
420
421
                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
422
         * shortcut failed loading to UNIT_INACTIVE_FAILED. */
Lennart Poettering's avatar
Lennart Poettering committed
423
424
425
426

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

427
428
429
430
431
432
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

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

433
434
435
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
436

437
438
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
439
440

        if (*s)
441
442
443
444
445
446
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
447

448
449
450
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
451

452
453
454
        assert(u);
        assert(other);

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

Michal Schmidt's avatar
Michal Schmidt committed
457
458
459
        set_free_free(other->names);
        other->names = NULL;
        other->id = NULL;
460

Michal Schmidt's avatar
Michal Schmidt committed
461
462
        SET_FOREACH(t, u->names, i)
                assert_se(hashmap_replace(u->manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
463
464
}

465
466
467
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
468
        int r;
469
470
471
472
473

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

474
        /* Fix backwards pointers */
Michal Schmidt's avatar
Michal Schmidt committed
475
        SET_FOREACH(back, other->dependencies[d], i) {
476
477
478
                UnitDependency k;

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

                                if (r == -EEXIST)
Michal Schmidt's avatar
Michal Schmidt committed
482
                                        set_remove(back->dependencies[k], other);
483
484
485
486
487
                                else
                                        assert(r == -ENOENT);
                        }
        }

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

Michal Schmidt's avatar
Michal Schmidt committed
490
491
        set_free(other->dependencies[d]);
        other->dependencies[d] = NULL;
492
493
494
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
495
496
497
498
        UnitDependency d;

        assert(u);
        assert(other);
Michal Schmidt's avatar
Michal Schmidt committed
499
500
        assert(u->manager == other->manager);
        assert(u->type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
501

502
503
        other = unit_follow_merge(other);

504
505
506
        if (other == u)
                return 0;

Michal Schmidt's avatar
Michal Schmidt committed
507
        if (u->type != other->type)
508
509
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
510
        if (!u->instance != !other->instance)
Lennart Poettering's avatar
Lennart Poettering committed
511
512
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
513
514
        if (other->load_state != UNIT_STUB &&
            other->load_state != UNIT_ERROR)
515
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
516

Michal Schmidt's avatar
Michal Schmidt committed
517
        if (other->job)
518
519
                return -EEXIST;

520
521
522
        if (other->nop_job)
                return -EEXIST;

523
        if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
524
525
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
526
        /* Merge names */
527
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
528

529
        /* Redirect all references */
Michal Schmidt's avatar
Michal Schmidt committed
530
531
        while (other->refs)
                unit_ref_set(other->refs, u);
532

Lennart Poettering's avatar
Lennart Poettering committed
533
534
        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
535
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
536

Michal Schmidt's avatar
Michal Schmidt committed
537
538
        other->load_state = UNIT_MERGED;
        other->merged_into = u;
539

540
541
        /* 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
542
        if (other->load_state != UNIT_STUB)
543
544
545
546
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
547
548
549
550
551
552
553
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
554
555
        int r;
        char *s = NULL;
556
557
558
559

        assert(u);
        assert(name);

560
        if (unit_name_is_template(name)) {
Michal Schmidt's avatar
Michal Schmidt committed
561
                if (!u->instance)
562
563
                        return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
564
                if (!(s = unit_name_replace_instance(name, u->instance)))
565
566
567
568
569
                        return -ENOMEM;

                name = s;
        }

Michal Schmidt's avatar
Michal Schmidt committed
570
        if (!(other = manager_get_unit(u->manager, name)))
571
572
573
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
574

575
576
        free(s);
        return r;
577
578
579
580
581
}

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

Michal Schmidt's avatar
Michal Schmidt committed
582
583
        while (u->load_state == UNIT_MERGED)
                assert_se(u = u->merged_into);
584
585
586
587
588
589
590
591
592
593

        return u;
}

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

        assert(u);
        assert(c);

594
595
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
596
            c->std_output != EXEC_OUTPUT_JOURNAL &&
597
598
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
599
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
600
            c->std_error != EXEC_OUTPUT_KMSG &&
601
            c->std_error != EXEC_OUTPUT_SYSLOG &&
602
            c->std_error != EXEC_OUTPUT_JOURNAL &&
603
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
604
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
605
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
606
607
608
609
610
                return 0;

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

Michal Schmidt's avatar
Michal Schmidt committed
611
        if (u->manager->running_as == MANAGER_SYSTEM)
612
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
613
614
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
615
616
617
618
619
620
        return 0;
}

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

Michal Schmidt's avatar
Michal Schmidt committed
621
622
        if (u->description)
                return u->description;
Lennart Poettering's avatar
Lennart Poettering committed
623

Michal Schmidt's avatar
Michal Schmidt committed
624
        return strna(u->id);
Lennart Poettering's avatar
Lennart Poettering committed
625
626
627
}

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

        assert(u);
Michal Schmidt's avatar
Michal Schmidt committed
642
        assert(u->type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
643
644
645

        if (!prefix)
                prefix = "";
646
647
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
648
649

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

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

676
677
678
        STRV_FOREACH(j, u->documentation)
                fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);

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

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

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

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

Michal Schmidt's avatar
Michal Schmidt committed
690
        if (dual_timestamp_is_set(&u->condition_timestamp))
691
692
693
                fprintf(f,
                        "%s\tCondition Timestamp: %s\n"
                        "%s\tCondition Result: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
694
695
                        prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
                        prefix, yes_no(u->condition_result));
696

Lennart Poettering's avatar
Lennart Poettering committed
697
698
699
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
700
701
                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
702
703
        }

704
705
706
707
708
709
710
711
712
713
        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
714
        if (u->load_state == UNIT_LOADED) {
715
716
717
                CGroupBonding *b;
                CGroupAttribute *a;

718
                fprintf(f,
719
                        "%s\tStopWhenUnneeded: %s\n"
720
721
                        "%s\tRefuseManualStart: %s\n"
                        "%s\tRefuseManualStop: %s\n"
722
                        "%s\tDefaultDependencies: %s\n"
723
                        "%s\tOnFailureIsolate: %s\n"
724
725
                        "%s\tIgnoreOnIsolate: %s\n"
                        "%s\tIgnoreOnSnapshot: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
726
727
728
729
730
731
732
733
734
                        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)
735
736
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
737

Michal Schmidt's avatar
Michal Schmidt committed
738
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
739
740
741
742
743
                        char *v = NULL;

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

744
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
745
746
747
748
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
749

750
751
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
752

Michal Schmidt's avatar
Michal Schmidt committed
753
        } else if (u->load_state == UNIT_MERGED)
754
755
                fprintf(f,
                        "%s\tMerged into: %s\n",
Michal Schmidt's avatar
Michal Schmidt committed
756
757
758
                        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));
759

Lennart Poettering's avatar
Lennart Poettering committed
760

Michal Schmidt's avatar
Michal Schmidt committed
761
762
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
763

764
765
766
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

767
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
768
769
770
}

/* Common implementation for multiple backends */
771
int unit_load_fragment_and_dropin(Unit *u) {
772
773
774
775
776
        int r;

        assert(u);

        /* Load a .service file */
777
        if ((r = unit_load_fragment(u)) < 0)
778
779
                return r;

Michal Schmidt's avatar
Michal Schmidt committed
780
        if (u->load_state == UNIT_STUB)
781
782
783
784
785
786
787
788
789
790
                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 */
791
int unit_load_fragment_and_dropin_optional(Unit *u) {
792
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
793
794
795

        assert(u);

796
797
798
799
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
803
804
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
805

Lennart Poettering's avatar
Lennart Poettering committed
806
        /* Load drop-in directory data */
807
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
808
809
                return r;

810
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
811
812
}

813
int unit_add_default_target_dependency(Unit *u, Unit *target) {
814
815
816
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
817
        if (target->type != UNIT_TARGET)
818
819
                return 0;

Harald Hoyer's avatar
Harald Hoyer committed
820
        /* Only add the dependency if both units are loaded, so that
821
         * that loop check below is reliable */
Michal Schmidt's avatar
Michal Schmidt committed
822
823
        if (u->load_state != UNIT_LOADED ||
            target->load_state != UNIT_LOADED)
824
825
                return 0;

826
827
        /* If either side wants no automatic dependencies, then let's
         * skip this */
Michal Schmidt's avatar
Michal Schmidt committed
828
829
        if (!u->default_dependencies ||
            !target->default_dependencies)
830
831
                return 0;

832
        /* Don't create loops */
Michal Schmidt's avatar
Michal Schmidt committed
833
        if (set_get(target->dependencies[UNIT_BEFORE], u))
834
835
836
837
838
839
                return 0;

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

static int unit_add_default_dependencies(Unit *u) {
840
841
842
843
844
845
846
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

847
        Unit *target;
848
849
        Iterator i;
        int r;
850
        unsigned k;
851
852
853

        assert(u);

854
        for (k = 0; k < ELEMENTSOF(deps); k++)
Michal Schmidt's avatar
Michal Schmidt committed
855
                SET_FOREACH(target, u->dependencies[deps[k]], i)
856
857
                        if ((r = unit_add_default_target_dependency(u, target)) < 0)
                                return r;
858

859
860
861
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
862
863
864
865
866
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
867
868
869
        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
870
871
        }

Michal Schmidt's avatar
Michal Schmidt committed
872
        if (u->type == _UNIT_TYPE_INVALID)
873
874
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
875
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
876
877
                return 0;

878
879
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
880
                        goto fail;
881

Michal Schmidt's avatar
Michal Schmidt committed
882
        if (u->load_state == UNIT_STUB) {
883
884
885
886
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
887
888
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
889
890
891
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

892
893
894
895
896
897
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

Michal Schmidt's avatar
Michal Schmidt committed
898
899
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
900
901

                log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
Michal Schmidt's avatar
Michal Schmidt committed
902
                          u->id);
903
904
905
906
907

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
908
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
909
910

        unit_add_to_dbus_queue(unit_follow_merge(u));
911
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
912
913
914
915

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
916
917
        u->load_state = UNIT_ERROR;
        u->load_error = r;
918
        unit_add_to_dbus_queue(u);
919
        unit_add_to_gc_queue(u);
920

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

Lennart Poettering's avatar
Lennart Poettering committed
923
924
925
        return r;
}

926
927
928
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
929
930
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
931

Michal Schmidt's avatar
Michal Schmidt committed
932
        return u->condition_result;
933
934
}

935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
static void unit_status_print_starting_stopping(Unit *u, bool stopping) {
        const UnitStatusMessageFormats *format_table;
        const char *format;

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

        format = format_table->starting_stopping[stopping];
        if (!format)
                return;

        unit_status_printf(u, "", format, unit_description(u));
}

Lennart Poettering's avatar
Lennart Poettering committed
950
/* Errors:
951
952
953
954
 *         -EBADR:     This unit type does not support starting.
 *         -EALREADY:  Unit is already started.
 *         -EAGAIN:    An operation is already in progress. Retry later.
 *         -ECANCELED: Too many requests for now.
Lennart Poettering's avatar
Lennart Poettering committed
955
956
957
 */
int unit_start(Unit *u) {
        UnitActiveState state;
958
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
959
960
961

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
962
        if (u->load_state != UNIT_LOADED)
963
964
                return -EINVAL;

965
966
967
968
        /* If this is already started, then this will succeed. Note
         * that this will even succeed if this unit is not startable
         * by the user. This is relied on to detect when we need to
         * wait for units and when waiting is finished. */
Lennart Poettering's avatar
Lennart Poettering committed
969
970
971
972
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

973
974
975
976
977
978
        /* If the conditions failed, don't do anything at all. If we
         * already are activating this call might still be useful to
         * speed up activation in case there is some hold-off time,
         * but we don't want to recheck the condition in that case. */
        if (state != UNIT_ACTIVATING &&
            !unit_condition_test(u)) {
Michal Schmidt's avatar
Michal Schmidt committed
979
                log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);