sshfs использует протокол передачи файлов SSH (SFTP). Обходное решение, которое вы включили, обходит семантику операции rename () над этим протоколом, когда «новое» имя уже существует.
Поведение POSIX для rename () в этом случае заключается в удалении существующего файла и завершении переименования.
В протоколе SFTP вы можете переименовать файл с помощью операции SSH_FXP_RENAME; однако, его поведение, когда целевое имя уже существует, зависит от версии протокола, который вы используете, и от того, какие флаги вы передаете. Страница википедии по протоколу SFTP содержит ссылки на различные проекты RFC для различных версий протокола. В черновике 00 поведение указано как:
Это ошибка, если уже существует файл с именем, указанным newpath.
В проекте 13 поведение указано как
Если флаги не включают 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 (), поэтому вы не захотите делать это по умолчанию.