2024-08-20 07:59:09 +02:00
|
|
|
const objc = @import("objc");
|
|
|
|
const std = @import("std");
|
2024-08-26 22:38:49 +02:00
|
|
|
const c = @cImport({
|
|
|
|
@cInclude("sys/types.h");
|
2024-08-20 07:59:09 +02:00
|
|
|
@cInclude("sys/utsname.h");
|
2024-08-26 22:38:49 +02:00
|
|
|
@cInclude("sys/sysctl.h");
|
|
|
|
@cInclude("sys/time.h");
|
2024-08-20 07:59:09 +02:00
|
|
|
});
|
|
|
|
const OsVersion = struct {
|
|
|
|
name: []const u8,
|
|
|
|
major: i64,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub fn macosVersionAtLeast(major: i64, minor: i64, patch: i64) bool {
|
|
|
|
// Get the objc class from the runtime
|
|
|
|
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
|
|
|
|
|
|
|
|
// Call a class method with no arguments that returns another objc object.
|
|
|
|
const info = NSProcessInfo.msgSend(objc.Object, "processInfo", .{});
|
|
|
|
|
|
|
|
// var NSOperatingSystemVersion = objc.getClass("NSOperatingSystemVersion").?;
|
|
|
|
|
|
|
|
// const os = info.msgSend(objc.Object, "")
|
|
|
|
|
|
|
|
// Call an instance method that returns a boolean and takes a single
|
|
|
|
// argument.
|
|
|
|
return info.msgSend(bool, "isOperatingSystemAtLeastVersion:", .{
|
|
|
|
NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch },
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn macos_version(allocator: std.mem.Allocator) ![]const u8 {
|
|
|
|
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
|
|
|
|
|
|
|
|
// Call a class method with no arguments that returns another objc object.
|
|
|
|
const info = NSProcessInfo.msgSend(objc.Object, "processInfo", .{});
|
|
|
|
|
|
|
|
const koko = info.msgSend(NSOperatingSystemVersion, "operatingSystemVersion", .{});
|
|
|
|
|
2024-08-26 22:38:49 +02:00
|
|
|
const buf = try std.fmt.allocPrint(allocator, ": macOS {s} {d}.{d}.{d}\n", .{ version_to_name(koko), koko.major, koko.minor, koko.patch });
|
2024-08-20 07:59:09 +02:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn macos_kernel_version(allocator: std.mem.Allocator) ![]const u8 {
|
2024-08-26 22:38:49 +02:00
|
|
|
var name: c.struct_utsname = undefined;
|
2024-08-20 07:59:09 +02:00
|
|
|
|
2024-08-26 22:38:49 +02:00
|
|
|
if (c.uname(&name) != 0) {
|
2024-08-20 07:59:09 +02:00
|
|
|
return error.UnameFailed;
|
|
|
|
}
|
|
|
|
|
2024-08-20 21:54:33 +02:00
|
|
|
const sysname = std.mem.sliceTo(name.sysname[0..], 0);
|
|
|
|
const version = std.mem.sliceTo(name.release[0..], 0);
|
2024-08-20 07:59:09 +02:00
|
|
|
|
2024-08-26 22:38:49 +02:00
|
|
|
const buf = try std.fmt.allocPrint(allocator, ": {s} {s}\n", .{ sysname, version });
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn macos_cpu_info(allocator: std.mem.Allocator) ![]const u8 {
|
|
|
|
var cpu_brand: [128]u8 = undefined;
|
|
|
|
var cpu_brand_size: usize = cpu_brand.len;
|
|
|
|
var cpu_cores: c_int = 0;
|
|
|
|
var cpu_cores_size: usize = @sizeOf(c_int);
|
|
|
|
|
|
|
|
if (c.sysctlbyname("machdep.cpu.core_count", &cpu_cores, @as([*c]usize, &cpu_cores_size), null, 0) < 0) {
|
|
|
|
return error.SysctlFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c.sysctlbyname("machdep.cpu.brand_string", &cpu_brand, &cpu_brand_size, null, 0) < 0) {
|
|
|
|
return error.SysctlFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (c.sysctlbyname("hw.cpufrequency", &))
|
|
|
|
const buf = try std.fmt.allocPrint(allocator, ": {s} ({d} cores)\n", .{ cpu_brand[0..cpu_brand_size], cpu_cores });
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn macos_uptime(allocator: std.mem.Allocator) ![]const u8 {
|
|
|
|
var mib: [2]c.integer_t = [_]c.integer_t{ c.CTL_KERN, c.KERN_BOOTTIME };
|
|
|
|
var boottime: c.struct_timeval = undefined;
|
|
|
|
var size: u64 = @sizeOf(c.struct_timeval);
|
|
|
|
|
|
|
|
if (c.sysctl(&mib[0], 2, &boottime, @as([*c]usize, &size), null, 0) < 0) {
|
|
|
|
return error.SysctlFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
var now: c.time_t = 0;
|
|
|
|
_ = c.time(&now);
|
|
|
|
|
|
|
|
const uptime_seconds: i64 = now - boottime.tv_sec;
|
|
|
|
|
|
|
|
const days = @divFloor(uptime_seconds, (24 * 60 * 60));
|
|
|
|
const hours = @divFloor(@rem(uptime_seconds, (24 * 60 * 60)), (60 * 60));
|
|
|
|
const minutes = @divFloor(@rem(uptime_seconds, (60 * 60)), 60);
|
|
|
|
|
|
|
|
const buf = try std.fmt.allocPrint(allocator, ": {d} days, {d} hours, {d} mins\n", .{ days, hours, minutes });
|
2024-08-20 07:59:09 +02:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn version_to_name(version: NSOperatingSystemVersion) []const u8 {
|
|
|
|
switch (version.major) {
|
|
|
|
15 => return "Sequoia",
|
|
|
|
14 => return "Sonoma",
|
|
|
|
13 => return "Ventura",
|
|
|
|
12 => return "Monterey",
|
|
|
|
11 => return "Big Sur",
|
|
|
|
10 => {
|
|
|
|
switch (version.minor) {
|
|
|
|
15 => return "Catalina",
|
|
|
|
14 => return "Mojave",
|
|
|
|
else => return "Unknown",
|
|
|
|
}
|
|
|
|
},
|
|
|
|
else => return "Unknown",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This extern struct matches the Cocoa headers for layout.
|
|
|
|
const NSOperatingSystemVersion = extern struct {
|
|
|
|
major: i64,
|
|
|
|
minor: i64,
|
|
|
|
patch: i64,
|
|
|
|
};
|