| ... | @@ -37,6 +37,8 @@ pub const MAX_PATH_BYTES = switch (builtin.os) { | ... | @@ -37,6 +37,8 @@ pub const MAX_PATH_BYTES = switch (builtin.os) { |
| 37 | else => @compileError("Unsupported OS"), | 37 | else => @compileError("Unsupported OS"), |
| 38 | }; | 38 | }; |
| 39 | | 39 | |
| | 40 | pub const MAX_BUF_BYTES: usize = 8192; |
| | 41 | |
| 40 | // here we replace the standard +/ with -_ so that it can be used in a file name | 42 | // here we replace the standard +/ with -_ so that it can be used in a file name |
| 41 | const b64_fs_encoder = base64.Base64Encoder.init("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", base64.standard_pad_char); | 43 | const b64_fs_encoder = base64.Base64Encoder.init("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", base64.standard_pad_char); |
| 42 | | 44 | |
| ... | @@ -371,7 +373,7 @@ const DeleteTreeError = error{ | ... | @@ -371,7 +373,7 @@ const DeleteTreeError = error{ |
| 371 | /// this function recursively removes its entries and then tries again. | 373 | /// this function recursively removes its entries and then tries again. |
| 372 | /// TODO determine if we can remove the allocator requirement | 374 | /// TODO determine if we can remove the allocator requirement |
| 373 | /// https://github.com/ziglang/zig/issues/2886 | 375 | /// https://github.com/ziglang/zig/issues/2886 |
| 374 | pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!void { | 376 | pub fn deleteTree(full_path: []const u8) DeleteTreeError!void { |
| 375 | start_over: while (true) { | 377 | start_over: while (true) { |
| 376 | var got_access_denied = false; | 378 | var got_access_denied = false; |
| 377 | // First, try deleting the item as a file. This way we don't follow sym links. | 379 | // First, try deleting the item as a file. This way we don't follow sym links. |
| ... | @@ -395,7 +397,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -395,7 +397,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 395 | => return err, | 397 | => return err, |
| 396 | } | 398 | } |
| 397 | { | 399 | { |
| 398 | var dir = Dir.open(allocator, full_path) catch |err| switch (err) { | 400 | var dir = Dir.open(full_path) catch |err| switch (err) { |
| 399 | error.NotDir => { | 401 | error.NotDir => { |
| 400 | if (got_access_denied) { | 402 | if (got_access_denied) { |
| 401 | return error.AccessDenied; | 403 | return error.AccessDenied; |
| ... | @@ -424,17 +426,14 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -424,17 +426,14 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 424 | }; | 426 | }; |
| 425 | defer dir.close(); | 427 | defer dir.close(); |
| 426 | | 428 | |
| 427 | var full_entry_buf = std.ArrayList(u8).init(allocator); | | |
| 428 | defer full_entry_buf.deinit(); | | |
| 429 | | | |
| 430 | while (try dir.next()) |entry| { | 429 | while (try dir.next()) |entry| { |
| 431 | try full_entry_buf.resize(full_path.len + entry.name.len + 1); | 430 | var full_entry_buf: [MAX_BUF_BYTES]u8 = undefined; |
| 432 | const full_entry_path = full_entry_buf.toSlice(); | 431 | const full_entry_path = full_entry_buf[0..]; |
| 433 | mem.copy(u8, full_entry_path, full_path); | 432 | mem.copy(u8, full_entry_path, full_path); |
| 434 | full_entry_path[full_path.len] = path.sep; | 433 | full_entry_path[full_path.len] = path.sep; |
| 435 | mem.copy(u8, full_entry_path[full_path.len + 1 ..], entry.name); | 434 | mem.copy(u8, full_entry_path[full_path.len + 1 ..], entry.name); |
| 436 | | 435 | |
| 437 | try deleteTree(allocator, full_entry_path); | 436 | try deleteTree(full_entry_path[0..full_path.len + entry.name.len + 1]); |
| 438 | } | 437 | } |
| 439 | } | 438 | } |
| 440 | return deleteDir(full_path); | 439 | return deleteDir(full_path); |
| ... | @@ -445,19 +444,18 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -445,19 +444,18 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 445 | /// files, and into the one that reads files from an open directory handle. | 444 | /// files, and into the one that reads files from an open directory handle. |
| 446 | pub const Dir = struct { | 445 | pub const Dir = struct { |
| 447 | handle: Handle, | 446 | handle: Handle, |
| 448 | allocator: *Allocator, | | |
| 449 | | 447 | |
| 450 | pub const Handle = switch (builtin.os) { | 448 | pub const Handle = switch (builtin.os) { |
| 451 | .macosx, .ios, .freebsd, .netbsd => struct { | 449 | .macosx, .ios, .freebsd, .netbsd => struct { |
| 452 | fd: i32, | 450 | fd: i32, |
| 453 | seek: i64, | 451 | seek: i64, |
| 454 | buf: []u8, | 452 | buf: [MAX_BUF_BYTES]u8, |
| 455 | index: usize, | 453 | index: usize, |
| 456 | end_index: usize, | 454 | end_index: usize, |
| 457 | }, | 455 | }, |
| 458 | .linux => struct { | 456 | .linux => struct { |
| 459 | fd: i32, | 457 | fd: i32, |
| 460 | buf: []u8, | 458 | buf: [MAX_BUF_BYTES]u8, |
| 461 | index: usize, | 459 | index: usize, |
| 462 | end_index: usize, | 460 | end_index: usize, |
| 463 | }, | 461 | }, |
| ... | @@ -512,9 +510,8 @@ pub const Dir = struct { | ... | @@ -512,9 +510,8 @@ pub const Dir = struct { |
| 512 | /// Call close when done. | 510 | /// Call close when done. |
| 513 | /// TODO remove the allocator requirement from this API | 511 | /// TODO remove the allocator requirement from this API |
| 514 | /// https://github.com/ziglang/zig/issues/2885 | 512 | /// https://github.com/ziglang/zig/issues/2885 |
| 515 | pub fn open(allocator: *Allocator, dir_path: []const u8) OpenError!Dir { | 513 | pub fn open(dir_path: []const u8) OpenError!Dir { |
| 516 | return Dir{ | 514 | return Dir{ |
| 517 | .allocator = allocator, | | |
| 518 | .handle = switch (builtin.os) { | 515 | .handle = switch (builtin.os) { |
| 519 | .windows => blk: { | 516 | .windows => blk: { |
| 520 | var find_file_data: os.windows.WIN32_FIND_DATAW = undefined; | 517 | var find_file_data: os.windows.WIN32_FIND_DATAW = undefined; |
| ... | @@ -548,7 +545,6 @@ pub const Dir = struct { | ... | @@ -548,7 +545,6 @@ pub const Dir = struct { |
| 548 | if (os.windows.is_the_target) { | 545 | if (os.windows.is_the_target) { |
| 549 | return os.windows.FindClose(self.handle.handle); | 546 | return os.windows.FindClose(self.handle.handle); |
| 550 | } | 547 | } |
| 551 | self.allocator.free(self.handle.buf); | | |
| 552 | os.close(self.handle.fd); | 548 | os.close(self.handle.fd); |
| 553 | } | 549 | } |
| 554 | | 550 | |
| ... | @@ -579,14 +575,10 @@ pub const Dir = struct { | ... | @@ -579,14 +575,10 @@ pub const Dir = struct { |
| 579 | fn nextDarwin(self: *Dir) !?Entry { | 575 | fn nextDarwin(self: *Dir) !?Entry { |
| 580 | start_over: while (true) { | 576 | start_over: while (true) { |
| 581 | if (self.handle.index >= self.handle.end_index) { | 577 | if (self.handle.index >= self.handle.end_index) { |
| 582 | if (self.handle.buf.len == 0) { | | |
| 583 | self.handle.buf = try self.allocator.alloc(u8, mem.page_size); | | |
| 584 | } | | |
| 585 | | | |
| 586 | while (true) { | 578 | while (true) { |
| 587 | const rc = os.system.__getdirentries64( | 579 | const rc = os.system.__getdirentries64( |
| 588 | self.handle.fd, | 580 | self.handle.fd, |
| 589 | self.handle.buf.ptr, | 581 | self.handle.buf[0..].ptr, |
| 590 | self.handle.buf.len, | 582 | self.handle.buf.len, |
| 591 | &self.handle.seek, | 583 | &self.handle.seek, |
| 592 | ); | 584 | ); |
| ... | @@ -596,10 +588,7 @@ pub const Dir = struct { | ... | @@ -596,10 +588,7 @@ pub const Dir = struct { |
| 596 | os.EBADF => unreachable, | 588 | os.EBADF => unreachable, |
| 597 | os.EFAULT => unreachable, | 589 | os.EFAULT => unreachable, |
| 598 | os.ENOTDIR => unreachable, | 590 | os.ENOTDIR => unreachable, |
| 599 | os.EINVAL => { | 591 | os.EINVAL => unreachable, |
| 600 | self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2); | | |
| 601 | continue; | | |
| 602 | }, | | |
| 603 | else => |err| return os.unexpectedErrno(err), | 592 | else => |err| return os.unexpectedErrno(err), |
| 604 | } | 593 | } |
| 605 | } | 594 | } |
| ... | @@ -666,21 +655,14 @@ pub const Dir = struct { | ... | @@ -666,21 +655,14 @@ pub const Dir = struct { |
| 666 | fn nextLinux(self: *Dir) !?Entry { | 655 | fn nextLinux(self: *Dir) !?Entry { |
| 667 | start_over: while (true) { | 656 | start_over: while (true) { |
| 668 | if (self.handle.index >= self.handle.end_index) { | 657 | if (self.handle.index >= self.handle.end_index) { |
| 669 | if (self.handle.buf.len == 0) { | | |
| 670 | self.handle.buf = try self.allocator.alloc(u8, mem.page_size); | | |
| 671 | } | | |
| 672 | | | |
| 673 | while (true) { | 658 | while (true) { |
| 674 | const rc = os.linux.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len); | 659 | const rc = os.linux.getdents64(self.handle.fd, self.handle.buf[0..].ptr, self.handle.buf.len); |
| 675 | switch (os.linux.getErrno(rc)) { | 660 | switch (os.linux.getErrno(rc)) { |
| 676 | 0 => {}, | 661 | 0 => {}, |
| 677 | os.EBADF => unreachable, | 662 | os.EBADF => unreachable, |
| 678 | os.EFAULT => unreachable, | 663 | os.EFAULT => unreachable, |
| 679 | os.ENOTDIR => unreachable, | 664 | os.ENOTDIR => unreachable, |
| 680 | os.EINVAL => { | 665 | os.EINVAL => unreachable, |
| 681 | self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2); | | |
| 682 | continue; | | |
| 683 | }, | | |
| 684 | else => |err| return os.unexpectedErrno(err), | 666 | else => |err| return os.unexpectedErrno(err), |
| 685 | } | 667 | } |
| 686 | if (rc == 0) return null; | 668 | if (rc == 0) return null; |
| ... | @@ -720,14 +702,10 @@ pub const Dir = struct { | ... | @@ -720,14 +702,10 @@ pub const Dir = struct { |
| 720 | fn nextBsd(self: *Dir) !?Entry { | 702 | fn nextBsd(self: *Dir) !?Entry { |
| 721 | start_over: while (true) { | 703 | start_over: while (true) { |
| 722 | if (self.handle.index >= self.handle.end_index) { | 704 | if (self.handle.index >= self.handle.end_index) { |
| 723 | if (self.handle.buf.len == 0) { | | |
| 724 | self.handle.buf = try self.allocator.alloc(u8, mem.page_size); | | |
| 725 | } | | |
| 726 | | | |
| 727 | while (true) { | 705 | while (true) { |
| 728 | const rc = os.system.getdirentries( | 706 | const rc = os.system.getdirentries( |
| 729 | self.handle.fd, | 707 | self.handle.fd, |
| 730 | self.handle.buf.ptr, | 708 | self.handle.buf[0..].ptr, |
| 731 | self.handle.buf.len, | 709 | self.handle.buf.len, |
| 732 | &self.handle.seek, | 710 | &self.handle.seek, |
| 733 | ); | 711 | ); |
| ... | @@ -736,10 +714,7 @@ pub const Dir = struct { | ... | @@ -736,10 +714,7 @@ pub const Dir = struct { |
| 736 | os.EBADF => unreachable, | 714 | os.EBADF => unreachable, |
| 737 | os.EFAULT => unreachable, | 715 | os.EFAULT => unreachable, |
| 738 | os.ENOTDIR => unreachable, | 716 | os.ENOTDIR => unreachable, |
| 739 | os.EINVAL => { | 717 | os.EINVAL => unreachable, |
| 740 | self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2); | | |
| 741 | continue; | | |
| 742 | }, | | |
| 743 | else => |err| return os.unexpectedErrno(err), | 718 | else => |err| return os.unexpectedErrno(err), |
| 744 | } | 719 | } |
| 745 | if (rc == 0) return null; | 720 | if (rc == 0) return null; |
| ... | @@ -807,7 +782,7 @@ pub const Walker = struct { | ... | @@ -807,7 +782,7 @@ pub const Walker = struct { |
| 807 | try self.name_buffer.append(base.name); | 782 | try self.name_buffer.append(base.name); |
| 808 | if (base.kind == .Directory) { | 783 | if (base.kind == .Directory) { |
| 809 | // TODO https://github.com/ziglang/zig/issues/2888 | 784 | // TODO https://github.com/ziglang/zig/issues/2888 |
| 810 | var new_dir = try Dir.open(self.stack.allocator, self.name_buffer.toSliceConst()); | 785 | var new_dir = try Dir.open(self.name_buffer.toSliceConst()); |
| 811 | { | 786 | { |
| 812 | errdefer new_dir.close(); | 787 | errdefer new_dir.close(); |
| 813 | try self.stack.append(StackItem{ | 788 | try self.stack.append(StackItem{ |
| ... | @@ -841,7 +816,7 @@ pub const Walker = struct { | ... | @@ -841,7 +816,7 @@ pub const Walker = struct { |
| 841 | pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker { | 816 | pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker { |
| 842 | assert(!mem.endsWith(u8, dir_path, path.sep_str)); | 817 | assert(!mem.endsWith(u8, dir_path, path.sep_str)); |
| 843 | | 818 | |
| 844 | var dir_it = try Dir.open(allocator, dir_path); | 819 | var dir_it = try Dir.open(dir_path); |
| 845 | errdefer dir_it.close(); | 820 | errdefer dir_it.close(); |
| 846 | | 821 | |
| 847 | var name_buffer = try std.Buffer.init(allocator, dir_path); | 822 | var name_buffer = try std.Buffer.init(allocator, dir_path); |