From 81fced01665d93a452486fa7f747ae1c9d1295d53211a1dcf6ca9e0fb891bb4e Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Wed, 2 Jun 2021 13:04:49 +0000 Subject: [PATCH] Accepting request 896791 from home:haasn:branches:Base:System - add fallback for filesystems without renameat2 This change makes it succeed successfully on my system, which has a ZFS rootfs (so no renameat2). OBS-URL: https://build.opensuse.org/request/show/896791 OBS-URL: https://build.opensuse.org/package/show/Base:System/compat-usrmerge?expand=0&rev=11 --- compat-usrmerge.changes | 5 +++++ xmv.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/compat-usrmerge.changes b/compat-usrmerge.changes index 6a2d438..eb5757f 100644 --- a/compat-usrmerge.changes +++ b/compat-usrmerge.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Jun 1 23:27:08 UTC 2021 - Niklas Haas + +- add fallback for filesystems without renameat2 + ------------------------------------------------------------------- Thu Mar 25 09:50:48 UTC 2021 - Ludwig Nussel diff --git a/xmv.c b/xmv.c index f7c31a4..d29bae5 100644 --- a/xmv.c +++ b/xmv.c @@ -66,10 +66,34 @@ int main(int argc, char** argv) if (argc-optind < 2) help(argv[0], 1); - r = syscall (SYS_renameat2, AT_FDCWD, argv[optind], AT_FDCWD, argv[optind+1], RENAME_EXCHANGE); + const char *source = argv[optind], *target = argv[optind+1]; + r = syscall (SYS_renameat2, AT_FDCWD, source, AT_FDCWD, target, RENAME_EXCHANGE); if (r < 0) { - perror("renameat2"); - return 1; + if (errno != EINVAL) { + perror("renameat2"); + return 1; + } + + /* Fallback for systems without renameat2 support */ + char *tmp; + r = asprintf(&tmp, "%s.XXXXXX", target); + if (r < 0) { + perror("asprintf"); + return 1; + } + mktemp(tmp); + + r = renameat(AT_FDCWD, target, AT_FDCWD, tmp); + if (!r) + r = renameat(AT_FDCWD, source, AT_FDCWD, target); + if (!r) + r = renameat(AT_FDCWD, tmp, AT_FDCWD, source); + free(tmp); + + if (r < 0) { + perror("renameat"); + return 1; + } } return 0;