Implement init/deinit of inotify system

Use RAII to handle inotify resource lifetime, i.e. initialize with actor
creation and deinitialize with actor deletion.
This commit is contained in:
T. R. Bernstein
2026-03-11 17:25:27 +01:00
parent 1a7e5ca5de
commit 098339f9d1
6 changed files with 65 additions and 2 deletions

View File

@@ -0,0 +1,24 @@
#ifndef CINOTIFY_H
#define CINOTIFY_H
#include <stdlib.h>
#include <sys/inotify.h>
#include <errno.h>
static inline int cinotify_deinit(int fd) {
return close(fd);
}
static inline int cinotify_get_errno(void) {
return errno;
}
static inline char* get_error_message() {
int error_number = errno;
errno = 0;
char* error_message = strerror(error_number);
if (errno > 0) return NULL;
return error_message;
}
#endif

View File

@@ -0,0 +1,4 @@
module CInotify [system] {
header "cinotify.h"
export *
}

View File

@@ -1,2 +1,16 @@
actor Inotify {
import CInotify
public actor Inotify {
private let fd: Int32
public init() throws {
self.fd = inotify_init1(Int32(IN_NONBLOCK | IN_CLOEXEC))
guard self.fd >= 0 else {
throw InotifyError.initFailed(errno: cinotify_get_errno())
}
}
deinit {
cinotify_deinit(self.fd)
}
}

View File

@@ -0,0 +1,19 @@
import CInotify
public enum InotifyError: Error, Sendable, CustomStringConvertible {
case initFailed(errno: Int32)
public var description: String {
switch self {
case .initFailed(let code):
"inotify_init1 failed: \(readableErrno(code))"
}
}
private func readableErrno(_ code: Int32) -> String {
if let cStr = get_error_message() {
return String(cString: cStr) + " (errno \(code))"
}
return "errno \(code)"
}
}