GNU bug report logs - #29475
filesystem does not allow ln to create bad symbolic link

Previous Next

Package: coreutils;

Reported by: bug-coreutils <at> trodman.com

Date: Mon, 27 Nov 2017 18:28:01 UTC

Severity: normal

Tags: notabug

Done: Assaf Gordon <assafgordon <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 29475 in the body.
You can then email your comments to 29475 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Mon, 27 Nov 2017 18:28:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to bug-coreutils <at> trodman.com:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Mon, 27 Nov 2017 18:28:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: bug-coreutils <at> trodman.com
To: bug-coreutils <at> gnu.org
Subject: filesystem does not allow ln to create bad symbolic link
Date: Mon, 27 Nov 2017 12:17:19 -0600
<not a bug, asking for advice>

I have a non root ssh account on a shared host; was unable to get the distro name.
I'm trying to untar several tar archives. Some of the sym links are bad until
all of the archives are untarred.

It's a large unknown filesystem - see df output.

The problem - ln refuses to create a bad symbolic link!

Has anyone run into this before?  My install script depends on
untarring a few bad sym links, which get resolved by later untars in
that script.  This script has worked fine for me on a dozen or so
centos, fedora, or umbuntu hosts for years.

Any comments appreciated.  Appears I have to rewrite the bash install script to untar all the
sym link target files first.  I plan to ask the host provider for help, but any
tips would be appreciated.

--
thanks,
Tom
--

$ cd /tmp
$ mktemp -d XXX
9ml
$ cd 9ml
$ ln -s not-there badlink
ln: failed to create symbolic link ‘badlink’: No such file or directory
$ df .
df: Warning: cannot read table of mounted file systems: No such file or directory
Filesystem      1K-blocks      Used  Available Use% Mounted on
-              1848231292 358987172 1395335948  21% /
$ uname -a
Linux slmp-550-137.slc.westdc.net 3.10.0-614.10.2.lve1.4.55.el7.x86_64 #1 SMP Tue Jun 20 08:59:12 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
$ ln --version
ln (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Parker and David MacKenzie.





Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Mon, 27 Nov 2017 22:38:01 GMT) Full text and rfc822 format available.

Message #8 received at 29475 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-coreutils <at> trodman.com, 29475 <at> debbugs.gnu.org
Subject: Re: bug#29475: filesystem does not allow ln to create bad symbolic
 link
Date: Mon, 27 Nov 2017 14:37:25 -0800
On 11/27/2017 10:17 AM, bug-coreutils <at> trodman.com wrote:
> $ ln -s not-there badlink
> ln: failed to create symbolic link ‘badlink’: No such file or directory

What happens if you do the following shell command instead?

strace ln -s not-there badlink

On my platform (Fedora 27) the strace output ends this way:

stat("badlink", 0x7ffebc9ddbe0)         = -1 ENOENT (No such file or 
directory)
symlinkat("not-there", AT_FDCWD, "badlink") = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?

which is expected. What happens on your platform?





Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Tue, 28 Nov 2017 00:12:02 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: bug-coreutils <at> trodman.com
To: bug-coreutils <at> gnu.org
Subject: Re: bug#29475: filesystem does not allow ln to create bad symbolic
 link
Date: Mon, 27 Nov 2017 18:11:38 -0600
Hi Paul:

On Mon 11/27/17 14:37 -0800 Paul Eggert wrote:
> On 11/27/2017 10:17 AM, bug-coreutils <at> trodman.com wrote:
> > $ ln -s not-there badlink
> > ln: failed to create symbolic link ‘badlink’: No such file or directory
> 
> What happens if you do the following shell command instead?
> 
> strace ln -s not-there badlink
> 
> On my platform (Fedora 27) the strace output ends this way:
> 
> stat("badlink", 0x7ffebc9ddbe0)         = -1 ENOENT (No such file or 
> directory)
> symlinkat("not-there", AT_FDCWD, "badlink") = 0
> lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
> close(0)                                = 0
> close(1)                                = 0
> close(2)                                = 0
> exit_group(0)                           = ?
> 
> which is expected. What happens on your platform?

Thanks for your help!

