diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2020-07-12 23:03:09 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2020-07-22 08:51:22 +0200 |
| commit | cc83d92b0b12f5b3fa6462ed878cd7bec7412940 (patch) | |
| tree | a8fa37b91ae55fb9b0ba3ca6a268079b9c5372ab /lib/std | |
| parent | 9225763f8bd3ab7062a55e6f9200657205c20e3b (diff) | |
| download | zig-cc83d92b0b12f5b3fa6462ed878cd7bec7412940.tar.gz zig-cc83d92b0b12f5b3fa6462ed878cd7bec7412940.zip | |
Start drafting out os.readlink on Windows
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/os.zig | 32 | ||||
| -rw-r--r-- | lib/std/os/windows/bits.zig | 27 |
2 files changed, 57 insertions, 2 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig index dfb47208ca..983f7f9a90 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2355,6 +2355,8 @@ pub const ReadLinkError = error{ FileNotFound, SystemResources, NotDir, + /// Windows-only. + UnsupportedSymlinkType, } || UnexpectedError; /// Read value of a symbolic link. @@ -2373,9 +2375,35 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); -/// Windows-only. Same as `readlink` expecte `file_path` is null-terminated, WTF16 encoded. -/// Seel also `readlinkZ`. +/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. +/// See also `readlinkZ`. pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { + const handle = windows.OpenFile(file_path, .{ + .access_mask = 0, + .creation = c.FILE_OPEN_REPARSE_POINT | c.FILE_LIST_DIRECTORY, + .io_mode = 0, + }) catch |err| { + switch (err) { + error.IsDir => unreachable, + error.NoDevice => return error.FileNotFound, + error.SharingViolation => return error.AccessDenied, + error.PipeBusy => unreachable, + error.PathAlreadyExists => unreachable, + error.WouldBlock => unreachable, + else => return err, + } + }; + var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; + _ = try windows.DeviceIoControl(handle, windows.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); + const reparse_struct = @bitCast(windows._REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(windows._REPARSE_DATA_BUFFER)]); + switch (reparse_struct.ReparseTag) { + windows.IO_REPARSE_TAG_SYMLINK => {}, + windows.IO_REPARSE_TAG_MOUNT_POINT => {}, + else => |value| { + std.debug.print("unsupported symlink type: {}", value); + return error.UnsupportedSymlinkType; + }, + } @compileError("TODO implement readlink for Windows"); } diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index a6a9e50d53..6182dc5de8 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -1542,3 +1542,30 @@ pub const POSVERSIONINFOW = *OSVERSIONINFOW; pub const LPOSVERSIONINFOW = *OSVERSIONINFOW; pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW; pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW; + +pub const _REPARSE_DATA_BUFFER = extern struct { + ReparseTag: ULONG, ReparseDataLength: USHORT, Reserved: USHORT, u: extern union { + SymbolicLinkReparseBuffer: extern struct { + SubstituteNameOffset: USHORT, + SubstituteNameLength: USHORT, + PrintNameOffset: USHORT, + PrintNameLength: USHORT, + Flags: ULONG, + PathBuffer: [1]WCHAR, + }, + MountPointReparseBuffer: extern struct { + SubstituteNameOffset: USHORT, + SubstituteNameLength: USHORT, + PrintNameOffset: USHORT, + PrintNameLength: USHORT, + PathBuffer: [1]WCHAR, + }, + GenericReparseBuffer: extern struct { + DataBuffer: [1]UCHAR, + }, + } +}; +pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; +pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; +pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c; +pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; |
