Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing a file with a hardlink to another file atomically

I have two directory entries, a and b. Before, a and b point to different inodes. Afterwards, I want b to point to the same inode as a does. I want this to be safe - by which I mean if it fails somewhere, b either points to its original inode or the a inode. I especially don't want to end up with b disappearing.

mv is atomic when overwriting, and ln appears to not work when the destination already exists. So it looks like i can say:

ln a tmp
mv tmp b

which in case of failure will leave a 'tmp' file around, which is undesirable but not a disaster.

Is there a better way to do this?

(What I'm actually trying to do is replace files that have identical content with a single inode containing that content, shared between all directory entries.)

like image 821
Ben Clifford Avatar asked Sep 03 '25 05:09

Ben Clifford


2 Answers

ln a tmp && mv tmp b || rm tmp

seems better, as then if ln fails, the mv will not get executed (and clutter up stderr when it fails).

like image 118
mtd Avatar answered Sep 05 '25 01:09

mtd


 ln a tmp ; mv tmp b

is in fact the fastest way to do it atomically, as you stated in your question.

(Nitpickers corner: faster to place both system calls in one program)

like image 31
Joshua Avatar answered Sep 04 '25 23:09

Joshua