Atomical swap contents of two files in Linux
I have two files: A
and B
, each with its own content.
I would like to swap these two files, so A
will become B
, and B
will become A
. But I would like to make sure that no other process finds these two files in an inconsistent state, and neither of the processes finds any of these files, even for a short time. So, as a side operation, I would also like to be sure that if something goes wrong during the operation, nothing will change (like a transaction, I guess).
OS X has a feature exchangedata()
, so I'm guessing I'm looking for a Linux equivalent, or at least an equivalent method for sharing kernel files.
source to share
You can use the (fairly recent) linux syscallrenameat2
Here's the definition:
int renameat2(int olddir, const char *oldname,
int newdir, const char *newname, unsigned int flags);
You can find its source code in the core Git repo if needed.
This is basically the same as, renameat
but if you pass the RENAME_EXCHANGE flag, it will replace the two files instead of renaming them to another.
The operation is atomic.
source to share
Depending on what you mean by "inconsistent state". If it is acceptable that there is a period of time during which the two files are identical, 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 a file open. Remember that paths are not files, they are just file references, so if process 1 opens a file on path "A" and then you change the names A and B, process 1 will still have the file passed by named A.
source to share