| ... | ... | @@ -1520,15 +1520,17 @@ pub const SymLinkError = error{ |
| 1520 | 1520 | /// If `sym_link_path` exists, it will not be overwritten. |
| 1521 | 1521 | /// See also `symlinkC` and `symlinkW`. |
| 1522 | 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 | 1526 | if (builtin.os.tag == .windows) { |
| 1524 | 1527 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); |
| 1525 | 1528 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); |
| 1526 | 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 | 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 | 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 | 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 | 1581 | const target_path_c = try toPosixPath(target_path); |
| 1566 | 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 | 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 | 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 | 1625 | switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) { |
| 1574 | 1626 | 0 => return, |
| 1575 | 1627 | EFAULT => unreachable, |
| ... | ... | @@ -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 | 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 | 2390 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2297 | 2391 | if (builtin.os.tag == .windows) { |
| 2298 | 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 | 2395 | const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len); |
| 2302 | 2396 | switch (errno(rc)) { |