diff --git a/include/crucible/openat2.h b/include/crucible/openat2.h index 45f2c7f..8d35350 100644 --- a/include/crucible/openat2.h +++ b/include/crucible/openat2.h @@ -1,11 +1,44 @@ #ifndef CRUCIBLE_OPENAT2_H #define CRUCIBLE_OPENAT2_H +#include + +// Compatibility for building on old libc for new kernel +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + #include -#include -#include -#include +#else + +#ifndef RESOLVE_NO_XDEV +#define RESOLVE_NO_XDEV 1 + +// RESOLVE_NO_XDEV was there from the beginning of openat2, +// so if that's missing, so is open_how + +struct open_how { + __u64 flags; + __u64 mode; + __u64 resolve; +}; +#endif + +#ifndef RESOLVE_NO_MAGICLINKS +#define RESOLVE_NO_MAGICLINKS 2 +#endif +#ifndef RESOLVE_NO_SYMLINKS +#define RESOLVE_NO_SYMLINKS 4 +#endif +#ifndef RESOLVE_BENEATH +#define RESOLVE_BENEATH 8 +#endif +#ifndef RESOLVE_IN_ROOT +#define RESOLVE_IN_ROOT 16 +#endif + +#endif // Linux version >= v5.6 extern "C" { diff --git a/lib/openat2.cc b/lib/openat2.cc index 95c9eb3..d868234 100644 --- a/lib/openat2.cc +++ b/lib/openat2.cc @@ -1,5 +1,27 @@ #include "crucible/openat2.h" +#include + +// Compatibility for building on old libc for new kernel + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) + +// Every arch that defines this uses 437, except Alpha, where 437 is +// mq_getsetattr. + +#ifndef SYS_openat2 +#ifdef __alpha__ +#define SYS_openat2 547 +#else +#define SYS_openat2 437 +#endif +#endif + +#endif // Linux version >= v5.6 + +#include +#include + extern "C" { int @@ -7,7 +29,12 @@ __attribute__((weak)) openat2(int const dirfd, const char *const pathname, struct open_how *const how, size_t const size) throw() { +#ifdef SYS_openat2 return syscall(SYS_openat2, dirfd, pathname, how, size); +#else + errno = ENOSYS; + return -1; +#endif } };