sshfs -oworkaround=rename
有什麼作用?
對於我正在學習的作業系統課程,我需要執行 Freebsd5.4。由於我不想嘗試在 git 發布之前發布的 bsd 版本上建構 git,所以我認為
git
從 Arch over使用它會很整潔sshfs
。無論如何,我找到了一種解決方法,建議我提供
sshfs
選項-o workaround=rename
。看起來
git
很開心,但我對剛剛發生的事情感到很困惑……手冊頁中有關解決方法的所有內容都是
fix renaming to existing file
但我完全不知道這意味著什麼……
該選項到底有什麼作用?
sshfs 使用 SSH 文件傳輸協議 (SFTP)。當“新”名稱已經存在時,您啟用的解決方法是圍繞該協議上的 rename() 操作的語義。
在這種情況下 rename() 的 POSIX 行為是刪除現有文件並完成重命名。
在 SFTP 協議中,可以通過 SSH_FXP_RENAME 操作重命名文件;但是,當目標名稱已經存在時,它的行為似乎取決於您使用的協議版本以及您傳遞的標誌。SFTP 協議的wikipedia 頁面有各種版本的協議的各種草案 RFC 的連結。在Draft 00中,行為被列為:
如果已經存在名稱由 newpath 指定的文件,則會出錯。
在草案 13中,該行為被列為
如果 flags 不包括 SSH_FXP_RENAME_OVERWRITE,並且已經存在具有 newpath 指定名稱的文件,則伺服器必須以 SSH_FX_FILE_ALREADY_EXISTS 響應。
如果 flags 包含 SSH_FXP_RENAME_ATOMIC,並且目標文件已經存在,則會以原子方式替換它。即,不存在名稱既不指舊文件也不指新文件的可觀察時刻。SSH_FXP_RENAME_ATOMIC 意味著 SSH_FXP_RENAME_OVERWRITE。
當目標名稱存在時,為了處理可能的 rename() 操作失敗,sshfs 提供了以下解決方法(如果啟用):
if (err == -EPERM && sshfs.rename_workaround) { size_t tolen = strlen(to); if (tolen + RENAME_TEMP_CHARS < PATH_MAX) { int tmperr; char totmp[PATH_MAX]; strcpy(totmp, to); random_string(totmp + tolen, RENAME_TEMP_CHARS); tmperr = sshfs_do_rename(to, totmp); if (!tmperr) { err = sshfs_do_rename(from, to); if (!err) err = sshfs_unlink(totmp); else sshfs_do_rename(totmp, to); } } }
在這段程式碼中,“from”是我們要重命名的文件的現有名稱,“to”是我們想要的新名稱。把一些路徑長度和錯誤簿記放在一邊,這個解決方法
- 將“to”重命名為“totmp”
- 將“從”重命名為“到”
- 取消連結(刪除)“totmp”
這避免了“文件已存在”的衝突,但也改變了 rename() 操作的語義,這就是為什麼你不想預設這樣做的原因。