From 0a4c945e48717b24fdb6416e47bbb2fa2a7372b4 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sat, 23 Aug 2025 08:06:17 +0200 Subject: add Fd type for requests This is not tested code, since there are no requests implemented yet using file descriptors. --- src/ancillary-data.zig | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.zig | 4 +++- src/wl/display.zig | 9 +++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/ancillary-data.zig (limited to 'src') diff --git a/src/ancillary-data.zig b/src/ancillary-data.zig new file mode 100644 index 0000000..0754720 --- /dev/null +++ b/src/ancillary-data.zig @@ -0,0 +1,65 @@ +const std = @import("std"); + +const ControlMessage = extern struct { + const Level = enum(u32) { + socket = std.posix.SOL.SOCKET, + }; + + // WARNING: this kind enum might be wrong for non-linux posix systems. + const Kind = enum(u32) { + rights = 1, + credentials = 2, + }; + + const Header = extern struct { + length: usize, + level: Level, + kind: Kind, + }; + + header: Header, + payload: union { + fd: [255]std.posix.fd_t, + }, + + pub fn alignment(length: usize) usize { + return (length + @sizeOf(usize) - 1) & ~(@sizeOf(usize) - 1); + } + + pub fn space(self: @This()) usize { + return self.alignment(self.length) + self.alignment(@sizeOf(Header)); + } + + pub fn from_fds(fds: []std.posix.fd_t) @This() { + var self: @This() = .{ + }; + + self.level = .socket; + self.kind = .rights; + self.length = self.alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t)); + + @memcpy(self.payload, fds); + } +}; + +pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t) !void { + var iobuf: [1]u8 = std.mem.zeroes([1]u8); + + const io = std.posix.iovec { + .base = &iobuf, + .len = iobuf.len, + }; + + var cmsg: ControlMessage = .from_fds(fds); + + const msghdr = std.posix.msghdr_const { + .name = null, + .namelen = 0, + .iov = &io, + .iolen = 1, + .control = &cmsg, + .controllen = cmsg.control_length(), + }; + + _ = try std.posix.sendmsg(socket, &msghdr, 0); +} diff --git a/src/types.zig b/src/types.zig index 2849af1..023f319 100644 --- a/src/types.zig +++ b/src/types.zig @@ -1,6 +1,8 @@ const std = @import("std"); -pub const Fd = struct { fd: std.posix.fd_t }; +pub const Fd = struct { + fd: std.posix.fd_t +}; pub const Fixed = struct { n: u24, diff --git a/src/wl/display.zig b/src/wl/display.zig index db5ed3c..ed4a94f 100644 --- a/src/wl/display.zig +++ b/src/wl/display.zig @@ -1,6 +1,7 @@ const std = @import("std"); const wayland = @import("../root.zig"); const wl = wayland.wl; +const ancillary_data = @import("../ancillary-data.zig"); const log = std.log.scoped(.display); @@ -85,6 +86,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v const id: u32 = @truncate(object.handle); var size: u32 = 8; + comptime var fds: []std.posix.fd_t = &.{}; inline for (data) |value| { switch (@TypeOf(value)) { @@ -94,6 +96,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v const padding_size: usize = padding_len(u8, value.len + 1); size += @as(u32, @intCast(@sizeOf(u32) + (value.len + 1) + padding_size)); }, + wayland.types.Fd => |fd| fds = fds ++ .{ fd }, else => |t| switch (@typeInfo(t)) { .pointer => |ptr| if (ptr.size == .slice) { const padding_size: usize = padding_len(ptr.child, value.len); @@ -119,6 +122,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v _ = try self.stream.writeAll(std.mem.asBytes(&@as(u8, 0))); } }, + wayland.types.Fd => {}, else => |t| switch (@typeInfo(t)) { .pointer => |ptr| if (ptr.size == .slice) { const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len * @sizeOf(ptr.child))))), 4); @@ -132,6 +136,11 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v }, } } + + if (fds.len > 0) { + try ancillary_data.send_fds(self.stream.handle, fds); + } + return; } } -- cgit v1.2.3-70-g09d2