Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomically swap contents of two files on Linux

Tags:

linux

libc

I have two files, A and B, each with its own content.

I would like to swap these two files, so A would become B, and B would become A. But I would like to do with a guaranty that no other process will find these two files in an inconsistent state, nor any process will find any of those files missing, even for a short while. So, as a side operation, I would also like to have a guaranty that if anything would go wrong during the operation, nothing will be changed (kind of like a transaction I guess).

On OS X there is a exchangedata() function, so I guess I'm looking for a Linux equivalent of it, or at least an equivalent method for doing atomic file swap.

like image 767
antonone Avatar asked Jan 09 '15 13:01

antonone


2 Answers

You can use the (fairly recent) linux syscall renameat2

Here is the definition :

int renameat2(int olddir, const char *oldname, 
      int newdir, const char *newname, unsigned int flags);

You can find its source code on the kernel's Git repo if needed.

It's basically the same as renameat, but if you pass the flag RENAME_EXCHANGE it will swap the two files instead of renaming one into the other.

The operation is atomic.

like image 153
tux3 Avatar answered Nov 14 '22 17:11

tux3


I depends on what you mean by "inconsistent state". If it is acceptable for there to be a period of time during which the two files are identical, then you can simply do:

ln A C
ln B D
ln -f D A  
# now, A and B have the same content
ln -f C B

It also depends on the behavior you want for processes that already have the file opened. Remember that paths are not files, but merely links to a file, so if process 1 opens a file via the path 'A', and then you swap the names A and B, process 1 will still have the file opened that was referred to by the name A.

like image 31
William Pursell Avatar answered Nov 14 '22 16:11

William Pursell