Function nextLinux [src]
Implementation of next that can return error.DirNotFound if the directory being
iterated was deleted during iteration (this error is Linux specific).
Prototype
pub fn nextLinux(self: *Self) ErrorLinux!?Entry
Parameters
self: *Self
Possible Errors
WASI-only. The path of an entry could not be encoded as valid UTF-8. WASI is unable to handle paths that cannot be encoded as well-formed UTF-8. https://github.com/WebAssembly/wasi-filesystem/issues/17#issuecomment-1430639353
The Operating System returned an undocumented error code.
This error is in theory not possible, but it would be better to handle this error than to invoke undefined behavior.
When this error code is observed, it usually means the Zig Standard Library needs a small patch to add the error code to the error set for the respective function.
Source
pub fn nextLinux(self: *Self) ErrorLinux!?Entry {
start_over: while (true) {
if (self.index >= self.end_index) {
if (self.first_iter) {
posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = linux.getdents64(self.dir.fd, &self.buf, self.buf.len);
switch (linux.E.init(rc)) {
.SUCCESS => {},
.BADF => unreachable, // Dir is invalid or was opened without iteration ability
.FAULT => unreachable,
.NOTDIR => unreachable,
.NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration.
.INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net.
.ACCES => return error.AccessDenied, // Do not have permission to iterate this directory.
else => |err| return posix.unexpectedErrno(err),
}
if (rc == 0) return null;
self.index = 0;
self.end_index = rc;
}
const linux_entry = @as(*align(1) linux.dirent64, @ptrCast(&self.buf[self.index]));
const next_index = self.index + linux_entry.reclen;
self.index = next_index;
const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&linux_entry.name)), 0);
// skip . and .. entries
if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
continue :start_over;
}
const entry_kind: Entry.Kind = switch (linux_entry.type) {
linux.DT.BLK => .block_device,
linux.DT.CHR => .character_device,
linux.DT.DIR => .directory,
linux.DT.FIFO => .named_pipe,
linux.DT.LNK => .sym_link,
linux.DT.REG => .file,
linux.DT.SOCK => .unix_domain_socket,
else => .unknown,
};
return Entry{
.name = name,
.kind = entry_kind,
};
}
}