The code that is shared between components is split into a few directories, each with a different purpose:
-`src/basic/` and `src/fundamental/` — those directories contain code primitives that are used by all other code.
`src/fundamental/` is stricter, because it used for EFI and user-space code, while `src/basic/` is only used for user-space code.
The code in `src/fundamental/` cannot depend on any other code in the tree, and `src/basic/` can depend only on itself and `src/fundamental/`.
For user-space, a static library is built from this code and linked statically in various places.
-`src/libsystemd/` implements the `libsystemd.so` shared library (also available as static `libsystemd.a`).
This code may use anything in `src/basic/` or `src/fundamental/`.
-`src/shared/` provides various utilities and code shared between other components that is exposed as the `libsystemd-shared-<nnn>.so` shared library.
The other subdirectories implement individual components.
They may depend only on `src/fundamental/` + `src/basic/`, or also on `src/libsystemd/`, or also on `src/shared/`.
You might wonder what kind of code belongs where.
In general, the rule is that code should be linked as few times as possible, ideally only once.
Thus code that is used by "higher-level" components (e.g. our binaries which are linked to `libsystemd-shared-<nnn>.so`),
would go to a subdirectory specific to that component if it is only used there.
If the code is to be shared between components, it'd go to `src/shared/`.
Shared code that is used by multiple components that do not link to `libsystemd-shared-<nnn>.so` may live either in `src/libsystemd/`, `src/basic/`, or `src/fundamental/`.
Any code that is used only for EFI goes under `src/boot/efi/`, and `src/fundamental/` if is shared with non-EFI compoenents.
1.*unit**files* are parsed in `src/core/load-fragment.c`, with many simple and fixed-type unit settings being parsed by common helpers, with the definition in the generator file `src/core/load-fragment-gperf.gperf.in`
Source files found under `src/test/` implement unit-level testing, mostly for modules found in `src/basic/` and `src/shared/`, but not exclusively.
Each test file is compiled in a standalone binary that can be run to exercise the corresponding module.
While most of the tests can be run by any user, some require privileges, and will attempt to clearly log about what they need (mostly in the form of effective capabilities).
These tests are self-contained, and generally safe to run on the host without side effects.
Fuzzers are a type of unit tests that execute code on an externally-supplied input sample.
Fuzzers are called `fuzz-*`.
Fuzzers for `src/basic/` and `src/shared` live under `src/fuzz/`, and those for other parts of the codebase should be located next to the code they test.
Files under `test/fuzz/` contain input data for fuzzers, one subdirectory for each fuzzer.
Some of the files are "seed corpora", i.e. files that contain lists of settings and input values intended to generate initial coverage, and other files are samples saved by the fuzzing engines when they find an issue.
When adding new input samples under `test/fuzz/*/`, please use some short-but-meaningful names.
Names of meson tests include the input file name and output looks awkward if they are too long.
Fuzzers are invoked primarily in three ways:
firstly, each fuzzer is compiled as a normal executable and executed for each of the input samples under `test/fuzz/` as part of the test suite.
Secondly, fuzzers may be instrumented with sanitizers and invoked as part of the test suite (if `-Dfuzz-tests=true` is configured).
Thirdly, fuzzers are executed through fuzzing engines that tryto find new "interesting" inputs through coverage feedback and massive parallelization; see the links for oss-fuzz in [Code quality](/CODE_QUALITY).
Most of those tests should be able to run via `systemd-nspawn`, which is orders-of-magnitude faster than `qemu`, but some tests require privileged operations like using `dm-crypt` or `loopdev`.
Manpages for binaries and libraries, and the DBUS interfaces, can be found under `man/` and should ideally be kept in sync with changes to the corresponding binaries and libraries.
The Service Manager takes configuration in the form of unit files, credentials, kernel command line options and D-Bus commands, and based on those manages the system and spawns other processes.
It runs in system mode as PID1, and in user mode with one instance per user session.
When starting a unit requires forking a new process, configuration for the new process will be serialized and passed over to the new process, created via a posix_spawn() call.
This is done in order to avoid excessive processing after a fork() but before an exec(), which is against glibc's best practices and can also result in a copy-on-write trap.
The new process will start as the `systemd-executor` binary, which will deserialize the configuration and apply all the options (sandboxing, namespacing, cgroup, etc.) before exec'ing the configured executable.