this repo has no description
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

ring: add statx

+208
+64
src/Kqueue.zig
··· 358 358 task.result = .{ .socket = error.Unexpected }; 359 359 }, 360 360 361 + .statx => |*req| { 362 + self.synchronous_queue.push(task); 363 + 364 + if (posix.fstatat(posix.AT.FDCWD, req.path, 0)) |stat| { 365 + req.result.* = .{ 366 + .mask = 0, 367 + .blksize = @intCast(stat.blksize), 368 + .attributes = 0, 369 + .nlink = @intCast(stat.nlink), 370 + .uid = @intCast(stat.uid), 371 + .gid = @intCast(stat.gid), 372 + .mode = @intCast(stat.mode), 373 + .__pad1 = 0, 374 + .ino = @intCast(stat.ino), 375 + .size = @intCast(stat.size), 376 + .blocks = @intCast(stat.blocks), 377 + .attributes_mask = 0, 378 + .atime = .{ 379 + .sec = @intCast(stat.atime().sec), 380 + .nsec = @intCast(stat.atime().nsec), 381 + }, 382 + .btime = .{ 383 + .sec = 0, 384 + .nsec = 0, 385 + }, 386 + .ctime = .{ 387 + .sec = @intCast(stat.ctime().sec), 388 + .nsec = @intCast(stat.ctime().nsec), 389 + }, 390 + .mtime = .{ 391 + .sec = @intCast(stat.mtime().sec), 392 + .nsec = @intCast(stat.mtime().nsec), 393 + }, 394 + .rdev_major = major(@intCast(stat.rdev)), 395 + .rdev_minor = minor(@intCast(stat.rdev)), 396 + .dev_major = major(@intCast(stat.dev)), 397 + .dev_minor = major(@intCast(stat.dev)), 398 + .__pad2 = undefined, 399 + }; 400 + } else |_| task.result = .{ .statx = error.Unexpected }; 401 + }, 402 + 361 403 .timer => { 362 404 const now = std.time.milliTimestamp(); 363 405 try self.addTimer(.{ .timeout = .{ .task = task, .added_ms = now } }); ··· 392 434 .msg_ring, 393 435 .noop, 394 436 .socket, 437 + .statx, 395 438 .userfd, 396 439 .usermsg, 397 440 .userptr, ··· 624 667 .msg_ring, 625 668 .noop, 626 669 .socket, 670 + .statx, 627 671 .userfd, 628 672 .usermsg, 629 673 .userptr, ··· 658 702 .poll => .{ .poll = error.Canceled }, 659 703 .recv => .{ .recv = error.Canceled }, 660 704 .socket => .{ .socket = error.Canceled }, 705 + .statx => .{ .statx = error.Canceled }, 661 706 .timer => .{ .timer = error.Canceled }, 662 707 .userfd, .usermsg, .userptr => unreachable, 663 708 .write => .{ .write = error.Canceled }, ··· 696 741 .msg_ring, 697 742 .noop, 698 743 .socket, 744 + .statx, 699 745 .timer, 700 746 .userfd, 701 747 .usermsg, ··· 823 869 }, 824 870 } 825 871 } 872 + fn major(dev: u64) u32 { 873 + return switch (@import("builtin").target.os.tag) { 874 + .macos, .visionos, .tvos, .ios, .watchos => @intCast((dev >> 24) & 0xff), 875 + .freebsd, .openbsd, .netbsd, .dragonfly => @intCast((dev >> 8) & 0xff), 876 + else => @compileError("unsupported OS for major()"), 877 + }; 878 + } 879 + 880 + fn minor(dev: u64) u32 { 881 + return switch (@import("builtin").target.os.tag) { 882 + .macos, .ios, .visionos, .tvos, .watchos => @intCast(dev & 0xffffff), 883 + .openbsd => @intCast(dev & 0xff), 884 + .freebsd => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 885 + .dragonfly => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 886 + .netbsd => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 887 + else => @compileError("unsupported OS for minor()"), 888 + }; 889 + }
+2
src/Mock.zig
··· 21 21 poll_cb: ?*const fn (*io.Task) io.Result = null, 22 22 recv_cb: ?*const fn (*io.Task) io.Result = null, 23 23 socket_cb: ?*const fn (*io.Task) io.Result = null, 24 + statx_cb: ?*const fn (*io.Task) io.Result = null, 24 25 timer_cb: ?*const fn (*io.Task) io.Result = null, 25 26 write_cb: ?*const fn (*io.Task) io.Result = null, 26 27 writev_cb: ?*const fn (*io.Task) io.Result = null, ··· 70 71 .poll => if (self.poll_cb) |cb| cb(task) else return error.NoMockCallback, 71 72 .recv => if (self.recv_cb) |cb| cb(task) else return error.NoMockCallback, 72 73 .socket => if (self.socket_cb) |cb| cb(task) else return error.NoMockCallback, 74 + .statx => if (self.statx_cb) |cb| cb(task) else return error.NoMockCallback, 73 75 .timer => if (self.timer_cb) |cb| cb(task) else return error.NoMockCallback, 74 76 .userfd => if (self.userfd_cb) |cb| cb(task) else return error.NoMockCallback, 75 77 .usermsg => if (self.usermsg_cb) |cb| cb(task) else return error.NoMockCallback,
+14
src/Uring.zig
··· 218 218 self.prepDeadline(task, sqe); 219 219 }, 220 220 221 + .statx => |*req| { 222 + const sqe = self.getSqe(); 223 + sqe.prep_statx(linux.AT.FDCWD, req.path, 0, linux.STATX_BASIC_STATS, @ptrCast(req.result)); 224 + sqe.user_data = @intFromPtr(task); 225 + self.prepDeadline(task, sqe); 226 + }, 227 + 221 228 // user* is only sent internally between rings and higher level wrappers 222 229 .userfd, .usermsg, .userptr => unreachable, 223 230 } ··· 335 342 336 343 .connect => .{ .connect = switch (cqeToE(cqe.res)) { 337 344 .SUCCESS => {}, 345 + .INVAL => io.ResultError.Invalid, 346 + .CANCELED => io.ResultError.Canceled, 347 + else => |e| unexpectedError(e), 348 + } }, 349 + 350 + .statx => |req| .{ .statx = switch (cqeToE(cqe.res)) { 351 + .SUCCESS => req.result, 338 352 .INVAL => io.ResultError.Invalid, 339 353 .CANCELED => io.ResultError.Canceled, 340 354 else => |e| unexpectedError(e),
+128
src/main.zig
··· 395 395 return task; 396 396 } 397 397 398 + pub fn stat( 399 + self: *Ring, 400 + path: [:0]const u8, 401 + result: *Statx, 402 + ctx: Context, 403 + ) Allocator.Error!*Task { 404 + const task = try self.getTask(); 405 + task.* = .{ 406 + .userdata = ctx.ptr, 407 + .msg = ctx.msg, 408 + .callback = ctx.cb, 409 + .req = .{ .statx = .{ .path = path, .result = result } }, 410 + }; 411 + 412 + self.submission_q.push(task); 413 + return task; 414 + } 415 + 398 416 /// Spawns a thread with a Ring instance. The thread will be idle and waiting to receive work 399 417 /// via msgRing when this function returns. Call kill on the returned thread to signal it to 400 418 /// shutdown. ··· 474 492 poll, 475 493 socket, 476 494 connect, 495 + statx, 477 496 478 497 /// userfd is meant to send file descriptors between Ring instances (using msgRing) 479 498 userfd, ··· 523 542 addr: *posix.sockaddr, 524 543 addr_len: posix.socklen_t, 525 544 }, 545 + statx: struct { 546 + path: [:0]const u8, 547 + result: *Statx, // this will be filled in by the op 548 + }, 526 549 527 550 userfd, 528 551 usermsg, ··· 543 566 poll: ResultError!void, 544 567 socket: ResultError!posix.fd_t, 545 568 connect: ResultError!void, 569 + statx: ResultError!*Statx, 546 570 547 571 userfd: anyerror!posix.fd_t, 548 572 usermsg: u16, ··· 591 615 } 592 616 }; 593 617 618 + /// Follows the ABI of linux statx. Not all platforms will contain all information, or may contain 619 + /// more information than requested 620 + pub const Statx = extern struct { 621 + /// Mask of bits indicating filled fields 622 + mask: u32, 623 + 624 + /// Block size for filesystem I/O 625 + blksize: u32, 626 + 627 + /// Extra file attribute indicators 628 + attributes: u64, 629 + 630 + /// Number of hard links 631 + nlink: u32, 632 + 633 + /// User ID of owner 634 + uid: posix.uid_t, 635 + 636 + /// Group ID of owner 637 + gid: posix.gid_t, 638 + 639 + /// File type and mode 640 + mode: u16, 641 + __pad1: u16, 642 + 643 + /// Inode number 644 + ino: u64, 645 + 646 + /// Total size in bytes 647 + size: u64, 648 + 649 + /// Number of 512B blocks allocated 650 + blocks: u64, 651 + 652 + /// Mask to show what's supported in `attributes`. 653 + attributes_mask: u64, 654 + 655 + /// Last access file timestamp 656 + atime: Timestamp, 657 + 658 + /// Creation file timestamp 659 + btime: Timestamp, 660 + 661 + /// Last status change file timestamp 662 + ctime: Timestamp, 663 + 664 + /// Last modification file timestamp 665 + mtime: Timestamp, 666 + 667 + /// Major ID, if this file represents a device. 668 + rdev_major: u32, 669 + 670 + /// Minor ID, if this file represents a device. 671 + rdev_minor: u32, 672 + 673 + /// Major ID of the device containing the filesystem where this file resides. 674 + dev_major: u32, 675 + 676 + /// Minor ID of the device containing the filesystem where this file resides. 677 + dev_minor: u32, 678 + 679 + __pad2: [14]u64, 680 + 681 + pub const Timestamp = extern struct { 682 + sec: i64, 683 + nsec: u32, 684 + __pad: u32 = 0, 685 + }; 686 + 687 + pub fn major(dev: u64) u32 { 688 + return switch (@import("builtin").target.os.tag) { 689 + .macos, .visionos, .tvos, .ios, .watchos => @intCast((dev >> 24) & 0xff), 690 + .freebsd, .openbsd, .netbsd, .dragonfly => @intCast((dev >> 8) & 0xff), 691 + else => @compileError("unsupported OS for major()"), 692 + }; 693 + } 694 + 695 + pub fn minor(dev: u64) u32 { 696 + return switch (@import("builtin").target.os.tag) { 697 + .macos, .ios, .visionos, .tvos, .watchos => @intCast(dev & 0xffffff), 698 + .openbsd => @intCast(dev & 0xff), 699 + .freebsd => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 700 + .dragonfly => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 701 + .netbsd => @intCast((dev & 0xff) | ((dev >> 12) & 0xfff00)), 702 + else => @compileError("unsupported OS for minor()"), 703 + }; 704 + } 705 + }; 706 + 594 707 test "runtime: noop" { 595 708 var rt: io.Ring = try .init(std.testing.allocator, 16); 596 709 defer rt.deinit(); ··· 834 947 try std.testing.expect(foo.did_work); 835 948 try std.testing.expect(foo.kill); 836 949 } 950 + 951 + test "runtime: stat" { 952 + const gpa = std.testing.allocator; 953 + var rt = try io.Ring.init(gpa, 16); 954 + defer rt.deinit(); 955 + 956 + var foo: Foo = .{}; 957 + const ctx: Context = .{ .ptr = &foo, .cb = Foo.callback }; 958 + 959 + var statx: Statx = undefined; 960 + const task = try rt.stat("build.zig", &statx, ctx); 961 + 962 + try rt.run(.until_done); 963 + try std.testing.expect(task.result != null); 964 + }