forked from nim-lang/Nim
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
- Use
renameat2withRENAME_EXCHANGEfor Atomic IO. renameat2is the same asrenameatbut allows additional arguments.RENAME_EXCHANGEis a constant int flag forrenameat2to atomically exchange an old path with a new path.- It is faster because is a single swap operation, but thats not the point.
- It is safer because the 2 paths do not exist at the same time, instead swap atomically.
- Tiny diff, because is used by
std/osonly. - Alternatively can be a new Nim symbol,
swapDir?.
Cons
renameat2andRENAME_EXCHANGEis Linux only, but thats easy to detect in Nim.- MUSL does NOT have
renameat2norRENAME_EXCHANGE, but thats easy to detect in Nim.
Solution: Fallback to current implementation iff MUSL or non-Linux.
Links
- https://github.com/nim-lang/Nim/blob/devel/lib/pure/os.nim#L1123
- https://stackoverflow.com/a/27862160
- https://man7.org/linux/man-pages/man2/rename.2.html
- https://lists.gnu.org/archive/html/coreutils/2021-05/msg00030.html
- https://gist.github.com/eatnumber1/f97ac7dad7b1f5a9721f
- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/namei.c?id=7bb91e06730140a693611e51a4a9636152448bd3#n4474
Sample
#include <fcntl.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
/* MUSL Fallback */
#ifndef RENAME_EXCHANGE
#define RENAME_EXCHANGE 2
#endif
int main(int argc, char** argv) {
/* MUSL Fallback */
if (syscall(SYS_renameat2, AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE)) {
perror(NULL);
return 1;
} else {
return 0;
}
}$ mkdir old
$ mkdir new
$ gcc -o moveit moveit.c
$ ./moveit "old" "new"You can use strace ./moveit "old" "new" or similar to see differences with rename API.
/cc @timotheecour