From: Stefan Metzmacher Date: Wed, 7 Aug 2024 11:01:48 +0000 (+0200) Subject: lib/replace: add renameat2() replacement X-Git-Tag: tdb-1.4.13~1314 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f6550e804ea5604b1d7ec67e629fad8baee87f8b;p=thirdparty%2Fsamba.git lib/replace: add renameat2() replacement BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/lib/replace/replace.c b/lib/replace/replace.c index 0b4e06d8bd5..359f43352bd 100644 --- a/lib/replace/replace.c +++ b/lib/replace/replace.c @@ -1171,3 +1171,63 @@ long rep_openat2(int dirfd, const char *pathname, #endif } #endif /* !HAVE_OPENAT2 */ + +#ifndef HAVE_RENAMEAT2 + +/* fallback to wellknown __NR_renameat2 values */ +#ifndef __NR_renameat2 +# if defined(LINUX) && defined(HAVE_SYS_SYSCALL_H) +# if defined(__i386__) +# define __NR_renameat2 353 +# elif defined(__x86_64__) && defined(__LP64__) +# define __NR_renameat2 316 /* 316 0x13C */ +# elif defined(__x86_64__) && defined(__ILP32__) +# define __NR_renameat2 1073742140 /* 1073742140 0x4000013C */ +# elif defined(__aarch64__) +# define __NR_renameat2 276 +# elif defined(__arm__) +# define __NR_renameat2 382 +# elif defined(__sparc__) +# define __NR_renameat2 345 +# endif +# endif /* defined(LINUX) && defined(HAVE_SYS_SYSCALL_H) */ +#endif /* !__NR_renameat2 */ + +#ifdef DISABLE_OPATH +/* + * systems without O_PATH also don't have renameat2, + * so make sure we at a realistic combination. + */ +#undef __NR_renameat2 +#endif /* DISABLE_OPATH */ + +int rep_renameat2(int __oldfd, const char *__old, int __newfd, + const char *__new, unsigned int __flags) +{ + if (__flags != 0) { +#ifdef __NR_renameat2 + int ret; + + ret = syscall(__NR_renameat2, + __oldfd, + __old, + __newfd, + __new, + __flags); + if (ret != -1 || errno != ENOSYS) { + /* + * if it's ENOSYS, we fallback + * to EINVAL below, otherwise + * we return what the kernel + * did. + */ + return ret; + } +#endif + errno = EINVAL; + return -1; + } + + return renameat(__oldfd, __old, __newfd, __new); +} +#endif /* ! HAVE_RENAMEAT2 */ diff --git a/lib/replace/system/filesys.h b/lib/replace/system/filesys.h index 8005b18780f..9738ad52935 100644 --- a/lib/replace/system/filesys.h +++ b/lib/replace/system/filesys.h @@ -278,4 +278,33 @@ long rep_openat2(int dirfd, const char *pathname, rep_openat2(dirfd, pathname, how, size) #endif /* !HAVE_OPENAT2 */ +#ifdef DISABLE_OPATH +/* + * Without O_PATH, the kernel + * most likely doesn't have renameat2() too + * and we should test the fallback code + */ +#undef HAVE_RENAMEAT2 +#endif + +#ifndef HAVE_RENAMEAT2 + +#ifndef RENAME_NOREPLACE +# define RENAME_NOREPLACE (1 << 0) +#endif + +#ifndef RENAME_EXCHANGE +# define RENAME_EXCHANGE (1 << 1) +#endif + +#ifndef RENAME_WHITEOUT +# define RENAME_WHITEOUT (1 << 2) +#endif + +int rep_renameat2(int __oldfd, const char *__old, int __newfd, + const char *__new, unsigned int __flags); +#define renameat2(__oldfd, __old, __newfd, __new, __flags) \ + rep_renameat2(__oldfd, __old, __newfd, __new, __flags) +#endif /* !HAVE_RENAMEAT2 */ + #endif diff --git a/lib/replace/wscript b/lib/replace/wscript index 77e655bb68b..f5114b69ffc 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -422,7 +422,7 @@ def configure(conf): conf.CHECK_FUNCS('link readlink symlink realpath snprintf vsnprintf') conf.CHECK_FUNCS('asprintf vasprintf setenv unsetenv strnlen strtoull __strtoull') conf.CHECK_FUNCS('strtouq strtoll __strtoll strtoq memalign posix_memalign') - conf.CHECK_FUNCS('fmemopen') + conf.CHECK_FUNCS('fmemopen renameat2') if conf.CONFIG_SET('HAVE_MEMALIGN'): conf.CHECK_DECLS('memalign', headers='malloc.h')