| author | |
| committer | |
| log | 66bbe4ec4c11839217d6a9d65771d60d45cd6bc1 |
| tree | cebd5ba00b67e673e8a68e7d7f87aff986788c31 |
| parent | a89d5cfc3eaaf97b914abc5d355099ec8357925d |
This covers mainly `ReadLink` and `CreateSymolicLink` functions.4 files changed, 83 insertions(+), 186 deletions(-)
lib/std/fs.zig+16-13| ... | @@ -1261,11 +1261,11 @@ pub const Dir = struct { | ... | @@ -1261,11 +1261,11 @@ pub const Dir = struct { |
| 1261 | /// are null-terminated, WTF16 encoded. | 1261 | /// are null-terminated, WTF16 encoded. |
| 1262 | pub fn symLinkW( | 1262 | pub fn symLinkW( |
| 1263 | self: Dir, | 1263 | self: Dir, |
| 1264 | target_path_w: [:0]const u16, | 1264 | target_path_w: []const u16, |
| 1265 | sym_link_path_w: [:0]const u16, | 1265 | sym_link_path_w: []const u16, |
| 1266 | flags: SymLinkFlags, | 1266 | flags: SymLinkFlags, |
| 1267 | ) !void { | 1267 | ) !void { |
| 1268 | return os.windows.CreateSymbolicLinkW(self.fd, sym_link_path_w, target_path_w, flags.is_directory); | 1268 | return os.windows.CreateSymbolicLink(self.fd, sym_link_path_w, target_path_w, flags.is_directory); |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| 1271 | /// Read value of a symbolic link. | 1271 | /// Read value of a symbolic link. |
| ... | @@ -1276,7 +1276,8 @@ pub const Dir = struct { | ... | @@ -1276,7 +1276,8 @@ pub const Dir = struct { |
| 1276 | return self.readLinkWasi(sub_path, buffer); | 1276 | return self.readLinkWasi(sub_path, buffer); |
| 1277 | } | 1277 | } |
| 1278 | if (builtin.os.tag == .windows) { | 1278 | if (builtin.os.tag == .windows) { |
| 1279 | return os.windows.ReadLink(self.fd, sub_path, buffer); | 1279 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 1280 | return self.readLinkW(sub_path_w.span(), buffer); | ||
| 1280 | } | 1281 | } |
| 1281 | const sub_path_c = try os.toPosixPath(sub_path); | 1282 | const sub_path_c = try os.toPosixPath(sub_path); |
| 1282 | return self.readLinkZ(&sub_path_c, buffer); | 1283 | return self.readLinkZ(&sub_path_c, buffer); |
| ... | @@ -1293,15 +1294,15 @@ pub const Dir = struct { | ... | @@ -1293,15 +1294,15 @@ pub const Dir = struct { |
| 1293 | pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 { | 1294 | pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 { |
| 1294 | if (builtin.os.tag == .windows) { | 1295 | if (builtin.os.tag == .windows) { |
| 1295 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | 1296 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); |
| 1296 | return self.readLinkW(sub_path_w, buffer); | 1297 | return self.readLinkW(sub_path_w.span(), buffer); |
| 1297 | } | 1298 | } |
| 1298 | return os.readlinkatZ(self.fd, sub_path_c, buffer); | 1299 | return os.readlinkatZ(self.fd, sub_path_c, buffer); |
| 1299 | } | 1300 | } |
| 1300 | 1301 | ||
| 1301 | /// Windows-only. Same as `readLink` except the pathname parameter | 1302 | /// Windows-only. Same as `readLink` except the pathname parameter |
| 1302 | /// is null-terminated, WTF16 encoded. | 1303 | /// is null-terminated, WTF16 encoded. |
| 1303 | pub fn readLinkW(self: Dir, sub_path_w: [*:0]const u16, buffer: []u8) ![]u8 { | 1304 | pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u8) ![]u8 { |
| 1304 | return os.windows.ReadLinkW(self.fd, sub_path_w, buffer); | 1305 | return os.windows.ReadLink(self.fd, sub_path_w, buffer); |
| 1305 | } | 1306 | } |
| 1306 | 1307 | ||
| 1307 | /// On success, caller owns returned buffer. | 1308 | /// On success, caller owns returned buffer. |
| ... | @@ -1811,7 +1812,9 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags | ... | @@ -1811,7 +1812,9 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags |
| 1811 | assert(path.isAbsolute(target_path)); | 1812 | assert(path.isAbsolute(target_path)); |
| 1812 | assert(path.isAbsolute(sym_link_path)); | 1813 | assert(path.isAbsolute(sym_link_path)); |
| 1813 | if (builtin.os.tag == .windows) { | 1814 | if (builtin.os.tag == .windows) { |
| 1814 | return os.windows.CreateSymbolicLink(null, sym_link_path, target_path, flags.is_directory); | 1815 | const target_path_w = try os.windows.sliceToPrefixedFileW(target_path); |
| 1816 | const sym_link_path_w = try os.windows.sliceToPrefixedFileW(sym_link_path); | ||
| 1817 | return os.windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory); | ||
| 1815 | } | 1818 | } |
| 1816 | return os.symlink(target_path, sym_link_path); | 1819 | return os.symlink(target_path, sym_link_path); |
| 1817 | } | 1820 | } |
| ... | @@ -1820,10 +1823,10 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags | ... | @@ -1820,10 +1823,10 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags |
| 1820 | /// Note that this function will by default try creating a symbolic link to a file. If you would | 1823 | /// Note that this function will by default try creating a symbolic link to a file. If you would |
| 1821 | /// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`. | 1824 | /// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`. |
| 1822 | /// See also `symLinkAbsolute`, `symLinkAbsoluteZ`. | 1825 | /// See also `symLinkAbsolute`, `symLinkAbsoluteZ`. |
| 1823 | pub fn symLinkAbsoluteW(target_path_w: [:0]const u16, sym_link_path_w: [:0]const u16, flags: SymLinkFlags) !void { | 1826 | pub fn symLinkAbsoluteW(target_path_w: []const u16, sym_link_path_w: []const u16, flags: SymLinkFlags) !void { |
| 1824 | assert(path.isAbsoluteWindowsW(target_path_w)); | 1827 | assert(path.isAbsoluteWindowsWTF16(target_path_w)); |
| 1825 | assert(path.isAbsoluteWindowsW(sym_link_path_w)); | 1828 | assert(path.isAbsoluteWindowsWTF16(sym_link_path_w)); |
| 1826 | return os.windows.CreateSymbolicLinkW(null, sym_link_path_w, target_path_w, flags.is_directory); | 1829 | return os.windows.CreateSymbolicLink(null, sym_link_path_w, target_path_w, flags.is_directory); |
| 1827 | } | 1830 | } |
| 1828 | 1831 | ||
| 1829 | /// Same as `symLinkAbsolute` except the parameters are null-terminated pointers. | 1832 | /// Same as `symLinkAbsolute` except the parameters are null-terminated pointers. |
| ... | @@ -1834,7 +1837,7 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons | ... | @@ -1834,7 +1837,7 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons |
| 1834 | if (builtin.os.tag == .windows) { | 1837 | if (builtin.os.tag == .windows) { |
| 1835 | const target_path_w = try os.windows.cStrToWin32PrefixedFileW(target_path_c); | 1838 | const target_path_w = try os.windows.cStrToWin32PrefixedFileW(target_path_c); |
| 1836 | const sym_link_path_w = try os.windows.cStrToWin32PrefixedFileW(sym_link_path_c); | 1839 | const sym_link_path_w = try os.windows.cStrToWin32PrefixedFileW(sym_link_path_c); |
| 1837 | return os.windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, flags.is_directory); | 1840 | return os.windows.CreateSymbolicLink(sym_link_path_w.span(), target_path_w.span(), flags.is_directory); |
| 1838 | } | 1841 | } |
| 1839 | return os.symlinkZ(target_path_c, sym_link_path_c); | 1842 | return os.symlinkZ(target_path_c, sym_link_path_c); |
| 1840 | } | 1843 | } |
lib/std/os.zig+25-23| ... | @@ -2087,7 +2087,7 @@ pub fn renameatW( | ... | @@ -2087,7 +2087,7 @@ pub fn renameatW( |
| 2087 | pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void { | 2087 | pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2088 | if (builtin.os.tag == .windows) { | 2088 | if (builtin.os.tag == .windows) { |
| 2089 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); | 2089 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); |
| 2090 | return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode); | 2090 | return mkdiratW(dir_fd, sub_dir_path_w.span(), mode); |
| 2091 | } else if (builtin.os.tag == .wasi) { | 2091 | } else if (builtin.os.tag == .wasi) { |
| 2092 | return mkdiratWasi(dir_fd, sub_dir_path, mode); | 2092 | return mkdiratWasi(dir_fd, sub_dir_path, mode); |
| 2093 | } else { | 2093 | } else { |
| ... | @@ -2145,13 +2145,13 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr | ... | @@ -2145,13 +2145,13 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr |
| 2145 | } | 2145 | } |
| 2146 | } | 2146 | } |
| 2147 | 2147 | ||
| 2148 | pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirError!void { | 2148 | pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!void { |
| 2149 | const sub_dir_handle = windows.OpenFile(std.mem.spanZ(sub_path_w), .{ | 2149 | const sub_dir_handle = windows.OpenFile(sub_path_w, .{ |
| 2150 | .dir = dir_fd, | 2150 | .dir = dir_fd, |
| 2151 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, | 2151 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, |
| 2152 | .creation = windows.FILE_CREATE, | 2152 | .creation = windows.FILE_CREATE, |
| 2153 | .io_mode = .blocking, | 2153 | .io_mode = .blocking, |
| 2154 | .expect_dir = true, | 2154 | .open_dir = true, |
| 2155 | }) catch |err| switch (err) { | 2155 | }) catch |err| switch (err) { |
| 2156 | error.IsDir => unreachable, | 2156 | error.IsDir => unreachable, |
| 2157 | error.PipeBusy => unreachable, | 2157 | error.PipeBusy => unreachable, |
| ... | @@ -2187,7 +2187,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { | ... | @@ -2187,7 +2187,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2187 | @compileError("mkdir is not supported in WASI; use mkdirat instead"); | 2187 | @compileError("mkdir is not supported in WASI; use mkdirat instead"); |
| 2188 | } else if (builtin.os.tag == .windows) { | 2188 | } else if (builtin.os.tag == .windows) { |
| 2189 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); | 2189 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); |
| 2190 | return mkdirW(dir_path_w.span().ptr, mode); | 2190 | return mkdirW(dir_path_w.span(), mode); |
| 2191 | } else { | 2191 | } else { |
| 2192 | const dir_path_c = try toPosixPath(dir_path); | 2192 | const dir_path_c = try toPosixPath(dir_path); |
| 2193 | return mkdirZ(&dir_path_c, mode); | 2193 | return mkdirZ(&dir_path_c, mode); |
| ... | @@ -2198,7 +2198,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { | ... | @@ -2198,7 +2198,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2198 | pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { | 2198 | pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { |
| 2199 | if (builtin.os.tag == .windows) { | 2199 | if (builtin.os.tag == .windows) { |
| 2200 | const dir_path_w = try windows.cStrToPrefixedFileW(dir_path); | 2200 | const dir_path_w = try windows.cStrToPrefixedFileW(dir_path); |
| 2201 | return mkdirW(dir_path_w.span().ptr, mode); | 2201 | return mkdirW(dir_path_w.span(), mode); |
| 2202 | } | 2202 | } |
| 2203 | switch (errno(system.mkdir(dir_path, mode))) { | 2203 | switch (errno(system.mkdir(dir_path, mode))) { |
| 2204 | 0 => return, | 2204 | 0 => return, |
| ... | @@ -2220,13 +2220,13 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { | ... | @@ -2220,13 +2220,13 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { |
| 2220 | } | 2220 | } |
| 2221 | 2221 | ||
| 2222 | /// Windows-only. Same as `mkdir` but the parameters is null-terminated, WTF16 encoded. | 2222 | /// Windows-only. Same as `mkdir` but the parameters is null-terminated, WTF16 encoded. |
| 2223 | pub fn mkdirW(dir_path_w: [*:0]const u16, mode: u32) MakeDirError!void { | 2223 | pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void { |
| 2224 | const sub_dir_handle = windows.OpenFile(std.mem.spanZ(dir_path_w), .{ | 2224 | const sub_dir_handle = windows.OpenFile(dir_path_w, .{ |
| 2225 | .dir = std.fs.cwd().fd, | 2225 | .dir = std.fs.cwd().fd, |
| 2226 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, | 2226 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, |
| 2227 | .creation = windows.FILE_CREATE, | 2227 | .creation = windows.FILE_CREATE, |
| 2228 | .io_mode = .blocking, | 2228 | .io_mode = .blocking, |
| 2229 | .expect_dir = true, | 2229 | .open_dir = true, |
| 2230 | }) catch |err| switch (err) { | 2230 | }) catch |err| switch (err) { |
| 2231 | error.IsDir => unreachable, | 2231 | error.IsDir => unreachable, |
| 2232 | error.PipeBusy => unreachable, | 2232 | error.PipeBusy => unreachable, |
| ... | @@ -2379,7 +2379,8 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { | ... | @@ -2379,7 +2379,8 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2379 | if (builtin.os.tag == .wasi) { | 2379 | if (builtin.os.tag == .wasi) { |
| 2380 | @compileError("readlink is not supported in WASI; use readlinkat instead"); | 2380 | @compileError("readlink is not supported in WASI; use readlinkat instead"); |
| 2381 | } else if (builtin.os.tag == .windows) { | 2381 | } else if (builtin.os.tag == .windows) { |
| 2382 | return windows.ReadLink(std.fs.cwd().fd, file_path, out_buffer); | 2382 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 2383 | return readlinkW(file_path_w.span(), out_buffer); | ||
| 2383 | } else { | 2384 | } else { |
| 2384 | const file_path_c = try toPosixPath(file_path); | 2385 | const file_path_c = try toPosixPath(file_path); |
| 2385 | return readlinkZ(&file_path_c, out_buffer); | 2386 | return readlinkZ(&file_path_c, out_buffer); |
| ... | @@ -2390,15 +2391,15 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); | ... | @@ -2390,15 +2391,15 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); |
| 2390 | 2391 | ||
| 2391 | /// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. | 2392 | /// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. |
| 2392 | /// See also `readlinkZ`. | 2393 | /// See also `readlinkZ`. |
| 2393 | pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { | 2394 | pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| 2394 | return windows.ReadLinkW(std.fs.cwd().fd, file_path, out_buffer); | 2395 | return windows.ReadLink(std.fs.cwd().fd, file_path, out_buffer); |
| 2395 | } | 2396 | } |
| 2396 | 2397 | ||
| 2397 | /// Same as `readlink` except `file_path` is null-terminated. | 2398 | /// Same as `readlink` except `file_path` is null-terminated. |
| 2398 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2399 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2399 | if (builtin.os.tag == .windows) { | 2400 | if (builtin.os.tag == .windows) { |
| 2400 | const file_path_w = try windows.cStrToWin32PrefixedFileW(file_path); | 2401 | const file_path_w = try windows.cStrToWin32PrefixedFileW(file_path); |
| 2401 | return readlinkW(file_path_w.span().ptr, out_buffer); | 2402 | return readlinkW(file_path_w.span(), out_buffer); |
| 2402 | } | 2403 | } |
| 2403 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); | 2404 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); |
| 2404 | switch (errno(rc)) { | 2405 | switch (errno(rc)) { |
| ... | @@ -2424,7 +2425,8 @@ pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLink | ... | @@ -2424,7 +2425,8 @@ pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLink |
| 2424 | return readlinkatWasi(dirfd, file_path, out_buffer); | 2425 | return readlinkatWasi(dirfd, file_path, out_buffer); |
| 2425 | } | 2426 | } |
| 2426 | if (builtin.os.tag == .windows) { | 2427 | if (builtin.os.tag == .windows) { |
| 2427 | return windows.ReadLink(dirfd, file_path, out_buffer); | 2428 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 2429 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); | ||
| 2428 | } | 2430 | } |
| 2429 | const file_path_c = try toPosixPath(file_path); | 2431 | const file_path_c = try toPosixPath(file_path); |
| 2430 | return readlinkatZ(dirfd, &file_path_c, out_buffer); | 2432 | return readlinkatZ(dirfd, &file_path_c, out_buffer); |
| ... | @@ -2454,8 +2456,8 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read | ... | @@ -2454,8 +2456,8 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read |
| 2454 | 2456 | ||
| 2455 | /// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded. | 2457 | /// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded. |
| 2456 | /// See also `readlinkat`. | 2458 | /// See also `readlinkat`. |
| 2457 | pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { | 2459 | pub fn readlinkatW(dirfd: fd_t, file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| 2458 | return windows.ReadLinkW(dirfd, file_path, out_buffer); | 2460 | return windows.ReadLink(dirfd, file_path, out_buffer); |
| 2459 | } | 2461 | } |
| 2460 | 2462 | ||
| 2461 | /// Same as `readlinkat` except `file_path` is null-terminated. | 2463 | /// Same as `readlinkat` except `file_path` is null-terminated. |
| ... | @@ -2463,7 +2465,7 @@ pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) Rea | ... | @@ -2463,7 +2465,7 @@ pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) Rea |
| 2463 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2465 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2464 | if (builtin.os.tag == .windows) { | 2466 | if (builtin.os.tag == .windows) { |
| 2465 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 2467 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| 2466 | return readlinkatW(dirfd, file_path_w.span().ptr, out_buffer); | 2468 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); |
| 2467 | } | 2469 | } |
| 2468 | const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); | 2470 | const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); |
| 2469 | switch (errno(rc)) { | 2471 | switch (errno(rc)) { |
| ... | @@ -3984,7 +3986,7 @@ pub const RealPathError = error{ | ... | @@ -3984,7 +3986,7 @@ pub const RealPathError = error{ |
| 3984 | pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 3986 | pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 3985 | if (builtin.os.tag == .windows) { | 3987 | if (builtin.os.tag == .windows) { |
| 3986 | const pathname_w = try windows.sliceToPrefixedFileW(pathname); | 3988 | const pathname_w = try windows.sliceToPrefixedFileW(pathname); |
| 3987 | return realpathW(pathname_w.span().ptr, out_buffer); | 3989 | return realpathW(pathname_w.span(), out_buffer); |
| 3988 | } | 3990 | } |
| 3989 | if (builtin.os.tag == .wasi) { | 3991 | if (builtin.os.tag == .wasi) { |
| 3990 | @compileError("Use std.fs.wasi.PreopenList to obtain valid Dir handles instead of using absolute paths"); | 3992 | @compileError("Use std.fs.wasi.PreopenList to obtain valid Dir handles instead of using absolute paths"); |
| ... | @@ -3999,7 +4001,7 @@ pub const realpathC = @compileError("deprecated: renamed realpathZ"); | ... | @@ -3999,7 +4001,7 @@ pub const realpathC = @compileError("deprecated: renamed realpathZ"); |
| 3999 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 4001 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 4000 | if (builtin.os.tag == .windows) { | 4002 | if (builtin.os.tag == .windows) { |
| 4001 | const pathname_w = try windows.cStrToPrefixedFileW(pathname); | 4003 | const pathname_w = try windows.cStrToPrefixedFileW(pathname); |
| 4002 | return realpathW(pathname_w.span().ptr, out_buffer); | 4004 | return realpathW(pathname_w.span(), out_buffer); |
| 4003 | } | 4005 | } |
| 4004 | if (builtin.os.tag == .linux and !builtin.link_libc) { | 4006 | if (builtin.os.tag == .linux and !builtin.link_libc) { |
| 4005 | const fd = openZ(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0) catch |err| switch (err) { | 4007 | const fd = openZ(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0) catch |err| switch (err) { |
| ... | @@ -4037,7 +4039,7 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP | ... | @@ -4037,7 +4039,7 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP |
| 4037 | 4039 | ||
| 4038 | /// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded. | 4040 | /// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded. |
| 4039 | /// TODO use ntdll for better semantics | 4041 | /// TODO use ntdll for better semantics |
| 4040 | pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 4042 | pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 4041 | const w = windows; | 4043 | const w = windows; |
| 4042 | 4044 | ||
| 4043 | const dir = std.fs.cwd().fd; | 4045 | const dir = std.fs.cwd().fd; |
| ... | @@ -4045,20 +4047,20 @@ pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) Real | ... | @@ -4045,20 +4047,20 @@ pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) Real |
| 4045 | const share_access = w.FILE_SHARE_READ; | 4047 | const share_access = w.FILE_SHARE_READ; |
| 4046 | const creation = w.FILE_OPEN; | 4048 | const creation = w.FILE_OPEN; |
| 4047 | const h_file = blk: { | 4049 | const h_file = blk: { |
| 4048 | const res = w.OpenFile(std.mem.spanZ(pathname), .{ | 4050 | const res = w.OpenFile(pathname, .{ |
| 4049 | .dir = dir, | 4051 | .dir = dir, |
| 4050 | .access_mask = access_mask, | 4052 | .access_mask = access_mask, |
| 4051 | .share_access = share_access, | 4053 | .share_access = share_access, |
| 4052 | .creation = creation, | 4054 | .creation = creation, |
| 4053 | .io_mode = .blocking, | 4055 | .io_mode = .blocking, |
| 4054 | }) catch |err| switch (err) { | 4056 | }) catch |err| switch (err) { |
| 4055 | error.IsDir => break :blk w.OpenFile(std.mem.spanZ(pathname), .{ | 4057 | error.IsDir => break :blk w.OpenFile(pathname, .{ |
| 4056 | .dir = dir, | 4058 | .dir = dir, |
| 4057 | .access_mask = access_mask, | 4059 | .access_mask = access_mask, |
| 4058 | .share_access = share_access, | 4060 | .share_access = share_access, |
| 4059 | .creation = creation, | 4061 | .creation = creation, |
| 4060 | .io_mode = .blocking, | 4062 | .io_mode = .blocking, |
| 4061 | .expect_dir = true, | 4063 | .open_dir = true, |
| 4062 | }) catch |er| switch (er) { | 4064 | }) catch |er| switch (er) { |
| 4063 | error.WouldBlock => unreachable, | 4065 | error.WouldBlock => unreachable, |
| 4064 | else => |e2| return e2, | 4066 | else => |e2| return e2, |
lib/std/os/test.zig+2-2| ... | @@ -27,7 +27,7 @@ test "symlink with relative paths" { | ... | @@ -27,7 +27,7 @@ test "symlink with relative paths" { |
| 27 | try cwd.writeFile("file.txt", "nonsense"); | 27 | try cwd.writeFile("file.txt", "nonsense"); |
| 28 | 28 | ||
| 29 | if (builtin.os.tag == .windows) { | 29 | if (builtin.os.tag == .windows) { |
| 30 | try os.windows.CreateSymbolicLink(cwd.fd, "symlinked", "file.txt", false); | 30 | try os.windows.CreateSymbolicLink(cwd.fd, &[_]u16{ 's', 'y', 'm', 'l', 'i', 'n', 'k', 'e', 'd' }, &[_]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, false); |
| 31 | } else { | 31 | } else { |
| 32 | try os.symlink("file.txt", "symlinked"); | 32 | try os.symlink("file.txt", "symlinked"); |
| 33 | } | 33 | } |
| ... | @@ -85,7 +85,7 @@ test "readlinkat" { | ... | @@ -85,7 +85,7 @@ test "readlinkat" { |
| 85 | 85 | ||
| 86 | // create a symbolic link | 86 | // create a symbolic link |
| 87 | if (builtin.os.tag == .windows) { | 87 | if (builtin.os.tag == .windows) { |
| 88 | try os.windows.CreateSymbolicLink(tmp.dir.fd, "link", "file.txt", false); | 88 | try os.windows.CreateSymbolicLink(tmp.dir.fd, &[_]u16{ 'l', 'i', 'n', 'k' }, &[_]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, false); |
| 89 | } else { | 89 | } else { |
| 90 | try os.symlinkat("file.txt", tmp.dir.fd, "link"); | 90 | try os.symlinkat("file.txt", tmp.dir.fd, "link"); |
| 91 | } | 91 | } |
lib/std/os/windows.zig+40-148| ... | @@ -69,16 +69,21 @@ pub const OpenFileOptions = struct { | ... | @@ -69,16 +69,21 @@ pub const OpenFileOptions = struct { |
| 69 | share_access_nonblocking: bool = false, | 69 | share_access_nonblocking: bool = false, |
| 70 | creation: ULONG, | 70 | creation: ULONG, |
| 71 | io_mode: std.io.ModeOverride, | 71 | io_mode: std.io.ModeOverride, |
| 72 | expect_dir: bool = false, | 72 | /// If true, tries to open path as a directory. |
| 73 | /// Defaults to false. | ||
| 74 | open_dir: bool = false, | ||
| 75 | /// If false, tries to open path as a reparse point without dereferencing it. | ||
| 76 | /// Defaults to true. | ||
| 77 | follow_symlinks: bool = true, | ||
| 73 | }; | 78 | }; |
| 74 | 79 | ||
| 75 | /// TODO when share_access_nonblocking is false, this implementation uses | 80 | /// TODO when share_access_nonblocking is false, this implementation uses |
| 76 | /// untinterruptible sleep() to block. This is not the final iteration of the API. | 81 | /// untinterruptible sleep() to block. This is not the final iteration of the API. |
| 77 | pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { | 82 | pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { |
| 78 | if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and !options.expect_dir) { | 83 | if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and !options.open_dir and options.follow_symlinks) { |
| 79 | return error.IsDir; | 84 | return error.IsDir; |
| 80 | } | 85 | } |
| 81 | if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and !options.expect_dir) { | 86 | if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and !options.open_dir and options.follow_symlinks) { |
| 82 | return error.IsDir; | 87 | return error.IsDir; |
| 83 | } | 88 | } |
| 84 | 89 | ||
| ... | @@ -105,8 +110,8 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN | ... | @@ -105,8 +110,8 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN |
| 105 | var delay: usize = 1; | 110 | var delay: usize = 1; |
| 106 | while (true) { | 111 | while (true) { |
| 107 | const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; | 112 | const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; |
| 108 | const file_or_dir_flag: ULONG = if (options.expect_dir) FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT else FILE_NON_DIRECTORY_FILE; | 113 | const file_or_dir_flag: ULONG = if (options.open_dir) FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT else FILE_NON_DIRECTORY_FILE; |
| 109 | const flags: ULONG = file_or_dir_flag | blocking_flag; | 114 | const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else FILE_OPEN_REPARSE_POINT; |
| 110 | const rc = ntdll.NtCreateFile( | 115 | const rc = ntdll.NtCreateFile( |
| 111 | &result, | 116 | &result, |
| 112 | options.access_mask, | 117 | options.access_mask, |
| ... | @@ -143,7 +148,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN | ... | @@ -143,7 +148,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN |
| 143 | .PIPE_BUSY => return error.PipeBusy, | 148 | .PIPE_BUSY => return error.PipeBusy, |
| 144 | .OBJECT_PATH_SYNTAX_BAD => unreachable, | 149 | .OBJECT_PATH_SYNTAX_BAD => unreachable, |
| 145 | .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, | 150 | .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, |
| 146 | .FILE_IS_A_DIRECTORY => if (options.expect_dir) unreachable else return error.IsDir, | 151 | .FILE_IS_A_DIRECTORY => if (options.open_dir) unreachable else return error.IsDir, |
| 147 | else => return unexpectedStatus(rc), | 152 | else => return unexpectedStatus(rc), |
| 148 | } | 153 | } |
| 149 | } | 154 | } |
| ... | @@ -598,27 +603,14 @@ pub const CreateSymbolicLinkError = error{ | ... | @@ -598,27 +603,14 @@ pub const CreateSymbolicLinkError = error{ |
| 598 | PathAlreadyExists, | 603 | PathAlreadyExists, |
| 599 | FileNotFound, | 604 | FileNotFound, |
| 600 | NameTooLong, | 605 | NameTooLong, |
| 601 | InvalidUtf8, | ||
| 602 | BadPathName, | ||
| 603 | NoDevice, | 606 | NoDevice, |
| 604 | Unexpected, | 607 | Unexpected, |
| 605 | }; | 608 | }; |
| 606 | 609 | ||
| 607 | pub fn CreateSymbolicLink( | 610 | pub fn CreateSymbolicLink( |
| 608 | dir: ?HANDLE, | 611 | dir: ?HANDLE, |
| 609 | sym_link_path: []const u8, | 612 | sym_link_path: []const u16, |
| 610 | target_path: []const u8, | 613 | target_path: []const u16, |
| 611 | is_directory: bool, | ||
| 612 | ) CreateSymbolicLinkError!void { | ||
| 613 | const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path); | ||
| 614 | const target_path_w = try sliceToPrefixedFileW(target_path); | ||
| 615 | return CreateSymbolicLinkW(dir, sym_link_path_w.span(), target_path_w.span(), is_directory); | ||
| 616 | } | ||
| 617 | |||
| 618 | pub fn CreateSymbolicLinkW( | ||
| 619 | dir: ?HANDLE, | ||
| 620 | sym_link_path: [:0]const u16, | ||
| 621 | target_path: [:0]const u16, | ||
| 622 | is_directory: bool, | 614 | is_directory: bool, |
| 623 | ) CreateSymbolicLinkError!void { | 615 | ) CreateSymbolicLinkError!void { |
| 624 | const SYMLINK_DATA = extern struct { | 616 | const SYMLINK_DATA = extern struct { |
| ... | @@ -632,70 +624,18 @@ pub fn CreateSymbolicLinkW( | ... | @@ -632,70 +624,18 @@ pub fn CreateSymbolicLinkW( |
| 632 | Flags: ULONG, | 624 | Flags: ULONG, |
| 633 | }; | 625 | }; |
| 634 | 626 | ||
| 635 | var symlink_handle: HANDLE = undefined; | 627 | const symlink_handle = OpenFile(sym_link_path, .{ |
| 636 | if (is_directory) { | 628 | .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, |
| 637 | const sym_link_len_bytes = math.cast(u16, sym_link_path.len * 2) catch |err| switch (err) { | 629 | .dir = dir, |
| 638 | error.Overflow => return error.NameTooLong, | 630 | .creation = FILE_CREATE, |
| 639 | }; | 631 | .io_mode = .blocking, |
| 640 | var nt_name = UNICODE_STRING{ | 632 | .open_dir = is_directory, |
| 641 | .Length = sym_link_len_bytes, | 633 | }) catch |err| switch (err) { |
| 642 | .MaximumLength = sym_link_len_bytes, | 634 | error.IsDir => return error.PathAlreadyExists, |
| 643 | .Buffer = @intToPtr([*]u16, @ptrToInt(sym_link_path.ptr)), | 635 | error.WouldBlock => unreachable, |
| 644 | }; | 636 | error.PipeBusy => unreachable, |
| 645 | 637 | else => |e| return e, | |
| 646 | if (sym_link_path[0] == '.' and sym_link_path[1] == 0) { | 638 | }; |
| 647 | // Windows does not recognize this, but it does work with empty string. | ||
| 648 | nt_name.Length = 0; | ||
| 649 | } | ||
| 650 | |||
| 651 | var attr = OBJECT_ATTRIBUTES{ | ||
| 652 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | ||
| 653 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sym_link_path)) null else dir, | ||
| 654 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. | ||
| 655 | .ObjectName = &nt_name, | ||
| 656 | .SecurityDescriptor = null, | ||
| 657 | .SecurityQualityOfService = null, | ||
| 658 | }; | ||
| 659 | |||
| 660 | var io: IO_STATUS_BLOCK = undefined; | ||
| 661 | const rc = ntdll.NtCreateFile( | ||
| 662 | &symlink_handle, | ||
| 663 | GENERIC_READ | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
| 664 | &attr, | ||
| 665 | &io, | ||
| 666 | null, | ||
| 667 | FILE_ATTRIBUTE_NORMAL, | ||
| 668 | FILE_SHARE_READ, | ||
| 669 | FILE_CREATE, | ||
| 670 | FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, | ||
| 671 | null, | ||
| 672 | 0, | ||
| 673 | ); | ||
| 674 | switch (rc) { | ||
| 675 | .SUCCESS => {}, | ||
| 676 | .OBJECT_NAME_INVALID => unreachable, | ||
| 677 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, | ||
| 678 | .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, | ||
| 679 | .NO_MEDIA_IN_DEVICE => return error.NoDevice, | ||
| 680 | .INVALID_PARAMETER => unreachable, | ||
| 681 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 682 | .OBJECT_PATH_SYNTAX_BAD => unreachable, | ||
| 683 | .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, | ||
| 684 | else => return unexpectedStatus(rc), | ||
| 685 | } | ||
| 686 | } else { | ||
| 687 | symlink_handle = OpenFile(sym_link_path, .{ | ||
| 688 | .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, | ||
| 689 | .dir = dir, | ||
| 690 | .creation = FILE_CREATE, | ||
| 691 | .io_mode = .blocking, | ||
| 692 | }) catch |err| switch (err) { | ||
| 693 | error.WouldBlock => unreachable, | ||
| 694 | error.IsDir => return error.PathAlreadyExists, | ||
| 695 | error.PipeBusy => unreachable, | ||
| 696 | else => |e| return e, | ||
| 697 | }; | ||
| 698 | } | ||
| 699 | defer CloseHandle(symlink_handle); | 639 | defer CloseHandle(symlink_handle); |
| 700 | 640 | ||
| 701 | // prepare reparse data buffer | 641 | // prepare reparse data buffer |
| ... | @@ -726,72 +666,24 @@ pub const ReadLinkError = error{ | ... | @@ -726,72 +666,24 @@ pub const ReadLinkError = error{ |
| 726 | Unexpected, | 666 | Unexpected, |
| 727 | NameTooLong, | 667 | NameTooLong, |
| 728 | UnsupportedReparsePointType, | 668 | UnsupportedReparsePointType, |
| 729 | InvalidUtf8, | ||
| 730 | BadPathName, | ||
| 731 | }; | 669 | }; |
| 732 | 670 | ||
| 733 | pub fn ReadLink( | 671 | pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| 734 | dir: ?HANDLE, | 672 | const result_handle = OpenFile(sub_path_w, .{ |
| 735 | sub_path: []const u8, | 673 | .dir = dir, |
| 736 | out_buffer: []u8, | 674 | .access_mask = FILE_READ_ATTRIBUTES, |
| 737 | ) ReadLinkError![]u8 { | 675 | .share_access = FILE_SHARE_READ, |
| 738 | const sub_path_w = try sliceToPrefixedFileW(sub_path); | 676 | .creation = FILE_OPEN, |
| 739 | return ReadLinkW(dir, sub_path_w.span().ptr, out_buffer); | 677 | .io_mode = .blocking, |
| 740 | } | 678 | .follow_symlinks = false, |
| 741 | 679 | }) catch |err| switch (err) { | |
| 742 | pub fn ReadLinkW(dir: ?HANDLE, sub_path_w: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { | 680 | error.WouldBlock => unreachable, |
| 743 | const path_len_bytes = math.cast(u16, mem.lenZ(sub_path_w) * 2) catch |err| switch (err) { | 681 | error.PipeBusy => unreachable, |
| 744 | error.Overflow => return error.NameTooLong, | 682 | error.IsDir => unreachable, |
| 745 | }; | 683 | error.NoDevice => unreachable, |
| 746 | var nt_name = UNICODE_STRING{ | 684 | error.PathAlreadyExists => unreachable, |
| 747 | .Length = path_len_bytes, | 685 | else => |e| return e, |
| 748 | .MaximumLength = path_len_bytes, | ||
| 749 | .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)), | ||
| 750 | }; | 686 | }; |
| 751 | |||
| 752 | if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { | ||
| 753 | // Windows does not recognize this, but it does work with empty string. | ||
| 754 | nt_name.Length = 0; | ||
| 755 | } | ||
| 756 | |||
| 757 | var attr = OBJECT_ATTRIBUTES{ | ||
| 758 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | ||
| 759 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dir, | ||
| 760 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. | ||
| 761 | .ObjectName = &nt_name, | ||
| 762 | .SecurityDescriptor = null, | ||
| 763 | .SecurityQualityOfService = null, | ||
| 764 | }; | ||
| 765 | var io: IO_STATUS_BLOCK = undefined; | ||
| 766 | var result_handle: HANDLE = undefined; | ||
| 767 | const rc = ntdll.NtCreateFile( | ||
| 768 | &result_handle, | ||
| 769 | FILE_READ_ATTRIBUTES, | ||
| 770 | &attr, | ||
| 771 | &io, | ||
| 772 | null, | ||
| 773 | FILE_ATTRIBUTE_NORMAL, | ||
| 774 | FILE_SHARE_READ, | ||
| 775 | FILE_OPEN, | ||
| 776 | FILE_OPEN_REPARSE_POINT, | ||
| 777 | null, | ||
| 778 | 0, | ||
| 779 | ); | ||
| 780 | switch (rc) { | ||
| 781 | .SUCCESS => {}, | ||
| 782 | .OBJECT_NAME_INVALID => unreachable, | ||
| 783 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, | ||
| 784 | .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, | ||
| 785 | .NO_MEDIA_IN_DEVICE => return error.FileNotFound, | ||
| 786 | .INVALID_PARAMETER => unreachable, | ||
| 787 | .SHARING_VIOLATION => return error.AccessDenied, | ||
| 788 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 789 | .PIPE_BUSY => return error.AccessDenied, | ||
| 790 | .OBJECT_PATH_SYNTAX_BAD => unreachable, | ||
| 791 | .OBJECT_NAME_COLLISION => unreachable, | ||
| 792 | .FILE_IS_A_DIRECTORY => unreachable, | ||
| 793 | else => return unexpectedStatus(rc), | ||
| 794 | } | ||
| 795 | defer CloseHandle(result_handle); | 687 | defer CloseHandle(result_handle); |
| 796 | 688 | ||
| 797 | var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; | 689 | var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; |