On Sun, Jul 22, 2012 at 9:53 AM, Florian Philipp <[email protected]> wrote:
> Hi list!
>
> This is more a general POSIX question but I guess here I have the best
> chance to get a definite answer.
>
> If I want to replace a file with another file without removing the first
> one and without having a moment in time at which the file name does not
> exist, I can use the following sequence:
>
> # swap $file1 with $file2 on the same file system
> dir=$(dirname "$file1")
> tmp=$(mktemp -u -d "$dir") # [1]
> ln "$file1" "$tmp"
> mv "$file2" "$file1"
> mv "$tmp" "$file2"
>
> This works because mv does not affect the hardlink to $file1 and a
> rename operation on a single file system is atomic. This is a handy
> procedure when you have a background process which occasionally opens
> $file1 and you don't want it to fail just because of bad timing.
>
> Now my question is: How can I do a similar thing for a directory? I
> cannot usually create hardlinks on directories (are there file systems
> where this actually works?) and I cannot use mv to overwrite one
> directory with another.
>
> The only idea I currently have is to create a level of indirection via
> symlinks and then atomically overwrite the symlink. Is there any other way?

I'd be very, very wary of doing something like this without knowing
exactly what programs might be accessing files inside the folder
you're swapping out. In order to avoid a race where some poor process
winds up with open file handles to some content in both your old and
new folders, you'd really need a way to:

1) lock the folder so no programs can gain new handles on it or any
file or folder inside
2) wait until all other open file handles to the folder and its
contents are closed
3) swap out the folder
4) unlock

(1) might be doable with flock() on a parent directory.
(2) you'll need to use fuser to find the processes which have open
handles and get them to release them.
(3) mv a a_tmp; mv b a; mv a_tmp b
(4) flock -u

-- 
:wq

Reply via email to