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:
@@ -22,9 +22,11 @@ let package = Package(
|
||||
.package(url: "https://github.com/tuist/Noora", from: "0.55.1")
|
||||
],
|
||||
targets: [
|
||||
.systemLibrary(name: "CInotify"),
|
||||
.target(
|
||||
name: "Inotify",
|
||||
dependencies: [
|
||||
"CInotify",
|
||||
.product(name: "Logging", package: "swift-log"),
|
||||
]
|
||||
),
|
||||
|
||||
24
Sources/CInotify/cinotify.h
Normal file
24
Sources/CInotify/cinotify.h
Normal 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
|
||||
4
Sources/CInotify/module.modulemap
Normal file
4
Sources/CInotify/module.modulemap
Normal file
@@ -0,0 +1,4 @@
|
||||
module CInotify [system] {
|
||||
header "cinotify.h"
|
||||
export *
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
19
Sources/Inotify/InotifyError.swift
Normal file
19
Sources/Inotify/InotifyError.swift
Normal 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)"
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ import Testing
|
||||
@Suite("Initialisation")
|
||||
struct InitTests {
|
||||
@Test func createsCleanly() async throws {
|
||||
let _ = Inotify()
|
||||
let _ = try Inotify()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user