🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
#!/bin/bash
# Compatibility shims for systemd 259.1 against the Pagan native rootfs headers.
set -euo pipefail
# systemd ships missing kernel UAPI bits under src/include/override and
# src/include/uapi. Meson adds those as -isystem, but pkg-config injects
# -I$PAGAN_ROOT/usr/include which wins and hides the overrides. Flip them
# to regular -I so MQUEUE_MAGIC, EXT4_IOC_RESIZE_FS, key_serial_t, etc. work.
if [[ -f meson.build ]]; then
python3 - <<'PY'
from pathlib import Path
p = Path("meson.build")
t = p.read_text()
t = t.replace("is_system : true", "is_system : false")
for kind in ("override", "uapi"):
t = t.replace(
f"'-isystem', meson.project_build_root() / 'src/include/{kind}'",
f"'-I', meson.project_build_root() / 'src/include/{kind}'",
)
t = t.replace(
f"'-isystem', meson.project_source_root() / 'src/include/{kind}'",
f"'-I', meson.project_source_root() / 'src/include/{kind}'",
)
# Inject missing MAGIC macros via -imacros after config.h.
marker = "userspace_c_args += ['-include', 'config.h']"
inject = (
marker
+ "\nuserspace_c_args += ['-imacros', meson.project_source_root() / 'src/include/override/pagan-compat.h']"
)
if marker in t and "pagan-compat.h" not in t:
t = t.replace(marker, inject, 1)
p.write_text(t)
print("patched meson.build: systemd override headers now use -I")
PY
fi
# keyctl.c provides missing_keyctl/missing_add_key/missing_request_key syscall
# wrappers (required at link time). We removed the keyutils.h injection that
# caused the old header conflict, so the file is safe to keep.
if [[ -f src/libc/meson.build ]] && ! grep -q "'keyctl.c'" src/libc/meson.build; then
sed -i "/'xattr.c',/a\ 'keyctl.c'," src/libc/meson.build
fi
# linux/keyctl.h on the target does not declare key_serial_t.
if [[ -f src/include/override/sys/keyctl.h ]]; then
if ! grep -q 'KEY_SERIAL_T_DEFINED' src/include/override/sys/keyctl.h; then
sed -i '1i #include <stdint.h>\n#ifndef KEY_SERIAL_T_DEFINED\n#define KEY_SERIAL_T_DEFINED\ntypedef int32_t key_serial_t;\n#endif' \
src/include/override/sys/keyctl.h
fi
fi
# Include libc networking headers before Linux netfilter headers.
if [[ -f src/shared/firewall-util.c ]]; then
sed -i \
-e '/^#include <linux\/netfilter\/nf_tables.h>/d' \
-e '/^#include <linux\/netfilter_ipv4.h>/d' \
-e '/^#include <netinet\/ip.h>/d' \
-e '/^#include <netinet\/ip6.h>/d' \
-e '/^#include <endian.h>$/a #include <netinet/ip.h>\n#include <netinet/ip6.h>\n#include <linux/netfilter/nf_tables.h>\n#include <linux/netfilter_ipv4.h>' \
src/shared/firewall-util.c
fi
# TASK_COMM_LEN is not exported by the target kernel headers.
if [[ -f src/shared/nsresource.c ]] && ! grep -q 'TASK_COMM_LEN 16' src/shared/nsresource.c; then
sed -i '1i #ifndef TASK_COMM_LEN\n#define TASK_COMM_LEN 16\n#endif' src/shared/nsresource.c
fi
# EXT4_IOC_RESIZE_FS lives in linux/ext4.h, not linux/fs.h.
if [[ -f src/shared/resize-fs.c ]] && ! grep -q 'linux/ext4.h' src/shared/resize-fs.c; then
sed -i '/#include <linux\/fs.h>/a #include <linux/ext4.h>' src/shared/resize-fs.c
fi
# The target sysroot linux/keyctl.h lacks the KEY_POS/KEY_USR/KEY_GRP/KEY_OTH
# keyring permission masks. systemd's override/linux/keyctl.h has them but is
# shadowed by uapi/linux/keyctl.h (uapi comes first in -I order). Inject the
# block into the uapi header that keyring code actually includes. Safe: the
# udev keyboard generator only includes <linux/input.h>, so it never sees them.
if [[ -f src/include/uapi/linux/keyctl.h ]] && ! grep -q 'define KEY_POS_VIEW' src/include/uapi/linux/keyctl.h; then
python3 - <<'PY'
from pathlib import Path
p = Path("src/include/uapi/linux/keyctl.h")
t = p.read_text()
block = '''
#ifndef KEY_POS_VIEW
#define KEY_POS_VIEW 0x01000000
#define KEY_POS_READ 0x02000000
#define KEY_POS_WRITE 0x04000000
#define KEY_POS_SEARCH 0x08000000
#define KEY_POS_LINK 0x10000000
#define KEY_POS_SETATTR 0x20000000
#define KEY_POS_ALL 0x3f000000
#define KEY_USR_VIEW 0x00010000
#define KEY_USR_READ 0x00020000
#define KEY_USR_WRITE 0x00040000
#define KEY_USR_SEARCH 0x00080000
#define KEY_USR_LINK 0x00100000
#define KEY_USR_SETATTR 0x00200000
#define KEY_USR_ALL 0x003f0000
#define KEY_GRP_VIEW 0x00000100
#define KEY_GRP_READ 0x00000200
#define KEY_GRP_WRITE 0x00000400
#define KEY_GRP_SEARCH 0x00000800
#define KEY_GRP_LINK 0x00001000
#define KEY_GRP_SETATTR 0x00002000
#define KEY_GRP_ALL 0x00003f00
#define KEY_OTH_VIEW 0x00000001
#define KEY_OTH_READ 0x00000002
#define KEY_OTH_WRITE 0x00000004
#define KEY_OTH_SEARCH 0x00000008
#define KEY_OTH_LINK 0x00000010
#define KEY_OTH_SETATTR 0x00000020
#define KEY_OTH_ALL 0x0000003f
#endif
'''
import re as _re
m = _re.search(r'#endif\s*/\*.*?_LINUX_KEYCTL_H.*?\*/', t, _re.S)
if m:
t = t[:m.start()] + block + '\n' + m.group(0)
else:
idx = t.rstrip().rfind('\n#endif')
t = t.rstrip()[:idx] + block + '\n#endif\n'
p.write_text(t)
print("patched uapi/linux/keyctl.h with keyring permission masks")
PY
fi
# Force-include remaining kernel constants that systemd's override headers
# also provide, in case some translation unit still misses them.
compat_h="src/include/override/pagan-compat.h"
cat > "$compat_h" <<'EOF'
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/* Macros only. Safe with -imacros: no includes, no typedefs. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16
#endif
#ifndef MQUEUE_MAGIC
#define MQUEUE_MAGIC 0x19800202
#endif
#ifndef BALLOON_KVM_MAGIC
#define BALLOON_KVM_MAGIC 0x13661366
#endif
#ifndef ZSMALLOC_MAGIC
#define ZSMALLOC_MAGIC 0x58295829
#endif
#ifndef Z3FOLD_MAGIC
#define Z3FOLD_MAGIC 0x33
#endif
#ifndef PPC_CMM_MAGIC
#define PPC_CMM_MAGIC 0xc7571590
#endif
#ifndef SHIFTFS_MAGIC
#define SHIFTFS_MAGIC 0x6a656a62
#endif
#ifndef FUSE_CTL_SUPER_MAGIC
#define FUSE_CTL_SUPER_MAGIC 0x65735543
#endif
#ifndef ORANGEFS_DEVREQ_MAGIC
#define ORANGEFS_DEVREQ_MAGIC 0x20030529
#endif
#ifndef GFS2_MAGIC
#define GFS2_MAGIC 0x01161970
#endif
#ifndef CONFIGFS_MAGIC
#define CONFIGFS_MAGIC 0x62656570
#endif
#ifndef VBOXSF_SUPER_MAGIC
#define VBOXSF_SUPER_MAGIC 0x786f4256
#endif
#ifndef RPC_PIPEFS_SUPER_MAGIC
#define RPC_PIPEFS_SUPER_MAGIC 0x67596969
#endif
#ifndef NTFS_SB_MAGIC
#define NTFS_SB_MAGIC 0x5346544e
#endif
#ifndef NTFS3_SUPER_MAGIC
#define NTFS3_SUPER_MAGIC 0x7366746e
#endif
#ifndef EXT4_IOC_RESIZE_FS
#define EXT4_IOC_RESIZE_FS _IOW('f', 16, unsigned long long)
#endif
#ifndef FILEID_KERNFS
#define FILEID_KERNFS 0xfe
#endif
/* NOTE: do NOT force-define the KEY_POS / KEY_USR keyring permission
* masks here. They are provided by systemd's override linux/keyctl.h
* (which now wins because overrides use -I). Injecting them globally
* would pollute the udev keyboard key list (compiled through our
* -imacros) and overflow its unsigned-short key code field. */
/* Unconditional BPF jump (from linux/filter.h). Function-like macro, so it
* only expands at call sites where struct bpf_insn / BPF_JMP / BPF_JA are
* already declared. */
#ifndef BPF_JMP_A
#define BPF_JMP_A(OFF) \
((struct bpf_insn) { .code = BPF_JMP | BPF_JA, .dst_reg = 0, .src_reg = 0, .off = (OFF), .imm = 0 })
#endif
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#ifndef O_NOATIME
#define O_NOATIME 01000000
#endif
#ifndef MFD_ALLOW_SEALING
#define MFD_ALLOW_SEALING 2U
#endif
EOF
# -imacros injects the macros without changing include search order
# and without parsing the file as a translation-unit include.
export CFLAGS="${CFLAGS:-} -D_GNU_SOURCE -imacros ${PWD}/${compat_h}"
export CXXFLAGS="${CXXFLAGS:-} -D_GNU_SOURCE -imacros ${PWD}/${compat_h}"