Compare commits

...

6 Commits

Author SHA1 Message Date
Jarred Sumner
7a021606c6 Update fs.zig 2025-02-20 13:15:08 -08:00
Jarred Sumner
cf266ec2a7 fix 2025-02-20 13:14:56 -08:00
Jarred Sumner
d1231e7cda Update fs.zig 2025-02-20 13:04:17 -08:00
Jarred Sumner
eecc73811f Update sys.zig 2025-02-20 13:01:26 -08:00
Jarred Sumner
b8f97d2a86 Update sys.zig 2025-02-20 13:00:51 -08:00
Jarred Sumner
70c08b23b4 Use bun.sys more instead of std.fs 2025-02-20 12:40:03 -08:00
4 changed files with 105 additions and 88 deletions

View File

@@ -129,10 +129,10 @@ pub const Fs = struct {
) !Entry {
var rfs = _fs.fs;
const file_handle: std.fs.File = if (_file_handle) |__file|
std.fs.File{ .handle = __file }
const file_handle: bun.sys.File = if (_file_handle) |__file|
bun.sys.File{ .handle = __file }
else
try std.fs.openFileAbsoluteZ(path, .{ .mode = .read_only });
try bun.sys.File.open(path, bun.sys.O.RDONLY, 0).unwrap();
defer {
if (rfs.needToCloseFiles() and _file_handle == null) {
@@ -183,11 +183,11 @@ pub const Fs = struct {
) !Entry {
var rfs = _fs.fs;
var file_handle: std.fs.File = if (_file_handle) |__file| __file.asFile() else undefined;
var file_handle: bun.sys.File = if (_file_handle) |__file| bun.sys.File{ .handle = __file } else undefined;
if (_file_handle == null) {
if (FeatureFlags.store_file_descriptors and dirname_fd != bun.invalid_fd and dirname_fd != .zero) {
file_handle = (bun.sys.openatA(dirname_fd, std.fs.path.basename(path), bun.O.RDONLY, 0).unwrap() catch |err| brk: {
file_handle = .{ .handle = (bun.sys.openatA(dirname_fd, std.fs.path.basename(path), bun.O.RDONLY, 0).unwrap() catch |err| brk: {
switch (err) {
error.ENOENT => {
const handle = try bun.openFile(path, .{ .mode = .read_only });
@@ -199,9 +199,9 @@ pub const Fs = struct {
},
else => return err,
}
}).asFile();
}) };
} else {
file_handle = try bun.openFile(path, .{ .mode = .read_only });
file_handle = .{ .handle = try bun.sys.openA(path, bun.sys.O.RDONLY, 0).unwrap() };
}
}
@@ -211,7 +211,6 @@ pub const Fs = struct {
const will_close = rfs.needToCloseFiles() and _file_handle == null;
defer {
if (will_close) {
debug("readFileWithAllocator close({d})", .{file_handle.handle});
file_handle.close();
}
}

View File

@@ -1135,7 +1135,7 @@ pub const FileSystem = struct {
fs: *RealFS,
path: string,
_size: ?usize,
file: std.fs.File,
file: bun.sys.File,
comptime use_shared_buffer: bool,
shared_buffer: *MutableString,
comptime stream: bool,
@@ -1157,19 +1157,18 @@ pub const FileSystem = struct {
allocator: std.mem.Allocator,
path: string,
_size: ?usize,
file: std.fs.File,
file: bun.sys.File,
comptime use_shared_buffer: bool,
shared_buffer: *MutableString,
comptime stream: bool,
) !PathContentsPair {
FileSystem.setMaxFd(file.handle);
if (comptime Environment.isPosix) {
FileSystem.setMaxFd(file.handle.int());
}
// Skip the extra file.stat() call when possible
var size = _size orelse (file.getEndPos() catch |err| {
fs.readFileError(path, err);
return err;
});
debug("stat({d}) = {d}", .{ file.handle, size });
var size = _size orelse try file.getEndPos().unwrap();
debug("stat({}) = {d}", .{ file.handle, size });
// Skip the pread call for empty files
// Otherwise will get out of bounds errors
@@ -1203,14 +1202,10 @@ pub const FileSystem = struct {
// We use pread to ensure if the file handle was open, it doesn't seek from the last position
const prev_file_pos = if (comptime Environment.isWindows) try file.getPos() else 0;
const read_count = file.preadAll(shared_buffer.list.items[offset..], offset) catch |err| {
fs.readFileError(path, err);
return err;
};
if (comptime Environment.isWindows) try file.seekTo(prev_file_pos);
shared_buffer.list.items = shared_buffer.list.items[0 .. read_count + offset];
const read_amount = try file.preadAll(shared_buffer.list.items[offset..], offset).unwrap();
if (comptime Environment.isWindows) try file.seekTo(@intCast(prev_file_pos));
shared_buffer.list.items = shared_buffer.list.items[0 .. read_amount + offset];
file_contents = shared_buffer.list.items;
debug("pread({d}, {d}) = {d}", .{ file.handle, size, read_count });
if (comptime stream) {
// check again that stat() didn't change the file size
@@ -1220,11 +1215,10 @@ pub const FileSystem = struct {
return err;
};
offset += read_count;
offset += read_amount;
// don't infinite loop is we're still not reading more
if (read_count == 0) break;
if (read_amount == 0) break;
if (offset < new_size) {
try shared_buffer.growBy(new_size - size);
shared_buffer.list.expandToCapacity();
@@ -1250,14 +1244,10 @@ pub const FileSystem = struct {
// stick a zero at the end
buf[size] = 0;
const prev_file_pos = if (comptime Environment.isWindows) try file.getPos() else 0;
const read_count = file.preadAll(buf, 0) catch |err| {
fs.readFileError(path, err);
return err;
};
if (comptime Environment.isWindows) try file.seekTo(prev_file_pos);
file_contents = buf[0..read_count];
debug("pread({d}, {d}) = {d}", .{ file.handle, size, read_count });
const read_buf = try file.preadAll(buf, 0).unwrap();
const prev_file_pos = if (comptime Environment.isWindows) try file.getPos().unwrap() else 0;
if (comptime Environment.isWindows) try file.seekTo(@intCast(prev_file_pos)).unwrap();
file_contents = buf[0..read_buf];
if (strings.BOM.detect(file_contents)) |bom| {
debug("Convert {s} BOM", .{@tagName(bom)});
@@ -1268,60 +1258,6 @@ pub const FileSystem = struct {
return PathContentsPair{ .path = Path.init(path), .contents = file_contents };
}
pub fn kindFromAbsolute(
fs: *RealFS,
absolute_path: [:0]const u8,
existing_fd: StoredFileDescriptorType,
store_fd: bool,
) !Entry.Cache {
var outpath: bun.PathBuffer = undefined;
const stat = try C.lstat_absolute(absolute_path);
const is_symlink = stat.kind == std.fs.File.Kind.SymLink;
var _kind = stat.kind;
var cache = Entry.Cache{
.kind = Entry.Kind.file,
.symlink = PathString.empty,
};
var symlink: []const u8 = "";
if (is_symlink) {
var file = try if (existing_fd != 0)
std.fs.File{ .handle = existing_fd }
else if (store_fd)
std.fs.openFileAbsoluteZ(absolute_path, .{ .mode = .read_only })
else
bun.openFileForPath(absolute_path);
setMaxFd(file.handle);
defer {
if ((!store_fd or fs.needToCloseFiles()) and existing_fd == 0) {
file.close();
} else if (comptime FeatureFlags.store_file_descriptors) {
cache.fd = file.handle;
}
}
const _stat = try file.stat();
symlink = try bun.getFdPath(file.handle, &outpath);
_kind = _stat.kind;
}
bun.assert(_kind != .SymLink);
if (_kind == .Directory) {
cache.kind = .dir;
} else {
cache.kind = .file;
}
if (symlink.len > 0) {
cache.symlink = PathString.init(try FilenameStore.instance.append([]const u8, symlink));
}
return cache;
}
pub fn kind(
fs: *RealFS,
_dir: string,

View File

@@ -2101,6 +2101,14 @@ pub fn pread(fd: bun.FileDescriptor, buf: []u8, offset: i64) Maybe(usize) {
}
}
if (comptime Environment.isWindows) {
if (bun.FDImpl.decode(fd).kind == .uv) {
return sys_uv.pread(fd, buf, offset);
}
return bun.C.readFile(fd, buf, @as(u64, @intCast(offset)));
}
const ioffset = @as(i64, @bitCast(offset)); // the OS treats this as unsigned
while (true) {
const rc = pread_sym(fd.cast(), buf.ptr, adjusted_len, ioffset);
@@ -4015,6 +4023,54 @@ pub const File = struct {
}
};
pub fn pread(this: File, buf: []u8, offset: usize) Maybe(usize) {
return bun.sys.pread(this.handle, buf, @intCast(offset));
}
pub fn seekTo(this: File, offset: i64) Maybe(void) {
if (comptime Environment.isWindows) {
const rc = std.os.windows.kernel32.SetFilePointerEx(this.handle.cast(), offset, null, std.os.windows.FILE_BEGIN);
if (Maybe(void).errnoSys(rc, .lseek)) |err| {
return err;
}
return .{ .result = {} };
}
return bun.sys.lseek(this.handle, offset, std.posix.SEEK.SET);
}
pub fn getPos(this: File) Maybe(usize) {
if (comptime Environment.isWindows) {
const rc = std.os.windows.kernel32.SetFilePointerEx(this.handle.cast(), 0, null, std.os.windows.FILE_CURRENT);
if (Maybe(usize).errnoSys(rc, .lseek)) |err| {
return err;
}
// Windows casts as unsigned
return .{ .result = @as(u32, @bitCast(rc)) };
}
return bun.sys.lseek(this.handle, 0, std.posix.SEEK.CUR);
}
pub fn preadAll(this: File, buf: []u8, offset: usize) Maybe(usize) {
var total: usize = 0;
while (true) {
const read_amount = switch (this.pread(buf[total..], offset + total)) {
.err => |err| return .{ .err = err },
.result => |amt| amt,
};
if (read_amount == 0) {
break;
}
total += read_amount;
}
return .{ .result = total };
}
pub fn readFillBuf(this: File, buf: []u8) Maybe([]u8) {
var read_amount: usize = 0;
while (read_amount < buf.len) {

View File

@@ -1330,6 +1330,32 @@ pub fn moveOpenedFileAt(
Maybe(void).errno(rc, .NtSetInformationFile);
}
/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into
/// multiple non-atomic reads.
pub fn readFile(in_hFile: bun.FileDescriptor, buffer: []u8, offset: ?u64) Maybe(usize) {
const want_read_count: w.DWORD = @min(@as(w.DWORD, std.math.maxInt(w.DWORD)), buffer.len);
var amt_read: w.DWORD = undefined;
var overlapped_data: w.OVERLAPPED = undefined;
const overlapped: ?*w.OVERLAPPED = if (offset) |off| blk: {
overlapped_data = .{
.Internal = 0,
.InternalHigh = 0,
.DUMMYUNIONNAME = .{
.DUMMYSTRUCTNAME = .{
.Offset = @as(u32, @truncate(off)),
.OffsetHigh = @as(u32, @truncate(off >> 32)),
},
},
.hEvent = null,
};
break :blk &overlapped_data;
} else null;
if (w.kernel32.ReadFile(in_hFile.cast(), buffer.ptr, want_read_count, &amt_read, overlapped) == 0) {
return .{ .err = bun.sys.Error.fromCode(bun.windows.getLastErrno(), .read) };
}
return .{ .result = amt_read };
}
/// Same as moveOpenedFileAt but allows new_path to be a path relative to new_dir_fd.
///
/// Aka: moveOpenedFileAtLoose(fd, dir, ".\\a\\relative\\not-normalized-path.txt", false);