From a77f2fc042a3bd84d8cadae6e877d928e91db3c7 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 12 Jan 2015 11:37:53 +0100 Subject: swap: atomically renames a file Uses the renameat2 syscall from Linux 3.15. --- swap.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 swap.c (limited to 'swap.c') diff --git a/swap.c b/swap.c new file mode 100644 index 0000000..3fc5777 --- /dev/null +++ b/swap.c @@ -0,0 +1,51 @@ +/* Rename two files atomically, swapping one for the other. + * Copyright (C) 2015 Peter Wu + */ + +#define _GNU_SOURCE +#include +#include +#include /* for RENAME_* */ +#include /* for AT_* */ +#include +#include + +int renameat2(int olddirfd, const char *oldpath, + int newdirfd, const char *newpath, unsigned int flags) +{ + long r; + r = syscall(SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, flags); + return (int)r; +} + +int main(int argc, char **argv) +{ + int olddirfd, newdirfd; + const char *oldpath, *newpath; + unsigned flags; + int r; + + if (argc - 1 < 2) { + fprintf(stderr, "Usage: %s file1 file2\n", argv[0]); + fprintf(stderr, "Atomically swaps file1 and file2.\n"); + return 1; + } + + olddirfd = AT_FDCWD; + newdirfd = AT_FDCWD; + oldpath = argv[1]; + newpath = argv[2]; + flags = RENAME_EXCHANGE; + + r = renameat2(olddirfd, oldpath, newdirfd, newpath, flags); + if (r < 0) { + if (errno == ENOSYS) { + fprintf(stderr, "renameat2 syscall not available!" + " You need Linux 3.15 or newer.\n"); + } else { + perror("renameat2 failed"); + } + } + + return r < 0 ? 1 : 0; +} -- cgit v1.2.1