unit.c 84.7 KB
Newer Older
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Lennart Poettering's avatar
Lennart Poettering committed
2

3
4
5
6
7
8
/***
  This file is part of systemd.

  Copyright 2010 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
9
10
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
11
12
13
14
15
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
  Lesser General Public License for more details.
17

18
  You should have received a copy of the GNU Lesser General Public License
19
20
21
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

Lennart Poettering's avatar
Lennart Poettering committed
22
23
24
25
26
27
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/poll.h>
28
29
#include <stdlib.h>
#include <unistd.h>
30
#include <sys/stat.h>
Lennart Poettering's avatar
Lennart Poettering committed
31

32
33
#include "systemd/sd-id128.h"
#include "systemd/sd-messages.h"
Lennart Poettering's avatar
Lennart Poettering committed
34
35
36
37
#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
Kay Sievers's avatar
Kay Sievers committed
38
#include "path-util.h"
Lennart Poettering's avatar
Lennart Poettering committed
39
40
41
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
42
#include "unit-name.h"
43
#include "dbus-unit.h"
44
#include "special.h"
45
#include "cgroup-util.h"
46
#include "missing.h"
47
#include "cgroup-attr.h"
48
#include "mkdir.h"
Lennart Poettering's avatar
Lennart Poettering committed
49
50
51
52
53
54
55
56
57

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

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

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

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

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

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

        return u;
}

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

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

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

        assert(u);
        assert(text);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);
        assert(name);

194
195
        if (unit_name_is_template(name)) {

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

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

                name = t;
        }

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

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

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

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

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

220
        unit_add_to_dbus_queue(u);
221

222
223
224
        return 0;
}

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

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

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

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

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

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

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

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

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

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

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

        return false;
}

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

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

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

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

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

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

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

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

        if (unit_check_gc(u))
                return;

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

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

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

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

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

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

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

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

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

        set_free(s);
}

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

        assert(u);

355
356
        bus_unit_send_removed_signal(u);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

508
509
        other = unit_follow_merge(other);

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

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

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

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

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

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

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

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

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

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

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

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

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

        return 0;
}

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

        assert(u);
        assert(name);

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

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

                name = s;
        }

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

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

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

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

        return u;
}

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

        assert(u);
        assert(c);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        free(v);
                }
758

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

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

Lennart Poettering's avatar
Lennart Poettering committed
769

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

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

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

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

        assert(u);

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

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

        assert(u);

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

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

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

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

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

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

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

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

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

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

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

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

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

        assert(u);

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

868
869
870
        return 0;
}

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

        assert(u);

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

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

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

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

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

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

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

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

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

                r = -EINVAL;
                goto fail;
        }

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

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

        return 0;

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

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

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

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

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

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

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

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

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

        format_table = &UNIT_VTABLE(u)->status_message_formats;
        if (!format_table)
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