@@ -1033,7 +1033,7 @@ fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mo
10331033 _ = dir ;
10341034 _ = sub_path ;
10351035 _ = mode ;
1036- @panic ("TODO" );
1036+ @panic ("TODO implement dirMakePathPosix " );
10371037}
10381038
10391039fn dirMakePathWindows (userdata : ? * anyopaque , dir : Io.Dir , sub_path : []const u8 , mode : Io.Dir.Mode ) Io.Dir.MakeError ! void {
@@ -1042,7 +1042,7 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8,
10421042 _ = dir ;
10431043 _ = sub_path ;
10441044 _ = mode ;
1045- @panic ("TODO" );
1045+ @panic ("TODO implement dirMakePathWindows " );
10461046}
10471047
10481048fn dirMakeOpenPathPosix (
@@ -1176,15 +1176,15 @@ fn dirMakeOpenPathWasi(
11761176 _ = dir ;
11771177 _ = sub_path ;
11781178 _ = mode ;
1179- @panic ("TODO" );
1179+ @panic ("TODO implement dirMakeOpenPathWindows " );
11801180}
11811181
11821182fn dirStat (userdata : ? * anyopaque , dir : Io.Dir ) Io.Dir.StatError ! Io.Dir.Stat {
11831183 const t : * Threaded = @ptrCast (@alignCast (userdata ));
11841184 try t .checkCancel ();
11851185
11861186 _ = dir ;
1187- @panic ("TODO" );
1187+ @panic ("TODO implement dirStat " );
11881188}
11891189
11901190fn dirStatPathLinux (
@@ -1375,8 +1375,48 @@ fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File
13751375fn fileStatWindows (userdata : ? * anyopaque , file : Io.File ) Io.File.StatError ! Io.File.Stat {
13761376 const t : * Threaded = @ptrCast (@alignCast (userdata ));
13771377 try t .checkCancel ();
1378- _ = file ;
1379- @panic ("TODO" );
1378+
1379+ var io_status_block : windows.IO_STATUS_BLOCK = undefined ;
1380+ var info : windows.FILE_ALL_INFORMATION = undefined ;
1381+ const rc = windows .ntdll .NtQueryInformationFile (file .handle , & io_status_block , & info , @sizeOf (windows .FILE_ALL_INFORMATION ), .FileAllInformation );
1382+ switch (rc ) {
1383+ .SUCCESS = > {},
1384+ // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer
1385+ // size provided. This is treated as success because the type of variable-length information that this would be relevant for
1386+ // (name, volume name, etc) we don't care about.
1387+ .BUFFER_OVERFLOW = > {},
1388+ .INVALID_PARAMETER = > unreachable ,
1389+ .ACCESS_DENIED = > return error .AccessDenied ,
1390+ else = > return windows .unexpectedStatus (rc ),
1391+ }
1392+ return .{
1393+ .inode = info .InternalInformation .IndexNumber ,
1394+ .size = @as (u64 , @bitCast (info .StandardInformation .EndOfFile )),
1395+ .mode = 0 ,
1396+ .kind = if (info .BasicInformation .FileAttributes & windows .FILE_ATTRIBUTE_REPARSE_POINT != 0 ) reparse_point : {
1397+ var tag_info : windows.FILE_ATTRIBUTE_TAG_INFO = undefined ;
1398+ const tag_rc = windows .ntdll .NtQueryInformationFile (file .handle , & io_status_block , & tag_info , @sizeOf (windows .FILE_ATTRIBUTE_TAG_INFO ), .FileAttributeTagInformation );
1399+ switch (tag_rc ) {
1400+ .SUCCESS = > {},
1401+ // INFO_LENGTH_MISMATCH and ACCESS_DENIED are the only documented possible errors
1402+ // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d295752f-ce89-4b98-8553-266d37c84f0e
1403+ .INFO_LENGTH_MISMATCH = > unreachable ,
1404+ .ACCESS_DENIED = > return error .AccessDenied ,
1405+ else = > return windows .unexpectedStatus (rc ),
1406+ }
1407+ if (tag_info .ReparseTag & windows .reparse_tag_name_surrogate_bit != 0 ) {
1408+ break :reparse_point .sym_link ;
1409+ }
1410+ // Unknown reparse point
1411+ break :reparse_point .unknown ;
1412+ } else if (info .BasicInformation .FileAttributes & windows .FILE_ATTRIBUTE_DIRECTORY != 0 )
1413+ .directory
1414+ else
1415+ .file ,
1416+ .atime = windows .fromSysTime (info .BasicInformation .LastAccessTime ),
1417+ .mtime = windows .fromSysTime (info .BasicInformation .LastWriteTime ),
1418+ .ctime = windows .fromSysTime (info .BasicInformation .ChangeTime ),
1419+ };
13801420}
13811421
13821422fn fileStatWasi (userdata : ? * anyopaque , file : Io.File ) Io.File.StatError ! Io.File.Stat {
@@ -2490,7 +2530,7 @@ fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, offset: i64) Io.File.SeekErr
24902530
24912531 _ = file ;
24922532 _ = offset ;
2493- @panic ("TODO" );
2533+ @panic ("TODO implement fileSeekBy " );
24942534}
24952535
24962536fn fileSeekTo (userdata : ? * anyopaque , file : Io.File , offset : u64 ) Io.File.SeekError ! void {
@@ -2571,7 +2611,7 @@ fn openSelfExe(userdata: ?*anyopaque, flags: Io.File.OpenFlags) Io.File.OpenSelf
25712611
25722612 return dirOpenFileWindowsInner (t , .{ .handle = cwd_handle }, image_path_name , flags );
25732613 }
2574- @panic ("TODO" );
2614+ @panic ("TODO implement openSelfExe " );
25752615}
25762616
25772617fn fileWritePositional (
@@ -2586,7 +2626,7 @@ fn fileWritePositional(
25862626 _ = file ;
25872627 _ = buffer ;
25882628 _ = offset ;
2589- @panic ("TODO" );
2629+ @panic ("TODO implement fileWritePositional " );
25902630 }
25912631}
25922632
@@ -2596,7 +2636,7 @@ fn fileWriteStreaming(userdata: ?*anyopaque, file: Io.File, buffer: [][]const u8
25962636 try t .checkCancel ();
25972637 _ = file ;
25982638 _ = buffer ;
2599- @panic ("TODO" );
2639+ @panic ("TODO implement fileWriteStreaming " );
26002640 }
26012641}
26022642
@@ -2922,7 +2962,7 @@ fn netListenUnixWindows(
29222962 try t .checkCancel ();
29232963 _ = address ;
29242964 _ = options ;
2925- @panic ("TODO" );
2965+ @panic ("TODO implement netListenUnixWindows " );
29262966}
29272967
29282968fn posixBindUnix (t : * Threaded , fd : posix.socket_t , addr : * const posix.sockaddr , addr_len : posix.socklen_t ) ! void {
@@ -3122,7 +3162,7 @@ fn netConnectIpPosix(
31223162 options : IpAddress.ConnectOptions ,
31233163) IpAddress.ConnectError ! net.Stream {
31243164 if (! have_networking ) return error .NetworkDown ;
3125- if (options .timeout != .none ) @panic ("TODO" );
3165+ if (options .timeout != .none ) @panic ("TODO implement netConnectIpPosix with timeout " );
31263166 const t : * Threaded = @ptrCast (@alignCast (userdata ));
31273167 const family = posixAddressFamily (address );
31283168 const socket_fd = try openSocketPosix (t , family , .{
@@ -3146,7 +3186,7 @@ fn netConnectIpWindows(
31463186 options : IpAddress.ConnectOptions ,
31473187) IpAddress.ConnectError ! net.Stream {
31483188 if (! have_networking ) return error .NetworkDown ;
3149- if (options .timeout != .none ) @panic ("TODO" );
3189+ if (options .timeout != .none ) @panic ("TODO implement netConnectIpWindows with timeout " );
31503190 const t : * Threaded = @ptrCast (@alignCast (userdata ));
31513191 const family = posixAddressFamily (address );
31523192 const socket_handle = try openSocketWsa (t , family , .{
@@ -3220,7 +3260,7 @@ fn netConnectUnixWindows(
32203260 const t : * Threaded = @ptrCast (@alignCast (userdata ));
32213261 try t .checkCancel ();
32223262 _ = address ;
3223- @panic ("TODO" );
3263+ @panic ("TODO implement netConnectUnixWindows " );
32243264}
32253265
32263266fn netBindIpPosix (
@@ -3525,7 +3565,7 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8
35253565 _ = t ;
35263566 _ = handle ;
35273567 _ = data ;
3528- @panic ("TODO" );
3568+ @panic ("TODO implement netReadWindows " );
35293569}
35303570
35313571fn netSendPosix (
@@ -3569,7 +3609,7 @@ fn netSendWindows(
35693609 _ = handle ;
35703610 _ = messages ;
35713611 _ = flags ;
3572- @panic ("TODO" );
3612+ @panic ("TODO netSendWindows " );
35733613}
35743614
35753615fn netSendOne (
@@ -3872,7 +3912,7 @@ fn netReceiveWindows(
38723912 _ = data_buffer ;
38733913 _ = flags ;
38743914 _ = timeout ;
3875- @panic ("TODO" );
3915+ @panic ("TODO implement netReceiveWindows " );
38763916}
38773917
38783918fn netWritePosix (
@@ -3970,7 +4010,7 @@ fn netWriteWindows(
39704010 _ = header ;
39714011 _ = data ;
39724012 _ = splat ;
3973- @panic ("TODO" );
4013+ @panic ("TODO implement netWriteWindows " );
39744014}
39754015
39764016fn addBuf (v : []posix.iovec_const , i : * @FieldType (posix.msghdr_const , "iovlen" ), bytes : []const u8 ) void {
@@ -4036,7 +4076,7 @@ fn netInterfaceNameResolve(
40364076
40374077 if (native_os == .windows ) {
40384078 try t .checkCancel ();
4039- @panic ("TODO" );
4079+ @panic ("TODO implement netInterfaceNameResolve for Windows " );
40404080 }
40414081
40424082 if (builtin .link_libc ) {
@@ -4055,15 +4095,15 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa
40554095
40564096 if (native_os == .linux ) {
40574097 _ = interface ;
4058- @panic ("TODO" );
4098+ @panic ("TODO implement netInterfaceName for linux " );
40594099 }
40604100
40614101 if (native_os == .windows ) {
4062- @panic ("TODO" );
4102+ @panic ("TODO implement netInterfaceName for windows " );
40634103 }
40644104
40654105 if (builtin .link_libc ) {
4066- @panic ("TODO" );
4106+ @panic ("TODO implement netInterfaceName for libc " );
40674107 }
40684108
40694109 @panic ("unimplemented" );
0 commit comments