对于我正在学习的操作系统课程,我需要运行 Freebsd5.4。由于我不想在 git 发布之前发布的 bsd 版本上尝试构建 git,我认为git
从 Arch over使用它会很整洁sshfs
。
无论如何,我找到了一个建议我给出选项的解决方法。sshfs
-o workaround=rename
看起来git
很开心,但我对刚刚发生的事情感到很困惑......
关于解决方法的所有手册页说的是
fix renaming to existing file
Run Code Online (Sandbox Code Playgroud)
但我完全不明白这意味着什么......
该选项究竟有什么作用?
Ste*_*n D 11
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 响应。
如果 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中,“from”是我们想要重命名的文件的现有名称,“to”是我们想要的新名称。把一些路径长度和错误簿记放在一边,这个解决方法
这避免了“文件已存在”冲突,但也改变了 rename() 操作的语义,这就是默认情况下您不想这样做的原因。