Herunterladen (l) und Hochladen (u) einzelner Dateien scheitern reproduzierbar direkt nach dem Verbinden:
Download: [Errno 2] No such file
Upload: [Errno 13] Permission denied
Ursache
SFTPBackend.connect() setzt self._cwd = self._sftp.getcwd() or ".". Paramikos getcwd() liefert nach open_sftp() aber None, solange kein explizites chdir() erfolgt ist. _cwd wird damit auf "." gesetzt.
Die App uebernimmt diesen Wert als remote_path und baut daraus via _join(".", "datei.txt", False) den Pfad "./datei.txt". SFTPBackend._abs() praefixt alles, was nicht mit / beginnt, mit einem Slash — Ergebnis: "/./datei.txt".
Der Server normalisiert das zu /datei.txt, also dem Dateisystem-Root statt dem Home-Verzeichnis. Daher No such file beim Download und Permission denied beim Upload.
Das Listing funktioniert trotzdem, weil listdir(".") serverseitig relativ zum Home aufgeloest wird — deshalb faellt der Fehler erst beim Transfer auf.
connect() muss den Pfad ueber self._sftp.normalize(".") auf einen absoluten Pfad aufloesen, statt auf "." zurueckzufallen. Zusaetzlich sollte _abs() relative Pfade gegen _cwd aufloesen statt blind einen Slash voranzustellen.
Zweiter, unabhaengiger Bug im selben Codepfad
BrowserScreen._copy_tree() (rekursiver Ordner-Transfer) hat die beiden mkdir-Zweige vertauscht:
download=True: ruft self.backend.mkdir(dst) auf, obwohl dst ein lokaler Pfad ist -> legt das Verzeichnis auf dem Server an
download=False: ruft os.makedirs(dst) auf, obwohl dst ein entfernter Pfad ist -> legt es lokal an
Ordner-Transfers in beide Richtungen sind dadurch defekt.
Betroffen
v0.3.1 und frueher, SFTP-Backend.
## Symptom
Herunterladen (`l`) und Hochladen (`u`) einzelner Dateien scheitern reproduzierbar direkt nach dem Verbinden:
```
Download: [Errno 2] No such file
Upload: [Errno 13] Permission denied
```
## Ursache
`SFTPBackend.connect()` setzt `self._cwd = self._sftp.getcwd() or "."`. Paramikos `getcwd()` liefert nach `open_sftp()` aber **`None`**, solange kein explizites `chdir()` erfolgt ist. `_cwd` wird damit auf `"."` gesetzt.
Die App uebernimmt diesen Wert als `remote_path` und baut daraus via `_join(".", "datei.txt", False)` den Pfad `"./datei.txt"`. `SFTPBackend._abs()` praefixt alles, was nicht mit `/` beginnt, mit einem Slash — Ergebnis: `"/./datei.txt"`.
Der Server normalisiert das zu `/datei.txt`, also dem **Dateisystem-Root** statt dem Home-Verzeichnis. Daher `No such file` beim Download und `Permission denied` beim Upload.
Das Listing funktioniert trotzdem, weil `listdir(".")` serverseitig relativ zum Home aufgeloest wird — deshalb faellt der Fehler erst beim Transfer auf.
## Reproduktion
```python
from ftptui.sftp_backend import SFTPBackend
from ftptui.app import _join
b = SFTPBackend()
b.connect(host, 22, user, password)
print(repr(b.pwd())) # '.'
print(repr(b._sftp.getcwd())) # None
print(repr(b._sftp.normalize('.'))) # '/home/<user>' <- korrekt
target = _join(b.pwd(), 'remotefile.txt', False)
print(repr(target), repr(b._abs(target))) # './remotefile.txt' '/./remotefile.txt'
b.download(target, '/tmp/dl.txt') # FileNotFoundError
```
## Loesung
`connect()` muss den Pfad ueber `self._sftp.normalize(".")` auf einen absoluten Pfad aufloesen, statt auf `"."` zurueckzufallen. Zusaetzlich sollte `_abs()` relative Pfade gegen `_cwd` aufloesen statt blind einen Slash voranzustellen.
## Zweiter, unabhaengiger Bug im selben Codepfad
`BrowserScreen._copy_tree()` (rekursiver Ordner-Transfer) hat die beiden `mkdir`-Zweige vertauscht:
- `download=True`: ruft `self.backend.mkdir(dst)` auf, obwohl `dst` ein **lokaler** Pfad ist -> legt das Verzeichnis auf dem Server an
- `download=False`: ruft `os.makedirs(dst)` auf, obwohl `dst` ein **entfernter** Pfad ist -> legt es lokal an
Ordner-Transfers in beide Richtungen sind dadurch defekt.
## Betroffen
v0.3.1 und frueher, SFTP-Backend.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Symptom
Herunterladen (
l) und Hochladen (u) einzelner Dateien scheitern reproduzierbar direkt nach dem Verbinden:Ursache
SFTPBackend.connect()setztself._cwd = self._sftp.getcwd() or ".". Paramikosgetcwd()liefert nachopen_sftp()aberNone, solange kein expliziteschdir()erfolgt ist._cwdwird damit auf"."gesetzt.Die App uebernimmt diesen Wert als
remote_pathund baut daraus via_join(".", "datei.txt", False)den Pfad"./datei.txt".SFTPBackend._abs()praefixt alles, was nicht mit/beginnt, mit einem Slash — Ergebnis:"/./datei.txt".Der Server normalisiert das zu
/datei.txt, also dem Dateisystem-Root statt dem Home-Verzeichnis. DaherNo such filebeim Download undPermission deniedbeim Upload.Das Listing funktioniert trotzdem, weil
listdir(".")serverseitig relativ zum Home aufgeloest wird — deshalb faellt der Fehler erst beim Transfer auf.Reproduktion
Loesung
connect()muss den Pfad ueberself._sftp.normalize(".")auf einen absoluten Pfad aufloesen, statt auf"."zurueckzufallen. Zusaetzlich sollte_abs()relative Pfade gegen_cwdaufloesen statt blind einen Slash voranzustellen.Zweiter, unabhaengiger Bug im selben Codepfad
BrowserScreen._copy_tree()(rekursiver Ordner-Transfer) hat die beidenmkdir-Zweige vertauscht:download=True: ruftself.backend.mkdir(dst)auf, obwohldstein lokaler Pfad ist -> legt das Verzeichnis auf dem Server andownload=False: ruftos.makedirs(dst)auf, obwohldstein entfernter Pfad ist -> legt es lokal anOrdner-Transfers in beide Richtungen sind dadurch defekt.
Betroffen
v0.3.1 und frueher, SFTP-Backend.