| ... | @@ -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(sym_link_path.ptr, sym_link_path.len, newdirfd, target_path.ptr, target_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, |