Features:
+* add a new systemd-project@.service that is very similar to user@.service but
+ uses DynamicUser=1 and no PAMName= to invoke an unprivileged somewhat
+ light-weight service manager. Use HOME=/var/lib/systemd/projects/%i as home
+ dir. Similar for $XDG_RUNTIME_DIR. Start project@%i.target. Use LogField= to
+ add a field identifying the project.
+
+* logind: add a new dbus call Sleep() which automatically redirects to one of
+ Suspend(), Hibernate(), SuspendThenHibernate() depending on what is
+ available, and also subject to some local configuration in
+ logind.conf. Should default to SuspendThenHibernate() if available, and then
+ fallback to Suspend() and finally Hibernate() if not. Then expose this as
+ "systemctl sleep", and tell DEs to default to this.
+
* in sd-boot and sd-stub measure the SMBIOS vendor strings to some PCR (at
least some subset of them that look like systemd stuff), because apparently
some firmware does not, but systemd honours it. avoid duplicate measurement
<varlistentry>
<term><varname>HibernateMode=</varname></term>
- <term><varname>HybridSleepMode=</varname></term>
- <listitem><para>The string to be written to <filename>/sys/power/disk</filename> by, respectively,
- <citerefentry><refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- and
- <citerefentry><refentrytitle>systemd-hybrid-sleep.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ <listitem><para>The string to be written to <filename>/sys/power/disk</filename> by <citerefentry>
+ <refentrytitle>systemd-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
More than one value can be specified by separating multiple values with whitespace. They will be
tried in turn, until one is written without error. If none of the writes succeed, the operation will
be aborted.</para>
url="https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation">the
kernel documentation</ulink> for more details.</para>
- <para>Note that hybrid sleep corresponds to the <literal>suspend</literal> disk mode. If <varname>HybridSleepMode=</varname>
- is overridden, you might get plain hibernation instead.</para>
-
<para>
<citerefentry><refentrytitle>systemd-suspend-then-hibernate.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
uses the value of <varname>SuspendMode=</varname> when suspending and the value of
static int can_do = -1;
int r;
+ assert(name);
+ assert(l < SIZE_MAX);
+
if (can_do == 0)
return 0;
can_do = false; /* We'll set it to true only if the whole process works */
char *nn;
nn_size = PAGE_ALIGN(l+1);
+ if (nn_size >= SIZE_MAX)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "The requested argument is too long.");
+
nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (nn == MAP_FAILED)
return log_debug_errno(errno, "mmap() failed: %m");
return -EIO;
}
- if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
+ if (lseek(fd, n, SEEK_CUR) < 0)
return -errno;
q += n;
#error "neither int nor long are four bytes long?!?"
#endif
+static inline uint64_t u64_multiply_safe(uint64_t a, uint64_t b) {
+ if (_unlikely_(a != 0 && b > (UINT64_MAX / a)))
+ return 0; /* overflow */
+
+ return a * b;
+}
+
/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
static inline unsigned long ALIGN_POWER2(unsigned long u) {
#include "memory-util-fundamental.h"
size_t page_size(void) _pure_;
-#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-#define PAGE_ALIGN_DOWN(l) ((l) & ~(page_size() - 1))
-#define PAGE_OFFSET(l) ((l) & (page_size() - 1))
+#define PAGE_ALIGN(l) ALIGN_TO(l, page_size())
+#define PAGE_ALIGN_U64(l) ALIGN_TO_U64(l, page_size())
+#define PAGE_ALIGN_DOWN(l) ALIGN_DOWN(l, page_size())
+#define PAGE_ALIGN_DOWN_U64(l) ALIGN_DOWN_U64(l, page_size())
+#define PAGE_OFFSET(l) ALIGN_OFFSET(l, page_size())
+#define PAGE_OFFSET_U64(l) ALIGN_OFFSET_U64(l, page_size())
/* Normal memcpy() requires src to be nonnull. We do nothing if n is 0. */
static inline void *memcpy_safe(void *dst, const void *src, size_t n) {
if (r < 0)
return r;
- if (lseek(fd_from, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd_from, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek in \"%s\": %m", from);
fd_to = safe_close(fd_to);
void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
_cleanup_close_ int _fd = -EBADF, lock_fd = -EBADF;
- const char *path = exec_context_tty_path(ASSERT_PTR(context));
int fd;
+ assert(context);
+
+ const char *path = exec_context_tty_path(context);
+
if (p && p->stdin_fd >= 0)
fd = p->stdin_fd;
else if (path) {
fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
- return;
+ return (void) log_debug_errno(fd, "Failed to open terminal '%s', ignoring: %m", path);
} else
return; /* nothing to do */
/* Take a synchronization lock for the duration of the setup that we do here.
- * systemd-vconsole-setup.service also takes the lock to avoid being interrupted.
- * We open a new fd that will be closed automatically, and operate on it for convenience.
- */
+ * systemd-vconsole-setup.service also takes the lock to avoid being interrupted. We open a new fd
+ * that will be closed automatically, and operate on it for convenience. */
lock_fd = lock_dev_console();
if (lock_fd < 0)
return (void) log_debug_errno(lock_fd,
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to serialize parameters: %m");
- if (fseeko(f, 0, SEEK_SET) == (off_t) -1)
+ if (fseeko(f, 0, SEEK_SET) < 0)
return log_unit_error_errno(unit, errno, "Failed to reseek on serialization stream: %m");
r = fd_cloexec(fileno(f), false);
if (r < 0)
return r;
- if (fseeko(f, 0, SEEK_SET) == (off_t) -1)
+ if (fseeko(f, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to rewind serialization fd: %m");
r = fd_cloexec(fileno(f), false);
_cleanup_close_ int fd_compressed = -EBADF;
uint64_t uncompressed_size = 0;
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek on coredump %s: %m", fn);
fn_compressed = strjoin(fn, default_compression_extension());
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp));
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek on coredump %s: %m", fn);
*ret_filename = TAKE_PTR(fn);
assert(ret);
assert(ret_size);
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_warning_errno(errno, "Failed to seek: %m");
field = malloc(9 + size);
static uint32_t arg_tpm2_seal_key_handle = 0;
static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL;
static size_t arg_tpm2_n_hash_pcr_values = 0;
-static bool arg_tpm2_hash_pcr_values_use_default = true;
static bool arg_tpm2_pin = false;
static char *arg_tpm2_public_key = NULL;
static uint32_t arg_tpm2_public_key_pcr_mask = 0;
-static bool arg_tpm2_public_key_pcr_mask_use_default = true;
static char *arg_tpm2_signature = NULL;
static char *arg_node = NULL;
static int *arg_wipe_slots = NULL;
{}
};
+ bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true;
int c, r;
assert(argc >= 0);
break;
case ARG_TPM2_PCRS:
- arg_tpm2_hash_pcr_values_use_default = false;
+ auto_hash_pcr_values = false;
r = tpm2_parse_pcr_argument_append(optarg, &arg_tpm2_hash_pcr_values, &arg_tpm2_n_hash_pcr_values);
if (r < 0)
return r;
break;
case ARG_TPM2_PUBLIC_KEY_PCRS:
- arg_tpm2_public_key_pcr_mask_use_default = false;
+ auto_public_key_pcr_mask = false;
r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
if (r < 0)
return r;
}
}
- if ((arg_enroll_type == ENROLL_FIDO2 && arg_unlock_type == UNLOCK_FIDO2)
- && !(arg_fido2_device && arg_unlock_fido2_device))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "When both enrolling and unlocking with FIDO2 tokens, automatic discovery is unsupported. "
- "Please specify device paths for enrolling and unlocking respectively.");
+ if (arg_enroll_type == ENROLL_FIDO2) {
- if (arg_enroll_type == ENROLL_FIDO2 && !arg_fido2_device) {
- r = fido2_find_device_auto(&arg_fido2_device);
- if (r < 0)
- return r;
+ if (arg_unlock_type == UNLOCK_FIDO2 && !(arg_fido2_device && arg_unlock_fido2_device))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "When both enrolling and unlocking with FIDO2 tokens, automatic discovery is unsupported. "
+ "Please specify device paths for enrolling and unlocking respectively.");
+
+ if (!arg_fido2_device) {
+ r = fido2_find_device_auto(&arg_fido2_device);
+ if (r < 0)
+ return r;
+ }
}
if (optind >= argc)
if (r < 0)
return r;
- if (arg_tpm2_public_key_pcr_mask_use_default && arg_tpm2_public_key)
+ if (auto_public_key_pcr_mask && arg_tpm2_public_key)
arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
- if (arg_tpm2_hash_pcr_values_use_default && !GREEDY_REALLOC_APPEND(
+ if (auto_hash_pcr_values && !GREEDY_REALLOC_APPEND(
arg_tpm2_hash_pcr_values,
arg_tpm2_n_hash_pcr_values,
&TPM2_PCR_VALUE_MAKE(TPM2_PCR_INDEX_DEFAULT, /* hash= */ 0, /* value= */ {}),
if (l > SIZE_MAX - (ali - 1))
return SIZE_MAX; /* indicate overflow */
- return ((l + ali - 1) & ~(ali - 1));
+ return ((l + (ali - 1)) & ~(ali - 1));
+}
+
+static inline uint64_t ALIGN_TO_U64(uint64_t l, uint64_t ali) {
+ assert(ISPOWEROF2(ali));
+
+ if (l > UINT64_MAX - (ali - 1))
+ return UINT64_MAX; /* indicate overflow */
+
+ return ((l + (ali - 1)) & ~(ali - 1));
+}
+
+static inline size_t ALIGN_DOWN(size_t l, size_t ali) {
+ assert(ISPOWEROF2(ali));
+
+ return l & ~(ali - 1);
+}
+
+static inline uint64_t ALIGN_DOWN_U64(uint64_t l, uint64_t ali) {
+ assert(ISPOWEROF2(ali));
+
+ return l & ~(ali - 1);
+}
+
+static inline size_t ALIGN_OFFSET(size_t l, size_t ali) {
+ assert(ISPOWEROF2(ali));
+
+ return l & (ali - 1);
+}
+
+static inline uint64_t ALIGN_OFFSET_U64(uint64_t l, uint64_t ali) {
+ assert(ISPOWEROF2(ali));
+
+ return l & (ali - 1);
}
#define ALIGN2(l) ALIGN_TO(l, 2)
return 0;
}
- if (lseek(fd, SEEK_SET, 0) == (off_t) -1)
+ if (lseek(fd, SEEK_SET, 0) < 0)
return log_error_errno(errno, "Failed to seek to beginning of memfd: %m");
f = take_fdopen(&fd, "r");
"Target file is not a regular file or block device");
if (i->offset != UINT64_MAX) {
- if (lseek(i->output_fd, i->offset, SEEK_SET) == (off_t) -1)
+ if (lseek(i->output_fd, i->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to offset: %m");
}
return 0;
p = lseek(i->input_fd, 0, SEEK_CUR);
- if (p == (off_t) -1)
+ if (p < 0)
return log_error_errno(errno, "Failed to read file offset of input file: %m");
/* Let's only try a btrfs reflink, if we are reading from the beginning of the file */
return log_error_errno(errno, "Failed to stat disk file: %m");
if (j->offset != UINT64_MAX) {
- if (lseek(j->disk_fd, j->offset, SEEK_SET) == (off_t) -1)
+ if (lseek(j->disk_fd, j->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek on file descriptor: %m");
}
}
assert(i->raw_job->disk_fd >= 0);
assert(i->offset == UINT64_MAX);
- if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1)
+ if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) < 0)
return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m");
}
}
sz = ftello(m->tmp);
- if (sz == (off_t) -1) {
+ if (sz < 0) {
log_error_errno(errno, "Failed to retrieve file position: %m");
return MHD_CONTENT_READER_END_WITH_ERROR;
}
}
sz = ftello(m->tmp);
- if (sz == (off_t) -1) {
+ if (sz < 0) {
log_error_errno(errno, "Failed to retrieve file position: %m");
return MHD_CONTENT_READER_END_WITH_ERROR;
}
/* The file is sealed, we can just map it and use it. */
ps = PAGE_ALIGN(st.st_size);
+ assert(ps < SIZE_MAX);
p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
if (p == MAP_FAILED) {
log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
#include "memory-util.h"
void close_and_munmap(int fd, void *address, size_t size) {
- if (size > 0)
- assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
+ if (size > 0) {
+ size = PAGE_ALIGN(size);
+ assert(size < SIZE_MAX);
+ assert_se(munmap(address, size) >= 0);
+ }
safe_close(fd);
}
shift = PAGE_OFFSET(part->memfd_offset);
psz = PAGE_ALIGN(part->size + shift);
+ if (psz >= SIZE_MAX)
+ return -EFBIG;
if (part->memfd >= 0)
p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
if (le64toh(header->start_usec) <= 0 || le64toh(header->interval_usec) <= 0)
return -EBADMSG;
- f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ size_t sz = PAGE_ALIGN(f->fss_file_size);
+ assert(sz < SIZE_MAX);
+ f->fss_file = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (f->fss_file == MAP_FAILED) {
f->fss_file = NULL;
return -errno;
#define DEFAULT_COMPRESS_THRESHOLD (512ULL)
#define MIN_COMPRESS_THRESHOLD (8ULL)
+#define U64_KB UINT64_C(1024)
+#define U64_MB (UINT64_C(1024) * U64_KB)
+#define U64_GB (UINT64_C(1024) * U64_MB)
+
/* This is the minimum journal file size */
-#define JOURNAL_FILE_SIZE_MIN (512 * 1024ULL) /* 512 KiB */
-#define JOURNAL_COMPACT_SIZE_MAX UINT32_MAX /* 4 GiB */
+#define JOURNAL_FILE_SIZE_MIN (512 * U64_KB) /* 512 KiB */
+#define JOURNAL_COMPACT_SIZE_MAX ((uint64_t) UINT32_MAX) /* 4 GiB */
-/* These are the lower and upper bounds if we deduce the max_use value
- * from the file system size */
-#define MAX_USE_LOWER (1 * 1024 * 1024ULL) /* 1 MiB */
-#define MAX_USE_UPPER (4 * 1024 * 1024 * 1024ULL) /* 4 GiB */
+/* These are the lower and upper bounds if we deduce the max_use value from the file system size */
+#define MAX_USE_LOWER (1 * U64_MB) /* 1 MiB */
+#define MAX_USE_UPPER (4 * U64_GB) /* 4 GiB */
/* Those are the lower and upper bounds for the minimal use limit,
* i.e. how much we'll use even if keep_free suggests otherwise. */
-#define MIN_USE_LOW (1 * 1024 * 1024ULL) /* 1 MiB */
-#define MIN_USE_HIGH (16 * 1024 * 1024ULL) /* 16 MiB */
+#define MIN_USE_LOW (1 * U64_MB) /* 1 MiB */
+#define MIN_USE_HIGH (16 * U64_MB) /* 16 MiB */
/* This is the upper bound if we deduce max_size from max_use */
-#define MAX_SIZE_UPPER (128 * 1024 * 1024ULL) /* 128 MiB */
+#define MAX_SIZE_UPPER (128 * U64_MB) /* 128 MiB */
-/* This is the upper bound if we deduce the keep_free value from the
- * file system size */
-#define KEEP_FREE_UPPER (4 * 1024 * 1024 * 1024ULL) /* 4 GiB */
+/* This is the upper bound if we deduce the keep_free value from the file system size */
+#define KEEP_FREE_UPPER (4 * U64_GB) /* 4 GiB */
-/* This is the keep_free value when we can't determine the system
- * size */
-#define DEFAULT_KEEP_FREE (1024 * 1024ULL) /* 1 MB */
+/* This is the keep_free value when we can't determine the system size */
+#define DEFAULT_KEEP_FREE (1 * U64_MB) /* 1 MB */
/* This is the default maximum number of journal files to keep around. */
#define DEFAULT_N_MAX_FILES 100
#define CHAIN_CACHE_MAX 20
/* How much to increase the journal file size at once each time we allocate something new. */
-#define FILE_SIZE_INCREASE (8 * 1024 * 1024ULL) /* 8MB */
+#define FILE_SIZE_INCREASE (8 * U64_MB) /* 8MB */
/* Reread fstat() of the file for detecting deletions at least this often */
#define LAST_STAT_REFRESH_USEC (5*USEC_PER_SEC)
#endif
#if HAVE_GCRYPT
- if (f->fss_file)
- munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
- else
+ if (f->fss_file) {
+ size_t sz = PAGE_ALIGN(f->fss_file_size);
+ assert(sz < SIZE_MAX);
+ munmap(f->fss_file, sz);
+ } else
free(f->fsprg_state);
free(f->fsprg_seed);
/* We assume that this file is not sparse, and we know that for sure, since we always call
* posix_fallocate() ourselves */
- if (size > PAGE_ALIGN_DOWN(UINT64_MAX) - offset)
+ if (size > PAGE_ALIGN_DOWN_U64(UINT64_MAX) - offset)
return -EINVAL;
if (mmap_cache_fd_got_sigbus(f->cache_fd))
old_header_size = le64toh(READ_NOW(f->header->header_size));
old_arena_size = le64toh(READ_NOW(f->header->arena_size));
- if (old_arena_size > PAGE_ALIGN_DOWN(UINT64_MAX) - old_header_size)
+ if (old_arena_size > PAGE_ALIGN_DOWN_U64(UINT64_MAX) - old_header_size)
return -EBADMSG;
old_size = old_header_size + old_arena_size;
- new_size = MAX(PAGE_ALIGN(offset + size), old_header_size);
+ new_size = MAX(PAGE_ALIGN_U64(offset + size), old_header_size);
if (new_size <= old_size) {
if (fstatvfs(f->fd, &svfs) >= 0) {
uint64_t available;
- available = LESS_BY((uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize, f->metrics.keep_free);
+ available = LESS_BY(u64_multiply_safe(svfs.f_bfree, svfs.f_bsize), f->metrics.keep_free);
if (new_size - old_size > available)
return -E2BIG;
assert(fd >= 0);
if (fstatvfs(fd, &ss) >= 0)
- fs_size = ss.f_frsize * ss.f_blocks;
+ fs_size = u64_multiply_safe(ss.f_frsize, ss.f_blocks);
else
log_debug_errno(errno, "Failed to determine disk size: %m");
if (m->max_use == UINT64_MAX) {
if (fs_size > 0)
- m->max_use = CLAMP(PAGE_ALIGN(fs_size / 10), /* 10% of file system size */
+ m->max_use = CLAMP(PAGE_ALIGN_U64(fs_size / 10), /* 10% of file system size */
MAX_USE_LOWER, MAX_USE_UPPER);
else
m->max_use = MAX_USE_LOWER;
} else {
- m->max_use = PAGE_ALIGN(m->max_use);
+ m->max_use = PAGE_ALIGN_U64(m->max_use);
if (m->max_use != 0 && m->max_use < JOURNAL_FILE_SIZE_MIN*2)
m->max_use = JOURNAL_FILE_SIZE_MIN*2;
if (m->min_use == UINT64_MAX) {
if (fs_size > 0)
- m->min_use = CLAMP(PAGE_ALIGN(fs_size / 50), /* 2% of file system size */
+ m->min_use = CLAMP(PAGE_ALIGN_U64(fs_size / 50), /* 2% of file system size */
MIN_USE_LOW, MIN_USE_HIGH);
else
m->min_use = MIN_USE_LOW;
m->min_use = m->max_use;
if (m->max_size == UINT64_MAX)
- m->max_size = MIN(PAGE_ALIGN(m->max_use / 8), /* 8 chunks */
+ m->max_size = MIN(PAGE_ALIGN_U64(m->max_use / 8), /* 8 chunks */
MAX_SIZE_UPPER);
else
- m->max_size = PAGE_ALIGN(m->max_size);
+ m->max_size = PAGE_ALIGN_U64(m->max_size);
if (compact && m->max_size > JOURNAL_COMPACT_SIZE_MAX)
m->max_size = JOURNAL_COMPACT_SIZE_MAX;
if (m->min_size == UINT64_MAX)
m->min_size = JOURNAL_FILE_SIZE_MIN;
else
- m->min_size = CLAMP(PAGE_ALIGN(m->min_size),
+ m->min_size = CLAMP(PAGE_ALIGN_U64(m->min_size),
JOURNAL_FILE_SIZE_MIN,
m->max_size ?: UINT64_MAX);
if (m->keep_free == UINT64_MAX) {
if (fs_size > 0)
- m->keep_free = MIN(PAGE_ALIGN(fs_size / 20), /* 5% of file system size */
+ m->keep_free = MIN(PAGE_ALIGN_U64(fs_size / 20), /* 5% of file system size */
KEEP_FREE_UPPER);
else
m->keep_free = DEFAULT_KEEP_FREE;
/* Tiny windows increase mmap activity and the chance of exposing unsafe use. */
# define WINDOW_SIZE (page_size())
#else
-# define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
+# define WINDOW_SIZE ((size_t) (UINT64_C(8) * UINT64_C(1024) * UINT64_C(1024)))
#endif
MMapCache* mmap_cache_new(void) {
struct stat *st,
Window **ret) {
- uint64_t woffset, wsize;
Window *w;
void *d;
int r;
assert(size > 0);
assert(ret);
- woffset = offset & ~((uint64_t) page_size() - 1ULL);
- wsize = size + (offset - woffset);
- wsize = PAGE_ALIGN(wsize);
+ /* overflow check */
+ if (size > SIZE_MAX - PAGE_OFFSET_U64(offset))
+ return -EADDRNOTAVAIL;
- if (wsize < WINDOW_SIZE) {
- uint64_t delta;
-
- delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2);
+ size = PAGE_ALIGN(size + PAGE_OFFSET_U64(offset));
+ offset = PAGE_ALIGN_DOWN_U64(offset);
- if (delta > offset)
- woffset = 0;
- else
- woffset -= delta;
+ if (size < WINDOW_SIZE) {
+ uint64_t delta;
- wsize = WINDOW_SIZE;
+ delta = PAGE_ALIGN((WINDOW_SIZE - size) / 2);
+ offset = LESS_BY(offset, delta);
+ size = WINDOW_SIZE;
}
if (st) {
/* Memory maps that are larger then the files underneath have undefined behavior. Hence,
* clamp things to the file size if we know it */
- if (woffset >= (uint64_t) st->st_size)
+ if (offset >= (uint64_t) st->st_size)
return -EADDRNOTAVAIL;
- if (woffset + wsize > (uint64_t) st->st_size)
- wsize = PAGE_ALIGN(st->st_size - woffset);
+ if (size > (uint64_t) st->st_size - offset)
+ size = PAGE_ALIGN((uint64_t) st->st_size - offset);
}
- r = mmap_try_harder(f, NULL, MAP_SHARED, woffset, wsize, &d);
+ if (size >= SIZE_MAX)
+ return -EADDRNOTAVAIL;
+
+ r = mmap_try_harder(f, NULL, MAP_SHARED, offset, size, &d);
if (r < 0)
return r;
- w = window_add(f, woffset, wsize, d);
+ w = window_add(f, offset, size, d);
if (!w) {
- (void) munmap(d, wsize);
+ (void) munmap(d, size);
return -ENOMEM;
}
assert(operation);
assert(operation->extra_fd >= 0);
- if (lseek(operation->extra_fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(operation->extra_fd, 0, SEEK_SET) < 0)
return -errno;
f = take_fdopen(&operation->extra_fd, "r");
};
if (!need_path) {
- if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
+ if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
t->whole_fd = whole_fd;
} else if (t->fd >= 0) {
struct stat st;
- if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
+ if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
- if (lseek(t->fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(t->fd, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to start of temporary file: %m");
if (fstat(t->fd, &st) < 0)
if (r < 0)
return log_error_errno(r, "Failed to pad string to %s", FORMAT_BYTES(p->new_size));
- if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
+ if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition %s offset: %m", strna(hint));
r = loop_write(whole_fd, text, p->new_size);
* _cleanup_() so that we really delete this, even on failure. */
if (c->dir_fd >= 0) {
+ /* <dir_fd> might be have already been used for reading, so we need to rewind it. */
+ if (lseek(c->dir_fd, 0, SEEK_SET) < 0)
+ log_debug_errno(errno, "Failed to lseek on file descriptor, ignoring: %m");
+
r = rm_rf_children(TAKE_FD(c->dir_fd), REMOVE_PHYSICAL, NULL); /* consumes dir_fd in all cases, even on failure */
if (r < 0)
log_debug_errno(r, "Failed to remove hardlink store (%s) contents, ignoring: %m", c->subdir);
assert(fd >= 0);
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_warning_errno(errno, "Failed to seek to beginning of the core file: %m");
if (ret && !memstream_init(&c.m))
assert(fd >= 0);
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_warning_errno(errno, "Failed to seek to beginning of the ELF file: %m");
if (ret && !memstream_init(&c.m))
}
if (writable) {
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek %s: %m", etc_machine_id);
if (ftruncate(fd, 0) < 0)
}
static int mount_in_namespace(
- PidRef *target,
+ const PidRef *target,
const char *propagate_path,
const char *incoming_path,
const char *src,
strna(path));
}
}
-
- /* Make sure we reset the iterator since we don't know the state the passed in file
- * descriptor is in. */
- rewinddir(d);
}
FOREACH_DIRENT_ALL(de, d, return -errno) {
int fstatat_flags,
RemoveFlags remove_flags);
+/* Note: directory file descriptors passed to the functions below must be
+ * positioned at the beginning. If the fd was already used for reading, rewind it. */
int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev);
int rm_rf_child(int fd, const char *name, RemoveFlags flags);
int rm_rf_at(int dir_fd, const char *path, RemoveFlags flags);
static char* const* const sleep_default_mode_table[_SLEEP_OPERATION_CONFIG_MAX] = {
/* Not used by SLEEP_SUSPEND */
[SLEEP_HIBERNATE] = STRV_MAKE("platform", "shutdown"),
- [SLEEP_HYBRID_SLEEP] = STRV_MAKE("suspend", "platform", "shutdown"),
+ [SLEEP_HYBRID_SLEEP] = STRV_MAKE("suspend"),
};
SleepConfig* sleep_config_free(SleepConfig *sc) {
if (strv_contains(sc->modes[SLEEP_HIBERNATE], "suspend"))
log_warning("Sleep mode 'suspend' should not be used by operation %s. Please use %s instead.",
sleep_operation_to_string(SLEEP_HIBERNATE), sleep_operation_to_string(SLEEP_HYBRID_SLEEP));
-
- if (!strv_contains(sc->modes[SLEEP_HYBRID_SLEEP], "suspend"))
- log_warning("Sleep mode 'suspend' is not set for operation %s. This would likely result in a plain hibernation.",
- sleep_operation_to_string(SLEEP_HYBRID_SLEEP));
}
int parse_sleep_config(SleepConfig **ret) {
};
const ConfigTableItem items[] = {
- { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend },
- { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate },
- { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h },
- { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep },
+ { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend },
+ { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate },
+ { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h },
+ { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep },
- { "Sleep", "SuspendState", config_parse_strv, 0, sc->states + SLEEP_SUSPEND },
- { "Sleep", "SuspendMode", config_parse_warn_compat, DISABLED_LEGACY, NULL },
+ { "Sleep", "SuspendState", config_parse_strv, 0, sc->states + SLEEP_SUSPEND },
+ { "Sleep", "SuspendMode", config_parse_warn_compat, DISABLED_LEGACY, NULL },
- { "Sleep", "HibernateState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
- { "Sleep", "HibernateMode", config_parse_strv, 0, sc->modes + SLEEP_HIBERNATE },
+ { "Sleep", "HibernateState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
+ { "Sleep", "HibernateMode", config_parse_strv, 0, sc->modes + SLEEP_HIBERNATE },
- { "Sleep", "HybridSleepState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
- { "Sleep", "HybridSleepMode", config_parse_strv, 0, sc->modes + SLEEP_HYBRID_SLEEP },
+ { "Sleep", "HybridSleepState", config_parse_warn_compat, DISABLED_LEGACY, NULL },
+ { "Sleep", "HybridSleepMode", config_parse_warn_compat, DISABLED_LEGACY, NULL },
- { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
- { "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
+ { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
+ { "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
{}
};
if (r < 0)
return log_debug_errno(r, "Failed to format JSON: %m");
- if (lseek(fd, 0, SEEK_END) == (off_t) -1)
+ if (lseek(fd, 0, SEEK_END) < 0)
return log_debug_errno(errno, "Failed to seek to end of JSON log: %m");
r = loop_write(fd, f, SIZE_MAX);
#AllowHybridSleep=yes
#SuspendState=mem standby freeze
#HibernateMode=platform shutdown
-#HybridSleepMode=suspend platform shutdown
#HibernateDelaySec=
#SuspendEstimationSec=60min
assert_se(ALIGN_TO(SIZE_MAX-1, 4) == SIZE_MAX); /* overflow */
assert_se(ALIGN_TO(SIZE_MAX, 4) == SIZE_MAX); /* overflow */
+ assert_se(ALIGN_TO_U64(0, 1) == 0);
+ assert_se(ALIGN_TO_U64(1, 1) == 1);
+ assert_se(ALIGN_TO_U64(2, 1) == 2);
+ assert_se(ALIGN_TO_U64(3, 1) == 3);
+ assert_se(ALIGN_TO_U64(4, 1) == 4);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-1, 1) == UINT64_MAX-1);
+ assert_se(ALIGN_TO_U64(UINT64_MAX, 1) == UINT64_MAX);
+
+ assert_se(ALIGN_TO_U64(0, 2) == 0);
+ assert_se(ALIGN_TO_U64(1, 2) == 2);
+ assert_se(ALIGN_TO_U64(2, 2) == 2);
+ assert_se(ALIGN_TO_U64(3, 2) == 4);
+ assert_se(ALIGN_TO_U64(4, 2) == 4);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-3, 2) == UINT64_MAX-3);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-2, 2) == UINT64_MAX-1);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-1, 2) == UINT64_MAX-1);
+ assert_se(ALIGN_TO_U64(UINT64_MAX, 2) == UINT64_MAX); /* overflow */
+
+ assert_se(ALIGN_TO_U64(0, 4) == 0);
+ assert_se(ALIGN_TO_U64(1, 4) == 4);
+ assert_se(ALIGN_TO_U64(2, 4) == 4);
+ assert_se(ALIGN_TO_U64(3, 4) == 4);
+ assert_se(ALIGN_TO_U64(4, 4) == 4);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-3, 4) == UINT64_MAX-3);
+ assert_se(ALIGN_TO_U64(UINT64_MAX-2, 4) == UINT64_MAX); /* overflow */
+ assert_se(ALIGN_TO_U64(UINT64_MAX-1, 4) == UINT64_MAX); /* overflow */
+ assert_se(ALIGN_TO_U64(UINT64_MAX, 4) == UINT64_MAX); /* overflow */
+
assert_cc(CONST_ALIGN_TO(96, 512) == 512);
assert_cc(CONST_ALIGN_TO(511, 512) == 512);
assert_cc(CONST_ALIGN_TO(512, 512) == 512);
assert_cc(__builtin_types_compatible_p(typeof(CONST_ALIGN_TO(SIZE_MAX, 512)), void));
}
+TEST(align_down) {
+ assert_se(ALIGN_DOWN(0, 1) == 0);
+ assert_se(ALIGN_DOWN(1, 1) == 1);
+ assert_se(ALIGN_DOWN(2, 1) == 2);
+ assert_se(ALIGN_DOWN(3, 1) == 3);
+ assert_se(ALIGN_DOWN(4, 1) == 4);
+ assert_se(ALIGN_DOWN(SIZE_MAX-1, 1) == SIZE_MAX-1);
+ assert_se(ALIGN_DOWN(SIZE_MAX, 1) == SIZE_MAX);
+
+ assert_se(ALIGN_DOWN(0, 2) == 0);
+ assert_se(ALIGN_DOWN(1, 2) == 0);
+ assert_se(ALIGN_DOWN(2, 2) == 2);
+ assert_se(ALIGN_DOWN(3, 2) == 2);
+ assert_se(ALIGN_DOWN(4, 2) == 4);
+ assert_se(ALIGN_DOWN(SIZE_MAX-1, 2) == SIZE_MAX-1);
+ assert_se(ALIGN_DOWN(SIZE_MAX, 2) == SIZE_MAX-1);
+
+ assert_se(ALIGN_DOWN(0, 4) == 0);
+ assert_se(ALIGN_DOWN(1, 4) == 0);
+ assert_se(ALIGN_DOWN(2, 4) == 0);
+ assert_se(ALIGN_DOWN(3, 4) == 0);
+ assert_se(ALIGN_DOWN(4, 4) == 4);
+ assert_se(ALIGN_DOWN(SIZE_MAX-1, 4) == SIZE_MAX-3);
+ assert_se(ALIGN_DOWN(SIZE_MAX, 4) == SIZE_MAX-3);
+
+ assert_se(ALIGN_DOWN_U64(0, 1) == 0);
+ assert_se(ALIGN_DOWN_U64(1, 1) == 1);
+ assert_se(ALIGN_DOWN_U64(2, 1) == 2);
+ assert_se(ALIGN_DOWN_U64(3, 1) == 3);
+ assert_se(ALIGN_DOWN_U64(4, 1) == 4);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 1) == UINT64_MAX-1);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX, 1) == UINT64_MAX);
+
+ assert_se(ALIGN_DOWN_U64(0, 2) == 0);
+ assert_se(ALIGN_DOWN_U64(1, 2) == 0);
+ assert_se(ALIGN_DOWN_U64(2, 2) == 2);
+ assert_se(ALIGN_DOWN_U64(3, 2) == 2);
+ assert_se(ALIGN_DOWN_U64(4, 2) == 4);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 2) == UINT64_MAX-1);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX, 2) == UINT64_MAX-1);
+
+ assert_se(ALIGN_DOWN_U64(0, 4) == 0);
+ assert_se(ALIGN_DOWN_U64(1, 4) == 0);
+ assert_se(ALIGN_DOWN_U64(2, 4) == 0);
+ assert_se(ALIGN_DOWN_U64(3, 4) == 0);
+ assert_se(ALIGN_DOWN_U64(4, 4) == 4);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX-1, 4) == UINT64_MAX-3);
+ assert_se(ALIGN_DOWN_U64(UINT64_MAX, 4) == UINT64_MAX-3);
+}
+
+TEST(align_offset) {
+ assert_se(ALIGN_OFFSET(0, 1) == 0);
+ assert_se(ALIGN_OFFSET(1, 1) == 0);
+ assert_se(ALIGN_OFFSET(2, 1) == 0);
+ assert_se(ALIGN_OFFSET(3, 1) == 0);
+ assert_se(ALIGN_OFFSET(4, 1) == 0);
+ assert_se(ALIGN_OFFSET(SIZE_MAX-1, 1) == 0);
+ assert_se(ALIGN_OFFSET(SIZE_MAX, 1) == 0);
+
+ assert_se(ALIGN_OFFSET(0, 2) == 0);
+ assert_se(ALIGN_OFFSET(1, 2) == 1);
+ assert_se(ALIGN_OFFSET(2, 2) == 0);
+ assert_se(ALIGN_OFFSET(3, 2) == 1);
+ assert_se(ALIGN_OFFSET(4, 2) == 0);
+ assert_se(ALIGN_OFFSET(SIZE_MAX-1, 2) == 0);
+ assert_se(ALIGN_OFFSET(SIZE_MAX, 2) == 1);
+
+ assert_se(ALIGN_OFFSET(0, 4) == 0);
+ assert_se(ALIGN_OFFSET(1, 4) == 1);
+ assert_se(ALIGN_OFFSET(2, 4) == 2);
+ assert_se(ALIGN_OFFSET(3, 4) == 3);
+ assert_se(ALIGN_OFFSET(4, 4) == 0);
+ assert_se(ALIGN_OFFSET(SIZE_MAX-1, 4) == 2);
+ assert_se(ALIGN_OFFSET(SIZE_MAX, 4) == 3);
+
+ assert_se(ALIGN_OFFSET_U64(0, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(1, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(2, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(3, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(4, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 1) == 0);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 1) == 0);
+
+ assert_se(ALIGN_OFFSET_U64(0, 2) == 0);
+ assert_se(ALIGN_OFFSET_U64(1, 2) == 1);
+ assert_se(ALIGN_OFFSET_U64(2, 2) == 0);
+ assert_se(ALIGN_OFFSET_U64(3, 2) == 1);
+ assert_se(ALIGN_OFFSET_U64(4, 2) == 0);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 2) == 0);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 2) == 1);
+
+ assert_se(ALIGN_OFFSET_U64(0, 4) == 0);
+ assert_se(ALIGN_OFFSET_U64(1, 4) == 1);
+ assert_se(ALIGN_OFFSET_U64(2, 4) == 2);
+ assert_se(ALIGN_OFFSET_U64(3, 4) == 3);
+ assert_se(ALIGN_OFFSET_U64(4, 4) == 0);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX-1, 4) == 2);
+ assert_se(ALIGN_OFFSET_U64(UINT64_MAX, 4) == 3);
+}
+
TEST(flags) {
enum {
F1 = 1 << 0,
TEST_ROUND_UP_BY_TYPE(uint64_t, UINT64_MAX);
}
+TEST(u64_multiply_safe) {
+ assert_se(u64_multiply_safe(0, 0) == 0);
+ assert_se(u64_multiply_safe(10, 0) == 0);
+ assert_se(u64_multiply_safe(0, 10) == 0);
+ assert_se(u64_multiply_safe(10, 10) == 100);
+
+ assert_se(u64_multiply_safe(UINT64_MAX, 0) == 0);
+ assert_se(u64_multiply_safe(UINT64_MAX, 1) == UINT64_MAX);
+ assert_se(u64_multiply_safe(UINT64_MAX, 2) == 0);
+ assert_se(u64_multiply_safe(0, UINT64_MAX) == 0);
+ assert_se(u64_multiply_safe(1, UINT64_MAX) == UINT64_MAX);
+ assert_se(u64_multiply_safe(2, UINT64_MAX) == 0);
+
+ assert_se(u64_multiply_safe(UINT64_MAX / 2, 0) == 0);
+ assert_se(u64_multiply_safe(UINT64_MAX / 2, 1) == UINT64_MAX / 2);
+ assert_se(u64_multiply_safe(UINT64_MAX / 2, 2) == UINT64_MAX - 1);
+ assert_se(u64_multiply_safe(UINT64_MAX / 2, 3) == 0);
+ assert_se(u64_multiply_safe(0, UINT64_MAX / 2) == 0);
+ assert_se(u64_multiply_safe(1, UINT64_MAX / 2) == UINT64_MAX / 2);
+ assert_se(u64_multiply_safe(2, UINT64_MAX / 2) == UINT64_MAX - 1);
+ assert_se(u64_multiply_safe(3, UINT64_MAX / 2) == 0);
+
+ assert_se(u64_multiply_safe(UINT64_MAX, UINT64_MAX) == 0);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);
free(saved_iov);
}
+TEST(page_align) {
+ assert_se(PAGE_ALIGN(page_size() - 1) == page_size());
+ assert_se(PAGE_ALIGN(page_size() ) == page_size());
+ assert_se(PAGE_ALIGN(page_size() + 1) == page_size() * 2);
+ assert_se(PAGE_ALIGN(page_size() * 123 - 1) == page_size() * 123);
+ assert_se(PAGE_ALIGN(page_size() * 123 ) == page_size() * 123);
+ assert_se(PAGE_ALIGN(page_size() * 123 + 1) == page_size() * 124);
+ assert_se(PAGE_ALIGN(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN(SIZE_MAX - page_size() ) == SIZE_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN(SIZE_MAX - page_size() + 2) == SIZE_MAX); /* overflow */
+ assert_se(PAGE_ALIGN(SIZE_MAX) == SIZE_MAX); /* overflow */
+
+ assert_se(PAGE_ALIGN_U64(page_size() - 1) == page_size());
+ assert_se(PAGE_ALIGN_U64(page_size() ) == page_size());
+ assert_se(PAGE_ALIGN_U64(page_size() + 1) == page_size() * 2);
+ assert_se(PAGE_ALIGN_U64(page_size() * 123 - 1) == page_size() * 123);
+ assert_se(PAGE_ALIGN_U64(page_size() * 123 ) == page_size() * 123);
+ assert_se(PAGE_ALIGN_U64(page_size() * 123 + 1) == page_size() * 124);
+ assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() - 1) == UINT64_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() ) == UINT64_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() + 1) == UINT64_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN_U64(UINT64_MAX - page_size() + 2) == UINT64_MAX); /* overflow */
+ assert_se(PAGE_ALIGN_U64(UINT64_MAX) == UINT64_MAX); /* overflow */
+
+ assert_se(PAGE_ALIGN_DOWN(page_size() - 1) == 0);
+ assert_se(PAGE_ALIGN_DOWN(page_size() ) == page_size());
+ assert_se(PAGE_ALIGN_DOWN(page_size() + 1) == page_size());
+ assert_se(PAGE_ALIGN_DOWN(page_size() * 123 - 1) == page_size() * 122);
+ assert_se(PAGE_ALIGN_DOWN(page_size() * 123 ) == page_size() * 123);
+ assert_se(PAGE_ALIGN_DOWN(page_size() * 123 + 1) == page_size() * 123);
+ assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() * 2 + 1);
+ assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() ) == SIZE_MAX - page_size() * 2 + 1);
+ assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN_DOWN(SIZE_MAX - page_size() + 2) == SIZE_MAX - page_size() + 1);
+
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() - 1) == 0);
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() ) == page_size());
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() + 1) == page_size());
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123 - 1) == page_size() * 122);
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123 ) == page_size() * 123);
+ assert_se(PAGE_ALIGN_DOWN_U64(page_size() * 123 + 1) == page_size() * 123);
+ assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() - 1) == SIZE_MAX - page_size() * 2 + 1);
+ assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() ) == SIZE_MAX - page_size() * 2 + 1);
+ assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() + 1) == SIZE_MAX - page_size() + 1);
+ assert_se(PAGE_ALIGN_DOWN_U64(SIZE_MAX - page_size() + 2) == SIZE_MAX - page_size() + 1);
+
+ assert_se(PAGE_OFFSET(page_size() - 1) == page_size() - 1);
+ assert_se(PAGE_OFFSET(page_size() ) == 0);
+ assert_se(PAGE_OFFSET(page_size() + 1) == 1);
+ assert_se(PAGE_OFFSET(page_size() * 123 - 1) == page_size() - 1);
+ assert_se(PAGE_OFFSET(page_size() * 123 ) == 0);
+ assert_se(PAGE_OFFSET(page_size() * 123 + 1) == 1);
+ assert_se(PAGE_OFFSET(SIZE_MAX - page_size() - 1) == page_size() - 2);
+ assert_se(PAGE_OFFSET(SIZE_MAX - page_size() ) == page_size() - 1);
+ assert_se(PAGE_OFFSET(SIZE_MAX - page_size() + 1) == 0);
+ assert_se(PAGE_OFFSET(SIZE_MAX - page_size() + 2) == 1);
+
+ assert_se(PAGE_OFFSET_U64(page_size() - 1) == page_size() - 1);
+ assert_se(PAGE_OFFSET_U64(page_size() ) == 0);
+ assert_se(PAGE_OFFSET_U64(page_size() + 1) == 1);
+ assert_se(PAGE_OFFSET_U64(page_size() * 123 - 1) == page_size() - 1);
+ assert_se(PAGE_OFFSET_U64(page_size() * 123 ) == 0);
+ assert_se(PAGE_OFFSET_U64(page_size() * 123 + 1) == 1);
+ assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() - 1) == page_size() - 2);
+ assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() ) == page_size() - 1);
+ assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() + 1) == 0);
+ assert_se(PAGE_OFFSET_U64(UINT64_MAX - page_size() + 2) == 1);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);
TEST_DESCRIPTION="shutdown testing"
IMAGE_NAME="shutdown"
-TEST_NO_QEMU=1
+TEST_NO_QEMU=yes
+# Prevent shutdown in test suite, the expect script does that manually.
+TEST_SKIP_SHUTDOWN=yes
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
test_append_files() {
local workspace="${1:?}"
- # prevent shutdown in test suite, the expect script does that manually.
- mkdir -p "${workspace:?}/etc/systemd/system/end.service.d"
- cat >"$workspace/etc/systemd/system/end.service.d/99-override.conf" <<EOF
-[Service]
-ExecStart=
-ExecStart=/bin/true
+
+ # Shorten the service stop/abort timeouts to let systemd SIGKILL stubborn
+ # processes as soon as possible, as we don't really care about them in this
+ # particular test
+ mkdir -p "$workspace/etc/systemd/system.conf.d"
+ cat >"$workspace/etc/systemd/system.conf.d/99-timeout.conf" <<EOF
+[Manager]
+DefaultTimeoutStopSec=30s
+DefaultTimeoutAbortSec=30s
EOF
+
inst /usr/bin/screen
echo "PS1='screen\$WINDOW # '" >>"$workspace/root/.bashrc"
echo 'startup_message off' >"$workspace/etc/screenrc"
TEST_DESCRIPTION="Test Soft-Rebooting"
# We temporarily remount rootfs read-only, so ignore any missing coverage
IGNORE_MISSING_COVERAGE=yes
+# Prevent shutdown in test suite, the expect script does that manually.
+TEST_SKIP_SHUTDOWN=yes
# shellcheck source=test/test-functions
. "$TEST_BASE_DIR/test-functions"
-test_append_files() {
- local workspace="${1:?}"
- # prevent shutdown in test suite, the expect script does that manually.
- mkdir -p "${workspace:?}/etc/systemd/system/end.service.d"
- cat >"$workspace/etc/systemd/system/end.service.d/99-override.conf" <<EOF
-[Service]
-ExecStart=
-ExecStart=/bin/true
-EOF
-}
-
do_test "$@"
"systemd.unit=testsuite.target"
"systemd.wants=testsuite-$1.service"
"noresume"
+ "oops=panic"
${TEST_MATCH_SUBTEST:+"systemd.setenv=TEST_MATCH_SUBTEST=$TEST_MATCH_SUBTEST"}
${TEST_MATCH_TESTCASE:+"systemd.setenv=TEST_MATCH_TESTCASE=$TEST_MATCH_TESTCASE"}
)
- if ! get_bool "$INTERACTIVE_DEBUG"; then
+ if ! get_bool "$INTERACTIVE_DEBUG" && ! get_bool "$TEST_SKIP_SHUTDOWN"; then
kernel_params+=(
- "oops=panic"
"panic=1"
"systemd.wants=end.service"
)
if get_bool "$INTERACTIVE_DEBUG"; then
nspawn_options+=("--console=interactive")
- else
+ elif ! get_bool "$TEST_SKIP_SHUTDOWN"; then
kernel_params+=("systemd.wants=end.service")
fi