diff --git a/src/ascii.zig b/src/ascii.zig index c24fc50..9bdb2f8 100644 --- a/src/ascii.zig +++ b/src/ascii.zig @@ -72,9 +72,10 @@ pub fn printAsciiAndModules(allocator: std.mem.Allocator, ascii_art_path: ?[]u8, var ascii_art_data: []const u8 = undefined; if (ascii_art_path) |ascii| { - var ascii_file = try std.fs.cwd().openFile(ascii, .{}); + const ascii_file = try std.fs.cwd().openFile(ascii, .{ .mode = .read_only }); defer ascii_file.close(); - ascii_art_data = try ascii_file.readToEndAlloc(allocator, std.math.maxInt(usize)); + const file_size = (try ascii_file.stat()).size; + ascii_art_data = try utils.readFile(allocator, ascii_file, file_size); } else { ascii_art_data = @embedFile("./assets/ascii/guy_fawks.txt"); } diff --git a/src/config.zig b/src/config.zig index ab15185..d538dc1 100644 --- a/src/config.zig +++ b/src/config.zig @@ -1,5 +1,6 @@ const std = @import("std"); const ascii = @import("ascii.zig"); +const utils = @import("utils.zig"); pub const Module = struct { type: []u8, @@ -68,14 +69,16 @@ pub fn readConfigFile(allocator: std.mem.Allocator) !?std.json.Parsed(Config) { const config_abs_path = try std.mem.concat(allocator, u8, &.{ home, "/.config/zigfetch/config.json" }); defer allocator.free(config_abs_path); - const file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) { + const config_file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) { error.FileNotFound => return null, else => return err, }; - defer file.close(); + defer config_file.close(); - const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); - defer allocator.free(data); + const file_size = (try config_file.stat()).size; - return try std.json.parseFromSlice(Config, allocator, data, .{ .allocate = .alloc_always }); + const config_data = try utils.readFile(allocator, config_file, file_size); + defer allocator.free(config_data); + + return try std.json.parseFromSlice(Config, allocator, config_data, .{ .allocate = .alloc_always }); } diff --git a/src/linux/hardware.zig b/src/linux/hardware.zig index d3c7fc5..6da6d86 100644 --- a/src/linux/hardware.zig +++ b/src/linux/hardware.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const utils = @import("../utils.zig"); const c_unistd = @cImport(@cInclude("unistd.h")); const c_statvfs = @cImport(@cInclude("sys/statvfs.h")); const c_libpci = @cImport(@cInclude("pci/pci.h")); @@ -44,9 +45,16 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo { // Reads /proc/cpuinfo const cpuinfo_path = "/proc/cpuinfo"; - var file = try std.fs.cwd().openFile(cpuinfo_path, .{}); - defer file.close(); - const cpuinfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + const cpuinfo_file = try std.fs.cwd().openFile(cpuinfo_path, .{ .mode = .read_only }); + defer cpuinfo_file.close(); + + // NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file + // https://docs.kernel.org/filesystems/proc.html + // https://en.wikipedia.org/wiki/Procfs + // + // Only the first section (core 0) will be parsed + // 512 is more than enough + const cpuinfo_data = try utils.readFile(allocator, cpuinfo_file, 512); defer allocator.free(cpuinfo_data); // Parsing /proc/cpuinfo @@ -77,6 +85,7 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo { var cpu_max_freq: f32 = 0.0; + // NOTE: this is the preferred approach beacause it is the most accurate const cpuinfo_max_freq_path = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"; var cmf_exists: bool = true; @@ -89,14 +98,13 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo { if (cmf_exists) { // Reads /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq - var file2 = try std.fs.cwd().openFile(cpuinfo_max_freq_path, .{}); - - defer file2.close(); - const cpuinfo_max_freq_data = try file2.readToEndAlloc(allocator, std.math.maxInt(usize)); - defer allocator.free(cpuinfo_max_freq_data); + const maxfreq_file = try std.fs.cwd().openFile(cpuinfo_max_freq_path, .{ .mode = .read_only }); + defer maxfreq_file.close(); + const maxfreq_data = try utils.readFile(allocator, maxfreq_file, 32); + defer allocator.free(maxfreq_data); // Parsing /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq - const trimmed = std.mem.trim(u8, cpuinfo_max_freq_data, " \n\r"); + const trimmed = std.mem.trim(u8, maxfreq_data, " \n\r"); const cpu_max_freq_khz: f32 = try std.fmt.parseFloat(f32, trimmed); cpu_max_freq = cpu_max_freq_khz / 1_000_000; } else { @@ -203,9 +211,16 @@ fn parseGpuName(allocator: std.mem.Allocator, name: []u8) !?[]u8 { pub fn getRamInfo(allocator: std.mem.Allocator) !RamInfo { // Reads /proc/meminfo const meminfo_path = "/proc/meminfo"; - const file = try std.fs.cwd().openFile(meminfo_path, .{}); - defer file.close(); - const meminfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + const meminfo_file = try std.fs.cwd().openFile(meminfo_path, .{ .mode = .read_only }); + defer meminfo_file.close(); + + // NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file + // https://docs.kernel.org/filesystems/proc.html + // https://en.wikipedia.org/wiki/Procfs + // + // We only need to read the first few lines + // 512 is more than enough + const meminfo_data = try utils.readFile(allocator, meminfo_file, 512); defer allocator.free(meminfo_data); // Parsing /proc/meminfo @@ -265,9 +280,16 @@ pub fn getRamInfo(allocator: std.mem.Allocator) !RamInfo { pub fn getSwapInfo(allocator: std.mem.Allocator) !?SwapInfo { // Reads /proc/meminfo const meminfo_path = "/proc/meminfo"; - const file = try std.fs.cwd().openFile(meminfo_path, .{}); - defer file.close(); - const meminfo_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + const meminfo_file = try std.fs.cwd().openFile(meminfo_path, .{ .mode = .read_only }); + defer meminfo_file.close(); + + // NOTE: procfs is a pseudo-filesystem, so it is not possible to determine the size of a file + // https://docs.kernel.org/filesystems/proc.html + // https://en.wikipedia.org/wiki/Procfs + // + // We only need to read the first few lines + // 512 is ok + const meminfo_data = try utils.readFile(allocator, meminfo_file, 512); defer allocator.free(meminfo_data); // Parsing /proc/meminfo diff --git a/src/linux/system.zig b/src/linux/system.zig index 5ebc159..7d6ee14 100644 --- a/src/linux/system.zig +++ b/src/linux/system.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const utils = @import("../utils.zig"); const c_sysinfo = @cImport(@cInclude("sys/sysinfo.h")); const c_utsname = @cImport(@cInclude("sys/utsname.h")); @@ -77,9 +78,10 @@ pub fn getKernelInfo(allocator: std.mem.Allocator) !KernelInfo { pub fn getOsInfo(allocator: std.mem.Allocator) ![]u8 { const os_release_path = "/etc/os-release"; - const file = try std.fs.cwd().openFile(os_release_path, .{}); - defer file.close(); - const os_release_data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + const os_release_file = try std.fs.cwd().openFile(os_release_path, .{ .mode = .read_only }); + defer os_release_file.close(); + const size = (try os_release_file.stat()).size; + const os_release_data = try utils.readFile(allocator, os_release_file, size); defer allocator.free(os_release_data); var pretty_name: ?[]const u8 = null; diff --git a/src/utils.zig b/src/utils.zig index b9b455b..8721cf4 100644 --- a/src/utils.zig +++ b/src/utils.zig @@ -114,3 +114,15 @@ test "getLongestAsciiArtRowLen" { try std.testing.expectEqual(40, try getLongestAsciiArtRowLen(rows[0..])); } + +pub fn readFile(allocator: std.mem.Allocator, file: std.fs.File, size: usize) ![]const u8 { + var file_buf = try allocator.alloc(u8, size); + defer allocator.free(file_buf); + + var reader = std.fs.File.Reader.init(file, file_buf); + const read = try reader.read(file_buf); + + const data = file_buf[0..read]; + + return allocator.dupe(u8, data); +}