Permissions

為什麼在將符號連結更新到具有權限的新目標時權限被拒絕?

  • November 21, 2019

在 Linux 機器(實際上是計算集群)上,我從另一個使用者那裡複製了一個文件夾(他使用適當的 chmod 授予我這樣做的權限)。

此文件夾包含指向我無法訪問的文件的符號連結。我想更新它們,使它們指向我擁有的相同文件的副本。

但是,當我嘗試這樣做時ln -sf,我得到了Permission denied.

為什麼呢?

那是連結:

$ 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

我無權訪問它的目標,但我有它的副本。這就是我想要的新目標:

$ 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

這就是我嘗試時發生的情況ln -sf

$ ln -sf ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
ln: accessing `50ATC_Rep2.fastq': Permission denied

似乎目前目標的權限才是最重要的,而不是連結本身的權限。

我可以通過首先刪除連結然後重新創建它來規避問題:

$ 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

為什麼我可以刪除連結,但不能更新?

似乎lnLinux 上的 GNU 實現使用該stat()函式來確定目標是否存在。此函式是解析符號連結所必需的,因此當無法訪問預先存在的連結的目標時,該函式返回EACCESS(“權限被拒絕”)並且實用程序失敗。這已strace在 Ubuntu Linux 系統上得到驗證。

要改為ln使用lstat()不解析符號連結的 GNU,您應該使用其(非標準)-n選項呼叫它(GNU 還--no-dereference用作 的別名-n)。

ln -s -n -f ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq

閱讀POSIX 規範ln,我真的無法確定 GNU 是否ln針對規範中的某些未定義或未指定的行為執行此操作,但它可能使用以下事實……

如果目標路徑存在並且是由上一步創建的,則未指定是否ln應將診斷消息寫入標準錯誤,對目前 source_file 不做任何事情,並繼續處理任何剩餘的 source_files;或將繼續處理目前的 source_file。

此處的“未指定”位可能會授予 GNUln行為的許可,至少如果我們允許自己將“前一步”解釋為“目標路徑是符號連結”。

-n選項的 GNU 文件主要關注目標是指向目錄的符號連結的情況:

'-n'
'--no-dereference'
    Do not treat the last operand specially when it is a symbolic link
    to a directory.  Instead, treat it as if it were a normal file.

    When the destination is an actual directory (not a symlink to one),
    there is no ambiguity.  The link is created in that directory.  But
    when the specified destination is a symlink to a directory, there
    are two ways to treat the user's request.  'ln' can treat the
    destination just as it would a normal directory and create the link
    in it.  On the other hand, the destination can be viewed as a
    non-directory--as the symlink itself.  In that case, 'ln' must
    delete or backup that symlink before creating the new link.  The
    default is to treat a destination that is a symlink to a directory
    just like a directory.

    This option is weaker than the '--no-target-directory' ('-T')
    option, so it has no effect if both options are given.

當目標是指向目錄的符號連結時,GNU 的預設行為ln是將新的符號連結放入該目錄中(即,它取消對目錄的連結的引用)。當預先存在的連結的目標不可訪問時,它會選擇發出診斷消息並失敗(標准文本允許)。

另一方面,當目標是可訪問目錄的符號連結時, OpenBSD ln(可能ln在其他 BSD 系統上)將表現得像 GNU ,但如果目標是預先存在的連結,則會根據請求取消連結並重新創建符號連結不可訪問。即,它選擇繼續操作(標准文本允許)。ln

此外,OpenBSD 上的 GNUln的行為類似於 OpenBSD 的 native ln,這有點有趣。

刪除預先存在的符號連結rm不是問題,因為您似乎對其所在的目錄具有寫入和可執行權限。

引用自:https://unix.stackexchange.com/questions/553415