On a Linux machine (a computing cluster, actually), I copied a folder from another user (who granted me permissions to do so using the appropriate chmod).
This folder contains symbolic links to files I cannot access. I want to update them so that they point to copies of the same files, that I own.
However, when I try to do so using ln -sf
, I get Permission denied
.
Why is that so?
That's the link:
$ ls -l 50ATC_Rep2.fastq
lrwxrwxrwx 1 bli cifs-BioIT 55 21 nov. 13:45 50ATC_Rep2.fastq -> /pasteur/homes/mmazzuol/Raw_data/CHIP_TEST/BM50.2.fastq
I don't have permission to access its target, but I have a copy of it. That's the new target I want:
$ ls -l ../../../raw_data/CHIP_TEST/BM50.2.fastq
-rwxr-xr-x 1 bli cifs-BioIT 4872660831 21 nov. 14:00 ../../../raw_data/CHIP_TEST/BM50.2.fastq
And that's what happens when I try ln -sf
:
$ ln -sf ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
ln: accessing `50ATC_Rep2.fastq': Permission denied
It seems that the permissions of the current target is what counts, not the permissions on the link itself.
I can circumvent the problem by first deleting the link, then re-creating it:
$ rm 50ATC_Rep2.fastq
rm: remove symbolic link `50ATC_Rep2.fastq'? y
$ ln -s ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
$ ls -l 50ATC_Rep2.fastq
lrwxrwxrwx 1 bli cifs-BioIT 40 21 nov. 18:57 50ATC_Rep2.fastq -> ../../../raw_data/CHIP_TEST/BM50.2.fastq
Why can I delete the link, but not update it?
Best Answer
It appears as if the GNU
ln
implementation on Linux uses thestat()
function to determine whether the target exists or not. This function is required to resolve symbolic links, so when the target of the pre-existing link is not accessible, the function returnsEACCESS
("permission denied") and the utility fails. This has been verified withstrace
to be true on a Ubuntu Linux system.To make the GNU
ln
uselstat()
instead, which does not resolve symbolic links, you should call it with its (non-standard)-n
option (GNU additionally uses--no-dereference
as an alias for-n
).Reading the POSIX specification for
ln
, I can't really make out whether GNUln
does this for some undefined or unspecified behaviour in the specification or not, but it is possible that it uses the fact that...The "unspecified" bit here may give GNU
ln
the license to behave as it does, at least if we allow ourselves to interpret "a previous step" as "the destination path is a symbolic link".The GNU documentation for the
-n
option is mostly concerned about the case when the target is a symbolic link to a directory:The default behaviour of GNU
ln
when the target is a symbolic link to a directory, is to put the new symbolic link inside that directory (i.e., it dereferences the link to the directory). When the target of the pre-existing link is not accessible, it chooses to emit a diagnostic message and fail (allowed by the standard text).OpenBSD
ln
(and presumablyln
on other BSD systems), on the other hand, will behave like GNUln
when the target is a symbolic link to an accessible directory, but will unlink and recreate the symbolic link as requested if the target of the pre-existing link is not accessible. I.e., it chooses to continue with the operation (allowed by the standard text).Also, GNU
ln
on OpenBSD behaves like OpenBSD's nativeln
, which is mildly interesting.Removing the pre-existing symbolic link with
rm
is not an issue whatsoever, as you appear to have write and executable permissions for the directory it's located in.