Commit Graph

13923 Commits

Author SHA1 Message Date
Sergei Zimmerman
6dfeff04c1 local-binary-cache-store: Check that paths don't escape the binary cache directory
Previously arguments to getFile, upsertFile weren't checked
to be inside the root directory. It's not a very big issue since
substituters/stores are already a trusted component and can't be
specified without being a trusted user. Still, it's nice to validate
the necessary preconditions. Also changes the binaryCacheDir to be a
std::filesystem::path. Note the gotcha with absolute paths and operator/.
2026-02-24 19:53:09 +03:00
Sergei Zimmerman
3d9174cec5 libutil: Accept std::filesystem::path in readFile 2026-02-24 19:53:08 +03:00
John Ericson
5ce241cbfd Merge pull request #15307 from nix-windows/windows-local-shorthand
windows: add a separate local_shorthand_path test
2026-02-23 19:42:48 +00:00
John Ericson
3bfd64c3cd Merge pull request #15323 from obsidiansystems/fix-eio-readline
libutil: treat EIO as EOF in `readLine`
2026-02-23 19:30:19 +00:00
Brian McKenna
3f419cfa4e ParsedURL::path <-> std::filesystem::path, use in StoreReference
This missing URL functionality allow us to properly fix the path
shorthand for local store URLs test case.
2026-02-23 13:32:07 -05:00
Amaan Qureshi
994137dcf7 libutil: treat EIO as EOF in readLine
Reading from a pty master returns `EIO` once the slave side closes, however, `readLine` lets it propagate as an uncaught `SysError`, which causes spurious build failures in gvisor and similar sandboxed environments where pty teardown races differently. This commit catches `EIO` inside the read lambda and maps it to a zero-length read, reusing the existing EOF path.
2026-02-23 13:30:05 -05:00
Amaan Qureshi
6cddf03b5a tests: add writeFull interrupt-handling regression test
This commit verifies that `writeFull` with `allowInterrupts=false` completes
successfully when the interrupt flag is set. This prevents regressions
like the one fixed by #15255 where `write()` called `checkInterrupt()`
unconditionally.
2026-02-23 12:20:54 -05:00
Sergei Zimmerman
658c775f01 libutil: Fix writeFull to respect allowInterrupts
c0e849b696 broke interrupt handling since
writeFull started throwing Interrupted even when allowInterrupts was false.
This would lead to exceptions leaking out when they must not (for example during
progress bar shutdown).
2026-02-23 15:34:18 +03:00
Sergei Zimmerman
b1ad42e6d5 Merge pull request #15242 from obsidiansystems/fix-prefetch-segfault
libstore: guard against empty archive in unpack paths
2026-02-22 19:14:11 +00:00
Amaan Qureshi
c6d93828bd registry: fix symlinked flake registry files broken by convert-end-exes
This commit reverts to using `getFSSourceAccessor()` so absolute symlink targets resolve correctly, since `makeFSSourceAccessor(path)` roots the accessor at `path` and can't follow symlinks that escape it.
2026-02-21 12:14:42 -05:00
Sergei Zimmerman
614072adcb Merge pull request #15286 from NixOS/failed-values-v2
Introduce a "failed" value type (v2)
2026-02-21 09:05:15 +00:00
John Ericson
42f6e9933d Merge pull request #15311 from obsidiansystems/convert-end-exes
libutil: return `std::filesystem::path` from XDG directory helpers
2026-02-21 04:22:26 +00:00
siddhantCodes
6808bfab92 libutil: return std::filesystem::path from XDG directory helpers
`getCacheDir`, `getConfigDir`, `getDataDir`, `getStateDir`, and related functions now return `std::filesystem::path` and use `getEnvOs` for native OS string handling, letting callsites replace string concatenation with `operator/` and drop the ad-hoc `namespace nix::fs` alias from six CLI files. `expandTilde` is fixed to strip both `~` and `/` before joining with `operator/` (an absolute right-hand operand silently replaces the left-hand side), and `ExecutablePath` gains `parseAppend` for incremental `PATH` construction.

Co-authored-by: Amaan Qureshi <git@amaanq.com>
2026-02-20 22:35:47 -05:00
John Ericson
92942071c7 Merge pull request #15310 from obsidiansystems/pathlocks-wine
`PathLocks` allow to fail on Wine
2026-02-21 03:32:18 +00:00
John Ericson
6363c1bf00 PathLocks allow to fail on Wine
It needs functionality Wine doesn't implement yet. So let's just have a
wine-only warn-and-keep-going.
2026-02-20 21:45:04 -05:00
John Ericson
5adb6a36b6 Fix initialization of ioport in Worker on Windows 2026-02-20 18:56:00 -05:00
John Ericson
c0e849b696 Centralize I/O error handling and make read/write functions portable
- Improve existing `read` and `readOffset` wrappers:
  - Unix: Add `EINTR` retry handling and `checkInterrupt`
  - Windows: Handle `ERROR_BROKEN_PIPE` as EOF, add `checkInterrupt`

- Add `write` wrapper with same treatment (`EINTR` on Unix, `checkInterrupt`)

- Improve many `windows/file-descriptor.cc` error messages with
  `descriptorToPath`

- Move `readFull`, `readLine`, `writeFull` to common file, using the
  platform wrappers instead of duplicating platform-specific logic.
  These ones don't need any `EINTR` or interrupt checking either. They
  only have `EGAIN` checking as Unix-specific code, but this is a temp
  hack to be removed per #12688, so its fine that it goes in the
  platform-agnostic file for now.

- Add `retryOnBlock` helper to abstract `EAGAIN`/`EWOULDBLOCK` poll-and-retry
  logic (Unix only, needed for buildhook workaround #12688)

- Simplify `FdSource::readUnbuffered` to just call `nix::read`

- Remove now-dead `EINTR` handling from `drainFD` and `copyFdRange`

- `writeErr` better impl on Windows
2026-02-20 11:39:05 -05:00
John Ericson
2470b7981a Merge pull request #15277 from puffnfresh/windows/remove-profiles-symlink
LocalStore: stop creating outdated profiles symlink
2026-02-20 05:52:49 +00:00
Brian McKenna
9799023545 LocalStore: stop creating outdated profiles symlink
The gcroots/profiles link became outdated in
aeb810b01e when the GC code started
reading directly from /profiles, and gcroots/profiles was even
partially deleted in that commit.
2026-02-20 11:48:13 +11:00
John Ericson
ae4e229c9f Change writeFile(AutoCloseFD &, ...) to take a Descriptor
The new signature is:
  writeFile(Descriptor fd, std::string_view s, FsSync sync = FsSync::No, const Path * origPath = nullptr)

This uses `descriptorToPath` if `origPath` is not provided.
2026-02-19 19:30:55 -05:00
Amaan Qureshi
b63f5d1914 libutil: refactor AutoCloseFD::fsync into standalone syncDescriptor
`AutoCloseFD::fsync()` contained platform-specific logic behind CPP
guards. This extracts it into a free function `syncDescriptor(Descriptor)`
with separate Unix and Windows implementations, and makes
`AutoCloseFD::fsync()` an inline wrapper that delegates to it. The
Windows implementation uses `FlushFileBuffers` (returns `BOOL`, true on
success) while Unix uses `::fsync` (or `F_FULLFSYNC` on macOS), so
splitting them avoids conflating the two calling conventions.
2026-02-19 19:23:49 -05:00
John Ericson
31d87afc5a openFileEnsureBeneathNoSymlinks now returns AutoCloseFD
This indicates that they are returning an owned handle (i.e. the caller
 should --- and will, thanks to RAII --- close it).

 `ntOpenAt` and friends (internal) also use `AutoCloseFD` for the same
 reason.
2026-02-19 19:08:31 -05:00
John Ericson
204618c9d8 Misc unit test improvements 2026-02-19 17:26:38 -05:00
John Ericson
f0d90d3bdb Create two more FSSourceAccessorTests
Make sure we're testing non-directory roots.
2026-02-19 17:25:54 -05:00
John Ericson
0730dcb4a8 Skip chmodIfNeeded test on Windows
It doesn't do anything on Windows, it appears.
2026-02-19 17:21:46 -05:00
John Ericson
9b363e1e5c libutil-tests: Use FS_ROOT macros consistently in file-system tests
Add FS_ROOT_NO_TRAILING_SLASH macro and update isInDir and isDirOrInDir tests to use FS_ROOT and FS_SEP macros for cross-platform compatibility.
2026-02-19 17:21:12 -05:00
John Ericson
3df67a8347 Merge pull request #15298 from dramforever/parse-derivation-empty-special-msg
Add special error message for empty derivation file
2026-02-19 20:12:38 +00:00
Sergei Zimmerman
fd4eee9d62 libexpr-tests: Add ValuePrintingTests.vFailed 2026-02-19 14:23:04 +03:00
Robert Hensing
17f344cdda libexpr: Add recoverable errors
This provides an explicit API for call-fail-retry-succeed evaluation
flows, such as currently used in NixOps4.

An alternative design would simply reset the `Value` to the original
thunk instead of `tFailed` under the condition of catching a
`RecoverableEvalError`.
That is somewhat simpler, but I believe the presence of `tFailed` is
beneficial for possible use in the repl; being able to show the error
sooner, without re-evaluation.

The hasPos method is required in order to avoid an include loop.
2026-02-19 14:23:02 +03:00
Eelco Dolstra
c33d9e31cc Introduce a "failed" value type
In the multithreaded evaluator, it's possible for multiple threads to
wait on the same thunk. If evaluation of the thunk results in an
exception, the waiting threads shouldn't try to re-force the thunk.
Instead, they should rethrow the same exception, without duplicating
any work.

Therefore, there is now a new value type `tFailed` that stores an
std::exception_ptr. If evaluation of a thunk/app results in an
exception, `forceValue()` overwrites the value with a `tFailed`. If
`forceValue()` encounters a `tFailed`, it rethrows the exception. So
you normally never need to check for failed values (since forcing them
causes a rethrow).

Co-authored-by: Robert Hensing <robert@roberthensing.nl>
2026-02-19 14:23:01 +03:00
Sergei Zimmerman
89158eedb5 treewide: Make exceptions cloneable
This is needed to make it possible to store exceptions in failed values
with each new rethrow getting a fresh copy of the exception object.
2026-02-19 14:22:58 +03:00
dramforever
c33c82f345 Add special error message for empty derivation file
This rather commonly occurs when the computer was uncleanly shut down
and fsync was not enabled. Show the user a more actionable message than
"expected string 'D'".
2026-02-19 17:34:57 +08:00
John Ericson
40abcebbe1 Merge pull request #15295 from NixOS/expr-op-update-dont-mutate-result
libexpr: Use temporary value in ExprOpUpdate::eval
2026-02-19 09:14:44 +00:00
John Ericson
3bf690a407 Merge pull request #15294 from NixOS/less-filesystem-to-string
libutil: Drop superflous .string() in pathExists and pathAccessible
2026-02-19 02:33:55 +00:00
Jörg Thalheim
360ff05e73 Merge pull request #15296 from Mic92/fix-nix-build
Reapply "Use the hash modulo in the derivation outputs"
2026-02-19 01:38:29 +00:00
Jörg Thalheim
100e7cc337 Reapply "Use the hash modulo in the derivation outputs"
This reverts commit 4f91e9599f.

This broke:

when I applied this pr, `--print-out-paths` wouldn't print anything:

```
shell-for-nix-env % nix build --print-out-paths .#legacyPackages.aarch64-darwin.homeConfigurations.macos.activationPackage
```

After dropping the patches from my fork, it does again.
```
shell-for-nix-env % nix build --print-out-paths .#legacyPackages.aarch64-darwin.homeConfigurations.macos.activationPackage
/nix/store/s8mlcalszdml0v8172w4hwqnx0m6477r-home-manager-generation
```
2026-02-19 01:50:17 +01:00
Sergei Zimmerman
247cc7013a libexpr: Use temporary value in ExprOpUpdate::eval 2026-02-19 02:49:10 +03:00
Sergei Zimmerman
9e865ae4ff libutil: Drop superflous .string() in pathExists and pathAccessible 2026-02-19 02:13:12 +03:00
Eelco Dolstra
fef83c9f9c Merge pull request #15287 from NixOS/narinfo-cache-meta-ttl
Add setting narinfo-cache-meta-ttl
2026-02-18 22:13:23 +00:00
Eelco Dolstra
8491e26cd4 Merge pull request #15291 from roberth/fix-evalstate-shared-from-this-usage
fix(EvalState): Use make_shared for enable_shared_from_this compatibi…
2026-02-18 22:06:03 +00:00
Robert Hensing
987ecca24a fix(EvalState): Use make_shared for enable_shared_from_this compatibility
EvalState inherits from enable_shared_from_this (added in b4c24a29 for
debugRepl), but was being stack-allocated or created with make_unique
in several places. This causes bad_weak_ptr errors when shared_from_this
is called.

Convert all EvalState allocations to use make_shared.
2026-02-18 22:14:20 +01:00
Jörg Thalheim
a98b43b994 Merge pull request #12464 from obsidiansystems/build-trace-rework
Realisations use regular drv paths again
2026-02-18 20:54:56 +00:00
Eelco Dolstra
6733f2e5ce Add setting narinfo-cache-meta-ttl
This makes the current hard-coded 7-day `nix-cache-info` TTL
configurable, making `--offline` and `--refresh` do the right thing.
2026-02-18 21:30:37 +01:00
John Ericson
bbcf2041e1 File system error improvements
- Make `descriptorToPath` cross-platform (renamed from
  `windows::handleToPath`). Uses `/proc/self/fd` on Linux and
  `F_GETPATH` on macOS. Add `HAVE_F_GETPATH` meson check.

  This is based on 7226a116a0, which was
  removed in 479c356510, but is now
  introduced more judiciously.

- Unix error messages in `readFull`, `writeFull`, `readLine` now include
  file paths via `descriptorToPath`.

- Convert `std::filesystem::filesystem_error` to `SystemError`

  Wrappers like `readLink`, `createDirs`, `DirectoryIterator`, etc. now
  catch `std::filesystem::filesystem_error` and rethrow as `SystemError`
  with the error code preserved. This ensures consistent exception types
  throughout the codebase.

  Call sites that previously caught `filesystem_error` and rethrew with
  `throw;` now throw `SystemError(e.code(), ...)` instead.

  Some call sites can stop catching `filesystem_error` at all,
  because they only call the wrapped functions.

- Rework `SystemError` constructors to auto-append error message

  The public `SystemError(std::error_code, ...)` constructor now
  automatically appends `errorCode.message()` to the error message.
  A protected constructor takes an explicit error message string for
  subclasses.

  `SysError` delegates to the protected constructor with `strerror(errNo)`.
  `WinError` delegates with `renderError(lastError)` (now static).

  This removes the need to manually append `e.code().message()` at call
  sites when converting `filesystem_error` to `SystemError`.

- Use perfect forwarding (`Args &&...` with `std::forward`) consistently
  in `BaseError`, `SystemError`, `SysError`, and `WinError` constructors.

Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
2026-02-18 12:29:11 -05:00
John Ericson
96bcf5928f Merge pull request #15273 from NixOS/more-robust-ubsan-macro
libutil: More robust check for NIX_UBSAN_ENABLED
2026-02-18 16:15:26 +00:00
Sergei Zimmerman
db853cf4fb libutil: More robust check for NIX_UBSAN_ENABLED
In 3df91bea62 I forgot that the header
might get included out-of-tree with -Wundef. Let's make this a public
config option for libutil as it can affect function bodies in headers.
2026-02-18 17:33:51 +03:00
Brian McKenna
c486e78235 Windows: don't use bar log format
Relies on terminal features that don't always work on Windows.
2026-02-18 14:35:35 +11:00
John Ericson
4fff871383 Merge pull request #15274 from obsidiansystems/tryToBuild-raii
libstore: refactor `tryToBuild` with coroutine lambdas and RAII
2026-02-17 22:10:42 +00:00
Amaan Qureshi
b9acea908e libstore: refactor tryToBuild with coroutine lambdas and RAII
`tryToBuild` threaded a single `PathLocks outputLocks` by reference
across all build phases and managed a `std::unique_ptr<Activity> actLock`
with explicit `if (!actLock)` guards and `.reset()` calls around the hook
retry loop. This commit introduces coroutine lambdas for the three phases:
`tryHookLoop` owns a `PathLocks` in a scoped block for the first attempt
and per-iteration in the retry loop, `tryBuildLocally` acquires its own
`PathLocks`, and the hook-wait `Activity` is a stack variable scoped to
the postpone block.
2026-02-17 16:23:44 -05:00
John Ericson
c3f0670b4e Merge pull request #15266 from obsidiansystems/fix-maxjobs-error
libstore: structured diagnostics for local build rejection
2026-02-17 18:39:58 +00:00