[comp.bugs.sys5] ln

harrison@utfyzx.uucp (David Harrison) (10/31/88)

Recently Geoff Collyer (utstat!geoff) has pointed out that under System 
V the command:
	ln old new
will destroy "new" if it already exists.  Historically and under other 
UNIX versions the same command will complain and refuse to make the link.  
Geoff calls the System V behaviour "an unintuitive shock". It certainly 
breaks any program that relies on `ln' refusing to link to "new" as a way
of doing locks (including parts of Cnews).

There certainly are lock problems under SV:  the print spooler will
croak if it is fed a large number of jobs nearly simultaneously; a
number of users changing their passwords nearly simultaneously can
leave you without an /etc/passwd file; etc.  Both of these have happened
to me and the fix I use is to write a SV IPC onionskin around these 
commands with semaphores to implement real kernel-level locks.

I have some questions and one comment on this situation.

First the questions:  if one re-writes ln (as Geoff has done) to
reproduce the old behaviour and replaces the SV `ln' in /bin
with this version what will break?   People have been using the 
old `ln' behaviour for some years, but are people now relying on 
the new behaviour too?  If so, how?  Will implementing such a change
make passwd and lp more reliable with lots of users?  What does
POSIX say?

Finally the comment:  if one adheres to traditional UNIX philosophy 
the System V `ln' is correct.  It now behaves just like its cousins 
`cp' and `mv':  tell it to do something and it will.  If one wishes 
to test for the existence of file "new" this philosophy says that
one should use a tool for that, not some behaviour of a program that 
is supposed to make links.  I know one problem with the above 
statement; code like:
	if [ !exists new ]	# new command `exists'
	then
		ln old new
	fi
leaves a terrible window of vulnerability between the test and the
link.  What is needed is a proper lock mechanism, and System V provides 
it with its IPC facilities in the kernel where they belong.
-- 
David Harrison, Dept. of Physics, Univ. of Toronto |  "Why do 3 notes make a
UUCP: {utgpu,sq,oscvax}!utfyzx!harrison            | triad and not a triangle?"
BITNET: HARRISON@UTORPHYS                          |         - Ernst Mach

les@chinet.chi.il.us (Leslie Mikesell) (11/02/88)

In article <1988Oct31.141701.11055@utfyzx.uucp> harrison@utfyzx.UUCP (David Harrison) writes:
>Recently Geoff Collyer (utstat!geoff) has pointed out that under System 
>V the command:
>	ln old new
>will destroy "new" if it already exists.  Historically and under other 

Many sysV's have /etc/link which just passes its arguments to the system
call.  In some versions it is executable only by root, but that is easy
to fix.  Personally, I think that ln should have had a -f flag to delete
an existing file with the same names as the destination (but I also think
that sysV is severely crippled by not having an atomic rename).

>There certainly are lock problems under SV:  the print spooler will
>croak if it is fed a large number of jobs nearly simultaneously; a

Can someone explain this one?  Does it involve the FIFO or creating
the spooled work file?  Does uucp have the same problem?

  Les Mikesell

geoff@desint.UUCP (Geoff Kuenning) (11/02/88)

In article <1988Oct31.141701.11055@utfyzx.uucp> harrison@utfyzx.UUCP (David Harrison) writes:

> Recently Geoff Collyer (utstat!geoff) has pointed out that under System 
> V the command:
> 	ln old new
> will destroy "new" if it already exists.  Historically and under other 
> UNIX versions the same command will complain and refuse to make the link.  
> Geoff calls the System V behaviour "an unintuitive shock". It certainly 
> breaks any program that relies on `ln' refusing to link to "new" as a way
> of doing locks (including parts of Cnews).
...
> code like:
> 	if [ !exists new ]	# new command `exists'
> 	then
> 		ln old new
> 	fi
> leaves a terrible window of vulnerability between the test and the
> link.

