sshfs usa el Protocolo de transferencia de archivos SSH (SFTP). La solución alternativa que ha habilitado es evitar la semántica de una operación rename () sobre ese protocolo cuando el nombre "nuevo" ya existe.
El comportamiento POSIX para rename () en este caso es eliminar el archivo existente y completar el cambio de nombre.
En el protocolo SFTP, puede cambiar el nombre de un archivo con la operación SSH_FXP_RENAME; sin embargo, su comportamiento cuando el nombre de destino ya existe parece depender de la versión del protocolo que esté utilizando y de los indicadores que pase. La página de wikipedia para el protocolo SFTP tiene enlaces a varios borradores de RFC para varias versiones del protocolo. En el Borrador 00, el comportamiento aparece como:
Es un error si ya existe un archivo con el nombre especificado por newpath.
En el Borrador 13 , el comportamiento se enumera como
Si las banderas no incluyen SSH_FXP_RENAME_OVERWRITE, y ya existe un archivo con el nombre especificado por newpath, el servidor DEBE responder con SSH_FX_FILE_ALREADY_EXISTS.
Si las banderas incluyen SSH_FXP_RENAME_ATOMIC, y el archivo de destino ya existe, se reemplaza de forma atómica. Es decir, no hay un instante observable en el tiempo en el que el nombre no se refiera al archivo antiguo ni al nuevo. SSH_FXP_RENAME_ATOMIC implica SSH_FXP_RENAME_OVERWRITE.
Para tratar la posible falla de una operación rename () cuando existe el nombre de destino, sshfs proporciona la siguiente solución (si está habilitada) :
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);
}
}
}
En este código, "from" es el nombre existente del archivo que queremos renombrar y "to" es el nuevo nombre que queremos. Dejando a un lado la longitud de la ruta y la contabilidad de errores, esto funciona
- Renombra "a" a "totmp"
- Renombra "de" a "a"
- Desvincula (elimina) "totmp"
Esto evita el conflicto "el archivo ya existe", pero también cambia la semántica de las operaciones rename (), por lo que no querrá hacerlo de forma predeterminada.