--
Tom
--
$ ls not*
ls: cannot access not*: No such file or directory
$ ln -s not-there badlink
ln: failed to create symbolic link ‘badlink’: No such file or directory
$ strace ln -s not-there badlink
execve("/usr/bin/ln", ["ln", "-s", "not-there", "badlink"], [/* 25 vars */]) = 0
brk(NULL)                               = 0x147d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4387544000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=54550, ...}) = 0
mmap(NULL, 54550, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4387536000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2127336, ...}) = 0
mmap(NULL, 3940800, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4386f61000
mprotect(0x7f4387119000, 2097152, PROT_NONE) = 0
mmap(0x7f4387319000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b8000) = 0x7f4387319000
mmap(0x7f438731f000, 16832, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f438731f000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4387535000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4387533000
arch_prctl(ARCH_SET_FS, 0x7f4387533740) = 0
mprotect(0x7f4387319000, 16384, PROT_READ) = 0
mprotect(0x60c000, 4096, PROT_READ)     = 0
mprotect(0x7f4387545000, 4096, PROT_READ) = 0
munmap(0x7f4387536000, 54550)           = 0
brk(NULL)                               = 0x147d000
brk(0x149e000)                          = 0x149e000
brk(NULL)                               = 0x149e000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4380a38000
close(3)                                = 0
stat("badlink", 0x7ffc0eb805a0)         = -1 ENOENT (No such file or directory)
symlink("not-there", "badlink")         = -1 ENOENT (No such file or directory)
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2502, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4387543000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2502
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f4387543000, 4096)            = 0
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib64/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory)
write(2, "ln: ", 4ln: )                     = 4
write(2, "failed to create symbolic link \342"..., 44failed to create symbolic link ‘badlink’) = 44
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": No such file or directory", 27: No such file or directory) = 27
write(2, "\n", 1
)                       = 1
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
$ doing? / interleave basement-attic-kitchen cleanup/declutter

$ strace ln -s not-there badlink
execve("/usr/bin/ln", ["ln", "-s", "not-there", "badlink"], [/* 25 vars */]) = 0
brk(NULL)                               = 0x1c8a000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2e8cc1d000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=54550, ...}) = 0
mmap(NULL, 54550, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2e8cc0f000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2127336, ...}) = 0
mmap(NULL, 3940800, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2e8c63a000
mprotect(0x7f2e8c7f2000, 2097152, PROT_NONE) = 0
mmap(0x7f2e8c9f2000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b8000) = 0x7f2e8c9f2000
mmap(0x7f2e8c9f8000, 16832, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2e8c9f8000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2e8cc0e000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2e8cc0c000
arch_prctl(ARCH_SET_FS, 0x7f2e8cc0c740) = 0
mprotect(0x7f2e8c9f2000, 16384, PROT_READ) = 0
mprotect(0x60c000, 4096, PROT_READ)     = 0
mprotect(0x7f2e8cc1e000, 4096, PROT_READ) = 0
munmap(0x7f2e8cc0f000, 54550)           = 0
brk(NULL)                               = 0x1c8a000
brk(0x1cab000)                          = 0x1cab000
brk(NULL)                               = 0x1cab000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2e86111000
close(3)                                = 0
stat("badlink", 0x7ffd46bc8b60)         = -1 ENOENT (No such file or directory)
symlink("not-there", "badlink")         = -1 ENOENT (No such file or directory)
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2502, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2e8cc1c000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2502
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f2e8cc1c000, 4096)            = 0
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib64/charset.alias", O_RDONLY|O_NOFOLLOW) = -1 ENOENT (No such file or directory)
write(2, "ln: ", 4ln: )                     = 4
write(2, "failed to create symbolic link \342"..., 44failed to create symbolic link ‘badlink’) = 44
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": No such file or directory", 27: No such file or directory) = 27
write(2, "\n", 1
)                       = 1
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
$





Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Tue, 28 Nov 2017 02:42:01 GMT) Full text and rfc822 format available.

Message #14 received at 29475 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-coreutils <at> trodman.com, 29475 <at> debbugs.gnu.org
Subject: Re: bug#29475: filesystem does not allow ln to create bad symbolic
 link
Date: Mon, 27 Nov 2017 18:41:12 -0800
bug-coreutils <at> trodman.com wrote:
> stat("badlink", 0x7ffc0eb805a0)         = -1 ENOENT (No such file or directory)
> symlink("not-there", "badlink")         = -1 ENOENT (No such file or directory)

My guess is that you've removed the working directory somehow, or are on a buggy 
filesystem that thinks the working directory has been removed. I can reproduce 
the situation as follows on Ubuntu 16.04.3:

$ cd /tmp
$ mkdir d
$ cd d
$ rmdir /tmp/d
$ LC_ALL=C strace ln -s a b
...
stat("b", 0x7fffe6df6140)               = -1 ENOENT (No such file or directory)
symlink("a", "b")                       = -1 ENOENT (No such file or directory)
...

