Help reading inotify_fd

Ok thanks, very much , i appreciate your time.
If I can i have another question i need help . the snippet i posted here is an attempt to monitor ( in a linux env ) when a file has being changed.
for that purpose i subscribe a system event with
_ = std.os.linux.inotify_add_watch(@intCast(inotify_fd), file_path0, std.os.linux.IN.ALL_EVENTS);

var buf: [4096]u8 = undefined;
while (true) {
    const bytes_read = try os.read(inotify_fd, &buf, buf.len);
    var offset: usize = 0;
    while (offset < bytes_read) {
        // const event = @ptrCast(*os.struct_inotify_event, @alignCast(&buf[offset]));
        const event: *const os.struct_inotify_event = @ptrCast(@alignCast(&buf[offset]));
        offset += os.struct_inotify_event.size;
        . . . .
        . . . .

then i try to read when the events get fired … but my code is wrong …I get error from compiler saying that os.read doesn’t exist …
what’s the correct way to to that ?
also i tried to read documentation on Zig Documentation … and when i try to search for “read” i get a lot of methods … but for the most there is no explanation to read about … it’s most generic… is the correct way to get docs ??
i thank you for your patience …

With new questions, please open new topics. I’ve split this one off for you.


the function you are looking for (i think) is std.posix.read. std.os was mostly renamed to std.posix, or pushed to more specific os api’s a few releases ago. Are you following an old tutorial?

1 Like

ok, thanks Calder-Ty
I tried but i got error ,specifically i open the file with

    const inotify_fd = std.posix.inotify_init1(IN_CLOEXEC); 
    defer std.posix.close(inotify_fd);         <<--error it want *anyopaque but inotify_fd  is i32...

also this resulting in error 
const bytes_read = try std.posix.read(inotify_fd, &buf);  <<-- because of *anyopaque

How this is possible there is inconsistency between init, read and close. I did something wrong ?? or what else ??

Could you post the full compile error. std.posix.close expects a fd_t which can vary from system to system, but isn’t ever an *anyopaque as far i see.

Hi , sure ,this is the compiler error :slight_smile:

src\MonitorExt.zig:183:27: error: expected type '*anyopaque', found 'error{SystemResources,Unexpected,ProcessFdQuotaExceeded,SystemFdQuotaExceeded}!i32'
    defer std.posix.close(inotify_fd);
                          ^~~~~~~~~~

if I comment out the defer std.posix.close(inotify_fd);
i got error in this line

  _ = std.os.linux.inotify_add_watch(inotify_fd, file_path0, std.os.linux.IN.ALL_EVENTS);
 
src\MonitorExt.zig:199:40: error: expected type 'i32', found 'error{SystemResources,Unexpected,ProcessFdQuotaExceeded,SystemFdQuotaExceeded}!i32'
    _ = std.os.linux.inotify_add_watch(inotify_fd, file_path0, std.os.linux.IN.ALL_EVENTS);
                                       ^~~~~~~~~~

I see,

 found 'error{SystemResources,Unexpected,ProcessFdQuotaExceeded,SystemFdQuotaExceeded}!i32

Is telling you that you are using and Error union. Looking at the signature of
pub fn inotify_init1(flags: u32) INotifyInitError!i32, you can see that this function can fail and so returns not an i32, but an error union. Try using try to unwrap:

const inotify_fd = try std.posix.inotify_init1(IN_CLOEXEC); 

or, handle the error in place:

const inotify_fd = std.posix.inotify_init1(IN_CLOEXEC) catch {
     // ERROR HANDLING CODE HERE
}
1 Like

Hi Calder-Ty,
i didn’t notice this INotifyInitError! … that’s why i’m a newbie with zig !!

I still have to study a little bit more.
any way i tried again, but I got error in the next line

    const inotify_fd = try std.posix.inotify_init1(IN_CLOEXEC);
    defer std.posix.close(inotify_fd);

src\MonitorExt.zig:183:27: error: expected type '*anyopaque', found 'i32'
    defer std.posix.close(inotify_fd);   <<-- Error

That’s was the inconsistency i was talking about… when use _init1 you get i32 and when you use .close it want *anyopaque… ???

The std.posix.inotify api isn’t supported on windows.

Either It’s just not implemented for windows yet

Or it’s not straightforward to map the inotify api to whatever windows has.

it is on windows libc (which is required when using the posix api on windows)

Hi vulpesx , I undestand , but i noted the same inconsistency using linux.
infact if you use std.os.linux.inotify_init1 you get
usize
but when you want use std.os.linux.close it want i32
for me this is an inconsistency.
I’m trying to learn, but in this way is more difficult even because i don’t know how convert between values.
so ,at the end what you suggest me to do ?? , even more there should be to better define struct for inotify_event , something like

const event: *const os.struct_inotify_event = @ptrCast(@alignCast(&buf[offset]));

…because os.struct_inotify_event seems doesn’t exist …
if you think it wort it , tell me what to do otherwise i’ll give up

I didn’t know anything about inotify but now I wanted to try.
On my Linux this seems to work with Zig 0.14.1

const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
    const fd = try std.posix.inotify_init1(std.os.linux.IN.CLOEXEC);
    defer std.posix.close(fd);
    print("fd={}\n", .{fd});
    
    const wd = try std.posix.inotify_add_watch(fd, "test.txt", std.os.linux.IN.ALL_EVENTS);
    print("wd={}\n", .{wd});

    var event: std.os.linux.inotify_event = undefined;
    const nb = try std.posix.read(fd, std.mem.asBytes(&event));
    print("{} bytes: {any}\n", .{nb, event});
}

Oof. I’ll be honest i kinda glossed over windows because… Well it’s windows, and also because i was pretty sure Inotify is a Linux API.

I still have to study a little bit more.
any way i tried again, but I got error in the next line

As @vulpesx points out, this won’t work on windows. You can’t just call into the std.os.linux code and expect things to work on windows. If you are using code from std.os.linux, you can only run that code on linux. If you are trying to cross compile, then you will need to make sure you add the corresponding --target flag to the build command.

EDIT:

inotify is a posix api, but doesn’t look like windows supports it.

Hi kudu, thanks for replay me.
I see your code and i take it as good, If you say it compile.
In my case it doesn’t. it’s becasue now i am on windows ??. i don’t know.

but as you saw in my post there is an inconsistency in .inotify_init1 that return an i32 and .close that want a *anyopaque pointer. ( if I’m not wrong)

in any case thanks for sharing your code.
I must try your code on arch ( my second env ) , so after that i can say something more.
just for info … to compile my code i wrote

    const inotify_fd = try std.posix.inotify_init1(IN_CLOEXEC);

    const c_fd: usize = @intCast(inotify_fd);
    const c_fd1: *anyopaque = @ptrFromInt(c_fd);

    defer std.posix.close(c_fd1);

@Calder-Ty
you right… "inotify is a posix api " … so I have to change my approach on windows. Have to consider this snippet an “attempt to”…

thank you for your support and time.

inotify is just a Linux kernel API, not part of posix. There are projects that try and port the API to non-Linux OSs, but calling std.posix.inotify_init1 is not going to work on non-Linux targets, just like calling std.posix.kqueue is not going to work on Linux.

3 Likes