unit.c 83.3 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
        free(u->fragment_path);
402
        free(u->source_path);
Michal Schmidt's avatar
Michal Schmidt committed
403
        free(u->instance);
Lennart Poettering's avatar
Lennart Poettering committed
404

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

503
504
        other = unit_follow_merge(other);

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

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

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

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

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

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

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

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

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

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

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

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

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

        return 0;
}

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

        assert(u);
        assert(name);

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

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

                name = s;
        }

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

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

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

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

        return u;
}

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

        assert(u);
        assert(c);

595
596
        if (c->std_output != EXEC_OUTPUT_KMSG &&
            c->std_output != EXEC_OUTPUT_SYSLOG &&
597
            c->std_output != EXEC_OUTPUT_JOURNAL &&
598
599
            c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
            c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
600
            c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
601
            c->std_error != EXEC_OUTPUT_KMSG &&
602
            c->std_error != EXEC_OUTPUT_SYSLOG &&
603
            c->std_error != EXEC_OUTPUT_JOURNAL &&
604
            c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
605
            c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
606
            c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
607
608
609
610
611
                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
612
        if (u->manager->running_as == MANAGER_SYSTEM)
613
                if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
614
615
                        return r;

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

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

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

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

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

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

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

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

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

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

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

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

686
687
688
        if (u->source_path)
                fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);

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

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

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

Lennart Poettering's avatar
Lennart Poettering committed
701
702
703
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

Michal Schmidt's avatar
Michal Schmidt committed
704
705
                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
706
707
        }

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

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

Michal Schmidt's avatar
Michal Schmidt committed
742
                LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
743
744
745
746
747
                        char *v = NULL;

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

748
                        fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
749
750
751
752
                                prefix, a->controller, a->name, v ? v : a->value);

                        free(v);
                }
753

754
755
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
756

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

Lennart Poettering's avatar
Lennart Poettering committed
764

Michal Schmidt's avatar
Michal Schmidt committed
765
766
        if (u->job)
                job_dump(u->job, f, prefix2);
Lennart Poettering's avatar
Lennart Poettering committed
767

768
769
770
        if (u->nop_job)
                job_dump(u->nop_job, f, prefix2);

771
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
772
773
774
}

/* Common implementation for multiple backends */
775
int unit_load_fragment_and_dropin(Unit *u) {
776
777
778
779
780
        int r;

        assert(u);

        /* Load a .service file */
781
        if ((r = unit_load_fragment(u)) < 0)
782
783
                return r;

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

        assert(u);

800
801
802
803
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

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

Michal Schmidt's avatar
Michal Schmidt committed
807
808
        if (u->load_state == UNIT_STUB)
                u->load_state = UNIT_LOADED;
809

Lennart Poettering's avatar
Lennart Poettering committed
810
        /* Load drop-in directory data */
811
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
812
813
                return r;

814
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
815
816
}

817
int unit_add_default_target_dependency(Unit *u, Unit *target) {
818
819
820
        assert(u);
        assert(target);

Michal Schmidt's avatar
Michal Schmidt committed
821
        if (target->type != UNIT_TARGET)
822
823
                return 0;

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

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

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

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

static int unit_add_default_dependencies(Unit *u) {
844
845
846
847
848
849
850
        static const UnitDependency deps[] = {
                UNIT_REQUIRED_BY,
                UNIT_REQUIRED_BY_OVERRIDABLE,
                UNIT_WANTED_BY,
                UNIT_BOUND_BY
        };

851
        Unit *target;
852
853
        Iterator i;
        int r;
854
        unsigned k;
855
856
857

        assert(u);

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

863
864
865
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
866
867
868
869
870
int unit_load(Unit *u) {
        int r;

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
871
872
873
        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
874
875
        }

Michal Schmidt's avatar
Michal Schmidt committed
876
        if (u->type == _UNIT_TYPE_INVALID)
877
878
                return -EINVAL;

Michal Schmidt's avatar
Michal Schmidt committed
879
        if (u->load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
880
881
                return 0;

882
883
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
884
                        goto fail;
885

Michal Schmidt's avatar
Michal Schmidt committed
886
        if (u->load_state == UNIT_STUB) {
887
888
889
890
                r = -ENOENT;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
891
892
        if (u->load_state == UNIT_LOADED &&
            u->default_dependencies)
893
894
895
                if ((r = unit_add_default_dependencies(u)) < 0)
                        goto fail;

896
897
898
899
900
901
        if (u->load_state == UNIT_LOADED) {
                r = unit_add_mount_links(u);
                if (r < 0)
                        return r;
        }

Michal Schmidt's avatar
Michal Schmidt committed
902
903
        if (u->on_failure_isolate &&
            set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
904
905

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

                r = -EINVAL;
                goto fail;
        }

Michal Schmidt's avatar
Michal Schmidt committed
912
        assert((u->load_state != UNIT_MERGED) == !u->merged_into);
913
914

        unit_add_to_dbus_queue(unit_follow_merge(u));
915
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
916
917
918
919

        return 0;

fail:
Michal Schmidt's avatar
Michal Schmidt committed
920
921
        u->load_state = UNIT_ERROR;
        u->load_error = r;
922
        unit_add_to_dbus_queue(u);
923
        unit_add_to_gc_queue(u);
924

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

Lennart Poettering's avatar
Lennart Poettering committed
927
928
929
        return r;
}

930
931
932
bool unit_condition_test(Unit *u) {
        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
933
934
        dual_timestamp_get(&u->condition_timestamp);
        u->condition_result = condition_test_list(u->conditions);
935

Michal Schmidt's avatar
Michal Schmidt committed
936
        return u->condition_result;
937
938
}

939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
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
954
/* Errors:
955
956
957
958
 *         -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
959
960
961
 */
int unit_start(Unit *u) {
        UnitActiveState state;
962
        Unit *following;
Lennart Poettering's avatar
Lennart Poettering committed
963
964
965

        assert(u);

Michal Schmidt's avatar
Michal Schmidt committed
966
        if (u->load_state != UNIT_LOADED)
967
968
                return -EINVAL;

969
970
971
972
        /* 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
973
974
975
976
        state =