[comp.unix.wizards] ln -f

barrett@undeed.UUCP (Alan P. Barrett) (07/25/90)

In article <3732@auspex.auspex.com>, guy@auspex.auspex.com (Guy Harris)
writes about 'ln -f file1 file2':

> the answer is "you can get that behavior without adding a flag to 'ln'
> - either remove the target first using a command that doesn't barf if
> it's not there, or check if it's there first and remove it if it is."

But that doesn't give the same result.  If you remove file2 first, then
there is a brief window between the 'rm' and the 'ln' during which no
file named file2 exists.  If you use a version of 'ln' that clobbers
file2 and replaces it with a link to file1 in an atomic operation, there
is no such window.  The difference might be important in some
applications.

--apb
Alan Barrett, Dept. of Electronic Eng., Univ. of Natal, Durban, South Africa
Internet: Barrett.UNDEE@f4.n494.z5.fidonet.org      UniNet-ZA: Barrett@UNDEE
Real Soon Now: Barrett@EE.UND.AC.ZA    PSI-Mail: PSI%(6550)13601353::BARRETT

djm@eng.umd.edu (David J. MacKenzie) (07/27/90)

In article <1056@undeed.UUCP> barrett@undeed.UUCP (Alan P. Barrett) writes:

> But that doesn't give the same result.  If you remove file2 first, then
> there is a brief window between the 'rm' and the 'ln' during which no
> file named file2 exists.  If you use a version of 'ln' that clobbers
> file2 and replaces it with a link to file1 in an atomic operation, there
> is no such window.  The difference might be important in some
> applications.

Wrong.  There is no way to clobber file2 and replace it with a hard
link in an atomic operation.  link(2) requires that the target file
not exist, otherwise it fails with:

     EEXIST		 The  link  referred  to  by  name2  does
			 exist.

Versions of ln that allow an existing target file remove it first with
unlink(2).  There is a *shorter* window during which file2 doesn't
exist than if rm(1) were used because there isn't the extra time of
starting up a new process in between the link and unlink operations,
but there *is* a window.
--
David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>

guy@auspex.auspex.com (Guy Harris) (07/28/90)

>But that doesn't give the same result.  If you remove file2 first, then
>there is a brief window between the 'rm' and the 'ln' during which no
>file named file2 exists.  
>If you use a version of 'ln' that clobbers file2 and replaces it with a
>link to file1 in an atomic operation, there is no such window.

As far as I know, there's no such atomic operation, either; I sure
haven't seen any such operation in any UNIX system I've ever run into.

Given that, every version of "ln" I know of that removes the target
first has to first "unlink()" the target, and then do the "link()".  As
such, the window is still there....

jfh@rpp386.cactus.org (John F. Haugh II) (07/29/90)

In article <3770@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>>But that doesn't give the same result.  If you remove file2 first, then
>>there is a brief window between the 'rm' and the 'ln' during which no
>>file named file2 exists.  
>>If you use a version of 'ln' that clobbers file2 and replaces it with a
>>link to file1 in an atomic operation, there is no such window.
>
>As far as I know, there's no such atomic operation, either; I sure
>haven't seen any such operation in any UNIX system I've ever run into.
>
>Given that, every version of "ln" I know of that removes the target
>first has to first "unlink()" the target, and then do the "link()".  As
>such, the window is still there....

My complaint is because 1). the behavior is useful [ obviously, since
AT&T and BSD both have ln's with different behaviors and no one has yet
decided that either is patently stupid ] 2). the behaviors are
different so you can't know whether the ln on the system you are using
is going to fail or succeed, depending on your definition of failure
or success.  Which means you are forced to use "rm -f $2 ; ln $1 $2"
to have the desired effect [ again, or not, depending on what "the
desired effect" is ].

Standardizing on "ln" and "ln -f" behavior, as I believe POSIX is trying
to do, will resolve the problem - there will be exactly one set of
POSIX-like "ln" and "ln -f" behavior.
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org

guy@auspex.auspex.com (Guy Harris) (07/31/90)

>My complaint...

...has nothing to do with the issue being discussed in the article to
which you're following up; that was discussing the non-existence of an
atomic "remove and link" operation, which the previous poster had,
apparently, assumed existed in UNIX and would be used by an "ln" that
removed the target first.

But, in any case...

>is because 1). the behavior is useful [ obviously, since
>AT&T and BSD both have ln's with different behaviors and no one has yet
>decided that either is patently stupid ] 2). the behaviors are
>different so you can't know whether the ln on the system you are using
>is going to fail or succeed, depending on your definition of failure
>or success.

Which means the ultimate problem isn't that one behavior is "good" and the
other is "bad", but that they're *different*.  Standardizing on either
one would have worked (modulo windows opened by having to implement one
behavior with multiple commands on a system that provides the other).

thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) (08/10/90)

guy@auspex.auspex.com (Guy Harris) writes:
>>If you use a version of 'ln' that clobbers file2 and replaces it with a
>>link to file1 in an atomic operation, there is no such window.

>As far as I know, there's no such atomic operation, either; I sure
>haven't seen any such operation in any UNIX system I've ever run into.

>Given that, every version of "ln" I know of that removes the target
>first has to first "unlink()" the target, and then do the "link()".  As
>such, the window is still there....

Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
use the rename system call?

    idavolde 2 >man rename
    ...
    DESCRIPTION
	 Rename causes the link named from to be renamed as to.  If
	 to exists, then it is first removed.  ...

	 Rename guarantees that an instance of to will always exist,
	 even if the system should crash in the middle of the opera-
	 tion.

I've heard that it was precisely because of the various race
conditions in connection with ln that made Berkeley put the function
into the kernel where inodes could be locked and updates done in
proper order.

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcsun!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn@diku.dk

guy@auspex.auspex.com (Guy Harris) (08/11/90)

>Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
>use the rename system call?

Because they're named "ln", not "mv".

"rename()" is *NOT* an atomic operation that removes the target and
makes an *additional* link from the source with the name of the target. 
It's an atomic operation that *renames* the source to the target, and if
it succeeds does *not* leave the source behind.

djm@eng.umd.edu (David J. MacKenzie) (08/11/90)

> Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
> use the rename system call?

Because rename doesn't do the same thing as ln.

If before you run ln, the file has n links, after you run ln
successfully the file will have n + 1 links.
If you just rename the file, it will still have n links, but one of
them will be different from before.
--
David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>

thorinn@skinfaxe.diku.dk (Lars Henrik Mathiesen) (08/17/90)

guy@auspex.auspex.com (Guy Harris) writes:
>[I write:]
>>Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
>>use the rename system call?
I tried to cancel this as soon as I realized my error, but it didn't
work, evidently.

>["rename" is]
>     an atomic operation that *renames* the source to the target, and if
>it succeeds does *not* leave the source behind.

I [usually] know that. But now that I think about it: Why doesn't ln:
	1) Create a new, randomly named, link in the target directory.
	2) Use "rename" to atomically replace the target with that link?
There will be no time when the target name doesn't exist. If the
machine crashes (or ln is killed), a funny link may be left behind,
but I think that is a smaller problem than the timing race.

I don't know if it would be wise to make this the default behaviour of
ln, but it might be useful to provide it as an option. (Of course, the
method would only be used if the target already existed.)

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcsun!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn@diku.dk