Files
bun.sh/test/js/bun/util/bun-file.test.ts
robobun 46e7a3b3c5 Implement birthtime support on Linux using statx syscall (#23209)
## Summary

- Adds birthtime (file creation time) support on Linux using the `statx`
syscall
- Stores birthtime in architecture-specific unused fields of the kernel
Stat struct (x86_64 and aarch64)
- Falls back to traditional `stat` on kernels < 4.11 that don't support
`statx`
- Includes comprehensive tests validating birthtime behavior

Fixes #6585

## Implementation Details

**src/sys.zig:**
- Added `StatxField` enum for field selection
- Implemented `statxImpl()`, `fstatx()`, `statx()`, and `lstatx()`
functions
- Stores birthtime in unused padding fields (architecture-specific for
x86_64 and aarch64)
- Graceful fallback to traditional stat if statx is not supported

**src/bun.js/node/node_fs.zig:**
- Updated `stat()`, `fstat()`, and `lstat()` to use statx functions on
Linux

**src/bun.js/node/Stat.zig:**
- Added `getBirthtime()` helper to extract birthtime from
architecture-specific storage

**test/js/node/fs/fs-birthtime-linux.test.ts:**
- Tests non-zero birthtime values
- Verifies birthtime immutability across file modifications
- Validates consistency across stat/lstat/fstat
- Tests BigInt stats with nanosecond precision
- Verifies birthtime ordering relative to other timestamps

## Test Plan

- [x] Run `bun bd test test/js/node/fs/fs-birthtime-linux.test.ts` - all
5 tests pass
- [x] Compare behavior with Node.js - identical behavior
- [x] Compare with system Bun - system Bun returns epoch, new
implementation returns real birthtime

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-10-04 04:57:29 -07:00

48 lines
1.4 KiB
TypeScript

import { expect, test } from "bun:test";
import fsPromises from "fs/promises";
import { tempDirWithFiles } from "harness";
import { join } from "path";
test("delete() and stat() should work with unicode paths", async () => {
const dir = tempDirWithFiles("delete-stat-unicode-path", {
"another-file.txt": "HEY",
});
const filename = join(dir, "🌟.txt");
expect(async () => {
await Bun.file(filename).delete();
}).toThrow(`ENOENT: no such file or directory, unlink '${filename}'`);
expect(async () => {
await Bun.file(filename).stat();
}).toThrow(
process.platform === "linux"
? `ENOENT: no such file or directory, statx '${filename}'`
: `ENOENT: no such file or directory, stat '${filename}'`,
);
await Bun.write(filename, "HI");
expect(await Bun.file(filename).stat()).toMatchObject({ size: 2 });
expect(await Bun.file(filename).delete()).toBe(undefined);
expect(await Bun.file(filename).exists()).toBe(false);
});
test("writer.end() should not close the fd if it does not own the fd", async () => {
const dir = tempDirWithFiles("writer-end-fd", {
"tmp.txt": "HI",
});
const filename = join(dir, "tmp.txt");
for (let i = 0; i < 30; i++) {
const fileHandle = await fsPromises.open(filename, "w", 0o666);
const fd = fileHandle.fd;
await Bun.file(fd).writer().end();
// @ts-ignore
await fsPromises.close(fd);
expect(await Bun.file(filename).text()).toBe("");
}
});