答案1
sshfs 使用 SSH 文件传输协议 (SFTP)。您启用的解决方法是当“新”名称已存在时,解决该协议上的 rename() 操作的语义。
在这种情况下,rename() 的 POSIX 行为是删除现有文件并完成重命名。
在SFTP协议中,可以通过SSH_FXP_RENAME操作重命名文件;然而,当目标名称已经存在时它的行为似乎取决于您正在使用的协议的版本以及您传递的标志。这SFTP 协议的维基百科页面具有指向不同版本协议的各种 RFC 草案的链接。在草案00该行为被列为:
如果已经存在由 newpath 指定名称的文件,则会发生错误。
在草案13,行为被列为
如果 flags 不包含 SSH_FXP_RENAME_OVERWRITE,并且已经存在名称由 newpath 指定的文件,则服务器必须使用 SSH_FX_FILE_ALREADY_EXISTS 进行响应。
如果标志包含 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() 操作的语义,这就是为什么您不想默认执行此操作。