GNU `getcwd` can allocate a buffer if passed `NULL` for it. This is an
extension which is e.g., not recognized by clang-tidy-19's
`StdCLibraryFunctions` check[^1] which emits a diagnostic on a violated
precondition `buf != NULL`,
```
The 1st argument to 'getcwd' is NULL but should not be NULL [clang-analyzer-unix.StdCLibraryFunctions,-warnings-as-errors]
[build] 3987 | std::unique_ptr<char, decltype(&std::free)> buffer{::getcwd(NULL, 0), std::free};
```
This patch modifies this use of `getcwd` with this extension behavior to
instead use `get_current_dir_name` which is also a GNU extension, but
does not trigger this diagnostic.
[^1]: https://clang.llvm.org/docs/analyzer/checkers.html#unix-stdclibraryfunctions-c
Two changes:
- (minor) Rename GHC_OS_MACOS -> GHC_OS_APPLE, since it is defined all apple platforms (iOS, watchOS, etc.), not just macOS.
- Changed the preprocessor conditional in last_write_time to align with its presumed intent. Previously, it would always have been true, which can't be intentional, because the *_OS_VERSION_MIN_REQUIRED is undefined and thus zero for platforms besides the current one, and therefore less than the constants--except for on very old SDKs where, e.g., MAC_OS_X_VERSION_10_13 and others would be undefined and therefore 0 and therefore making the clause false when it needed to be true. Therefore, I changed the conditions to be parallel to those in the dynamic selection headers, checking for the undefined, zero case and hardcoding the version values to support old SDKs.
Reduces duplication and tendency to get out of sync.
As evidence of the problem, the snippet had previously (before this PR) started to diverge. It seemed more prudent to delete than to fix, given the usage instructions seem to be centralized in the readme and the dynamic selection headers should probably be recommended anyway.
There is no path length limitation there, even via pathconf. But glibc
provides a getcwd function that allocates the buffer dynamically so we can
just leverage that.
The previous implementation tried to detect old deployment targets for macOS that doesn't have the newer `utimensat` call. Unfortunately, it would just detect macOS, and didn't check for the corresponding iOS/tvOS/watchOS version numbers. On those platforms, last_write_time() was effectively a no-op, failing silently and not modifying the mtime of the file.
This patch adds detection for these platforms. It also removes the special casing when newer versions of macOS/iOS/tvOS/watchOS are used as the deployment targets, and instead folds it into the default POSIX branch.
The old code truncated time_t to a 32-bit value
when using Int32x32To64. This example code has been fixed
on MSDN a while ago, so this change only updates it to
the current version.
More on this issue:
https://cookieplmonster.github.io/2022/02/17/year-2038-problem/
This ensures that all cases where the result actually does fit in a
uintmax_t are correctly handled. Before, the multiplication could be
performed in a smaller type, leading to an incorrect result or, worse,
undefined behavior due to signed integer overflow.
This fixes a test failure that was actually observed on an i686 Linux
system.