Skip to content

Instantly share code, notes, and snippets.

@condekind
Created February 21, 2020 05:35
Show Gist options
  • Save condekind/6f8f8ccdf832b270cbaa1f1051c22822 to your computer and use it in GitHub Desktop.
Save condekind/6f8f8ccdf832b270cbaa1f1051c22822 to your computer and use it in GitHub Desktop.
Atomic file swap on GNU/Linux
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#ifndef RENAME_EXCHANGE
#define RENAME_EXCHANGE (1 << 1)
#endif
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
int main(int argc, char *argv[])
{
if (argc != 3) { printf("Error: Wrong number of arguments\n"); return -1; }
int path_max = (( PATH_MAX < 1024) ? 1024 : PATH_MAX);
if (strlen(argv[1]) >= path_max) { printf("Error: Long path\n"); return -1; }
if (strlen(argv[2]) >= path_max) { printf("Error: Long path\n"); return -1; }
char f1ap[path_max]; memset(f1ap, 0, path_max); realpath(argv[1], f1ap);
char f2ap[path_max]; memset(f2ap, 0, path_max); realpath(argv[2], f2ap);
int fd1 = open(f1ap, O_PATH), fd2 = open(f2ap, O_PATH), err;
switch (err = renameat2(fd1, f1ap, fd2, f2ap, RENAME_EXCHANGE)) {
case 0: close(fd1); close(fd2); return 0;
default: perror("Error"); return err;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment