| author | |
| committer | |
| log | 002d444964869a5fd4d588d45c46f3acfa16cf5d |
| tree | a92f8dcd1de9c85613a721d4f92f71f20bb520a4 |
| parent | 018e34271fe58e540dc46e8bca529ce399625bef |
4 files changed, 25 insertions(+), 9 deletions(-)
lib/std/Io/Dir.zig+6-1| ... | @@ -102,7 +102,12 @@ pub const Reader = struct { | ... | @@ -102,7 +102,12 @@ pub const Reader = struct { |
| 102 | end: usize, | 102 | end: usize, |
| 103 | 103 | ||
| 104 | /// A length for `buffer` that allows all implementations to function. | 104 | /// A length for `buffer` that allows all implementations to function. |
| 105 | pub const min_buffer_len = std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)); | 105 | pub const min_buffer_len = switch (native_os) { |
| 106 | .linux => @sizeOf(std.os.linux.dirent64) + | ||
| 107 | std.mem.alignForward(usize, max_name_bytes, @alignOf(std.os.linux.dirent64)), | ||
| 108 | .windows => std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)), | ||
| 109 | else => if (builtin.link_libc) @sizeOf(std.c.dirent) else std.mem.alignForward(usize, max_name_bytes, @alignOf(usize)), | ||
| 110 | }; | ||
| 106 | 111 | ||
| 107 | pub const State = enum { | 112 | pub const State = enum { |
| 108 | /// Indicates the next call to `read` should rewind and start over the | 113 | /// Indicates the next call to `read` should rewind and start over the |
lib/std/Io/Threaded.zig+14-3| ... | @@ -3399,7 +3399,10 @@ fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir | ... | @@ -3399,7 +3399,10 @@ fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir |
| 3399 | dr.state = .finished; | 3399 | dr.state = .finished; |
| 3400 | return 0; | 3400 | return 0; |
| 3401 | }, | 3401 | }, |
| 3402 | .INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net. | 3402 | // This can occur when reading /proc/$PID/net, or |
| 3403 | // if the provided buffer is too small. Neither | ||
| 3404 | // scenario is intended to be handled by this API. | ||
| 3405 | .INVAL => return error.Unexpected, | ||
| 3403 | .ACCES => return error.AccessDenied, // Lacking permission to iterate this directory. | 3406 | .ACCES => return error.AccessDenied, // Lacking permission to iterate this directory. |
| 3404 | else => |err| return posix.unexpectedErrno(err), | 3407 | else => |err| return posix.unexpectedErrno(err), |
| 3405 | } | 3408 | } |
| ... | @@ -3413,11 +3416,19 @@ fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir | ... | @@ -3413,11 +3416,19 @@ fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir |
| 3413 | dr.index = 0; | 3416 | dr.index = 0; |
| 3414 | dr.end = n; | 3417 | dr.end = n; |
| 3415 | } | 3418 | } |
| 3416 | const linux_entry: *align(1) linux.dirent64 = @ptrCast(&dr.buffer[dr.index]); | 3419 | // Linux aligns the header by padding after the null byte of the name |
| 3420 | // to align the next entry. This means we can find the end of the name | ||
| 3421 | // by looking at only the 8 bytes before the next record. However since | ||
| 3422 | // file names are usually short it's better to keep the machine code | ||
| 3423 | // simpler. | ||
| 3424 | const linux_entry: *linux.dirent64 = @ptrCast(@alignCast(&dr.buffer[dr.index])); | ||
| 3417 | const next_index = dr.index + linux_entry.reclen; | 3425 | const next_index = dr.index + linux_entry.reclen; |
| 3418 | dr.index = next_index; | 3426 | dr.index = next_index; |
| 3427 | const name_ptr: [*]u8 = &linux_entry.name; | ||
| 3428 | const padded_name = name_ptr[0 .. linux_entry.reclen - @offsetOf(linux.dirent64, "name")]; | ||
| 3429 | const name_len = std.mem.findScalar(u8, padded_name, 0).?; | ||
| 3430 | const name = name_ptr[0..name_len :0]; | ||
| 3419 | 3431 | ||
| 3420 | const name = std.mem.sliceTo(@as([*:0]u8, @ptrCast(&linux_entry.name)), 0); | ||
| 3421 | if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) continue; | 3432 | if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) continue; |
| 3422 | 3433 | ||
| 3423 | const entry_kind: File.Kind = switch (linux_entry.type) { | 3434 | const entry_kind: File.Kind = switch (linux_entry.type) { |
lib/std/fs/test.zig+4-4| ... | @@ -1418,12 +1418,12 @@ test "max file name component lengths" { | ... | @@ -1418,12 +1418,12 @@ test "max file name component lengths" { |
| 1418 | // On WASI, the maxed filename depends on the host OS, so in order for this test to | 1418 | // On WASI, the maxed filename depends on the host OS, so in order for this test to |
| 1419 | // work on any host, we need to use a length that will work for all platforms | 1419 | // work on any host, we need to use a length that will work for all platforms |
| 1420 | // (i.e. the minimum max_name_bytes of all supported platforms). | 1420 | // (i.e. the minimum max_name_bytes of all supported platforms). |
| 1421 | const maxed_wasi_filename1 = [_]u8{'1'} ** 255; | 1421 | const maxed_wasi_filename1: [255]u8 = @splat('1'); |
| 1422 | const maxed_wasi_filename2 = [_]u8{'2'} ** 255; | 1422 | const maxed_wasi_filename2: [255]u8 = @splat('2'); |
| 1423 | try testFilenameLimits(io, tmp.dir, &maxed_wasi_filename1, &maxed_wasi_filename2); | 1423 | try testFilenameLimits(io, tmp.dir, &maxed_wasi_filename1, &maxed_wasi_filename2); |
| 1424 | } else { | 1424 | } else { |
| 1425 | const maxed_ascii_filename1 = [_]u8{'1'} ** std.fs.max_name_bytes; | 1425 | const maxed_ascii_filename1: [Dir.max_name_bytes]u8 = @splat('1'); |
| 1426 | const maxed_ascii_filename2 = [_]u8{'2'} ** std.fs.max_name_bytes; | 1426 | const maxed_ascii_filename2: [Dir.max_name_bytes]u8 = @splat('2'); |
| 1427 | try testFilenameLimits(io, tmp.dir, &maxed_ascii_filename1, &maxed_ascii_filename2); | 1427 | try testFilenameLimits(io, tmp.dir, &maxed_ascii_filename1, &maxed_ascii_filename2); |
| 1428 | } | 1428 | } |
| 1429 | } | 1429 | } |
lib/std/os/linux.zig+1-1| ... | @@ -6040,7 +6040,7 @@ pub const dirent64 = extern struct { | ... | @@ -6040,7 +6040,7 @@ pub const dirent64 = extern struct { |
| 6040 | off: u64, | 6040 | off: u64, |
| 6041 | reclen: u16, | 6041 | reclen: u16, |
| 6042 | type: u8, | 6042 | type: u8, |
| 6043 | name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 | 6043 | name: [0]u8, |
| 6044 | }; | 6044 | }; |
| 6045 | 6045 | ||
| 6046 | pub const dl_phdr_info = extern struct { | 6046 | pub const dl_phdr_info = extern struct { |