// SPDX-FileCopyrightText: © 2026 Francesc Muñoz // SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie // SPDX-License-Identifier: MIT //! Running the tools the collectors read, and reading the files they read. //! Every failure is an empty answer: a tool that is missing, or that cannot //! see what it was asked about, is the same to the panels as one that found //! nothing, and the program keeps the last good sample rather than stopping. const std = @import("std"); const Allocator = std.mem.Allocator; const Io = std.Io; const max_output = 16 << 20; /// What a command wrote to standard output, allocated from `arena`. Its /// standard error is read and thrown away. pub fn run(arena: Allocator, io: Io, argv: []const []const u8) Io.Cancelable![]const u8 { const result = std.process.run(arena, io, .{ .argv = argv, .stdout_limit = .limited(max_output), .stderr_limit = .limited(max_output), }) catch |err| switch (err) { error.Canceled => return error.Canceled, else => return "", }; return result.stdout; } /// The whole of a file, read as a stream rather than by its size, because /// the files under `/proc` all claim to be empty. pub fn readFile(arena: Allocator, io: Io, path: []const u8) Io.Cancelable![]const u8 { const file = Io.Dir.cwd().openFile(io, path, .{}) catch |err| switch (err) { error.Canceled => return error.Canceled, else => return "", }; defer file.close(io); var buffer: [4096]u8 = undefined; var reader = file.readerStreaming(io, &buffer); return reader.interface.allocRemaining(arena, .limited(max_output)) catch |err| switch (err) { error.ReadFailed => if (reader.err) |e| switch (e) { error.Canceled => return error.Canceled, else => return "", } else "", else => return "", }; } test "readFile reads a file that claims to be empty" { var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); defer arena.deinit(); const text = try readFile(arena.allocator(), std.testing.io, "/proc/self/status"); if (text.len == 0) return error.SkipZigTest; try std.testing.expect(std.mem.startsWith(u8, text, "Name:")); }