sshfsはSSHファイル転送プロトコル(SFTP)を使用します。有効にした回避策は、「新しい」名前が既に存在する場合に、そのプロトコルに対するrename()操作のセマンティクスを回避することです。
この場合のrename()のPOSIXの動作は、既存のファイルを削除して名前変更を完了することです。
SFTPプロトコルでは、SSH_FXP_RENAME操作を使用してファイルの名前を変更できます。ただし、ターゲット名が既に存在する場合の動作は、使用しているプロトコルのバージョンと渡すフラグによって異なります。SFTPプロトコルのウィキペディアページには、プロトコルのさまざまなバージョンのさまざまなRFCドラフトへのリンクがあります。でドラフト00の動作は次のようにリストされます。
newpathで指定された名前のファイルが既に存在する場合、エラーになります。
ドラフト13、動作は次のように記載されています
フラグに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」に変更
- 「from」から「to」に名前を変更
- リンク解除(削除) "totmp"
これにより、「ファイルはすでに存在します」という競合を回避しますが、rename()操作のセマンティクスも変更するため、デフォルトでは実行したくないのです。