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);