Files
systemd/src/basic/memory-util.h
Daan De Meyer 74d392ed1b tree-wide: standardize header names across src/fundamental, src/basic and src/shared
Drop the -fundamental suffix from src/fundamental/ headers in favor of names
that match their src/basic/ or src/shared/ counterparts (e.g.
macro-fundamental.h -> macro.h, assert-fundamental.h -> assert-util.h,
cleanup-fundamental.h -> cleanup-util.h). Rename src/basic/{btrfs,label}.{c,h}
to use the -util suffix to match the existing shared/btrfs-util and
shared/label-util siblings. Rename src/shared/mkdir-label.{c,h} to mkdir.{c,h}
and src/shared/tmpfile-util-label.{c,h} to tmpfile-util.{c,h} to match the
corresponding src/basic names.

This saves us from having to come up with separate names for files that do
the same thing across tiers, and it makes it easier to move stuff between
src/fundamental, src/basic and src/shared: consumers just #include "foo.h"
and pick up whichever tier their -I path resolves to first, so call sites
don't need to be updated when an API moves between layers.

Where a higher-tier wrapper exists (e.g. src/basic/macro.h wrapping
src/fundamental/macro.h), the wrapper uses an explicit "../fundamental/foo.h"
or "../basic/foo.h" relative include for the lower-tier header. We can't use
GCC's #include_next directive for this — when the wrapper is reachable both
via same-dir-as-source lookup and via -I (e.g. -Isrc/shared) for the
directory it lives in, #include_next advances by exactly one slot in libcpp's
internal directory chain and lands on the same physical directory it was
already in, never reaching the lower-tier sibling (see make_cpp_dir() in
gcc/libcpp/files.cc:1986).

To make sure the right headers are always picked up, the include directories
are reordered so that e.g. src/shared always takes priority over src/basic and
similar for the other directories.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 10:33:03 +09:00

104 lines
3.4 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <string.h>
#include "basic-forward.h"
#include "../fundamental/memory-util.h" /* IWYU pragma: export */
size_t page_size(void) _pure_;
#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 (n == 0)
return dst;
assert(src);
return memcpy(dst, src, n);
}
/* Normal mempcpy() requires src to be nonnull. We do nothing if n is 0. */
static inline void* mempcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0)
return dst;
assert(src);
return mempcpy(dst, src, n);
}
#define _mempcpy_typesafe(dst, src, n, sz) \
({ \
size_t sz; \
assert_se(MUL_SAFE(&sz, sizeof((dst)[0]), n)); \
(typeof((dst)[0])*) mempcpy_safe(dst, src, sz); \
})
#define mempcpy_typesafe(dst, src, n) \
_mempcpy_typesafe(dst, src, n, UNIQ_T(sz, UNIQ))
/* Normal memcmp() requires s1 and s2 to be nonnull. We do nothing if n is 0. */
static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
if (n == 0)
return 0;
assert(s1);
assert(s2);
return memcmp(s1, s2, n);
}
/* Compare s1 (length n1) with s2 (length n2) in lexicographic order. */
static inline int memcmp_nn(const void *s1, size_t n1, const void *s2, size_t n2) {
return memcmp_safe(s1, s2, MIN(n1, n2))
?: CMP(n1, n2);
}
#define zero(x) (memzero(&(x), sizeof(x)))
static inline void* mempset(void *s, int c, size_t n) {
memset(s, c, n);
return (uint8_t*) s + n;
}
/* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
static inline void* memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
if (needlelen <= 0)
return (void*) haystack;
if (haystacklen < needlelen)
return NULL;
assert(haystack);
assert(needle);
return memmem(haystack, haystacklen, needle, needlelen);
}
static inline void* mempmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
const uint8_t *p;
p = memmem_safe(haystack, haystacklen, needle, needlelen);
if (!p)
return NULL;
return (uint8_t*) p + needlelen;
}
void* erase_and_free(void *p);
static inline void erase_and_freep(void *p) {
erase_and_free(*(void**) p);
}
/* Use with _cleanup_ to erase a single 'char' when leaving scope */
static inline void erase_char(char *p) {
explicit_bzero_safe(p, sizeof(char));
}
/* Makes a copy of the buffer with reversed order of bytes */
void* memdup_reverse(const void *mem, size_t size);