authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-13 23:41:06+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:22+02:00
log49b58153642bbff19ab976b70e329c5592fa1684
tree7633506ceccb3e25d86c1651c194c7827a549e41
parent92d11fd4e95b86d6ace166783cda69030647e688

Add windows.ReadLink similar to OpenFile but for reparse points only


3 files changed, 54 insertions(+), 19 deletions(-)

lib/std/os.zig+1-6
......@@ -2393,12 +2393,7 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
23932393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.
23942394/// See also `readlinkZ`.
23952395pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
2396 const handle = windows.OpenFile(file_path, .{
2397 .access_mask = windows.GENERIC_READ,
2398 .creation = windows.FILE_OPEN,
2399 .options = windows.FILE_OPEN_REPARSE_POINT,
2400 .io_mode = std.io.default_mode,
2401 }) catch |err| {
2396 const handle = windows.ReadLink(file_path) catch |err| {
24022397 switch (err) {
24032398 error.IsDir => unreachable,
24042399 error.NoDevice => return error.FileNotFound,
lib/std/os/test.zig+1-2
......@@ -45,8 +45,7 @@ test "readlink" {
4545 if (builtin.os.tag == .wasi) return error.SkipZigTest;
4646
4747 var tmp = tmpDir(.{});
48 //defer tmp.cleanup();
49 std.debug.print("tmp = {}\n", .{tmp.sub_path[0..]});
48 defer tmp.cleanup();
5049
5150 // create file
5251 try tmp.dir.writeFile("file.txt", "nonsense");
lib/std/os/windows.zig+52-11
......@@ -110,7 +110,6 @@ pub const OpenFileOptions = struct {
110110 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
111111 share_access_nonblocking: bool = false,
112112 creation: ULONG,
113 options: ?ULONG = null,
114113 io_mode: std.io.ModeOverride,
115114};
116115
......@@ -147,14 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
147146 var delay: usize = 1;
148147 while (true) {
149148 var flags: ULONG = undefined;
150 if (options.options) |opt| {
151 flags = opt;
152 } else {
153 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
154 flags = FILE_NON_DIRECTORY_FILE | blocking_flag;
155 }
156 // const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
157 // const flags = if (options.options) |opt| opt else FILE_NON_DIRECTORY_FILE;
149 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
158150 const rc = ntdll.NtCreateFile(
159151 &result,
160152 options.access_mask,
......@@ -164,8 +156,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
164156 FILE_ATTRIBUTE_NORMAL,
165157 options.share_access,
166158 options.creation,
167 // flags | blocking_flag,
168 flags,
159 FILE_NON_DIRECTORY_FILE | blocking_flag,
169160 null,
170161 0,
171162 );
......@@ -1380,3 +1371,53 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
13801371 }
13811372 return error.Unexpected;
13821373}
1374
1375pub fn ReadLink(path_w: []const u16) OpenError!HANDLE {
1376 var result: HANDLE = undefined;
1377
1378 const path_len_bytes = math.cast(u16, path_w.len * 2) catch |err| switch (err) {
1379 error.Overflow => return error.NameTooLong,
1380 };
1381 var nt_name = UNICODE_STRING{
1382 .Length = path_len_bytes,
1383 .MaximumLength = path_len_bytes,
1384 .Buffer = @intToPtr([*]u16, @ptrToInt(path_w.ptr)),
1385 };
1386 var attr = OBJECT_ATTRIBUTES{
1387 .Length = @sizeOf(OBJECT_ATTRIBUTES),
1388 .RootDirectory = null,
1389 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
1390 .ObjectName = &nt_name,
1391 .SecurityDescriptor = null,
1392 .SecurityQualityOfService = null,
1393 };
1394 var io: IO_STATUS_BLOCK = undefined;
1395 const rc = ntdll.NtCreateFile(
1396 &result,
1397 FILE_LIST_DIRECTORY,
1398 &attr,
1399 &io,
1400 null,
1401 FILE_ATTRIBUTE_NORMAL,
1402 FILE_SHARE_READ | FILE_SHARE_DELETE,
1403 FILE_OPEN,
1404 FILE_OPEN_REPARSE_POINT,
1405 null,
1406 0,
1407 );
1408 switch (rc) {
1409 .SUCCESS => return result,
1410 .OBJECT_NAME_INVALID => unreachable,
1411 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
1412 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
1413 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
1414 .INVALID_PARAMETER => unreachable,
1415 .SHARING_VIOLATION => return error.WouldBlock,
1416 .ACCESS_DENIED => return error.AccessDenied,
1417 .PIPE_BUSY => return error.PipeBusy,
1418 .OBJECT_PATH_SYNTAX_BAD => unreachable,
1419 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
1420 .FILE_IS_A_DIRECTORY => return error.IsDir,
1421 else => return unexpectedStatus(rc),
1422 }
1423}
\ No newline at end of file