Zig way of handling xattrs and ACLs

As the title says. What would be correct way to do it in zig? Should I go with std.posix, but that would be removed in the future as I understood it. Is there something currently in std that does like reading and setting them?

In case someone is interested to see, this is how I’m handling them for linux:

// --- Linux Implementation ---
fn copyLinuxMetadata(acl_list: []u8, acl_value: []u8, src_fd: c_int, dest_fd: c_int) !void {

    // List attributes
    const list_size = std.os.linux.flistxattr(src_fd, acl_list.ptr, acl_list.len);
    if (list_size == 0) return;

    // Iterate and Copy (Linux handles ACLs as "system.posix_acl_access")
    var it = std.mem.splitScalar(u8, acl_list, 0);
    while (it.next()) |name| {
        if (name.len == 0) continue;
        const name_c_ptr: [*:0]const u8 = @ptrCast(name.ptr);
        const val_size = std.os.linux.fgetxattr(
            src_fd,
            name_c_ptr,
            acl_value.ptr,
            acl_value.len,
        );
        if (val_size == 0) continue;
        _ = std.os.linux.fsetxattr(
            dest_fd,
            name_c_ptr,
            acl_value.ptr,
            val_size,
            0,
        );
    }
}

I don’t like that pointer conversion. Maybe I’m using std.mem.splitScalar() wrongly here?
P.S. I’ve read that for Windows, I’d need to use some external dll, and for MacOS I forgot. But at least this was an initial step to get something working at least

You can do this instead of a ptr cast.

name_c_ptr = name[0..name.len - 1 :0].ptr;

It’s safer too, as it panics if the sentinel is not there, which a ptr cast will not.

1 Like