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");...@@ -2393,12 +2393,7 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
2393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.2393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.
2394/// See also `readlinkZ`.2394/// See also `readlinkZ`.
2395pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {2395pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
2396 const handle = windows.OpenFile(file_path, .{2396 const handle = windows.ReadLink(file_path) catch |err| {
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| {
2402 switch (err) {2397 switch (err) {
2403 error.IsDir => unreachable,2398 error.IsDir => unreachable,
2404 error.NoDevice => return error.FileNotFound,2399 error.NoDevice => return error.FileNotFound,
lib/std/os/test.zig+1-2
...@@ -45,8 +45,7 @@ test "readlink" {...@@ -45,8 +45,7 @@ test "readlink" {
45 if (builtin.os.tag == .wasi) return error.SkipZigTest;45 if (builtin.os.tag == .wasi) return error.SkipZigTest;
4646
47 var tmp = tmpDir(.{});47 var tmp = tmpDir(.{});
48 //defer tmp.cleanup();48 defer tmp.cleanup();
49 std.debug.print("tmp = {}\n", .{tmp.sub_path[0..]});
5049
51 // create file50 // create file
52 try tmp.dir.writeFile("file.txt", "nonsense");51 try tmp.dir.writeFile("file.txt", "nonsense");
lib/std/os/windows.zig+52-11
...@@ -110,7 +110,6 @@ pub const OpenFileOptions = struct {...@@ -110,7 +110,6 @@ pub const OpenFileOptions = struct {
110 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,110 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
111 share_access_nonblocking: bool = false,111 share_access_nonblocking: bool = false,
112 creation: ULONG,112 creation: ULONG,
113 options: ?ULONG = null,
114 io_mode: std.io.ModeOverride,113 io_mode: std.io.ModeOverride,
115};114};
116115
...@@ -147,14 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -147,14 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
147 var delay: usize = 1;146 var delay: usize = 1;
148 while (true) {147 while (true) {
149 var flags: ULONG = undefined;148 var flags: ULONG = undefined;
150 if (options.options) |opt| {149 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
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;
158 const rc = ntdll.NtCreateFile(150 const rc = ntdll.NtCreateFile(
159 &result,151 &result,
160 options.access_mask,152 options.access_mask,
...@@ -164,8 +156,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -164,8 +156,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
164 FILE_ATTRIBUTE_NORMAL,156 FILE_ATTRIBUTE_NORMAL,
165 options.share_access,157 options.share_access,
166 options.creation,158 options.creation,
167 // flags | blocking_flag,159 FILE_NON_DIRECTORY_FILE | blocking_flag,
168 flags,
169 null,160 null,
170 0,161 0,
171 );162 );
...@@ -1380,3 +1371,53 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {...@@ -1380,3 +1371,53 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
1380 }1371 }
1381 return error.Unexpected;1372 return error.Unexpected;
1382}1373}
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