Skip to content

zig fmt --stdin is broken on Windows (File.Reader.getSize() returns bogus values for pipes) #24984

@castholm

Description

@castholm

Zig Version

0.16.0-dev.23+47a2f2dda

Steps to Reproduce and Observed Behavior

Pipe any valid Zig source file larger than 5 KiB in size to zig fmt --stdin, e.g.:

Get-Content foo.zig | zig fmt --stdin

It will likely report an error like <stdin>:166:24: error: expected '}', found 'EOF', indicating that it didn't read the file in full.

This is because std.zig.readSourceFileToEndAlloc() uses std.File.Reader.getSize(), which is implemented by calling GetFileSizeEx() on Windows. But the GetFileSize() family of functions doesn't support nonseeking file handles:

You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device. To determine the file type for hFile, use the GetFileType function.

Instead of returning an error status, they seem to return the size of the buffer used internally. You can see this in action by piping a > 5 KiB file to this program:

const std = @import("std");

pub fn main() !void {
    const stdin: std.fs.File = .stdin();
    var file_reader: std.fs.File.Reader = stdin.reader(&.{});
    std.debug.print("{}\n", .{file_reader.getSize() catch 0});
}

On Windows 10 it prints 4098 rather than the actual file size 2911222.

Expected Behavior

zig fmt --stdin works and File.Reader.getSize() returns error.Streaming (and transitions the reader mode to streaming).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavioros-windowsMicrosoft WindowsregressionIt worked in a previous version of Zig, but stopped working.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions