| author | |
| committer | |
| log | 213ef953462341b44c52adc0696ab3fbc60e82b4 |
| tree | 2a2580d329b06c672beb8e0491e165c8e710c34d |
| parent | 2f372b3dc00c60a625e1cc3518fa1bda3429de59 |
see #66004 files changed, 51 insertions(+), 109 deletions(-)
lib/std/dynamic_library.zig+15-23| ... | @@ -148,7 +148,7 @@ const ElfDynLibError = error{ | ... | @@ -148,7 +148,7 @@ const ElfDynLibError = error{ |
| 148 | ElfHashTableNotFound, | 148 | ElfHashTableNotFound, |
| 149 | Canceled, | 149 | Canceled, |
| 150 | Streaming, | 150 | Streaming, |
| 151 | } || posix.OpenError || posix.MMapError; | 151 | } || Io.File.OpenError || posix.MMapError; |
| 152 | 152 | ||
| 153 | pub const ElfDynLib = struct { | 153 | pub const ElfDynLib = struct { |
| 154 | strings: [*:0]u8, | 154 | strings: [*:0]u8, |
| ... | @@ -177,27 +177,20 @@ pub const ElfDynLib = struct { | ... | @@ -177,27 +177,20 @@ pub const ElfDynLib = struct { |
| 177 | return parent; | 177 | return parent; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | fn resolveFromSearchPath(io: Io, search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t { | 180 | fn resolveFromSearchPath(io: Io, search_path: []const u8, file_name: []const u8, delim: u8) ?Io.File { |
| 181 | var paths = std.mem.tokenizeScalar(u8, search_path, delim); | 181 | var paths = std.mem.tokenizeScalar(u8, search_path, delim); |
| 182 | while (paths.next()) |p| { | 182 | while (paths.next()) |p| { |
| 183 | var dir = openPath(io, p) catch continue; | 183 | var dir = openPath(io, p) catch continue; |
| 184 | defer dir.close(io); | 184 | defer dir.close(io); |
| 185 | const fd = posix.openat(dir.handle, file_name, .{ | 185 | return dir.openFile(io, file_name, .{}) catch continue; |
| 186 | .ACCMODE = .RDONLY, | ||
| 187 | .CLOEXEC = true, | ||
| 188 | }, 0) catch continue; | ||
| 189 | return fd; | ||
| 190 | } | 186 | } |
| 191 | return null; | 187 | return null; |
| 192 | } | 188 | } |
| 193 | 189 | ||
| 194 | fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?posix.fd_t { | 190 | fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?Io.File { |
| 195 | var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch return null; | 191 | var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch return null; |
| 196 | defer dir.close(io); | 192 | defer dir.close(io); |
| 197 | return posix.openat(dir.handle, file_name, .{ | 193 | return dir.openFile(io, file_name, .{}) catch null; |
| 198 | .ACCMODE = .RDONLY, | ||
| 199 | .CLOEXEC = true, | ||
| 200 | }, 0) catch null; | ||
| 201 | } | 194 | } |
| 202 | 195 | ||
| 203 | // This implements enough to be able to load system libraries in general | 196 | // This implements enough to be able to load system libraries in general |
| ... | @@ -205,10 +198,10 @@ pub const ElfDynLib = struct { | ... | @@ -205,10 +198,10 @@ pub const ElfDynLib = struct { |
| 205 | // - DT_RPATH of the calling binary is not used as a search path | 198 | // - DT_RPATH of the calling binary is not used as a search path |
| 206 | // - DT_RUNPATH of the calling binary is not used as a search path | 199 | // - DT_RUNPATH of the calling binary is not used as a search path |
| 207 | // - /etc/ld.so.cache is not read | 200 | // - /etc/ld.so.cache is not read |
| 208 | fn resolveFromName(io: Io, path_or_name: []const u8, LD_LIBRARY_PATH: ?[]const u8) !posix.fd_t { | 201 | fn resolveFromName(io: Io, path_or_name: []const u8, LD_LIBRARY_PATH: ?[]const u8) !Io.File { |
| 209 | // If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname | 202 | // If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname |
| 210 | if (std.mem.findScalarPos(u8, path_or_name, 0, '/')) |_| { | 203 | if (std.mem.findScalarPos(u8, path_or_name, 0, '/')) |_| { |
| 211 | return posix.open(path_or_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); | 204 | return Io.Dir.cwd().openFile(io, path_or_name, .{}); |
| 212 | } | 205 | } |
| 213 | 206 | ||
| 214 | // Only read LD_LIBRARY_PATH if the binary is not setuid/setgid | 207 | // Only read LD_LIBRARY_PATH if the binary is not setuid/setgid |
| ... | @@ -216,15 +209,15 @@ pub const ElfDynLib = struct { | ... | @@ -216,15 +209,15 @@ pub const ElfDynLib = struct { |
| 216 | std.os.linux.getegid() == std.os.linux.getgid()) | 209 | std.os.linux.getegid() == std.os.linux.getgid()) |
| 217 | { | 210 | { |
| 218 | if (LD_LIBRARY_PATH) |ld_library_path| { | 211 | if (LD_LIBRARY_PATH) |ld_library_path| { |
| 219 | if (resolveFromSearchPath(io, ld_library_path, path_or_name, ':')) |fd| { | 212 | if (resolveFromSearchPath(io, ld_library_path, path_or_name, ':')) |file| { |
| 220 | return fd; | 213 | return file; |
| 221 | } | 214 | } |
| 222 | } | 215 | } |
| 223 | } | 216 | } |
| 224 | 217 | ||
| 225 | // Lastly the directories /lib and /usr/lib are searched (in this exact order) | 218 | // Lastly the directories /lib and /usr/lib are searched (in this exact order) |
| 226 | if (resolveFromParent(io, "/lib", path_or_name)) |fd| return fd; | 219 | if (resolveFromParent(io, "/lib", path_or_name)) |file| return file; |
| 227 | if (resolveFromParent(io, "/usr/lib", path_or_name)) |fd| return fd; | 220 | if (resolveFromParent(io, "/usr/lib", path_or_name)) |file| return file; |
| 228 | return error.FileNotFound; | 221 | return error.FileNotFound; |
| 229 | } | 222 | } |
| 230 | 223 | ||
| ... | @@ -232,10 +225,9 @@ pub const ElfDynLib = struct { | ... | @@ -232,10 +225,9 @@ pub const ElfDynLib = struct { |
| 232 | pub fn open(path: []const u8, LD_LIBRARY_PATH: ?[]const u8) Error!ElfDynLib { | 225 | pub fn open(path: []const u8, LD_LIBRARY_PATH: ?[]const u8) Error!ElfDynLib { |
| 233 | const io = std.Options.debug_io; | 226 | const io = std.Options.debug_io; |
| 234 | 227 | ||
| 235 | const fd = try resolveFromName(io, path, LD_LIBRARY_PATH); | 228 | const file = try resolveFromName(io, path, LD_LIBRARY_PATH); |
| 236 | defer posix.close(fd); | 229 | defer file.close(io); |
| 237 | 230 | ||
| 238 | const file: Io.File = .{ .handle = fd }; | ||
| 239 | const stat = try file.stat(io); | 231 | const stat = try file.stat(io); |
| 240 | const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig; | 232 | const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig; |
| 241 | 233 | ||
| ... | @@ -248,7 +240,7 @@ pub const ElfDynLib = struct { | ... | @@ -248,7 +240,7 @@ pub const ElfDynLib = struct { |
| 248 | mem.alignForward(usize, size, page_size), | 240 | mem.alignForward(usize, size, page_size), |
| 249 | posix.PROT.READ, | 241 | posix.PROT.READ, |
| 250 | .{ .TYPE = .PRIVATE }, | 242 | .{ .TYPE = .PRIVATE }, |
| 251 | fd, | 243 | file.handle, |
| 252 | 0, | 244 | 0, |
| 253 | ); | 245 | ); |
| 254 | defer posix.munmap(file_bytes); | 246 | defer posix.munmap(file_bytes); |
| ... | @@ -318,7 +310,7 @@ pub const ElfDynLib = struct { | ... | @@ -318,7 +310,7 @@ pub const ElfDynLib = struct { |
| 318 | extended_memsz, | 310 | extended_memsz, |
| 319 | prot, | 311 | prot, |
| 320 | .{ .TYPE = .PRIVATE, .FIXED = true }, | 312 | .{ .TYPE = .PRIVATE, .FIXED = true }, |
| 321 | fd, | 313 | file.handle, |
| 322 | ph.p_offset - extra_bytes, | 314 | ph.p_offset - extra_bytes, |
| 323 | ); | 315 | ); |
| 324 | } else { | 316 | } else { |
lib/std/os/linux/IoUring/test.zig+24-18| ... | @@ -932,6 +932,8 @@ test "accept/connect/recv/cancel" { | ... | @@ -932,6 +932,8 @@ test "accept/connect/recv/cancel" { |
| 932 | } | 932 | } |
| 933 | 933 | ||
| 934 | test "register_files_update" { | 934 | test "register_files_update" { |
| 935 | const io = testing.io; | ||
| 936 | |||
| 935 | var ring = IoUring.init(1, 0) catch |err| switch (err) { | 937 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 936 | error.SystemOutdated => return error.SkipZigTest, | 938 | error.SystemOutdated => return error.SkipZigTest, |
| 937 | error.PermissionDenied => return error.SkipZigTest, | 939 | error.PermissionDenied => return error.SkipZigTest, |
| ... | @@ -939,13 +941,13 @@ test "register_files_update" { | ... | @@ -939,13 +941,13 @@ test "register_files_update" { |
| 939 | }; | 941 | }; |
| 940 | defer ring.deinit(); | 942 | defer ring.deinit(); |
| 941 | 943 | ||
| 942 | const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); | 944 | const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); |
| 943 | defer posix.close(fd); | 945 | defer file.close(io); |
| 944 | 946 | ||
| 945 | var registered_fds = [_]linux.fd_t{0} ** 2; | 947 | var registered_fds = [_]linux.fd_t{0} ** 2; |
| 946 | const fd_index = 0; | 948 | const fd_index = 0; |
| 947 | const fd_index2 = 1; | 949 | const fd_index2 = 1; |
| 948 | registered_fds[fd_index] = fd; | 950 | registered_fds[fd_index] = file.handle; |
| 949 | registered_fds[fd_index2] = -1; | 951 | registered_fds[fd_index2] = -1; |
| 950 | 952 | ||
| 951 | ring.register_files(registered_fds[0..]) catch |err| switch (err) { | 953 | ring.register_files(registered_fds[0..]) catch |err| switch (err) { |
| ... | @@ -957,10 +959,10 @@ test "register_files_update" { | ... | @@ -957,10 +959,10 @@ test "register_files_update" { |
| 957 | // Test IORING_REGISTER_FILES_UPDATE | 959 | // Test IORING_REGISTER_FILES_UPDATE |
| 958 | // Only available since Linux 5.5 | 960 | // Only available since Linux 5.5 |
| 959 | 961 | ||
| 960 | const fd2 = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); | 962 | const file2 = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); |
| 961 | defer posix.close(fd2); | 963 | defer file2.close(io); |
| 962 | 964 | ||
| 963 | registered_fds[fd_index] = fd2; | 965 | registered_fds[fd_index] = file2.handle; |
| 964 | registered_fds[fd_index2] = -1; | 966 | registered_fds[fd_index2] = -1; |
| 965 | try ring.register_files_update(0, registered_fds[0..]); | 967 | try ring.register_files_update(0, registered_fds[0..]); |
| 966 | 968 | ||
| ... | @@ -1339,6 +1341,8 @@ test "linkat" { | ... | @@ -1339,6 +1341,8 @@ test "linkat" { |
| 1339 | } | 1341 | } |
| 1340 | 1342 | ||
| 1341 | test "provide_buffers: read" { | 1343 | test "provide_buffers: read" { |
| 1344 | const io = testing.io; | ||
| 1345 | |||
| 1342 | var ring = IoUring.init(1, 0) catch |err| switch (err) { | 1346 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 1343 | error.SystemOutdated => return error.SkipZigTest, | 1347 | error.SystemOutdated => return error.SkipZigTest, |
| 1344 | error.PermissionDenied => return error.SkipZigTest, | 1348 | error.PermissionDenied => return error.SkipZigTest, |
| ... | @@ -1346,8 +1350,8 @@ test "provide_buffers: read" { | ... | @@ -1346,8 +1350,8 @@ test "provide_buffers: read" { |
| 1346 | }; | 1350 | }; |
| 1347 | defer ring.deinit(); | 1351 | defer ring.deinit(); |
| 1348 | 1352 | ||
| 1349 | const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); | 1353 | const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); |
| 1350 | defer posix.close(fd); | 1354 | defer file.close(io); |
| 1351 | 1355 | ||
| 1352 | const group_id = 1337; | 1356 | const group_id = 1337; |
| 1353 | const buffer_id = 0; | 1357 | const buffer_id = 0; |
| ... | @@ -1380,9 +1384,9 @@ test "provide_buffers: read" { | ... | @@ -1380,9 +1384,9 @@ test "provide_buffers: read" { |
| 1380 | 1384 | ||
| 1381 | var i: usize = 0; | 1385 | var i: usize = 0; |
| 1382 | while (i < buffers.len) : (i += 1) { | 1386 | while (i < buffers.len) : (i += 1) { |
| 1383 | const sqe = try ring.read(0xdededede, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); | 1387 | const sqe = try ring.read(0xdededede, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); |
| 1384 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); | 1388 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 1385 | try testing.expectEqual(@as(i32, fd), sqe.fd); | 1389 | try testing.expectEqual(@as(i32, file.handle), sqe.fd); |
| 1386 | try testing.expectEqual(@as(u64, 0), sqe.addr); | 1390 | try testing.expectEqual(@as(u64, 0), sqe.addr); |
| 1387 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); | 1391 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); |
| 1388 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); | 1392 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); |
| ... | @@ -1406,9 +1410,9 @@ test "provide_buffers: read" { | ... | @@ -1406,9 +1410,9 @@ test "provide_buffers: read" { |
| 1406 | // This read should fail | 1410 | // This read should fail |
| 1407 | 1411 | ||
| 1408 | { | 1412 | { |
| 1409 | const sqe = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); | 1413 | const sqe = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); |
| 1410 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); | 1414 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 1411 | try testing.expectEqual(@as(i32, fd), sqe.fd); | 1415 | try testing.expectEqual(@as(i32, file.handle), sqe.fd); |
| 1412 | try testing.expectEqual(@as(u64, 0), sqe.addr); | 1416 | try testing.expectEqual(@as(u64, 0), sqe.addr); |
| 1413 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); | 1417 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); |
| 1414 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); | 1418 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); |
| ... | @@ -1445,9 +1449,9 @@ test "provide_buffers: read" { | ... | @@ -1445,9 +1449,9 @@ test "provide_buffers: read" { |
| 1445 | // Final read which should work | 1449 | // Final read which should work |
| 1446 | 1450 | ||
| 1447 | { | 1451 | { |
| 1448 | const sqe = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); | 1452 | const sqe = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); |
| 1449 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); | 1453 | try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); |
| 1450 | try testing.expectEqual(@as(i32, fd), sqe.fd); | 1454 | try testing.expectEqual(@as(i32, file.handle), sqe.fd); |
| 1451 | try testing.expectEqual(@as(u64, 0), sqe.addr); | 1455 | try testing.expectEqual(@as(u64, 0), sqe.addr); |
| 1452 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); | 1456 | try testing.expectEqual(@as(u32, buffer_len), sqe.len); |
| 1453 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); | 1457 | try testing.expectEqual(@as(u16, group_id), sqe.buf_index); |
| ... | @@ -1469,6 +1473,8 @@ test "provide_buffers: read" { | ... | @@ -1469,6 +1473,8 @@ test "provide_buffers: read" { |
| 1469 | } | 1473 | } |
| 1470 | 1474 | ||
| 1471 | test "remove_buffers" { | 1475 | test "remove_buffers" { |
| 1476 | const io = testing.io; | ||
| 1477 | |||
| 1472 | var ring = IoUring.init(1, 0) catch |err| switch (err) { | 1478 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 1473 | error.SystemOutdated => return error.SkipZigTest, | 1479 | error.SystemOutdated => return error.SkipZigTest, |
| 1474 | error.PermissionDenied => return error.SkipZigTest, | 1480 | error.PermissionDenied => return error.SkipZigTest, |
| ... | @@ -1476,8 +1482,8 @@ test "remove_buffers" { | ... | @@ -1476,8 +1482,8 @@ test "remove_buffers" { |
| 1476 | }; | 1482 | }; |
| 1477 | defer ring.deinit(); | 1483 | defer ring.deinit(); |
| 1478 | 1484 | ||
| 1479 | const fd = try posix.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); | 1485 | const file = try Io.Dir.openFileAbsolute(io, "/dev/zero", .{}); |
| 1480 | defer posix.close(fd); | 1486 | defer file.close(io); |
| 1481 | 1487 | ||
| 1482 | const group_id = 1337; | 1488 | const group_id = 1337; |
| 1483 | const buffer_id = 0; | 1489 | const buffer_id = 0; |
| ... | @@ -1522,7 +1528,7 @@ test "remove_buffers" { | ... | @@ -1522,7 +1528,7 @@ test "remove_buffers" { |
| 1522 | // This read should work | 1528 | // This read should work |
| 1523 | 1529 | ||
| 1524 | { | 1530 | { |
| 1525 | _ = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); | 1531 | _ = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); |
| 1526 | try testing.expectEqual(@as(u32, 1), try ring.submit()); | 1532 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| 1527 | 1533 | ||
| 1528 | const cqe = try ring.copy_cqe(); | 1534 | const cqe = try ring.copy_cqe(); |
| ... | @@ -1542,7 +1548,7 @@ test "remove_buffers" { | ... | @@ -1542,7 +1548,7 @@ test "remove_buffers" { |
| 1542 | // Final read should _not_ work | 1548 | // Final read should _not_ work |
| 1543 | 1549 | ||
| 1544 | { | 1550 | { |
| 1545 | _ = try ring.read(0xdfdfdfdf, fd, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); | 1551 | _ = try ring.read(0xdfdfdfdf, file.handle, .{ .buffer_selection = .{ .group_id = group_id, .len = buffer_len } }, 0); |
| 1546 | try testing.expectEqual(@as(u32, 1), try ring.submit()); | 1552 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| 1547 | 1553 | ||
| 1548 | const cqe = try ring.copy_cqe(); | 1554 | const cqe = try ring.copy_cqe(); |
lib/std/posix.zig-60| ... | @@ -448,66 +448,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -448,66 +448,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 448 | 448 | ||
| 449 | pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; | 449 | pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; |
| 450 | 450 | ||
| 451 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | ||
| 452 | /// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). | ||
| 453 | /// On WASI, `file_path` should be encoded as valid UTF-8. | ||
| 454 | /// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. | ||
| 455 | /// See also `openZ`. | ||
| 456 | pub fn open(file_path: []const u8, flags: O, perm: mode_t) OpenError!fd_t { | ||
| 457 | if (native_os == .windows) { | ||
| 458 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); | ||
| 459 | } else if (native_os == .wasi and !builtin.link_libc) { | ||
| 460 | return openat(AT.FDCWD, file_path, flags, perm); | ||
| 461 | } | ||
| 462 | const file_path_c = try toPosixPath(file_path); | ||
| 463 | return openZ(&file_path_c, flags, perm); | ||
| 464 | } | ||
| 465 | |||
| 466 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | ||
| 467 | /// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). | ||
| 468 | /// On WASI, `file_path` should be encoded as valid UTF-8. | ||
| 469 | /// On other platforms, `file_path` is an opaque sequence of bytes with no particular encoding. | ||
| 470 | /// See also `open`. | ||
| 471 | pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t { | ||
| 472 | if (native_os == .windows) { | ||
| 473 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); | ||
| 474 | } else if (native_os == .wasi and !builtin.link_libc) { | ||
| 475 | return open(mem.sliceTo(file_path, 0), flags, perm); | ||
| 476 | } | ||
| 477 | |||
| 478 | const open_sym = if (lfs64_abi) system.open64 else system.open; | ||
| 479 | while (true) { | ||
| 480 | const rc = open_sym(file_path, flags, perm); | ||
| 481 | switch (errno(rc)) { | ||
| 482 | .SUCCESS => return @intCast(rc), | ||
| 483 | .INTR => continue, | ||
| 484 | |||
| 485 | .FAULT => unreachable, | ||
| 486 | .INVAL => return error.BadPathName, | ||
| 487 | .ACCES => return error.AccessDenied, | ||
| 488 | .FBIG => return error.FileTooBig, | ||
| 489 | .OVERFLOW => return error.FileTooBig, | ||
| 490 | .ISDIR => return error.IsDir, | ||
| 491 | .LOOP => return error.SymLinkLoop, | ||
| 492 | .MFILE => return error.ProcessFdQuotaExceeded, | ||
| 493 | .NAMETOOLONG => return error.NameTooLong, | ||
| 494 | .NFILE => return error.SystemFdQuotaExceeded, | ||
| 495 | .NODEV => return error.NoDevice, | ||
| 496 | .NOENT => return error.FileNotFound, | ||
| 497 | // Can happen on Linux when opening procfs files. | ||
| 498 | .SRCH => return error.FileNotFound, | ||
| 499 | .NOMEM => return error.SystemResources, | ||
| 500 | .NOSPC => return error.NoSpaceLeft, | ||
| 501 | .NOTDIR => return error.NotDir, | ||
| 502 | .PERM => return error.PermissionDenied, | ||
| 503 | .EXIST => return error.PathAlreadyExists, | ||
| 504 | .BUSY => return error.DeviceBusy, | ||
| 505 | .ILSEQ => return error.BadPathName, | ||
| 506 | else => |err| return unexpectedErrno(err), | ||
| 507 | } | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 451 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 512 | /// `file_path` is relative to the open directory handle `dir_fd`. | 452 | /// `file_path` is relative to the open directory handle `dir_fd`. |
| 513 | /// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). | 453 | /// On Windows, `file_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). |
lib/std/posix/test.zig+12-8| ... | @@ -463,8 +463,12 @@ test "rename smoke test" { | ... | @@ -463,8 +463,12 @@ test "rename smoke test" { |
| 463 | // Create some file using `open`. | 463 | // Create some file using `open`. |
| 464 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); | 464 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); |
| 465 | defer gpa.free(file_path); | 465 | defer gpa.free(file_path); |
| 466 | const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); | 466 | const file = try Io.Dir.cwd().createFile(io, file_path, .{ |
| 467 | posix.close(fd); | 467 | .read = true, |
| 468 | .exclusive = true, | ||
| 469 | .permissions = .fromMode(mode), | ||
| 470 | }); | ||
| 471 | file.close(io); | ||
| 468 | 472 | ||
| 469 | // Rename the file | 473 | // Rename the file |
| 470 | const new_file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); | 474 | const new_file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); |
| ... | @@ -476,15 +480,15 @@ test "rename smoke test" { | ... | @@ -476,15 +480,15 @@ test "rename smoke test" { |
| 476 | // Try opening renamed file | 480 | // Try opening renamed file |
| 477 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); | 481 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); |
| 478 | defer gpa.free(file_path); | 482 | defer gpa.free(file_path); |
| 479 | const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR }, mode); | 483 | const file = try Io.Dir.cwd().openFile(io, file_path, .{ .mode = .read_write }); |
| 480 | posix.close(fd); | 484 | file.close(io); |
| 481 | } | 485 | } |
| 482 | 486 | ||
| 483 | { | 487 | { |
| 484 | // Try opening original file - should fail with error.FileNotFound | 488 | // Try opening original file - should fail with error.FileNotFound |
| 485 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); | 489 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); |
| 486 | defer gpa.free(file_path); | 490 | defer gpa.free(file_path); |
| 487 | try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode)); | 491 | try expectError(error.FileNotFound, Io.Dir.cwd().openFile(io, file_path, .{ .mode = .read_write })); |
| 488 | } | 492 | } |
| 489 | 493 | ||
| 490 | { | 494 | { |
| ... | @@ -503,15 +507,15 @@ test "rename smoke test" { | ... | @@ -503,15 +507,15 @@ test "rename smoke test" { |
| 503 | // Try opening renamed directory | 507 | // Try opening renamed directory |
| 504 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_dir" }); | 508 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_dir" }); |
| 505 | defer gpa.free(file_path); | 509 | defer gpa.free(file_path); |
| 506 | const fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode); | 510 | const dir = try Io.Dir.cwd().openDir(io, file_path, .{}); |
| 507 | posix.close(fd); | 511 | dir.close(io); |
| 508 | } | 512 | } |
| 509 | 513 | ||
| 510 | { | 514 | { |
| 511 | // Try opening original directory - should fail with error.FileNotFound | 515 | // Try opening original directory - should fail with error.FileNotFound |
| 512 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); | 516 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); |
| 513 | defer gpa.free(file_path); | 517 | defer gpa.free(file_path); |
| 514 | try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode)); | 518 | try expectError(error.FileNotFound, Io.Dir.cwd().openDir(io, file_path, .{})); |
| 515 | } | 519 | } |
| 516 | } | 520 | } |
| 517 | 521 |