After seeing this, I checked on my system, since several of my important
scripts use 'ln' to implement locks.  However, I found that all of these
scripts use the following sequence to make the lock:

	trap "" 1 2 15
	touch lock
	ln lock lock1  ||  exit 1
	trap "rm -f lock lock1; exit 1" 1 2 15

This *will* work, because ln will fail complaining the "lock" and "lock1"
are identical.

On the other hand, if your scripts use the following sequence, they will
fail to lock on System V:

	touch lock.$$
	ln lock.$$ lock  ||  exit 1
-- 
	Geoff Kuenning   geoff@ITcorp.com   uunet!desint!geoff

rta@pixar.UUCP (Rick Ace) (11/02/88)

In article <1988Oct31.141701.11055@utfyzx.uucp>, harrison@utfyzx.uucp (David Harrison) writes:
> Recently Geoff Collyer (utstat!geoff) has pointed out that under System 
> V the command:
> 	ln old new
> will destroy "new" if it already exists.  Historically and under other 
> UNIX versions the same command will complain and refuse to make the link.  
> Geoff calls the System V behaviour "an unintuitive shock". It certainly 
> breaks any program that relies on `ln' refusing to link to "new" as a way
> of doing locks (including parts of Cnews).
>  ...
> I have some questions and one comment on this situation.
> 
> First the questions:  if one re-writes ln (as Geoff has done) to
> reproduce the old behaviour and replaces the SV `ln' in /bin
> with this version what will break?

Don't do this.  Other pieces of the vendor's software likely depend
(or will come to depend in future releases) upon the new behavior
of ln.  If you install your own ln, you waive the right to go back
to the vendor and complain when you have problems; if they ask you
if you're running the software the way it came "out of the box,"
you cannot all honesty answer "yes."

As an anecdote, consider this:  at NYIT, we were running 4.1bsd on
our Vax systems.  Along came 4.2bsd with its new signal(3) semantics.
The change in semantics broke several of our programs, so I charged
ahead and "fixed" signal in the C library to work the way it did under
4.1bsd.  That cured one problem, but others surfaced when I recompiled
some Berkeley programs that had expected to get the new signal.
After a bit of head-scratching, the solution I chose was to restore
the 4.2bsd semantics to signal, implement a new library routine called
v7signal(), and change our software to use v7signal().

If you want something that works like Seventh Edition ln, code it up
and install it under another name, like v7ln.

Rick Ace
Pixar
3240 Kerner Blvd, San Rafael CA 94901
...!{sun,ucbvax}!pixar!rta

jfh@rpp386.Dallas.TX.US (John F. Haugh II) (11/04/88)

In article <2630@pixar.UUCP> rta@pixar.UUCP (Rick Ace) writes:
>If you want something that works like Seventh Edition ln, code it up
>and install it under another name, like v7ln.

Or, create a directory /v7bin and put all of the working v7 binaries
you write in there.  And put that directory before /bin in your PATH
-- 
John F. Haugh II                        +----Make believe quote of the week----
VoiceNet: (214) 250-3311   Data: -6272  | Nancy Reagan on Richard Stallman:
InterNet: jfh@rpp386.Dallas.TX.US       |          "Just say `Gno'"
UucpNet : <backbone>!killer!rpp386!jfh  +--------------------------------------

geoff@utstat.uucp (Geoff Collyer) (11/06/88)

I see a race in Geoff Kuenning's inventive solution to locking with
ln(1) on System V:

>	trap "" 1 2 15
>	touch lock
>	ln lock lock1  ||  exit 1
>	trap "rm -f lock lock1; exit 1" 1 2 15

If the "rm -f lock lock1" runs in one copy of this script just after the
"touch lock" runs in another, then the ln will fail unnecessarily.  The
race can be fixed by simply not removing "lock", since "lock1" is the
real lock.
-- 
Geoff Collyer	utzoo!utstat!geoff, geoff@utstat.toronto.edu