The only suggestion I have is "don't do that". If memory serves, POSIX doesn't 
specify the behavior in this case.




Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Fri, 01 Dec 2017 01:00:01 GMT) Full text and rfc822 format available.

Message #17 received at 29475 <at> debbugs.gnu.org (full text, mbox):

From: bug-coreutils <at> trodman.com
To: 29475 <at> debbugs.gnu.org, bug-coreutils <at> gnu.org
Subject: Re: bug#29475: filesystem (apparently cagefs) does not allow ln to
 create bad symbolic link
Date: Thu, 30 Nov 2017 18:59:21 -0600
On Mon 11/27/17 18:41 -0800 Paul Eggert wrote:
> bug-coreutils <at> trodman.com wrote:
> > stat("badlink", 0x7ffc0eb805a0)         = -1 ENOENT (No such file or directory)
> > symlink("not-there", "badlink")         = -1 ENOENT (No such file or directory)
> 
> My guess is that you've removed the working directory somehow, or are on a buggy 
> filesystem that thinks the working directory has been removed. I can reproduce 
> the situation as follows on Ubuntu 16.04.3:
> 
> $ cd /tmp
> $ mkdir d
> $ cd d
> $ rmdir /tmp/d
> $ LC_ALL=C strace ln -s a b
> ...
> stat("b", 0x7fffe6df6140)               = -1 ENOENT (No such file or directory)
> symlink("a", "b")                       = -1 ENOENT (No such file or directory)
> ...
> 
> The only suggestion I have is "don't do that". If memory serves, POSIX doesn't 
> specify the behavior in this case.

Thanks for all your help Paul.

I talked w/a level one help person. They said the host distro is Cloudlinux, and the
filesystem is cagefs. My quick web search results:

    https://docs.cloudlinux.com/index.html?cagefs.html

From my trial and error, this file system does not let you create bad sym links. I just have to work
around it; tar up dirs in two passes one for sym links only, then the reverse. When untarring,
do non sym links first.

--
Tom




Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Fri, 01 Dec 2017 01:08:03 GMT) Full text and rfc822 format available.

Message #20 received at 29475 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-coreutils <at> trodman.com, 29475 <at> debbugs.gnu.org
Subject: Re: bug#29475: filesystem (apparently cagefs) does not allow ln to
 create bad symbolic link
Date: Thu, 30 Nov 2017 17:07:17 -0800
On 11/30/2017 04:59 PM, bug-coreutils <at> trodman.com wrote:
>  From my trial and error, this file system does not let you create bad sym links.

Hmm, yes, apparently that filesystem can be configured to disallow 
creation of dangling symlinks or links to files they don't own. See:

https://www.cloudlinux.com/getting-started-with-cloudlinux-os/41-security-features/933-activating-securelink

Using this feature will break a lot of programs (not just ln), but 
evidently they're not concerned about that.





Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Fri, 01 Dec 2017 15:46:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-coreutils <at> gnu.org:
bug#29475; Package coreutils. (Tue, 30 Oct 2018 02:14:02 GMT) Full text and rfc822 format available.

Message #26 received at 29475 <at> debbugs.gnu.org (full text, mbox):

From: Assaf Gordon <assafgordon <at> gmail.com>
To: 29475 <at> debbugs.gnu.org
Subject: Re: bug#29475: filesystem (apparently cagefs) does not allow ln to
 create bad symbolic link
Date: Mon, 29 Oct 2018 20:13:32 -0600
tags 29475 notabug
close 29475
stop

(triaging old bugs)

On 2017-11-30 6:07 p.m., Paul Eggert wrote:
> On 11/30/2017 04:59 PM, bug-coreutils <at> trodman.com wrote:
>>  From my trial and error, this file system does not let you create bad 
>> sym links.
> 
> Hmm, yes, apparently that filesystem can be configured to disallow 
> creation of dangling symlinks or links to files they don't own. See:
> 
> https://www.cloudlinux.com/getting-started-with-cloudlinux-os/41-security-features/933-activating-securelink 
> 
> Using this feature will break a lot of programs (not just ln), but 
> evidently they're not concerned about that.
> 

Given the above, I'm closing this bug.
Discussion can continue by replying to this thread.

-assaf





Added tag(s) notabug. Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 30 Oct 2018 02:14:03 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 29475 <at> debbugs.gnu.org and bug-coreutils <at> trodman.com Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 30 Oct 2018 02:14:03 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 27 Nov 2018 12:24:12 GMT) Full text and rfc822 format available.

This bug report was last modified 5 years and 123 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.