diff --git a/src/async/posix_event_loop.zig b/src/async/posix_event_loop.zig index ed0f74893b..2ad65e05df 100644 --- a/src/async/posix_event_loop.zig +++ b/src/async/posix_event_loop.zig @@ -309,59 +309,59 @@ pub const FilePoll = struct { var ptr = poll.owner; switch (ptr.tag()) { @field(Owner.Tag, bun.meta.typeBaseName(@typeName(FIFO))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) FIFO", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) FIFO", .{poll.fd}); ptr.as(FIFO).ready(size_or_offset, poll.flags.contains(.hup)); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellBufferedInput))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellBufferedInput", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellBufferedInput", .{poll.fd}); ptr.as(ShellBufferedInput).onPoll(size_or_offset, 0); }, @field(Owner.Tag, "Subprocess") => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) Subprocess", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) Subprocess", .{poll.fd}); var loader = ptr.as(JSC.Subprocess); loader.onExitNotificationTask(); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellBufferedWriter))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellBufferedWriter", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellBufferedWriter", .{poll.fd}); var loader = ptr.as(ShellBufferedWriter); loader.onPoll(size_or_offset, 0); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellBufferedWriterMini))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellBufferedWriterMini", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellBufferedWriterMini", .{poll.fd}); var loader = ptr.as(ShellBufferedWriterMini); loader.onPoll(size_or_offset, 0); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellSubprocessCapturedBufferedWriter))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellSubprocessCapturedBufferedWriter", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellSubprocessCapturedBufferedWriter", .{poll.fd}); var loader = ptr.as(ShellSubprocessCapturedBufferedWriter); loader.onPoll(size_or_offset, 0); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellSubprocessCapturedBufferedWriterMini))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellSubprocessCapturedBufferedWriterMini", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellSubprocessCapturedBufferedWriterMini", .{poll.fd}); var loader = ptr.as(ShellSubprocessCapturedBufferedWriterMini); loader.onPoll(size_or_offset, 0); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellSubprocess))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellSubprocess", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellSubprocess", .{poll.fd}); var loader = ptr.as(ShellSubprocess); loader.onExitNotificationTask(); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellSubprocessMini))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) ShellSubprocessMini", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) ShellSubprocessMini", .{poll.fd}); var loader = ptr.as(ShellSubprocessMini); loader.onExitNotificationTask(); }, @field(Owner.Tag, bun.meta.typeBaseName(@typeName(JSC.WebCore.FileSink))) => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) FileSink", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) FileSink", .{poll.fd}); var loader = ptr.as(JSC.WebCore.FileSink); loader.onPoll(size_or_offset, 0); }, @field(Owner.Tag, "DNSResolver") => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) DNSResolver", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) DNSResolver", .{poll.fd}); var loader: *DNSResolver = ptr.as(DNSResolver); loader.onDNSPoll(poll); }, @@ -371,25 +371,25 @@ pub const FilePoll = struct { unreachable; } - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) GetAddrInfoRequest", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) GetAddrInfoRequest", .{poll.fd}); var loader: *GetAddrInfoRequest = ptr.as(GetAddrInfoRequest); loader.onMachportChange(); }, @field(Owner.Tag, "OutputReader") => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) OutputReader", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) OutputReader", .{poll.fd}); var output: *LifecycleScriptSubprocessOutputReader = ptr.as(LifecycleScriptSubprocessOutputReader); output.onPoll(size_or_offset); }, @field(Owner.Tag, "PidPollData") => { - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) LifecycleScriptSubprocess Pid", .{poll.fd}); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) LifecycleScriptSubprocess Pid", .{poll.fd}); var loader: *bun.install.LifecycleScriptSubprocess = @ptrCast(ptr.as(LifecycleScriptSubprocessPid)); loader.onProcessUpdate(size_or_offset); }, else => { const possible_name = Owner.typeNameFromTag(@intFromEnum(ptr.tag())); - log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {d}) disconnected? (maybe: {s})", .{ poll.fd, possible_name orelse "" }); + log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) disconnected? (maybe: {s})", .{ poll.fd, possible_name orelse "" }); }, } } @@ -731,7 +731,7 @@ pub const FilePoll = struct { pub fn registerWithFd(this: *FilePoll, loop: *Loop, flag: Flags, one_shot: bool, fd: bun.FileDescriptor) JSC.Maybe(void) { const watcher_fd = loop.fd; - log("register: {s} ({d})", .{ @tagName(flag), fd }); + log("register: {s} ({})", .{ @tagName(flag), fd }); std.debug.assert(fd != invalid_fd); @@ -908,7 +908,7 @@ pub const FilePoll = struct { }; if (this.flags.contains(.needs_rearm) and !force_unregister) { - log("unregister: {s} ({d}) skipped due to needs_rearm", .{ @tagName(flag), fd }); + log("unregister: {s} ({}) skipped due to needs_rearm", .{ @tagName(flag), fd }); this.flags.remove(.poll_process); this.flags.remove(.poll_readable); this.flags.remove(.poll_process); @@ -916,7 +916,7 @@ pub const FilePoll = struct { return JSC.Maybe(void).success; } - log("unregister: {s} ({d})", .{ @tagName(flag), fd }); + log("unregister: {s} ({})", .{ @tagName(flag), fd }); if (comptime Environment.isLinux) { const ctl = linux.epoll_ctl( diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 22f6db7395..24fe68d0da 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1519,7 +1519,7 @@ pub fn NewFileSink(comptime EventLoop: JSC.EventLoopKind) type { remain = remain[res.result..]; total += res.result; - log("Wrote {d} bytes (fd: {d}, head: {d}, {d}/{d})", .{ res.result, fd, this.head, remain.len, total }); + log("Wrote {d} bytes (fd: {}, head: {d}, {d}/{d})", .{ res.result, fd, this.head, remain.len, total }); if (res.result == 0) { if (this.poll_ref) |poll| { diff --git a/src/bun.zig b/src/bun.zig index 015ba67584..605855ddba 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -466,7 +466,7 @@ pub fn isReadable(fd: FileDescriptor) PollFlag { }; const result = (std.os.poll(&polls, 0) catch 0) != 0; - global_scope_log("poll({d}) readable: {any} ({d})", .{ fd, result, polls[0].revents }); + global_scope_log("poll({}) readable: {any} ({d})", .{ fd, result, polls[0].revents }); return if (result and polls[0].revents & std.os.POLL.HUP != 0) PollFlag.hup else if (result) @@ -487,7 +487,7 @@ pub fn isWritable(fd: FileDescriptor) PollFlag { }; const rc = std.os.windows.ws2_32.WSAPoll(&polls, 1, 0); const result = (if (rc != std.os.windows.ws2_32.SOCKET_ERROR) @as(usize, @intCast(rc)) else 0) != 0; - global_scope_log("poll({d}) writable: {any} ({d})", .{ fd, result, polls[0].revents }); + global_scope_log("poll({}) writable: {any} ({d})", .{ fd, result, polls[0].revents }); if (result and polls[0].revents & std.os.POLL.WRNORM != 0) { return .hup; } else if (result) { @@ -507,7 +507,7 @@ pub fn isWritable(fd: FileDescriptor) PollFlag { }; const result = (std.os.poll(&polls, 0) catch 0) != 0; - global_scope_log("poll({d}) writable: {any} ({d})", .{ fd, result, polls[0].revents }); + global_scope_log("poll({}) writable: {any} ({d})", .{ fd, result, polls[0].revents }); if (result and polls[0].revents & std.os.POLL.HUP != 0) { return .hup; } else if (result) { diff --git a/src/cache.zig b/src/cache.zig index 42e990ccbd..81a6c5b5af 100644 --- a/src/cache.zig +++ b/src/cache.zig @@ -175,7 +175,7 @@ pub const Fs = struct { error.ENOENT => { const handle = try bun.openFile(path, .{ .mode = .read_only }); Output.prettyErrorln( - "Internal error: directory mismatch for directory \"{s}\", fd {d}. You don't need to do anything, but this indicates a bug.", + "Internal error: directory mismatch for directory \"{s}\", fd {}. You don't need to do anything, but this indicates a bug.", .{ path, dirname_fd }, ); break :brk bun.toFD(handle.handle); @@ -189,7 +189,7 @@ pub const Fs = struct { } if (comptime !Environment.isWindows) // skip on Windows because NTCreateFile will do it. - debug("openat({d}, {s}) = {}", .{ dirname_fd, path, bun.toFD(file_handle.handle) }); + debug("openat({}, {s}) = {}", .{ dirname_fd, path, bun.toFD(file_handle.handle) }); const will_close = rfs.needToCloseFiles() and _file_handle == null; defer { diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig index a43c4b280e..1e534d4fd1 100644 --- a/src/cli/bunx_command.zig +++ b/src/cli/bunx_command.zig @@ -54,9 +54,44 @@ pub const BunxCommand = struct { return new_str; } + const seconds_cache_valid = 60 * 60 * 24; // 1 day + const nanoseconds_cache_valid = seconds_cache_valid * 1000000000; + fn getBinNameFromSubpath(bundler: *bun.Bundler, dir_fd: bun.FileDescriptor, subpath_z: [:0]const u8) ![]const u8 { const target_package_json_fd = try std.os.openatZ(dir_fd.cast(), subpath_z, std.os.O.RDONLY, 0); const target_package_json = std.fs.File{ .handle = target_package_json_fd }; + + const is_stale = is_stale: { + if (Environment.isWindows) { + var io_status_block: std.os.windows.IO_STATUS_BLOCK = undefined; + var info: std.os.windows.FILE_BASIC_INFORMATION = undefined; + const rc = std.os.windows.ntdll.NtQueryInformationFile(target_package_json_fd, &io_status_block, &info, @sizeOf(std.os.windows.FILE_BASIC_INFORMATION), .FileBasicInformation); + switch (rc) { + .SUCCESS => { + const time = std.os.windows.fromSysTime(info.LastWriteTime); + const now = std.time.nanoTimestamp(); + break :is_stale (now - time > nanoseconds_cache_valid); + }, + // treat failures to stat as stale + else => break :is_stale true, + } + } else { + var stat: std.os.Stat = undefined; + const rc = std.c.fstat(target_package_json_fd, &stat); + if (rc != 0) { + break :is_stale true; + } + break :is_stale std.time.timestamp() - stat.mtime().tv_sec > seconds_cache_valid; + } + }; + + if (is_stale) { + target_package_json.close(); + // If delete fails, oh well. Hope installation takes care of it. + dir_fd.asDir().deleteTree(subpath_z) catch {}; + return error.NeedToInstall; + } + defer target_package_json.close(); const package_json_contents = try target_package_json.readToEndAlloc(bundler.allocator, std.math.maxInt(u32)); @@ -158,7 +193,7 @@ pub const BunxCommand = struct { }; } - fn exit_with_usage() noreturn { + fn exitWithUsage() noreturn { Command.Tag.printHelp(.BunxCommand, false); Global.exit(1); } @@ -202,7 +237,7 @@ pub const BunxCommand = struct { // check if package_name_for_update_request is empty string or " " if (package_name_for_update_request[0].len == 0) { - exit_with_usage(); + exitWithUsage(); } const update_requests = bun.PackageManager.UpdateRequest.parse( @@ -214,7 +249,7 @@ pub const BunxCommand = struct { ); if (update_requests.len == 0) { - exit_with_usage(); + exitWithUsage(); } // this shouldn't happen @@ -321,28 +356,56 @@ pub const BunxCommand = struct { ctx.allocator.free(PATH_FOR_BIN_DIRS); } } - if (PATH.len > 0) { - PATH = try std.fmt.allocPrint( + + // The bunx cache path is at the following location + // + // /bunx--/node_modules/.bin/ + // + // Reasoning: + // - Prefix with "bunx" to identify the bunx cache, make it easier to "rm -r" + // - Suffix would not work because scoped packages have a "/" in them, and + // before Bun 1.1 this was practically impossible to clear the cache manually. + // It was easier to just remove the entire temp directory. + // - Use the uid to prevent conflicts between users. If the paths were the same + // across users, you run into permission conflicts + // - If you set permission to 777, you run into a potential attack vector + // where a user can replace the directory with malicious code. + const uid = if (bun.Environment.isPosix) bun.C.getuid() else windowsUserUniqueId(); + PATH = switch (PATH.len > 0) { + inline else => |path_is_nonzero| try std.fmt.allocPrint( ctx.allocator, - bun.pathLiteral("{s}/{s}--bunx/node_modules/.bin:{s}"), - .{ temp_dir, package_fmt, PATH }, - ); - } else { - PATH = try std.fmt.allocPrint( - ctx.allocator, - bun.pathLiteral("{s}/{s}--bunx/node_modules/.bin"), - .{ temp_dir, package_fmt }, - ); - } + bun.pathLiteral("{s}/bunx-{d}-{s}/node_modules/.bin{s}{s}"), + .{ + temp_dir, + uid, + package_fmt, + if (path_is_nonzero) ":" else "", + PATH, + }, + ), + }; + try this_bundler.env.map.put("PATH", PATH); - const bunx_cache_dir = PATH[0 .. temp_dir.len + "/--bunx".len + package_fmt.len]; + const bunx_cache_dir = PATH[0 .. temp_dir.len + + "/bunx--".len + + package_fmt.len + + if (Environment.isPosix) + std.fmt.count("{d}", .{uid}) + else + 0]; var absolute_in_cache_dir_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - var absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, bun.pathLiteral("{s}/node_modules/.bin/{s}"), .{ bunx_cache_dir, initial_bin_name }) catch unreachable; + var absolute_in_cache_dir = std.fmt.bufPrint( + &absolute_in_cache_dir_buf, + bun.pathLiteral("{s}/node_modules/.bin/{s}"), + .{ bunx_cache_dir, initial_bin_name }, + ) catch unreachable; const passthrough = passthrough_list.items; - if (update_request.version.literal.isEmpty() or update_request.version.tag != .dist_tag) { + var do_cache_bust = update_request.version.tag == .dist_tag; + + if (update_request.version.literal.isEmpty() or update_request.version.tag != .dist_tag) try_run_existing: { var destination_: ?[:0]const u8 = null; // Only use the system-installed version if there is no version specified @@ -365,7 +428,48 @@ pub const BunxCommand = struct { absolute_in_cache_dir, )) |destination| { const out = bun.asByteSlice(destination); - _ = try Run.runBinary( + + // If this directory was installed by bunx, we want to perform cache invalidation on it + // this way running `bunx hello` will update hello automatically to the latest version + if (bun.strings.hasPrefix(out, bunx_cache_dir)) { + const is_stale = is_stale: { + if (Environment.isWindows) { + const fd = bun.sys.openat(bun.invalid_fd, destination, std.os.O.RDONLY, 0).unwrap() catch { + // if we cant open this, we probably will just fail when we run it + // and that error message is likely going to be better than the one from `bun add` + break :is_stale false; + }; + defer _ = bun.sys.close(fd); + + var io_status_block: std.os.windows.IO_STATUS_BLOCK = undefined; + var info: std.os.windows.FILE_BASIC_INFORMATION = undefined; + const rc = std.os.windows.ntdll.NtQueryInformationFile(fd.cast(), &io_status_block, &info, @sizeOf(std.os.windows.FILE_BASIC_INFORMATION), .FileBasicInformation); + switch (rc) { + .SUCCESS => { + const time = std.os.windows.fromSysTime(info.LastWriteTime); + const now = std.time.nanoTimestamp(); + break :is_stale (now - time > nanoseconds_cache_valid); + }, + // treat failures to stat as stale + else => break :is_stale true, + } + } else { + var stat: std.os.Stat = undefined; + const rc = std.c.stat(destination, &stat); + if (rc != 0) { + break :is_stale true; + } + break :is_stale std.time.timestamp() - stat.mtime().tv_sec > seconds_cache_valid; + } + }; + + if (is_stale) { + do_cache_bust = true; + break :try_run_existing; + } + } + + try Run.runBinary( ctx, try this_bundler.fs.dirname_store.append(@TypeOf(out), out), this_bundler.fs.top_level_dir, @@ -373,11 +477,12 @@ pub const BunxCommand = struct { passthrough, null, ); - // we are done! - Global.exit(0); + // runBinary is noreturn + comptime unreachable; } // 2. The "bin" is possibly not the same as the package name, so we load the package.json to figure out what "bin" to use + // TODO: root_dir_fd was observed on Windows to be zero, which is incorrect. figure out why const root_dir_fd = root_dir_info.getFileDescriptor(); if (root_dir_fd != .zero) { if (getBinName(&this_bundler, root_dir_fd, bunx_cache_dir, initial_bin_name)) |package_name_for_bin| { @@ -402,7 +507,7 @@ pub const BunxCommand = struct { absolute_in_cache_dir, )) |destination| { const out = bun.asByteSlice(destination); - _ = try Run.runBinary( + try Run.runBinary( ctx, try this_bundler.fs.dirname_store.append(@TypeOf(out), out), this_bundler.fs.top_level_dir, @@ -410,8 +515,8 @@ pub const BunxCommand = struct { passthrough, null, ); - // we are done! - Global.exit(0); + // runBinary is noreturn + comptime unreachable; } } } else |err| { @@ -423,15 +528,7 @@ pub const BunxCommand = struct { } } - const bunx_install_dir_path = try std.fmt.allocPrint( - ctx.allocator, - "{s}/{s}--bunx", - .{ temp_dir, package_fmt }, - ); - - // TODO: fix this after zig upgrade - const bunx_install_iterable_dir = try std.fs.cwd().makeOpenPath(bunx_install_dir_path, .{}); - var bunx_install_dir = bunx_install_iterable_dir; + const bunx_install_dir = try std.fs.cwd().makeOpenPath(bunx_cache_dir, .{}); create_package_json: { // create package.json, but only if it doesn't exist @@ -441,18 +538,28 @@ pub const BunxCommand = struct { } var args_buf = [_]string{ - try std.fs.selfExePathAlloc(ctx.allocator), "add", "--no-summary", + try std.fs.selfExePathAlloc(ctx.allocator), + "add", + "--no-summary", package_fmt, + + // the following two args are stripped off if `do_cache_bust` is false + // disable the manifest cache when a tag is specified // so that @latest is fetched from the registry - "--no-cache", + "--no-cache", + // forcefully re-install packages in this mode too + "--force", }; - const argv_to_use: []const string = args_buf[0 .. args_buf.len - @as(usize, @intFromBool(update_request.version.tag != .dist_tag))]; + const argv_to_use: []const string = args_buf[0 .. args_buf.len - 2 * @as(usize, @intFromBool(!do_cache_bust))]; var child_process = std.ChildProcess.init(argv_to_use, default_allocator); - child_process.cwd = bunx_install_dir_path; child_process.cwd_dir = bunx_install_dir; + // https://github.com/ziglang/zig/issues/5190 + if (Environment.isWindows) { + child_process.cwd = bunx_cache_dir; + } const env_map = try this_bundler.env.map.cloneToEnvMap(ctx.allocator); child_process.env_map = &env_map; child_process.stderr_behavior = .Inherit; @@ -473,19 +580,15 @@ pub const BunxCommand = struct { Global.exit(exit_code); } }, - .Signal => |signal| { - Global.exit(@as(u7, @truncate(signal))); + .Signal, .Stopped => |signal| { + Global.raiseIgnoringPanicHandler(signal); }, - .Stopped => |signal| { - Global.exit(@as(u7, @truncate(signal))); - }, - // shouldn't happen - else => { + .Unknown => { Global.exit(1); }, } - absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, initial_bin_name }) catch unreachable; + absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, bun.pathLiteral("{s}/node_modules/.bin/{s}"), .{ bunx_cache_dir, initial_bin_name }) catch unreachable; // Similar to "npx": // @@ -498,7 +601,7 @@ pub const BunxCommand = struct { absolute_in_cache_dir, )) |destination| { const out = bun.asByteSlice(destination); - _ = try Run.runBinary( + try Run.runBinary( ctx, try this_bundler.fs.dirname_store.append(@TypeOf(out), out), this_bundler.fs.top_level_dir, @@ -506,8 +609,8 @@ pub const BunxCommand = struct { passthrough, null, ); - // we are done! - Global.exit(0); + // runBinary is noreturn + comptime unreachable; } // 2. The "bin" is possibly not the same as the package name, so we load the package.json to figure out what "bin" to use @@ -522,7 +625,7 @@ pub const BunxCommand = struct { absolute_in_cache_dir, )) |destination| { const out = bun.asByteSlice(destination); - _ = try Run.runBinary( + try Run.runBinary( ctx, try this_bundler.fs.dirname_store.append(@TypeOf(out), out), this_bundler.fs.top_level_dir, @@ -530,8 +633,8 @@ pub const BunxCommand = struct { passthrough, null, ); - // we are done! - Global.exit(0); + // runBinary is noreturn + comptime unreachable; } } } else |_| {} @@ -540,3 +643,25 @@ pub const BunxCommand = struct { Global.exit(1); } }; + +extern fn GetUserNameW( + lpBuffer: bun.windows.LPWSTR, + pcbBuffer: bun.windows.LPDWORD, +) bun.windows.BOOL; + +/// Is not the actual UID of the user, but just a hash of username. +fn windowsUserUniqueId() u32 { + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/165836c1-89d7-4abb-840d-80cf2510aa3e + // UNLEN + 1 + var buf: [257]u16 = undefined; + var size: u32 = buf.len; + if (GetUserNameW(@ptrCast(&buf), &size) == 0) { + if (Environment.isDebug) std.debug.panic("GetUserNameW failed: {}", .{bun.windows.GetLastError()}); + return 0; + } + const name = buf[0..size]; + if (Environment.isWindows) { + Output.scoped(.windowsUserUniqueId, false)("username: {}", .{std.unicode.fmtUtf16le(name)}); + } + return bun.hash32(std.mem.sliceAsBytes(name)); +} diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index bd7cf01124..4a96db87ce 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -413,7 +413,7 @@ pub const RunCommand = struct { env: *DotEnv.Loader, passthrough: []const string, original_script_for_bun_run: ?[]const u8, - ) !bool { + ) !noreturn { var argv_ = [_]string{executable}; var argv: []const string = &argv_; @@ -509,8 +509,6 @@ pub const RunCommand = struct { Global.exit(1); }, } - - return true; } pub fn ls(ctx: Command.Context) !void { diff --git a/src/fd.zig b/src/fd.zig index 28cec3987c..334d62107d 100644 --- a/src/fd.zig +++ b/src/fd.zig @@ -303,13 +303,18 @@ pub const FDImpl = packed struct { } pub fn format(this: FDImpl, comptime fmt: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - if (fmt.len == 1 and fmt[0] == 'd') { - try writer.print("{d}", .{this.system()}); - return; - } - if (fmt.len != 0) { - @compileError("invalid format string for FDImpl.format. must be either '' or 'd'"); + // The reason for this error is because formatting FD as an integer on windows is + // ambiguous and almost certainly a mistake. You probably meant to format fd.cast(). + // + // Remember this formatter will + // - on posix, print the numebr + // - on windows, print if it is a handle or a libuv file descriptor + // - in debug on all platforms, print the path of the file descriptor + // + // Not having this error caused a linux+debug only crash in bun.sys.getFdPath because + // we forgot to change the thing being printed to "fd.cast()" when FDImpl was introduced. + @compileError("invalid format string for FDImpl.format. must be empty like '{}'"); } if (!this.isValid()) { diff --git a/src/glob.zig b/src/glob.zig index d7b18edff8..df0d4c8289 100644 --- a/src/glob.zig +++ b/src/glob.zig @@ -339,7 +339,7 @@ pub fn GlobWalker_( }; }; - log("Transition(dirpath={s}, fd={d}, component_idx={d})", .{ dir_path, fd, component_idx }); + log("Transition(dirpath={s}, fd={}, component_idx={d})", .{ dir_path, fd, component_idx }); this.iter_state.directory.fd = fd; const iterator = DirIterator.iterate(fd.asDir(), .u8); diff --git a/src/io/io.zig b/src/io/io.zig index 1aef8995c0..d2d8494504 100644 --- a/src/io/io.zig +++ b/src/io/io.zig @@ -192,7 +192,7 @@ pub const Loop = struct { const current_events: []std.os.linux.epoll_event = events[0..rc]; if (rc != 0) { - log("epoll_wait({d}) = {d}", .{ this.pollfd(), rc }); + log("epoll_wait({}) = {d}", .{ this.pollfd(), rc }); } for (current_events) |event| { @@ -743,7 +743,7 @@ pub const Poll = struct { fd: bun.FileDescriptor, kqueue_event: *std.os.system.kevent64_s, ) void { - log("register({s}, {d})", .{ @tagName(action), fd }); + log("register({s}, {})", .{ @tagName(action), fd }); defer { switch (comptime action) { .readable => poll.flags.insert(Flags.poll_readable), @@ -873,7 +873,7 @@ pub const Poll = struct { pub fn registerForEpoll(this: *Poll, tag: Pollable.Tag, loop: *Loop, comptime flag: Flags, one_shot: bool, fd: bun.FileDescriptor) JSC.Maybe(void) { const watcher_fd = loop.pollfd(); - log("register: {s} ({d})", .{ @tagName(flag), fd }); + log("register: {s} ({})", .{ @tagName(flag), fd }); std.debug.assert(fd != bun.invalid_fd); diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig index 24d4c31442..36cb8a70c6 100644 --- a/src/resolver/resolve_path.zig +++ b/src/resolver/resolve_path.zig @@ -2119,7 +2119,9 @@ pub const PosixToWinNormalizer = struct { const source_root = windowsFilesystemRoot(source_dir); @memcpy(buf[0..source_root.len], source_root); @memcpy(buf[source_root.len..][0 .. maybe_posix_path.len - 1], maybe_posix_path[1..]); - return buf[0 .. source_root.len + maybe_posix_path.len - 1]; + const res = buf[0 .. source_root.len + maybe_posix_path.len - 1]; + std.debug.assert(!bun.strings.isWindowsAbsolutePathMissingDriveLetter(u8, res)); + return res; } } } @@ -2142,7 +2144,9 @@ pub const PosixToWinNormalizer = struct { const source_root = windowsFilesystemRoot(cwd); std.debug.assert(source_root.ptr == source_root.ptr); @memcpy(buf[source_root.len..][0 .. maybe_posix_path.len - 1], maybe_posix_path[1..]); - return buf[0 .. source_root.len + maybe_posix_path.len - 1]; + const res = buf[0 .. source_root.len + maybe_posix_path.len - 1]; + std.debug.assert(!bun.strings.isWindowsAbsolutePathMissingDriveLetter(u8, res)); + return res; } } } @@ -2167,7 +2171,9 @@ pub const PosixToWinNormalizer = struct { std.debug.assert(source_root.ptr == source_root.ptr); @memcpy(buf[source_root.len..][0 .. maybe_posix_path.len - 1], maybe_posix_path[1..]); buf[source_root.len + maybe_posix_path.len - 1] = 0; - return buf[0 .. source_root.len + maybe_posix_path.len - 1 :0]; + const res = buf[0 .. source_root.len + maybe_posix_path.len - 1 :0]; + std.debug.assert(!bun.strings.isWindowsAbsolutePathMissingDriveLetter(u8, res)); + return res; } } } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 15ca1d79a3..a87015bbc7 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -2118,7 +2118,7 @@ pub const Resolver = struct { dir_entries_ptr.fd = bun.toFD(open_dir.fd); } - bun.fs.debug("readdir({d}, {s}) = {d}", .{ bun.toFD(open_dir.fd), dir_path, dir_entries_ptr.data.count() }); + bun.fs.debug("readdir({}, {s}) = {d}", .{ bun.toFD(open_dir.fd), dir_path, dir_entries_ptr.data.count() }); dir_entries_option = rfs.entries.put(&cached_dir_entry_result, .{ .entries = dir_entries_ptr, @@ -2779,7 +2779,7 @@ pub const Resolver = struct { dir_entries_option = try rfs.entries.put(&cached_dir_entry_result, .{ .entries = dir_entries_ptr, }); - bun.fs.debug("readdir({d}, {s}) = {d}", .{ bun.toFD(open_dir.fd), dir_path, dir_entries_ptr.data.count() }); + bun.fs.debug("readdir({}, {s}) = {d}", .{ bun.toFD(open_dir.fd), dir_path, dir_entries_ptr.data.count() }); } // We must initialize it as empty so that the result index is correct. diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index e46e3f0fef..c3458d6c17 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -7698,7 +7698,7 @@ pub fn MaybeChild(comptime T: type) type { pub fn closefd(fd: bun.FileDescriptor) void { if (Syscall.close2(fd)) |err| { _ = err; - log("ERR closefd: {d}\n", .{fd}); + log("ERR closefd: {}\n", .{fd}); // stderr_mutex.lock(); // defer stderr_mutex.unlock(); // const stderr = std.io.getStdErr().writer(); diff --git a/src/string_immutable.zig b/src/string_immutable.zig index b58ad59990..0efe7e6019 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -1827,11 +1827,11 @@ pub fn assertIsValidWindowsPath(comptime T: type, path: []const T) void { if (bun.path.Platform.windows.isAbsoluteT(T, path) and isWindowsAbsolutePathMissingDriveLetter(T, path)) { - std.debug.panic("Do not pass posix paths to windows APIs, was given '{s}' (missing a root like 'C:\\', see PosixToWinNormalizer for why this is an assertion)", .{ + std.debug.panic("Internal Error: Do not pass posix paths to Windows APIs, was given '{s}'" ++ if (Environment.isDebug) " (missing a root like 'C:\\', see PosixToWinNormalizer for why this is an assertion)" else ". Please open an issue on GitHub with a reproduction.", .{ if (T == u8) path else std.unicode.fmtUtf16le(path), }); } - if (hasPrefixComptimeType(T, path, ":/")) { + if (hasPrefixComptimeType(T, path, ":/") and Environment.isDebug) { std.debug.panic("Path passed to windows API '{s}' is almost certainly invalid. Where did the drive letter go?", .{ if (T == u8) path else std.unicode.fmtUtf16le(path), }); diff --git a/src/sys.zig b/src/sys.zig index 2a45295483..a7eab5a02e 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -412,7 +412,7 @@ pub fn fstat(fd: bun.FileDescriptor) Maybe(bun.Stat) { const rc = fstatSym(fd.cast(), &stat_); if (comptime Environment.allow_assert) - log("fstat({d}) = {d}", .{ fd, rc }); + log("fstat({}) = {d}", .{ fd, rc }); if (Maybe(bun.Stat).errnoSys(rc, .fstat)) |err| return err; return Maybe(bun.Stat){ .result = stat_ }; @@ -758,12 +758,12 @@ pub fn openFileAtWindowsNtPath( // - access_mask probably needs w.SYNCHRONIZE, // - options probably needs w.FILE_SYNCHRONOUS_IO_NONALERT // - disposition probably needs w.FILE_OPEN - bun.Output.debugWarn("NtCreateFile({d}, {}) = {s} (file) = {d}\nYou are calling this function with the wrong flags!!!", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); + bun.Output.debugWarn("NtCreateFile({}, {}) = {s} (file) = {d}\nYou are calling this function with the wrong flags!!!", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); } else if (rc == .OBJECT_PATH_SYNTAX_BAD or rc == .OBJECT_NAME_INVALID) { // See above comment. For absolute paths you must have \??\ at the start. - bun.Output.debugWarn("NtCreateFile({d}, {}) = {s} (file) = {d}\nYou are calling this function without normalizing the path correctly!!!", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); + bun.Output.debugWarn("NtCreateFile({}, {}) = {s} (file) = {d}\nYou are calling this function without normalizing the path correctly!!!", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); } else { - log("NtCreateFile({d}, {}) = {s} (file) = {d}", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); + log("NtCreateFile({}, {}) = {s} (file) = {d}", .{ dir, bun.fmt.fmtUTF16(path), @tagName(rc), @intFromPtr(result) }); } } @@ -908,7 +908,7 @@ pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flag // https://opensource.apple.com/source/xnu/xnu-7195.81.3/libsyscall/wrappers/open-base.c const rc = system.@"openat$NOCANCEL"(dirfd.cast(), file_path.ptr, @as(c_uint, @intCast(flags)), @as(c_int, @intCast(perm))); if (comptime Environment.allow_assert) - log("openat({d}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); + log("openat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); return Maybe(bun.FileDescriptor).errnoSys(rc, .open) orelse .{ .result = bun.toFD(rc) }; } else if (comptime Environment.isWindows) { @@ -918,7 +918,7 @@ pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flag while (true) { const rc = Syscall.system.openat(dirfd.cast(), file_path, flags, perm); if (comptime Environment.allow_assert) - log("openat({d}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); + log("openat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); return switch (Syscall.getErrno(rc)) { .SUCCESS => .{ .result = bun.toFD(rc) }, .INTR => continue, @@ -984,7 +984,7 @@ pub fn close(fd: bun.FileDescriptor) ?Syscall.Error { pub fn close2(fd: bun.FileDescriptor) ?Syscall.Error { if (fd == bun.STDOUT_FD or fd == bun.STDERR_FD or fd == bun.STDIN_FD) { - log("close({d}) SKIPPED", .{fd}); + log("close({}) SKIPPED", .{fd}); return null; } @@ -1008,7 +1008,7 @@ pub fn write(fd: bun.FileDescriptor, bytes: []const u8) Maybe(usize) { return switch (Environment.os) { .mac => { const rc = system.@"write$NOCANCEL"(fd.cast(), bytes.ptr, adjusted_len); - log("write({d}, {d}) = {d}", .{ fd, adjusted_len, rc }); + log("write({}, {d}) = {d}", .{ fd, adjusted_len, rc }); if (Maybe(usize).errnoSysFd(rc, .write, fd)) |err| { return err; @@ -1019,7 +1019,7 @@ pub fn write(fd: bun.FileDescriptor, bytes: []const u8) Maybe(usize) { .linux => { while (true) { const rc = sys.write(fd.cast(), bytes.ptr, adjusted_len); - log("write({d}, {d}) = {d}", .{ fd, adjusted_len, rc }); + log("write({}, {d}) = {d}", .{ fd, adjusted_len, rc }); if (Maybe(usize).errnoSysFd(rc, .write, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1040,7 +1040,7 @@ pub fn write(fd: bun.FileDescriptor, bytes: []const u8) Maybe(usize) { &bytes_written, null, ); - log("WriteFile({d}, {d}) = {d} (written: {d})", .{ @intFromPtr(fd.cast()), adjusted_len, rc, bytes_written }); + log("WriteFile({}, {d}) = {d} (written: {d})", .{ fd, adjusted_len, rc, bytes_written }); if (rc == 0) { return .{ .err = Syscall.Error{ @@ -1068,7 +1068,7 @@ pub fn writev(fd: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { if (comptime Environment.isMac) { const rc = writev_sym(fd.cast(), @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), @as(i32, @intCast(buffers.len))); if (comptime Environment.allow_assert) - log("writev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("writev({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .writev, fd)) |err| { return err; @@ -1079,7 +1079,7 @@ pub fn writev(fd: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { while (true) { const rc = writev_sym(fd.cast(), @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), buffers.len); if (comptime Environment.allow_assert) - log("writev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("writev({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .writev, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1099,7 +1099,7 @@ pub fn pwritev(fd: bun.FileDescriptor, buffers: []const bun.PlatformIOVecConst, if (comptime Environment.isMac) { const rc = pwritev_sym(fd.cast(), buffers.ptr, @as(i32, @intCast(buffers.len)), position); if (comptime Environment.allow_assert) - log("pwritev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("pwritev({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .pwritev, fd)) |err| { return err; @@ -1110,7 +1110,7 @@ pub fn pwritev(fd: bun.FileDescriptor, buffers: []const bun.PlatformIOVecConst, while (true) { const rc = pwritev_sym(fd.cast(), buffers.ptr, buffers.len, position); if (comptime Environment.allow_assert) - log("pwritev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("pwritev({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .pwritev, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1133,7 +1133,7 @@ pub fn readv(fd: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { if (comptime Environment.isMac) { const rc = readv_sym(fd.cast(), buffers.ptr, @as(i32, @intCast(buffers.len))); if (comptime Environment.allow_assert) - log("readv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("readv({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .readv, fd)) |err| { return err; @@ -1144,7 +1144,7 @@ pub fn readv(fd: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { while (true) { const rc = readv_sym(fd.cast(), buffers.ptr, buffers.len); if (comptime Environment.allow_assert) - log("readv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("readv({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .readv, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1167,7 +1167,7 @@ pub fn preadv(fd: bun.FileDescriptor, buffers: []std.os.iovec, position: isize) if (comptime Environment.isMac) { const rc = preadv_sym(fd.cast(), buffers.ptr, @as(i32, @intCast(buffers.len)), position); if (comptime Environment.allow_assert) - log("preadv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("preadv({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .preadv, fd)) |err| { return err; @@ -1178,7 +1178,7 @@ pub fn preadv(fd: bun.FileDescriptor, buffers: []std.os.iovec, position: isize) while (true) { const rc = preadv_sym(fd.cast(), buffers.ptr, buffers.len, position); if (comptime Environment.allow_assert) - log("preadv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); + log("preadv({}, {d}) = {d}", .{ fd, veclen(buffers), rc }); if (Maybe(usize).errnoSysFd(rc, .preadv, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1286,7 +1286,7 @@ pub fn read(fd: bun.FileDescriptor, buf: []u8) Maybe(usize) { .mac => { const rc = system.@"read$NOCANCEL"(fd.cast(), buf.ptr, adjusted_len); - log("read({d}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); + log("read({}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); if (Maybe(usize).errnoSysFd(rc, .read, fd)) |err| { return err; @@ -1297,7 +1297,7 @@ pub fn read(fd: bun.FileDescriptor, buf: []u8) Maybe(usize) { .linux => { while (true) { const rc = sys.read(fd.cast(), buf.ptr, adjusted_len); - log("read({d}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); + log("read({}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); if (Maybe(usize).errnoSysFd(rc, .read, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1321,7 +1321,7 @@ pub fn recv(fd: bun.FileDescriptor, buf: []u8, flag: u32) Maybe(usize) { if (comptime Environment.isMac) { const rc = system.@"recvfrom$NOCANCEL"(fd.cast(), buf.ptr, adjusted_len, flag, null, null); - log("recv({d}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); + log("recv({}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); if (Maybe(usize).errnoSys(rc, .recv)) |err| { return err; @@ -1331,7 +1331,7 @@ pub fn recv(fd: bun.FileDescriptor, buf: []u8, flag: u32) Maybe(usize) { } else { while (true) { const rc = linux.recvfrom(fd.cast(), buf.ptr, adjusted_len, flag | os.SOCK.CLOEXEC | linux.MSG.CMSG_CLOEXEC, null, null); - log("recv({d}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); + log("recv({}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); if (Maybe(usize).errnoSysFd(rc, .recv, fd)) |err| { if (err.getErrno() == .INTR) continue; @@ -1435,11 +1435,11 @@ pub fn renameat(from_dir: bun.FileDescriptor, from: [:0]const u8, to_dir: bun.Fi if (Maybe(void).errnoSys(sys.renameat(from_dir.cast(), from, to_dir.cast(), to), .rename)) |err| { if (err.getErrno() == .INTR) continue; if (comptime Environment.allow_assert) - log("renameat({d}, {s}, {d}, {s}) = {d}", .{ from_dir, from, to_dir, to, @intFromEnum(err.getErrno()) }); + log("renameat({}, {s}, {}, {s}) = {d}", .{ from_dir, from, to_dir, to, @intFromEnum(err.getErrno()) }); return err; } if (comptime Environment.allow_assert) - log("renameat({d}, {s}, {d}, {s}) = {d}", .{ from_dir, from, to_dir, to, 0 }); + log("renameat({}, {s}, {}, {s}) = {d}", .{ from_dir, from, to_dir, to, 0 }); return Maybe(void).success; } } @@ -1531,11 +1531,11 @@ pub fn unlinkatWithFlags(dirfd: bun.FileDescriptor, to: anytype, flags: c_uint) if (Maybe(void).errnoSys(sys.unlinkat(dirfd.cast(), to, flags), .unlink)) |err| { if (err.getErrno() == .INTR) continue; if (comptime Environment.allow_assert) - log("unlinkat({d}, {s}) = {d}", .{ dirfd, bun.sliceTo(to, 0), @intFromEnum(err.getErrno()) }); + log("unlinkat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(to, 0), @intFromEnum(err.getErrno()) }); return err; } if (comptime Environment.allow_assert) - log("unlinkat({d}, {s}) = 0", .{ dirfd, bun.sliceTo(to, 0) }); + log("unlinkat({}, {s}) = 0", .{ dirfd, bun.sliceTo(to, 0) }); return Maybe(void).success; } unreachable; @@ -1549,11 +1549,11 @@ pub fn unlinkat(dirfd: bun.FileDescriptor, to: anytype) Maybe(void) { if (Maybe(void).errnoSys(sys.unlinkat(dirfd.cast(), to, 0), .unlink)) |err| { if (err.getErrno() == .INTR) continue; if (comptime Environment.allow_assert) - log("unlinkat({d}, {s}) = {d}", .{ dirfd, bun.sliceTo(to, 0), @intFromEnum(err.getErrno()) }); + log("unlinkat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(to, 0), @intFromEnum(err.getErrno()) }); return err; } if (comptime Environment.allow_assert) - log("unlinkat({d}, {s}) = 0", .{ dirfd, bun.sliceTo(to, 0) }); + log("unlinkat({}, {s}) = 0", .{ dirfd, bun.sliceTo(to, 0) }); return Maybe(void).success; } } @@ -1582,7 +1582,7 @@ pub fn getFdPath(fd: bun.FileDescriptor, out_buffer: *[MAX_PATH_BYTES]u8) Maybe( .linux => { // TODO: alpine linux may not have /proc/self var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined; - const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/fd/{d}\x00", .{fd}) catch unreachable; + const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/fd/{d}\x00", .{fd.cast()}) catch unreachable; return switch (readlink(proc_path, out_buffer)) { .err => |err| return .{ .err = err }, @@ -1943,7 +1943,7 @@ pub fn dup(fd: bun.FileDescriptor) Maybe(bun.FileDescriptor) { } const out = std.c.dup(fd.cast()); - log("dup({d}) = {d}", .{ fd.cast(), out }); + log("dup({}) = {d}", .{ fd, out }); return Maybe(bun.FileDescriptor).errnoSysFd(out, .dup, fd) orelse Maybe(bun.FileDescriptor){ .result = bun.toFD(out) }; }