mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-24 15:23:13 +03:00
fix(vfs): data safety, SSH policy and liveness fixes from the pre-merge review
Data safety (VFS): - Copies write a temporary sibling and replace the destination only once it is complete (as writeAll() already did): a failed overwrite kept nothing of the old destination, and copying onto a hard link to the source truncated the source itself. A destination symlink is written through, and one that resolves to the source fails as the same file. - Moving a symlink to another file system is refused: the fallback copy followed it and then removed the copied entries through the link, emptying its target. - Saves keep the exact mode of the file they replace: the temporary was created with it, but filtered through the umask. Deadlocks and blocking: - writeAll( createParents ) waited on makeDirs() queued on its own orchestration pool: one thread deadlocked at once, two with two concurrent saves. Orchestration jobs now create parents directly. - Copies and moves run on their own pool (Config::transferThreads), so long transfers no longer delay saves, reads and recursive removals. - Local watches are registered and removed on the I/O pool: efsw and the directory checks touch the filesystem, which blocked the UI thread on slow mounts. SSH security: - "@revoked" known_hosts keys are rejected; they were skipped as unknown, so StrictHostKeyChecking accept-new trusted them. - Sessions are shared only between configurations with the same security policy (known hosts, host key checking, algorithms, authentication settings), not just the same destination: a strict alias reused a session a permissive one had accepted. - A configured algorithm restriction that permits nothing this libssh2 supports fails the connection instead of using libssh2's defaults. SSH liveness: - Operations submitted to a failed or closed connection fail with ConnectionLost instead of staying pending forever. - ssh-agent requests run on a worker thread (SSHAgent, Unix-domain sockets), with libssh2_userauth_publickey() and a sign callback that waits without blocking: an agent waiting for a hardware key touch no longer stalls every other session. Windows keeps libssh2's agent. - Connecting no longer holds a helper thread while the user answers a host key or password prompt: the setup continues from the session's ready task, one ProxyJump hop at a time. Jump hosts only need to authenticate, not to offer SFTP. - Idle connections close after SFTPProviderConfig::idleTimeout. The old check compared use_count() with 1 and never passed: connections now track their users (open handles, pumps, jump children). - A remote watch agent that never answers falls back to polling after 5 seconds; the directory listing waited for it indefinitely. Core: - CancellationSource::cancel() keeps the shared state alive while its callbacks run: a callback destroying the source freed it mid-cancel (heap use after free under AddressSanitizer). - MainThreadExecutor::shutdown() detaches the executor from its dispatcher node and drops queued and later functions. - String::icompare(): case-insensitive comparison without allocations. VFSDirectoryModel (UI thread): - Names compare with String::icompare() instead of lowercased copies, which made every sort, merge and insertion allocate (about 2x slower when sorting). - Sorting by type asks the type provider once per entry instead of twice per comparison. - The case-insensitive plain text filter keeps a search table instead of lowercasing every name on each row rebuild. - Watch events update the visible rows in place instead of rebuilding them from every entry per event. Drag and drop: - The X11 drag source showed the pending badge over the source window for every application, which broke the X11 drag and drop integration tests in CI. DragOffer::sourceHandlesDrops now asks for it; eefm sets it, since it completes those drops as its own drag. eefm: - Shutdown destroyed the main thread executor before the VFS and the thread pool while continuations still held it: closing during a transfer could dispatch through freed memory. Transfers are cancelled, the VFS is destroyed, the executor is detached, and only then are the scene, its pool and the executor destroyed. - Remote files opened locally were downloaded to /tmp/eefm/<scheme>/<host>/<name>: files with the same name from other folders, users or ports overwrote each other, in a directory shared by every user. They now go to a per-file folder (a hash of the complete URI) in the user's cache. Every fix comes with a regression test.
This commit is contained in:
@@ -216,7 +216,9 @@ including one the user switches to with Alt+Tab mid-drag. Internal drag feedback
|
||||
the source window still receives the pointer. Ignore the internal drag's release while the native
|
||||
session is active and resolve it from the completion instead. On X11, a release over the source
|
||||
window ends the session `Cancelled` with `DragResult::releasedOverSource` set, so the application
|
||||
completes it as its internal drop. Elsewhere, such a drop arrives as `FileDropped` events.
|
||||
completes it as its internal drop. Elsewhere, such a drop arrives as `FileDropped` events. Set
|
||||
`DragOffer::sourceHandlesDrops` so the preview shows a pending drop, not a rejected one, while the
|
||||
pointer is over the source window.
|
||||
|
||||
Applications that install their own `SDL_SetX11EventHook` must coordinate its use: SDL3 has a single
|
||||
hook slot, which eepp uses during an active native drag and clears afterwards.
|
||||
|
||||
@@ -110,6 +110,12 @@ Moves use a native rename when both sides are on the same provider/authority and
|
||||
plus removal of the entries that were completely copied; a source is never removed after a partial
|
||||
transfer.
|
||||
|
||||
File copies are written to a temporary sibling before publication. `Fail` and `Skip` also apply
|
||||
when a destination appears while the copy is running. The `Overwrite` policy requires
|
||||
`AtomicReplace`; otherwise the transfer returns `Unsupported` and preserves the old contents.
|
||||
Creating a file with `Fail` or `Skip` requires `Rename`. Moving a symlink through the copy fallback
|
||||
is unsupported; native same-filesystem renames still move the link itself.
|
||||
|
||||
## Watching
|
||||
|
||||
```cpp
|
||||
|
||||
Reference in New Issue
Block a user