Skip to content

renameat2 for atomic IO #810

@juancarlospaco

Description

@juancarlospaco
  • Use renameat2 with RENAME_EXCHANGE for Atomic IO.
  • renameat2 is the same as renameat but allows additional arguments.
  • RENAME_EXCHANGE is a constant int flag for renameat2 to 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/os only.
  • Alternatively can be a new Nim symbol, swapDir ?.

Cons

  • renameat2 and RENAME_EXCHANGE is Linux only, but thats easy to detect in Nim.
  • MUSL does NOT have renameat2 nor RENAME_EXCHANGE, but thats easy to detect in Nim.

Solution: Fallback to current implementation iff MUSL or non-Linux.

Links

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions