1 |
On Sun, 22 Jul 2012 10:59:46 -0400 |
2 |
Michael Mol <mikemol@×××××.com> wrote: |
3 |
|
4 |
> On Sun, Jul 22, 2012 at 9:53 AM, Florian Philipp |
5 |
> <lists@×××××××××××.net> wrote: |
6 |
> > Hi list! |
7 |
> > |
8 |
> > This is more a general POSIX question but I guess here I have the |
9 |
> > best chance to get a definite answer. |
10 |
> > |
11 |
> > If I want to replace a file with another file without removing the |
12 |
> > first one and without having a moment in time at which the file |
13 |
> > name does not exist, I can use the following sequence: |
14 |
> > |
15 |
> > # swap $file1 with $file2 on the same file system |
16 |
> > dir=$(dirname "$file1") |
17 |
> > tmp=$(mktemp -u -d "$dir") # [1] |
18 |
> > ln "$file1" "$tmp" |
19 |
> > mv "$file2" "$file1" |
20 |
> > mv "$tmp" "$file2" |
21 |
> > |
22 |
> > This works because mv does not affect the hardlink to $file1 and a |
23 |
> > rename operation on a single file system is atomic. This is a handy |
24 |
> > procedure when you have a background process which occasionally |
25 |
> > opens $file1 and you don't want it to fail just because of bad |
26 |
> > timing. |
27 |
> > |
28 |
> > Now my question is: How can I do a similar thing for a directory? I |
29 |
> > cannot usually create hardlinks on directories (are there file |
30 |
> > systems where this actually works?) and I cannot use mv to |
31 |
> > overwrite one directory with another. |
32 |
> > |
33 |
> > The only idea I currently have is to create a level of indirection |
34 |
> > via symlinks and then atomically overwrite the symlink. Is there |
35 |
> > any other way? |
36 |
> |
37 |
> I'd be very, very wary of doing something like this without knowing |
38 |
> exactly what programs might be accessing files inside the folder |
39 |
> you're swapping out. In order to avoid a race where some poor process |
40 |
> winds up with open file handles to some content in both your old and |
41 |
> new folders, you'd really need a way to: |
42 |
> |
43 |
> 1) lock the folder so no programs can gain new handles on it or any |
44 |
> file or folder inside |
45 |
> 2) wait until all other open file handles to the folder and its |
46 |
> contents are closed |
47 |
> 3) swap out the folder |
48 |
> 4) unlock |
49 |
> |
50 |
> (1) might be doable with flock() on a parent directory. |
51 |
> (2) you'll need to use fuser to find the processes which have open |
52 |
> handles and get them to release them. |
53 |
> (3) mv a a_tmp; mv b a; mv a_tmp b |
54 |
> (4) flock -u |
55 |
> |
56 |
|
57 |
|
58 |
I'd argue that what the OP wants is fundamentally impossible - there is |
59 |
no such thing to my knowledge as a directory locking mechanism that is |
60 |
guaranteed to always work in all cases - it would have to be |
61 |
kernel-based to do that and I've personally never heard of such a |
62 |
mechanism. |
63 |
|
64 |
The fact is, that directory operations are not atomic wrt the directory |
65 |
contents, and the OP needs to find a different way to solve his problem. |
66 |
|
67 |
As for the OPs question re: hard-linking directories, Linux never allows |
68 |
this as a user action - it can cause un-solveable loops when traversing |
69 |
directory trees. Most other Unixes have the same rule for the same |
70 |
reason. Some do allow it; but I forget which ones and I'm too lazy on a |
71 |
Sunday afternoon to Google it :-) |
72 |
|
73 |
The kernel is of course perfectly able to hard-link directories - it |
74 |
has to to be able to create . and .. at all, but that code only runs as |
75 |
part of what mkdir does. In all other cases the kernel is hard-coded to |
76 |
just refuse to do it. |
77 |
|
78 |
-- |
79 |
Alan McKinnon |
80 |
alan.mckinnon@×××××.com |