| ... | @@ -1665,13 +1665,15 @@ pub const UnlinkError = error{ | ... | @@ -1665,13 +1665,15 @@ pub const UnlinkError = error{ |
| 1665 | /// Delete a name and possibly the file it refers to. | 1665 | /// Delete a name and possibly the file it refers to. |
| 1666 | /// See also `unlinkC`. | 1666 | /// See also `unlinkC`. |
| 1667 | pub fn unlink(file_path: []const u8) UnlinkError!void { | 1667 | pub fn unlink(file_path: []const u8) UnlinkError!void { |
| | 1668 | if (builtin.os.tag == .wasi) { |
| | 1669 | @compileError("unlink is not supported in WASI; use unlinkat instead"); |
| | 1670 | } |
| 1668 | if (builtin.os.tag == .windows) { | 1671 | if (builtin.os.tag == .windows) { |
| 1669 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 1672 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 1670 | return windows.DeleteFileW(file_path_w.span().ptr); | 1673 | return windows.DeleteFileW(file_path_w.span().ptr); |
| 1671 | } else { | | |
| 1672 | const file_path_c = try toPosixPath(file_path); | | |
| 1673 | return unlinkZ(&file_path_c); | | |
| 1674 | } | 1674 | } |
| | 1675 | const file_path_c = try toPosixPath(file_path); |
| | 1676 | return unlinkZ(&file_path_c); |
| 1675 | } | 1677 | } |
| 1676 | | 1678 | |
| 1677 | pub const unlinkC = @compileError("deprecated: renamed to unlinkZ"); | 1679 | pub const unlinkC = @compileError("deprecated: renamed to unlinkZ"); |
| ... | @@ -1722,6 +1724,8 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo | ... | @@ -1722,6 +1724,8 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo |
| 1722 | | 1724 | |
| 1723 | pub const unlinkatC = @compileError("deprecated: renamed to unlinkatZ"); | 1725 | pub const unlinkatC = @compileError("deprecated: renamed to unlinkatZ"); |
| 1724 | | 1726 | |
| | 1727 | /// WASI-only. Same as `unlinkat` but targeting WASI. |
| | 1728 | /// See also `unlinkat`. |
| 1725 | pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { | 1729 | pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { |
| 1726 | const remove_dir = (flags & AT_REMOVEDIR) != 0; | 1730 | const remove_dir = (flags & AT_REMOVEDIR) != 0; |
| 1727 | const res = if (remove_dir) | 1731 | const res = if (remove_dir) |
| ... | @@ -1868,15 +1872,17 @@ const RenameError = error{ | ... | @@ -1868,15 +1872,17 @@ const RenameError = error{ |
| 1868 | | 1872 | |
| 1869 | /// Change the name or location of a file. | 1873 | /// Change the name or location of a file. |
| 1870 | pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { | 1874 | pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { |
| | 1875 | if (builtin.os.tag == .wasi) { |
| | 1876 | @compileError("rename is not supported in WASI; use renameat instead"); |
| | 1877 | } |
| 1871 | if (builtin.os.tag == .windows) { | 1878 | if (builtin.os.tag == .windows) { |
| 1872 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); | 1879 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); |
| 1873 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); | 1880 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); |
| 1874 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); | 1881 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); |
| 1875 | } else { | | |
| 1876 | const old_path_c = try toPosixPath(old_path); | | |
| 1877 | const new_path_c = try toPosixPath(new_path); | | |
| 1878 | return renameZ(&old_path_c, &new_path_c); | | |
| 1879 | } | 1882 | } |
| | 1883 | const old_path_c = try toPosixPath(old_path); |
| | 1884 | const new_path_c = try toPosixPath(new_path); |
| | 1885 | return renameZ(&old_path_c, &new_path_c); |
| 1880 | } | 1886 | } |
| 1881 | | 1887 | |
| 1882 | pub const renameC = @compileError("deprecated: renamed to renameZ"); | 1888 | pub const renameC = @compileError("deprecated: renamed to renameZ"); |
| ... | @@ -1939,7 +1945,8 @@ pub fn renameat( | ... | @@ -1939,7 +1945,8 @@ pub fn renameat( |
| 1939 | } | 1945 | } |
| 1940 | } | 1946 | } |
| 1941 | | 1947 | |
| 1942 | /// Same as `renameat` expect only WASI. | 1948 | /// WASI-only. Same as `renameat` expect targeting WASI. |
| | 1949 | /// See also `renameat`. |
| 1943 | pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, new_path: []const u8) RenameError!void { | 1950 | pub fn renameatWasi(old_dir_fd: fd_t, old_path: []const u8, new_dir_fd: fd_t, new_path: []const u8) RenameError!void { |
| 1944 | switch (wasi.path_rename(old_dir_fd, old_path.ptr, old_path.len, new_dir_fd, new_path.ptr, new_path.len)) { | 1951 | switch (wasi.path_rename(old_dir_fd, old_path.ptr, old_path.len, new_dir_fd, new_path.ptr, new_path.len)) { |
| 1945 | wasi.ESUCCESS => return, | 1952 | wasi.ESUCCESS => return, |
| ... | @@ -2144,14 +2151,16 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirErro | ... | @@ -2144,14 +2151,16 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirErro |
| 2144 | /// Create a directory. | 2151 | /// Create a directory. |
| 2145 | /// `mode` is ignored on Windows. | 2152 | /// `mode` is ignored on Windows. |
| 2146 | pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { | 2153 | pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { |
| | 2154 | if (builtin.os.tag == .wasi) { |
| | 2155 | @compileError("mkdir is not supported in WASI; use mkdirat instead"); |
| | 2156 | } |
| 2147 | if (builtin.os.tag == .windows) { | 2157 | if (builtin.os.tag == .windows) { |
| 2148 | const sub_dir_handle = try windows.CreateDirectory(null, dir_path, null); | 2158 | const sub_dir_handle = try windows.CreateDirectory(null, dir_path, null); |
| 2149 | windows.CloseHandle(sub_dir_handle); | 2159 | windows.CloseHandle(sub_dir_handle); |
| 2150 | return; | 2160 | return; |
| 2151 | } else { | | |
| 2152 | const dir_path_c = try toPosixPath(dir_path); | | |
| 2153 | return mkdirZ(&dir_path_c, mode); | | |
| 2154 | } | 2161 | } |
| | 2162 | const dir_path_c = try toPosixPath(dir_path); |
| | 2163 | return mkdirZ(&dir_path_c, mode); |
| 2155 | } | 2164 | } |
| 2156 | | 2165 | |
| 2157 | /// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string. | 2166 | /// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string. |
| ... | @@ -2197,13 +2206,15 @@ pub const DeleteDirError = error{ | ... | @@ -2197,13 +2206,15 @@ pub const DeleteDirError = error{ |
| 2197 | | 2206 | |
| 2198 | /// Deletes an empty directory. | 2207 | /// Deletes an empty directory. |
| 2199 | pub fn rmdir(dir_path: []const u8) DeleteDirError!void { | 2208 | pub fn rmdir(dir_path: []const u8) DeleteDirError!void { |
| | 2209 | if (builtin.os.tag == .wasi) { |
| | 2210 | @compileError("rmdir is not supported in WASI; use unlinkat instead"); |
| | 2211 | } |
| 2200 | if (builtin.os.tag == .windows) { | 2212 | if (builtin.os.tag == .windows) { |
| 2201 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); | 2213 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); |
| 2202 | return windows.RemoveDirectoryW(dir_path_w.span().ptr); | 2214 | return windows.RemoveDirectoryW(dir_path_w.span().ptr); |
| 2203 | } else { | | |
| 2204 | const dir_path_c = try toPosixPath(dir_path); | | |
| 2205 | return rmdirZ(&dir_path_c); | | |
| 2206 | } | 2215 | } |
| | 2216 | const dir_path_c = try toPosixPath(dir_path); |
| | 2217 | return rmdirZ(&dir_path_c); |
| 2207 | } | 2218 | } |
| 2208 | | 2219 | |
| 2209 | pub const rmdirC = @compileError("deprecated: renamed to rmdirZ"); | 2220 | pub const rmdirC = @compileError("deprecated: renamed to rmdirZ"); |
| ... | @@ -2246,13 +2257,15 @@ pub const ChangeCurDirError = error{ | ... | @@ -2246,13 +2257,15 @@ pub const ChangeCurDirError = error{ |
| 2246 | /// Changes the current working directory of the calling process. | 2257 | /// Changes the current working directory of the calling process. |
| 2247 | /// `dir_path` is recommended to be a UTF-8 encoded string. | 2258 | /// `dir_path` is recommended to be a UTF-8 encoded string. |
| 2248 | pub fn chdir(dir_path: []const u8) ChangeCurDirError!void { | 2259 | pub fn chdir(dir_path: []const u8) ChangeCurDirError!void { |
| | 2260 | if (builtin.os.tag == .wasi) { |
| | 2261 | @compileError("chdir is not supported in WASI"); |
| | 2262 | } |
| 2249 | if (builtin.os.tag == .windows) { | 2263 | if (builtin.os.tag == .windows) { |
| 2250 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); | 2264 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); |
| 2251 | @compileError("TODO implement chdir for Windows"); | 2265 | @compileError("TODO implement chdir for Windows"); |
| 2252 | } else { | | |
| 2253 | const dir_path_c = try toPosixPath(dir_path); | | |
| 2254 | return chdirZ(&dir_path_c); | | |
| 2255 | } | 2266 | } |
| | 2267 | const dir_path_c = try toPosixPath(dir_path); |
| | 2268 | return chdirZ(&dir_path_c); |
| 2256 | } | 2269 | } |
| 2257 | | 2270 | |
| 2258 | pub const chdirC = @compileError("deprecated: renamed to chdirZ"); | 2271 | pub const chdirC = @compileError("deprecated: renamed to chdirZ"); |
| ... | @@ -2310,22 +2323,30 @@ pub const ReadLinkError = error{ | ... | @@ -2310,22 +2323,30 @@ pub const ReadLinkError = error{ |
| 2310 | /// Read value of a symbolic link. | 2323 | /// Read value of a symbolic link. |
| 2311 | /// The return value is a slice of `out_buffer` from index 0. | 2324 | /// The return value is a slice of `out_buffer` from index 0. |
| 2312 | pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2325 | pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| | 2326 | if (builtin.os.tag == .wasi) { |
| | 2327 | @compileError("readlink is not supported in WASI; use readlinkat instead"); |
| | 2328 | } |
| 2313 | if (builtin.os.tag == .windows) { | 2329 | if (builtin.os.tag == .windows) { |
| 2314 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 2330 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 2315 | @compileError("TODO implement readlink for Windows"); | 2331 | return readlinkW(file_path_w.span().ptr, out_buffer); |
| 2316 | } else { | | |
| 2317 | const file_path_c = try toPosixPath(file_path); | | |
| 2318 | return readlinkZ(&file_path_c, out_buffer); | | |
| 2319 | } | 2332 | } |
| | 2333 | const file_path_c = try toPosixPath(file_path); |
| | 2334 | return readlinkZ(&file_path_c, out_buffer); |
| 2320 | } | 2335 | } |
| 2321 | | 2336 | |
| 2322 | pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); | 2337 | pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); |
| 2323 | | 2338 | |
| | 2339 | /// Windows-only. Same as `readlink` expecte `file_path` is null-terminated, WTF16 encoded. |
| | 2340 | /// Seel also `readlinkZ`. |
| | 2341 | pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| | 2342 | @compileError("TODO implement readlink for Windows"); |
| | 2343 | } |
| | 2344 | |
| 2324 | /// Same as `readlink` except `file_path` is null-terminated. | 2345 | /// Same as `readlink` except `file_path` is null-terminated. |
| 2325 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2346 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2326 | if (builtin.os.tag == .windows) { | 2347 | if (builtin.os.tag == .windows) { |
| 2327 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 2348 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| 2328 | @compileError("TODO implement readlink for Windows"); | 2349 | return readlinkW(file_path_w.span().ptr, out_buffer); |
| 2329 | } | 2350 | } |
| 2330 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); | 2351 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); |
| 2331 | switch (errno(rc)) { | 2352 | switch (errno(rc)) { |
| ... | @@ -3055,6 +3076,7 @@ pub const FStatError = error{ | ... | @@ -3055,6 +3076,7 @@ pub const FStatError = error{ |
| 3055 | AccessDenied, | 3076 | AccessDenied, |
| 3056 | } || UnexpectedError; | 3077 | } || UnexpectedError; |
| 3057 | | 3078 | |
| | 3079 | /// Return information about a file descriptor. |
| 3058 | pub fn fstat(fd: fd_t) FStatError!Stat { | 3080 | pub fn fstat(fd: fd_t) FStatError!Stat { |
| 3059 | if (builtin.os.tag == .wasi) { | 3081 | if (builtin.os.tag == .wasi) { |
| 3060 | var stat: wasi.filestat_t = undefined; | 3082 | var stat: wasi.filestat_t = undefined; |
| ... | @@ -3081,13 +3103,39 @@ pub fn fstat(fd: fd_t) FStatError!Stat { | ... | @@ -3081,13 +3103,39 @@ pub fn fstat(fd: fd_t) FStatError!Stat { |
| 3081 | | 3103 | |
| 3082 | pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound }; | 3104 | pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound }; |
| 3083 | | 3105 | |
| | 3106 | /// Similar to `fstat`, but returns stat of a resource pointed to by `pathname` |
| | 3107 | /// which is relative to `dirfd` handle. |
| | 3108 | /// See also `fstatatZ` and `fstatatWasi`. |
| 3084 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { | 3109 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { |
| | 3110 | if (builtin.os.tag == .wasi) { |
| | 3111 | return fstatatWasi(dirfd, pathname, flags); |
| | 3112 | } |
| 3085 | const pathname_c = try toPosixPath(pathname); | 3113 | const pathname_c = try toPosixPath(pathname); |
| 3086 | return fstatatZ(dirfd, &pathname_c, flags); | 3114 | return fstatatZ(dirfd, &pathname_c, flags); |
| 3087 | } | 3115 | } |
| 3088 | | 3116 | |
| 3089 | pub const fstatatC = @compileError("deprecated: renamed to fstatatZ"); | 3117 | pub const fstatatC = @compileError("deprecated: renamed to fstatatZ"); |
| 3090 | | 3118 | |
| | 3119 | /// WASI-only. Same as `fstatat` but targeting WASI. |
| | 3120 | /// See also `fstatat`. |
| | 3121 | pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { |
| | 3122 | var stat: wasi.filestat_t = undefined; |
| | 3123 | switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) { |
| | 3124 | wasi.ESUCCESS => return Stat.fromFilestat(stat), |
| | 3125 | wasi.EINVAL => unreachable, |
| | 3126 | wasi.EBADF => unreachable, // Always a race condition. |
| | 3127 | wasi.ENOMEM => return error.SystemResources, |
| | 3128 | wasi.EACCES => return error.AccessDenied, |
| | 3129 | wasi.EFAULT => unreachable, |
| | 3130 | wasi.ENAMETOOLONG => return error.NameTooLong, |
| | 3131 | wasi.ENOENT => return error.FileNotFound, |
| | 3132 | wasi.ENOTDIR => return error.FileNotFound, |
| | 3133 | else => |err| return unexpectedErrno(err), |
| | 3134 | } |
| | 3135 | } |
| | 3136 | |
| | 3137 | /// Same as `fstatat` but `pathname` is null-terminated. |
| | 3138 | /// See also `fstatat`. |
| 3091 | pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { | 3139 | pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { |
| 3092 | var stat: Stat = undefined; | 3140 | var stat: Stat = undefined; |
| 3093 | switch (errno(system.fstatat(dirfd, pathname, &stat, flags))) { | 3141 | switch (errno(system.fstatat(dirfd, pathname, &stat, flags))) { |