| ... | @@ -1520,15 +1520,17 @@ pub const SymLinkError = error{ | ... | @@ -1520,15 +1520,17 @@ pub const SymLinkError = error{ |
| 1520 | /// If `sym_link_path` exists, it will not be overwritten. | 1520 | /// If `sym_link_path` exists, it will not be overwritten. |
| 1521 | /// See also `symlinkC` and `symlinkW`. | 1521 | /// See also `symlinkC` and `symlinkW`. |
| 1522 | pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void { | 1522 | pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void { |
| | 1523 | if (builtin.os.tag == .wasi) { |
| | 1524 | @compileError("symlink is not supported in WASI; use symlinkat instead"); |
| | 1525 | } |
| 1523 | if (builtin.os.tag == .windows) { | 1526 | if (builtin.os.tag == .windows) { |
| 1524 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); | 1527 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); |
| 1525 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); | 1528 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); |
| 1526 | return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0); | 1529 | return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0); |
| 1527 | } else { | | |
| 1528 | const target_path_c = try toPosixPath(target_path); | | |
| 1529 | const sym_link_path_c = try toPosixPath(sym_link_path); | | |
| 1530 | return symlinkZ(&target_path_c, &sym_link_path_c); | | |
| 1531 | } | 1530 | } |
| | 1531 | const target_path_c = try toPosixPath(target_path); |
| | 1532 | const sym_link_path_c = try toPosixPath(sym_link_path); |
| | 1533 | return symlinkZ(&target_path_c, &sym_link_path_c); |
| 1532 | } | 1534 | } |
| 1533 | | 1535 | |
| 1534 | pub const symlinkC = @compileError("deprecated: renamed to symlinkZ"); | 1536 | pub const symlinkC = @compileError("deprecated: renamed to symlinkZ"); |
| ... | @@ -1561,15 +1563,65 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin | ... | @@ -1561,15 +1563,65 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin |
| 1561 | } | 1563 | } |
| 1562 | } | 1564 | } |
| 1563 | | 1565 | |
| | 1566 | /// Similar to `symlink`, however, creates a symbolic link named `sym_link_path` which contains the string |
| | 1567 | /// `target_path` **relative** to `newdirfd` directory handle. |
| | 1568 | /// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent |
| | 1569 | /// one; the latter case is known as a dangling link. |
| | 1570 | /// If `sym_link_path` exists, it will not be overwritten. |
| | 1571 | /// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`. |
| 1564 | pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { | 1572 | pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { |
| | 1573 | if (builtin.os.tag == .wasi) { |
| | 1574 | return symlinkatWasi(target_path, newdirfd, sym_link_path); |
| | 1575 | } |
| | 1576 | if (builtin.os.tag == .windows) { |
| | 1577 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); |
| | 1578 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); |
| | 1579 | return symlinkatW(target_path_w.span().ptr, newdirfd, sym_link_path_w.span().ptr); |
| | 1580 | } |
| 1565 | const target_path_c = try toPosixPath(target_path); | 1581 | const target_path_c = try toPosixPath(target_path); |
| 1566 | const sym_link_path_c = try toPosixPath(sym_link_path); | 1582 | const sym_link_path_c = try toPosixPath(sym_link_path); |
| 1567 | return symlinkatZ(target_path_c, newdirfd, sym_link_path_c); | 1583 | return symlinkatZ(&target_path_c, newdirfd, &sym_link_path_c); |
| 1568 | } | 1584 | } |
| 1569 | | 1585 | |
| 1570 | pub const symlinkatC = @compileError("deprecated: renamed to symlinkatZ"); | 1586 | pub const symlinkatC = @compileError("deprecated: renamed to symlinkatZ"); |
| 1571 | | 1587 | |
| | 1588 | /// WASI-only. The same as `symlinkat` but targeting WASI. |
| | 1589 | /// See also `symlinkat`. |
| | 1590 | pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { |
| | 1591 | switch (wasi.path_symlink(target_path.ptr, target_path.len, newdirfd, sym_link_path.ptr, sym_link_path.len)) { |
| | 1592 | wasi.ESUCCESS => {}, |
| | 1593 | wasi.EFAULT => unreachable, |
| | 1594 | wasi.EINVAL => unreachable, |
| | 1595 | wasi.EACCES => return error.AccessDenied, |
| | 1596 | wasi.EPERM => return error.AccessDenied, |
| | 1597 | wasi.EDQUOT => return error.DiskQuota, |
| | 1598 | wasi.EEXIST => return error.PathAlreadyExists, |
| | 1599 | wasi.EIO => return error.FileSystem, |
| | 1600 | wasi.ELOOP => return error.SymLinkLoop, |
| | 1601 | wasi.ENAMETOOLONG => return error.NameTooLong, |
| | 1602 | wasi.ENOENT => return error.FileNotFound, |
| | 1603 | wasi.ENOTDIR => return error.NotDir, |
| | 1604 | wasi.ENOMEM => return error.SystemResources, |
| | 1605 | wasi.ENOSPC => return error.NoSpaceLeft, |
| | 1606 | wasi.EROFS => return error.ReadOnlyFileSystem, |
| | 1607 | else => |err| return unexpectedErrno(err), |
| | 1608 | } |
| | 1609 | } |
| | 1610 | |
| | 1611 | /// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded. |
| | 1612 | /// See also `symlinkat`. |
| | 1613 | pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymlinkError!void { |
| | 1614 | @compileError("TODO implement on Windows"); |
| | 1615 | } |
| | 1616 | |
| | 1617 | /// The same as `symlinkat` except the parameters are null-terminated pointers. |
| | 1618 | /// See also `symlinkat`. |
| 1572 | pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void { | 1619 | pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void { |
| | 1620 | if (builtin.os.tag == .windows) { |
| | 1621 | const target_path_w = try windows.cStrToPrefixedFileW(target_path); |
| | 1622 | const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path); |
| | 1623 | return symlinkatW(target_path_w.span().ptr, newdirfd, sym_link_path.span().ptr); |
| | 1624 | } |
| 1573 | switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) { | 1625 | switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) { |
| 1574 | 0 => return, | 1626 | 0 => return, |
| 1575 | EFAULT => unreachable, | 1627 | EFAULT => unreachable, |
| ... | @@ -2291,12 +2343,54 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 | ... | @@ -2291,12 +2343,54 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 |
| 2291 | } | 2343 | } |
| 2292 | } | 2344 | } |
| 2293 | | 2345 | |
| | 2346 | /// Similar to `readlink` except reads value of a symbolink link **relative** to `dirfd` directory handle. |
| | 2347 | /// The return value is a slice of `out_buffer` from index 0. |
| | 2348 | /// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`. |
| | 2349 | pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| | 2350 | if (builtin.os.tag == .wasi) { |
| | 2351 | return readlinkatWasi(dirfd, file_path, out_buffer); |
| | 2352 | } |
| | 2353 | if (builtin.os.tag == .windows) { |
| | 2354 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| | 2355 | return readlinkatW(dirfd, file_path.span().ptr, out_buffer); |
| | 2356 | } |
| | 2357 | const file_path_c = try toPosixPath(file_path); |
| | 2358 | return readlinkatZ(dirfd, &file_path_c, out_buffer); |
| | 2359 | } |
| | 2360 | |
| 2294 | pub const readlinkatC = @compileError("deprecated: renamed to readlinkatZ"); | 2361 | pub const readlinkatC = @compileError("deprecated: renamed to readlinkatZ"); |
| 2295 | | 2362 | |
| | 2363 | /// WASI-only. Same as `readlinkat` but targets WASI. |
| | 2364 | /// See also `readlinkat`. |
| | 2365 | pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| | 2366 | var bufused: usize = undefined; |
| | 2367 | switch (wasi.path_readlink(dirfd, file_path.ptr, file_path.len, out_buffer.ptr, out_buffer.len, &bufused)) { |
| | 2368 | wasi.ESUCCESS => return out_buffer[0..bufused], |
| | 2369 | wasi.EACCES => return error.AccessDenied, |
| | 2370 | wasi.EFAULT => unreachable, |
| | 2371 | wasi.EINVAL => unreachable, |
| | 2372 | wasi.EIO => return error.FileSystem, |
| | 2373 | wasi.ELOOP => return error.SymLinkLoop, |
| | 2374 | wasi.ENAMETOOLONG => return error.NameTooLong, |
| | 2375 | wasi.ENOENT => return error.FileNotFound, |
| | 2376 | wasi.ENOMEM => return error.SystemResources, |
| | 2377 | wasi.ENOTDIR => return error.NotDir, |
| | 2378 | else => |err| return unexpectedErrno(err), |
| | 2379 | } |
| | 2380 | } |
| | 2381 | |
| | 2382 | /// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded. |
| | 2383 | /// See also `readlinkat`. |
| | 2384 | pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| | 2385 | @compileError("TODO implement on Windows"); |
| | 2386 | } |
| | 2387 | |
| | 2388 | /// Same as `readlinkat` except `file_path` is null-terminated. |
| | 2389 | /// See also `readlinkat`. |
| 2296 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2390 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2297 | if (builtin.os.tag == .windows) { | 2391 | if (builtin.os.tag == .windows) { |
| 2298 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 2392 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| 2299 | @compileError("TODO implement readlink for Windows"); | 2393 | return readlinkatW(dirfd, file_path_w.span().ptr, out_buffer); |
| 2300 | } | 2394 | } |
| 2301 | const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); | 2395 | const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); |
| 2302 | switch (errno(rc)) { | 2396 | switch (errno(rc)) { |