| author | |
| committer | |
| log | f3723b42e1f05d14479d6f5507943cd1905e0fcf |
| tree | 3941dddf0af4affbc29c5a2dc8f4cc16b800f74f |
| parent | 446c145ca86b014d6743f5666e9ee1d671b56045 |
4 files changed, 69 insertions(+), 18 deletions(-)
lib/std/Io/Dir.zig+33| ... | ... | @@ -989,6 +989,39 @@ pub fn renameAbsolute(io: Io, old_path: []const u8, new_path: []const u8) Rename |
| 989 | 989 | return io.vtable.dirRename(io.userdata, my_cwd, old_path, my_cwd, new_path); |
| 990 | 990 | } |
| 991 | 991 | |
| 992 | pub const HardLinkOptions = struct { | |
| 993 | follow_symlinks: bool = true, | |
| 994 | }; | |
| 995 | ||
| 996 | pub const HardLinkError = error{ | |
| 997 | AccessDenied, | |
| 998 | PermissionDenied, | |
| 999 | DiskQuota, | |
| 1000 | PathAlreadyExists, | |
| 1001 | HardwareFailure, | |
| 1002 | /// Either the OS or the filesystem does not support hard links. | |
| 1003 | OperationUnsupported, | |
| 1004 | SymLinkLoop, | |
| 1005 | LinkQuotaExceeded, | |
| 1006 | FileNotFound, | |
| 1007 | SystemResources, | |
| 1008 | NoSpaceLeft, | |
| 1009 | ReadOnlyFileSystem, | |
| 1010 | NotSameFileSystem, | |
| 1011 | NotDir, | |
| 1012 | } || Io.Cancelable || PathNameError || Io.UnexpectedError; | |
| 1013 | ||
| 1014 | pub fn hardLink( | |
| 1015 | old_dir: Dir, | |
| 1016 | old_sub_path: []const u8, | |
| 1017 | new_dir: Dir, | |
| 1018 | new_sub_path: []const u8, | |
| 1019 | io: Io, | |
| 1020 | options: HardLinkOptions, | |
| 1021 | ) HardLinkError!void { | |
| 1022 | return io.vtable.dirHardLink(io.userdata, old_dir, old_sub_path, new_dir, new_sub_path, options); | |
| 1023 | } | |
| 1024 | ||
| 992 | 1025 | /// Use with `symLink`, `symLinkAtomic`, and `symLinkAbsolute` to |
| 993 | 1026 | /// specify whether the symlink will point to a file or a directory. This value |
| 994 | 1027 | /// is ignored on all hosts except Windows where creating symlinks to different |
lib/std/Io/File.zig+5-1| ... | ... | @@ -17,6 +17,7 @@ pub const Atomic = @import("File/Atomic.zig"); |
| 17 | 17 | |
| 18 | 18 | pub const Handle = std.posix.fd_t; |
| 19 | 19 | pub const INode = std.posix.ino_t; |
| 20 | pub const NLink = std.posix.nlink_t; | |
| 20 | 21 | pub const Uid = std.posix.uid_t; |
| 21 | 22 | pub const Gid = std.posix.gid_t; |
| 22 | 23 | |
| ... | ... | @@ -47,6 +48,7 @@ pub const Stat = struct { |
| 47 | 48 | /// The FileIndex on Windows is similar. It is a number for a file that |
| 48 | 49 | /// is unique to each filesystem. |
| 49 | 50 | inode: INode, |
| 51 | nlink: NLink, | |
| 50 | 52 | size: u64, |
| 51 | 53 | permissions: Permissions, |
| 52 | 54 | kind: Kind, |
| ... | ... | @@ -101,9 +103,11 @@ pub const OpenFlags = struct { |
| 101 | 103 | mode: OpenMode = .read_only, |
| 102 | 104 | |
| 103 | 105 | /// Determines the behavior when opening a path that refers to a directory. |
| 106 | /// | |
| 104 | 107 | /// If set to true, directories may be opened, but `error.IsDir` is still |
| 105 | 108 | /// possible in certain scenarios, e.g. attempting to open a directory with |
| 106 | 109 | /// write permissions. |
| 110 | /// | |
| 107 | 111 | /// If set to false, `error.IsDir` will always be returned when opening a directory. |
| 108 | 112 | /// |
| 109 | 113 | /// When set to false: |
| ... | ... | @@ -289,7 +293,7 @@ pub fn sync(file: File, io: Io) SyncError!void { |
| 289 | 293 | return io.vtable.fileSync(io.userdata, file); |
| 290 | 294 | } |
| 291 | 295 | |
| 292 | /// Test whether the file refers to a terminal. | |
| 296 | /// Test whether the file refers to a terminal (similar to libc "isatty"). | |
| 293 | 297 | /// |
| 294 | 298 | /// See also: |
| 295 | 299 | /// * `enableAnsiEscapeCodes` |
lib/std/Io/Threaded.zig+30-16| ... | ... | @@ -1829,19 +1829,21 @@ fn dirStatFileLinux( |
| 1829 | 1829 | dir.handle, |
| 1830 | 1830 | sub_path_posix, |
| 1831 | 1831 | flags, |
| 1832 | .{ .TYPE = true, .MODE = true, .ATIME = true, .MTIME = true, .CTIME = true, .INO = true, .SIZE = true }, | |
| 1832 | .{ | |
| 1833 | .TYPE = true, | |
| 1834 | .MODE = true, | |
| 1835 | .ATIME = true, | |
| 1836 | .MTIME = true, | |
| 1837 | .CTIME = true, | |
| 1838 | .INO = true, | |
| 1839 | .SIZE = true, | |
| 1840 | .NLINK = true, | |
| 1841 | }, | |
| 1833 | 1842 | &statx, |
| 1834 | 1843 | ); |
| 1835 | 1844 | switch (sys.errno(rc)) { |
| 1836 | 1845 | .SUCCESS => { |
| 1837 | 1846 | current_thread.endSyscall(); |
| 1838 | assert(statx.mask.TYPE); | |
| 1839 | assert(statx.mask.MODE); | |
| 1840 | assert(statx.mask.ATIME); | |
| 1841 | assert(statx.mask.MTIME); | |
| 1842 | assert(statx.mask.CTIME); | |
| 1843 | assert(statx.mask.INO); | |
| 1844 | assert(statx.mask.SIZE); | |
| 1845 | 1847 | return statFromLinux(&statx); |
| 1846 | 1848 | }, |
| 1847 | 1849 | .INTR => { |
| ... | ... | @@ -2082,19 +2084,21 @@ fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { |
| 2082 | 2084 | file.handle, |
| 2083 | 2085 | "", |
| 2084 | 2086 | linux.AT.EMPTY_PATH, |
| 2085 | .{ .TYPE = true, .MODE = true, .ATIME = true, .MTIME = true, .CTIME = true, .INO = true, .SIZE = true }, | |
| 2087 | .{ | |
| 2088 | .TYPE = true, | |
| 2089 | .MODE = true, | |
| 2090 | .ATIME = true, | |
| 2091 | .MTIME = true, | |
| 2092 | .CTIME = true, | |
| 2093 | .INO = true, | |
| 2094 | .SIZE = true, | |
| 2095 | .NLINK = true, | |
| 2096 | }, | |
| 2086 | 2097 | &statx, |
| 2087 | 2098 | ); |
| 2088 | 2099 | switch (sys.errno(rc)) { |
| 2089 | 2100 | .SUCCESS => { |
| 2090 | 2101 | current_thread.endSyscall(); |
| 2091 | assert(statx.mask.TYPE); | |
| 2092 | assert(statx.mask.MODE); | |
| 2093 | assert(statx.mask.ATIME); | |
| 2094 | assert(statx.mask.MTIME); | |
| 2095 | assert(statx.mask.CTIME); | |
| 2096 | assert(statx.mask.INO); | |
| 2097 | assert(statx.mask.SIZE); | |
| 2098 | 2102 | return statFromLinux(&statx); |
| 2099 | 2103 | }, |
| 2100 | 2104 | .INTR => { |
| ... | ... | @@ -10499,11 +10503,20 @@ fn clockToWasi(clock: Io.Clock) std.os.wasi.clockid_t { |
| 10499 | 10503 | } |
| 10500 | 10504 | |
| 10501 | 10505 | fn statFromLinux(stx: *const std.os.linux.Statx) File.Stat { |
| 10506 | assert(stx.mask.TYPE); | |
| 10507 | assert(stx.mask.MODE); | |
| 10508 | assert(stx.mask.ATIME); | |
| 10509 | assert(stx.mask.MTIME); | |
| 10510 | assert(stx.mask.CTIME); | |
| 10511 | assert(stx.mask.INO); | |
| 10512 | assert(stx.mask.SIZE); | |
| 10513 | assert(stx.mask.NLINK); | |
| 10502 | 10514 | const atime = stx.atime; |
| 10503 | 10515 | const mtime = stx.mtime; |
| 10504 | 10516 | const ctime = stx.ctime; |
| 10505 | 10517 | return .{ |
| 10506 | 10518 | .inode = stx.ino, |
| 10519 | .nlink = stx.nlink, | |
| 10507 | 10520 | .size = stx.size, |
| 10508 | 10521 | .permissions = .fromMode(stx.mode), |
| 10509 | 10522 | .kind = switch (stx.mode & std.os.linux.S.IFMT) { |
| ... | ... | @@ -10528,6 +10541,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat { |
| 10528 | 10541 | const ctime = st.ctime(); |
| 10529 | 10542 | return .{ |
| 10530 | 10543 | .inode = st.ino, |
| 10544 | .nlink = st.nlink, | |
| 10531 | 10545 | .size = @bitCast(st.size), |
| 10532 | 10546 | .permissions = .fromMode(st.mode), |
| 10533 | 10547 | .kind = k: { |
lib/std/c.zig+1-1| ... | ... | @@ -162,7 +162,7 @@ pub const nlink_t = switch (native_os) { |
| 162 | 162 | .freebsd, .serenity => u64, |
| 163 | 163 | .openbsd, .netbsd, .illumos => u32, |
| 164 | 164 | .haiku => i32, |
| 165 | else => void, | |
| 165 | else => u0, | |
| 166 | 166 | }; |
| 167 | 167 | |
| 168 | 168 | pub const uid_t = switch (native_os) { |