Commit aaae579
committed
Handle ERROR_INVALID_FUNCTION on filesystems without junction support
Might close bazelbuild#17192.
**Problem:**
Bazel fails completely on Windows when using filesystems that don't
support junction/reparse point operations (e.g., virtiofs, VirtualBox
shared folders, network drives, RAM disks).
The fatal error occurs when `ReadSymlinkOrJunction` fails during path
resolution (e.g., when Starlark code calls `.realpath`): "Cannot read
link: DeviceIoControl: Incorrect function"
This causes build analysis to abort completely.
Additionally, `CreateJunction` failures when creating convenience
symlinks produce cryptic error messages, though these were already
non-fatal warnings.
Both fail because `DeviceIoControl` returns `ERROR_INVALID_FUNCTION`
when the filesystem doesn't implement `FSCTL_GET_REPARSE_POINT` or
`FSCTL_SET_REPARSE_POINT` operations.
**Solution:**
Handle `ERROR_INVALID_FUNCTION` gracefully by treating it as a "not
supported" condition rather than a fatal error:
1. in `ReadSymlinkOrJunction` (`file.cc`:592): return `kNotALink`
instead of `kError` when `ERROR_INVALID_FUNCTION` occurs. This
allows path resolution to continue for non-symlink paths on
unsupported filesystems.
2. in `CreateJunction` (`file.cc`:461): return new `kNotSupported`
result code when `ERROR_INVALID_FUNCTION` occurs. This produces
clearer "filesystem does not support junctions" warnings instead of
cryptic "Incorrect function" messages. This improves UX but doesn't
change behavior (these failures were already non-fatal).
This follows the try-first, fallback-on-error pattern (EAFP) used by
other major projects when handling unsupported filesystem operations.
**Prior art:**
- Rust (rust-lang/rust#138133): checks `ERROR_INVALID_FUNCTION`,
`ERROR_NOT_SUPPORTED`, and `ERROR_INVALID_PARAMETER` for filesystem
operation fallbacks in `std::fs::rename`.
- Rust (rust-lang/rust#43801): reduced symlink usage in build system
after encountering os error 1 on VirtualBox shared folders.
- Microsoft STL (microsoft/STL#2077): handles junctions and reparse
point errors including `ERROR_INVALID_PARAMETER` with robust
fallback logic in `filesystem.cpp`.
- Go (golang/go#20506): uses fallback strategies when symlink APIs
are unavailable on different Windows versions.
- WinFsp (winfsp/winfsp#88): documents that `ERROR_INVALID_FUNCTION`
indicates `STATUS_NOT_IMPLEMENTED` for unsupported operations.
- Microsoft Learn: recommends checking `FILE_SUPPORTS_REPARSE_POINTS`
flag via `GetVolumeInformation`, but try-catch approach is simpler
and handles edge cases where detection succeeds but operations fail.
**Impact:**
- enables Bazel builds on virtiofs, VirtualBox shared folders, RAM
disks, and other filesystems that don't support Windows junction
operations
- convenience symlinks (bazel-bin, bazel-out, etc.) still won't be
created, but now with clearer error messages
**Limitations:**
Full junction support would require filesystem-level changes (e.g.,
virtiofs driver improvements).
**Testing:**
Tested on Windows 11 VM with host directory mounted via virtiofs,
with [rules_pkg](https://github.com/bazelbuild/rules_pkg/blob/6cdaba69ee76463b2b8e97e8d243dbb6115c3aee/toolchains/git/git_configure.bzl#L40).
Before change: build analysis aborted with "Cannot read link" fatal
error. After change: builds complete successfully with clearer
warnings about unsupported junctions for convenience symlinks.1 parent 1cdafcf commit aaae579
File tree
3 files changed
+15
-0
lines changed- src/main
- java/com/google/devtools/build/lib/windows
- native/windows
3 files changed
+15
-0
lines changedLines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
| 73 | + | |
73 | 74 | | |
74 | 75 | | |
75 | 76 | | |
| |||
172 | 173 | | |
173 | 174 | | |
174 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
175 | 179 | | |
176 | 180 | | |
177 | 181 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
456 | 456 | | |
457 | 457 | | |
458 | 458 | | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
459 | 464 | | |
460 | 465 | | |
461 | 466 | | |
| |||
587 | 592 | | |
588 | 593 | | |
589 | 594 | | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
590 | 600 | | |
591 | 601 | | |
592 | 602 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
| 116 | + | |
116 | 117 | | |
117 | 118 | | |
118 | 119 | | |
| |||
0 commit comments