что делает `sshfs -oworkaround = rename`?

17

Для класса операционных систем, который я использую, мне нужно было запустить Freebsd5.4. Так как я не хотел бороться с попыткой собрать git на версии bsd, выпущенной до выпуска git, я подумал, что будет полезно использовать gitArch из Arch sshfs.

Во всяком случае, я нашел обходной путь, который предложил мне дать sshfsвариант -o workaround=rename.

Кажется, это делает gitсчастливым, но я не совсем понимаю, что только что произошло ...

Вся страница руководства говорит об обходном пути

fix renaming to existing file

но я совершенно сбит с толку относительно того, что это значит ...

Что именно делает этот вариант?

math4tots
источник
3
Указатель для того, кто хочет разобраться, что именно это означает (и написать ответ, и, надеюсь, патч для документации): sourceforge.net/p/fuse/sshfs/ci/master/tree/sshfs.c, начиная со строки 2300.
Дероберт

Ответы:

10

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 (), поэтому вы не захотите делать это по умолчанию.

Стивен Д
источник