authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-15 00:24:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:22+02:00
log99e3e29e2e611cf86941921770644401a3cf74b7
tree33729c1d9afa019af7c14716c05ce3fa9ca9ae4d
parentc47cb8d09f7cf1c02d3af59ebbca665ce78c85ca

Refactor


4 files changed, 33 insertions(+), 31 deletions(-)

lib/std/os.zig+20-9
...@@ -1568,8 +1568,7 @@ pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");...@@ -1568,8 +1568,7 @@ pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");
1568/// like to create a symbolic link to a directory, use `std.os.windows.CreateSymbolicLinkW` directly1568/// like to create a symbolic link to a directory, use `std.os.windows.CreateSymbolicLinkW` directly
1569/// specifying as flags `std.os.windows.CreateSymbolicLinkFlags.Directory`.1569/// specifying as flags `std.os.windows.CreateSymbolicLinkFlags.Directory`.
1570pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16) SymLinkError!void {1570pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16) SymLinkError!void {
1571 const flags = windows.CreateSymbolicLinkFlags.File;1571 return windows.CreateSymbolicLinkW(sym_link_path, target_path, false);
1572 return windows.CreateSymbolicLinkW(sym_link_path, target_path, flags);
1573}1572}
15741573
1575/// This is the same as `symlink` except the parameters are null-terminated pointers.1574/// This is the same as `symlink` except the parameters are null-terminated pointers.
...@@ -2395,20 +2394,20 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");...@@ -2395,20 +2394,20 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
2395pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {2394pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
2396 const w = windows;2395 const w = windows;
23972396
2398 const dir = if (std.fs.path.isAbsoluteWindowsW(file_path)) null else std.fs.cwd().fd;2397 const sharing = w.FILE_SHARE_DELETE | w.FILE_SHARE_READ | w.FILE_SHARE_WRITE;
2399 const handle = w.OpenAsReparsePoint(dir, file_path) catch |err| {2398 const disposition = w.OPEN_EXISTING;
2399 const flags = w.FILE_FLAG_BACKUP_SEMANTICS | w.FILE_FLAG_OPEN_REPARSE_POINT;
2400 const handle = w.CreateFileW(file_path, 0, sharing, null, disposition, flags, null) catch |err| {
2400 switch (err) {2401 switch (err) {
2401 error.SharingViolation => return error.AccessDenied,2402 error.SharingViolation => return error.AccessDenied,
2402 error.PipeBusy => unreachable,2403 error.PipeBusy => unreachable,
2403 error.PathAlreadyExists => unreachable,2404 error.PathAlreadyExists => unreachable,
2404 error.NoDevice => return error.FileNotFound,
2405 else => |e| return e,2405 else => |e| return e,
2406 }2406 }
2407 };2407 };
24082408
2409 var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;2409 var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
2410 _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null);2410 _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null);
2411 // std.debug.warn("\n\n{x}\n\n", .{reparse_buf});
2412 const reparse_struct = @ptrCast(*const w.REPARSE_DATA_BUFFER, @alignCast(@alignOf(w.REPARSE_DATA_BUFFER), &reparse_buf[0]));2411 const reparse_struct = @ptrCast(*const w.REPARSE_DATA_BUFFER, @alignCast(@alignOf(w.REPARSE_DATA_BUFFER), &reparse_buf[0]));
2413 switch (reparse_struct.ReparseTag) {2412 switch (reparse_struct.ReparseTag) {
2414 w.IO_REPARSE_TAG_SYMLINK => {2413 w.IO_REPARSE_TAG_SYMLINK => {
...@@ -2434,9 +2433,9 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8...@@ -2434,9 +2433,9 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8
2434}2433}
24352434
2436fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {2435fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {
2437 const out_len = std.unicode.utf16leToUtf8(out_buffer, path) catch unreachable;2436 const prefix = [_]u16{ '\\', '?', '?', '\\' };
2438 std.debug.warn("got symlink => utf8={}\n", .{out_buffer[0..out_len]});2437 const start_index = if (mem.startsWith(u16, path, &prefix)) prefix.len else 0;
2439 // TODO handle absolute paths and namespace prefix '/??/'2438 const out_len = std.unicode.utf16leToUtf8(out_buffer, path[start_index..]) catch unreachable;
2440 return out_buffer[0..out_len];2439 return out_buffer[0..out_len];
2441}2440}
24422441
...@@ -2502,6 +2501,18 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read...@@ -2502,6 +2501,18 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
2502/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.2501/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.
2503/// See also `readlinkat`.2502/// See also `readlinkat`.
2504pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {2503pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
2504 const w = windows;
2505
2506 const handle = w.OpenReparsePoint(dir, file_path) catch |err| {
2507 switch (err) {
2508 error.SharingViolation => return error.AccessDenied,
2509 error.PathAlreadyExists => unreachable,
2510 error.PipeBusy => unreachable,
2511 error.PathAlreadyExists => unreachable,
2512 error.NoDevice => return error.FileNotFound,
2513 else => |e| return e,
2514 }
2515 };
2505 @compileError("TODO implement on Windows");2516 @compileError("TODO implement on Windows");
2506}2517}
25072518
lib/std/os/test.zig+1
...@@ -86,6 +86,7 @@ test "readlink" {...@@ -86,6 +86,7 @@ test "readlink" {
86 // now, read the link and verify86 // now, read the link and verify
87 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;87 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
88 const given = try os.readlink(symlink_path, buffer[0..]);88 const given = try os.readlink(symlink_path, buffer[0..]);
89 std.debug.warn("given={}\n", .{given});
89 expect(mem.eql(u8, symlink_path, given));90 expect(mem.eql(u8, symlink_path, given));
90 }91 }
91}92}
lib/std/os/windows.zig+11-20
...@@ -602,43 +602,34 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {...@@ -602,43 +602,34 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
602 return buffer[0..end_index];602 return buffer[0..end_index];
603}603}
604604
605pub const CreateSymbolicLinkError = error{605pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, Unexpected };
606 AccessDenied,
607 PathAlreadyExists,
608 FileNotFound,
609 Unexpected
610};
611
612pub const CreateSymbolicLinkFlags = enum(DWORD) {
613 File = SYMBOLIC_LINK_FLAG_FILE,
614 Directory = SYMBOLIC_LINK_FLAG_DIRECTORY,
615};
616606
617pub fn CreateSymbolicLink(607pub fn CreateSymbolicLink(
618 sym_link_path: []const u8,608 sym_link_path: []const u8,
619 target_path: []const u8,609 target_path: []const u8,
620 flags: CreateSymbolicLinkFlags,610 is_directory: bool,
621) CreateSymbolicLinkError!void {611) CreateSymbolicLinkError!void {
622 const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path);612 const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path);
623 const target_path_w = try sliceToPrefixedFileW(target_path);613 const target_path_w = try sliceToPrefixedFileW(target_path);
624 return CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, flags);614 return CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, is_directory);
625}615}
626616
627pub fn CreateSymbolicLinkW(617pub fn CreateSymbolicLinkW(
628 sym_link_path: [*:0]const u16,618 sym_link_path: [*:0]const u16,
629 target_path: [*:0]const u16,619 target_path: [*:0]const u16,
630 flags: CreateSymbolicLinkFlags,620 is_directory: bool,
631) CreateSymbolicLinkError!void {621) CreateSymbolicLinkError!void {
632 // Previously, until Win 10 Creators Update, creating symbolic links required622 // Previously, until Win 10 Creators Update, creating symbolic links required
633 // SeCreateSymbolicLink privilege. Currently, this is no longer required if the623 // SeCreateSymbolicLink privilege. Currently, this is no longer required if the
634 // OS is in Developer Mode; however, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE624 // OS is in Developer Mode; however, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
635 // must be added to the input flags.625 // must be added to the input flags.
636 if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {626 const flags = if (is_directory) SYMBOLIC_LINK_FLAG_DIRECTORY else 0;
627 if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
637 switch (kernel32.GetLastError()) {628 switch (kernel32.GetLastError()) {
638 .INVALID_PARAMETER => {629 .INVALID_PARAMETER => {
639 // If we're on Windows pre Creators Update, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE630 // If we're on Windows pre Creators Update, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
640 // flag is an invalid parameter, in which case repeat without the flag.631 // flag is an invalid parameter, in which case repeat without the flag.
641 if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags)) == 0) {632 if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags) == 0) {
642 switch (kernel32.GetLastError()) {633 switch (kernel32.GetLastError()) {
643 .PRIVILEGE_NOT_HELD => return error.AccessDenied,634 .PRIVILEGE_NOT_HELD => return error.AccessDenied,
644 .FILE_NOT_FOUND => return error.FileNotFound,635 .FILE_NOT_FOUND => return error.FileNotFound,
...@@ -1372,7 +1363,7 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {...@@ -1372,7 +1363,7 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
1372 return error.Unexpected;1363 return error.Unexpected;
1373}1364}
13741365
1375pub const OpenAsReparsePointError = error {1366pub const OpenReparsePointError = error{
1376 FileNotFound,1367 FileNotFound,
1377 NoDevice,1368 NoDevice,
1378 SharingViolation,1369 SharingViolation,
...@@ -1384,10 +1375,10 @@ pub const OpenAsReparsePointError = error {...@@ -1384,10 +1375,10 @@ pub const OpenAsReparsePointError = error {
1384};1375};
13851376
1386/// Open file as a reparse point1377/// Open file as a reparse point
1387pub fn OpenAsReparsePoint(1378pub fn OpenReparsePoint(
1388 dir: ?HANDLE,1379 dir: ?HANDLE,
1389 sub_path_w: [*:0]const u16,1380 sub_path_w: [*:0]const u16,
1390) OpenAsReparsePointError!HANDLE {1381) OpenReparsePointError!HANDLE {
1391 const path_len_bytes = math.cast(u16, mem.lenZ(sub_path_w) * 2) catch |err| switch (err) {1382 const path_len_bytes = math.cast(u16, mem.lenZ(sub_path_w) * 2) catch |err| switch (err) {
1392 error.Overflow => return error.NameTooLong,1383 error.Overflow => return error.NameTooLong,
1393 };1384 };
...@@ -1440,4 +1431,4 @@ pub fn OpenAsReparsePoint(...@@ -1440,4 +1431,4 @@ pub fn OpenAsReparsePoint(
1440 .FILE_IS_A_DIRECTORY => unreachable,1431 .FILE_IS_A_DIRECTORY => unreachable,
1441 else => return unexpectedStatus(rc),1432 else => return unexpectedStatus(rc),
1442 }1433 }
1443}
\ No newline at end of file
1434}
lib/std/os/windows/bits.zig+1-2
...@@ -1568,8 +1568,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;...@@ -1568,8 +1568,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
1568pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;1568pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
1569pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;1569pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
1570pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;1570pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
1571pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x00000001;1571pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x1;
15721572
1573pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;
1574pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;1573pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
1575pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;1574pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;