subvolumes if the backing filesystem supports them. If set to `0`, these
lines will always create directories.
+`systemd-sysusers`
+
+* `SOURCE_DATE_EPOCH` — if unset, the field of the date of last password change
+ in `/etc/shadow` will be the number of days from Jan 1, 1970 00:00 UTC until
+ today. If SOURCE_DATE_EPOCH is set to a valid UNIX epoch value in seconds,
+ then the field will be the number of days until that time instead. This is to
+ support creating bit-by-bit reproducible system images by choosing a
+ reproducible value for the field of the date of last password change in
+ `/etc/shadow`. See: https://reproducible-builds.org/specs/source-date-epoch/
+
`systemd-sysv-generator`:
* `$SYSTEMD_SYSVINIT_PATH` — Controls where `systemd-sysv-generator` looks for
return parse_boolean(e);
}
+int getenv_uint64_secure(const char *p, uint64_t *ret) {
+ const char *e;
+
+ assert(p);
+
+ e = secure_getenv(p);
+ if (!e)
+ return -ENXIO;
+
+ return safe_atou64(e, ret);
+}
+
int set_unset_env(const char *name, const char *value, bool overwrite) {
assert(name);
int getenv_bool(const char *p);
int getenv_bool_secure(const char *p);
+int getenv_uint64_secure(const char *p, uint64_t *ret);
+
/* Like setenv, but calls unsetenv if value == NULL. */
int set_unset_env(const char *name, const char *value, bool overwrite);
#include "creds-util.h"
#include "def.h"
#include "dissect-image.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
return 0;
}
+static usec_t epoch_or_now(void) {
+ uint64_t epoch;
+
+ if (getenv_uint64_secure("SOURCE_DATE_EPOCH", &epoch) >= 0) {
+ if (epoch > UINT64_MAX/USEC_PER_SEC) /* Overflow check */
+ return USEC_INFINITY;
+ return (usec_t) epoch * USEC_PER_SEC;
+ }
+
+ return now(CLOCK_REALTIME);
+}
+
static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char **tmpfile_path) {
_cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
_cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
if (r < 0)
return log_debug_errno(r, "Failed to open temporary copy of %s: %m", shadow_path);
- lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
+ lstchg = (long) (epoch_or_now() / USEC_PER_DAY);
original = fopen(shadow_path, "re");
if (original) {