@@ -1369,8 +1369,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
1369
1369
@compileError ("realpath is not available on WASI" );
1370
1370
}
1371
1371
if (native_os == .windows ) {
1372
- const pathname_w = try windows .sliceToPrefixedFileW (self .fd , pathname );
1373
- return self .realpathW (pathname_w .span (), out_buffer );
1372
+ var pathname_w = try windows .sliceToPrefixedFileW (self .fd , pathname );
1373
+
1374
+ const wide_slice = try self .realpathW2 (pathname_w .span (), & pathname_w .data );
1375
+
1376
+ const len = std .unicode .calcWtf8Len (wide_slice );
1377
+ if (len > out_buffer .len )
1378
+ return error .NameTooLong ;
1379
+
1380
+ const end_index = std .unicode .wtf16LeToWtf8 (out_buffer , wide_slice );
1381
+ return out_buffer [0.. end_index ];
1374
1382
}
1375
1383
const pathname_c = try posix .toPosixPath (pathname );
1376
1384
return self .realpathZ (& pathname_c , out_buffer );
@@ -1380,8 +1388,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
1380
1388
/// See also `Dir.realpath`, `realpathZ`.
1381
1389
pub fn realpathZ (self : Dir , pathname : [* :0 ]const u8 , out_buffer : []u8 ) RealPathError ! []u8 {
1382
1390
if (native_os == .windows ) {
1383
- const pathname_w = try windows .cStrToPrefixedFileW (self .fd , pathname );
1384
- return self .realpathW (pathname_w .span (), out_buffer );
1391
+ var pathname_w = try windows .cStrToPrefixedFileW (self .fd , pathname );
1392
+
1393
+ const wide_slice = try self .realpathW2 (pathname_w .span (), & pathname_w .data );
1394
+
1395
+ const len = std .unicode .calcWtf8Len (wide_slice );
1396
+ if (len > out_buffer .len )
1397
+ return error .NameTooLong ;
1398
+
1399
+ const end_index = std .unicode .wtf16LeToWtf8 (out_buffer , wide_slice );
1400
+ return out_buffer [0.. end_index ];
1385
1401
}
1386
1402
1387
1403
var flags : posix.O = .{};
@@ -1410,10 +1426,34 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE
1410
1426
return result ;
1411
1427
}
1412
1428
1429
+ /// Deprecated: use `realpathW2`.
1430
+ ///
1413
1431
/// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded.
1414
1432
/// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
1415
1433
/// See also `Dir.realpath`, `realpathW`.
1416
1434
pub fn realpathW (self : Dir , pathname : []const u16 , out_buffer : []u8 ) RealPathError ! []u8 {
1435
+ var wide_buf : [std .os .windows .PATH_MAX_WIDE ]u16 = undefined ;
1436
+
1437
+ const wide_slice = try self .realpathW2 (pathname , & wide_buf );
1438
+
1439
+ var big_out_buf : [fs .max_path_bytes ]u8 = undefined ;
1440
+ const end_index = std .unicode .wtf16LeToWtf8 (& big_out_buf , wide_slice );
1441
+ if (end_index > out_buffer .len )
1442
+ return error .NameTooLong ;
1443
+ const result = out_buffer [0.. end_index ];
1444
+ @memcpy (result , big_out_buf [0.. end_index ]);
1445
+ return result ;
1446
+ }
1447
+
1448
+ /// Windows-only. Same as `Dir.realpath` except
1449
+ /// * `pathname` and the result are WTF-16 LE encoded
1450
+ /// * `pathname` is relative or has the NT namespace prefix. See `windows.wToPrefixedFileW` for details.
1451
+ ///
1452
+ /// Additionally, `pathname` will never be accessed after `out_buffer` has been written to, so it
1453
+ /// is safe to reuse a single buffer for both.
1454
+ ///
1455
+ /// See also `Dir.realpath`, `realpathW`.
1456
+ pub fn realpathW2 (self : Dir , pathname : []const u16 , out_buffer : []u16 ) RealPathError ! []u16 {
1417
1457
const w = windows ;
1418
1458
1419
1459
const access_mask = w .GENERIC_READ | w .SYNCHRONIZE ;
@@ -1434,13 +1474,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr
1434
1474
};
1435
1475
defer w .CloseHandle (h_file );
1436
1476
1437
- var wide_buf : [w .PATH_MAX_WIDE ]u16 = undefined ;
1438
- const wide_slice = try w .GetFinalPathNameByHandle (h_file , .{}, & wide_buf );
1439
- const len = std .unicode .calcWtf8Len (wide_slice );
1440
- if (len > out_buffer .len )
1441
- return error .NameTooLong ;
1442
- const end_index = std .unicode .wtf16LeToWtf8 (out_buffer , wide_slice );
1443
- return out_buffer [0.. end_index ];
1477
+ return w .GetFinalPathNameByHandle (h_file , .{}, out_buffer );
1444
1478
}
1445
1479
1446
1480
pub const RealPathAllocError = RealPathError || Allocator .Error ;
0 commit comments