| ... | @@ -595,6 +595,19 @@ pub const IterableDir = struct { | ... | @@ -595,6 +595,19 @@ pub const IterableDir = struct { |
| 595 | /// Memory such as file names referenced in this returned entry becomes invalid | 595 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 596 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. | 596 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. |
| 597 | pub fn next(self: *Self) Error!?Entry { | 597 | pub fn next(self: *Self) Error!?Entry { |
| | 598 | return self.nextLinux() catch |err| switch (err) { |
| | 599 | // To be consistent across platforms, iteration ends if the directory being iterated is deleted during iteration. |
| | 600 | // This matches the behavior of non-Linux UNIX platforms. |
| | 601 | error.DirNotFound => null, |
| | 602 | else => |e| return e, |
| | 603 | }; |
| | 604 | } |
| | 605 | |
| | 606 | pub const ErrorLinux = error{DirNotFound} || IteratorError; |
| | 607 | |
| | 608 | /// Implementation of `next` that can return `error.DirNotFound` if the directory being |
| | 609 | /// iterated was deleted during iteration (this error is Linux specific). |
| | 610 | pub fn nextLinux(self: *Self) ErrorLinux!?Entry { |
| 598 | start_over: while (true) { | 611 | start_over: while (true) { |
| 599 | if (self.index >= self.end_index) { | 612 | if (self.index >= self.end_index) { |
| 600 | if (self.first_iter) { | 613 | if (self.first_iter) { |
| ... | @@ -607,7 +620,7 @@ pub const IterableDir = struct { | ... | @@ -607,7 +620,7 @@ pub const IterableDir = struct { |
| 607 | .BADF => unreachable, // Dir is invalid or was opened without iteration ability | 620 | .BADF => unreachable, // Dir is invalid or was opened without iteration ability |
| 608 | .FAULT => unreachable, | 621 | .FAULT => unreachable, |
| 609 | .NOTDIR => unreachable, | 622 | .NOTDIR => unreachable, |
| 610 | .NOENT => return null, // The directory being iterated was deleted during iteration. | 623 | .NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration. |
| 611 | .INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net. | 624 | .INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net. |
| 612 | else => |err| return os.unexpectedErrno(err), | 625 | else => |err| return os.unexpectedErrno(err), |
| 613 | } | 626 | } |
| ... | @@ -729,6 +742,20 @@ pub const IterableDir = struct { | ... | @@ -729,6 +742,20 @@ pub const IterableDir = struct { |
| 729 | /// Memory such as file names referenced in this returned entry becomes invalid | 742 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 730 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. | 743 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. |
| 731 | pub fn next(self: *Self) Error!?Entry { | 744 | pub fn next(self: *Self) Error!?Entry { |
| | 745 | return self.nextWasi() catch |err| switch (err) { |
| | 746 | // To be consistent across platforms, iteration ends if the directory being iterated is deleted during iteration. |
| | 747 | // This matches the behavior of non-Linux UNIX platforms. |
| | 748 | error.DirNotFound => null, |
| | 749 | else => |e| return e, |
| | 750 | }; |
| | 751 | } |
| | 752 | |
| | 753 | pub const ErrorWasi = error{DirNotFound} || IteratorError; |
| | 754 | |
| | 755 | /// Implementation of `next` that can return platform-dependent errors depending on the host platform. |
| | 756 | /// When the host platform is Linux, `error.DirNotFound` can be returned if the directory being |
| | 757 | /// iterated was deleted during iteration. |
| | 758 | pub fn nextWasi(self: *Self) ErrorWasi!?Entry { |
| 732 | // We intentinally use fd_readdir even when linked with libc, | 759 | // We intentinally use fd_readdir even when linked with libc, |
| 733 | // since its implementation is exactly the same as below, | 760 | // since its implementation is exactly the same as below, |
| 734 | // and we avoid the code complexity here. | 761 | // and we avoid the code complexity here. |
| ... | @@ -742,7 +769,7 @@ pub const IterableDir = struct { | ... | @@ -742,7 +769,7 @@ pub const IterableDir = struct { |
| 742 | .FAULT => unreachable, | 769 | .FAULT => unreachable, |
| 743 | .NOTDIR => unreachable, | 770 | .NOTDIR => unreachable, |
| 744 | .INVAL => unreachable, | 771 | .INVAL => unreachable, |
| 745 | .NOENT => return null, // The directory being iterated was deleted during iteration. | 772 | .NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration. |
| 746 | .NOTCAPABLE => return error.AccessDenied, | 773 | .NOTCAPABLE => return error.AccessDenied, |
| 747 | else => |err| return os.unexpectedErrno(err), | 774 | else => |err| return os.unexpectedErrno(err), |
| 748 | } | 775 | } |