diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-24 06:33:50 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-24 06:33:50 +0200 |
commit | 65bdefaf7a0e0299e2a4361d107a9721eac9dd4e (patch) | |
tree | b605c47cb1ca162b1bd9893784938b43bc343f4c /src | |
parent | 16e6d5386fecba7895aa64c035eabec664472de6 (diff) |
Handle statvfs in C.
This is necessary for musl support because musl's version of struct
statvfs contains bitfields, which Zig does not know how to import.
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/dir.zig | 25 | ||||
-rw-r--r-- | src/statvfs_helper.c | 19 |
2 files changed, 36 insertions, 8 deletions
diff --git a/src/cmd/dir.zig b/src/cmd/dir.zig index 94ca29b..774bd8c 100644 --- a/src/cmd/dir.zig +++ b/src/cmd/dir.zig @@ -5,9 +5,6 @@ const ArrayList = std.ArrayList; const c = @cImport({ @cInclude("errno.h"); @cInclude("stdio.h"); - if (@import("builtin").os.tag != .windows) { - @cInclude("sys/statvfs.h"); - } }); const paths = @import("../paths.zig"); @@ -93,20 +90,31 @@ fn isLeapYear(year: u32) bool { return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0); } -const GetFreeDiskSpaceError = error{ NotImplemented, AccessDenied }; +const GetFreeDiskSpaceError = error{ NotImplemented, AccessDenied, OutOfMemory }; fn getFreeDiskSpace(path: []const u8) GetFreeDiskSpaceError!u64 { if (@import("builtin").os.tag == .windows) { return error.NotImplemented; } - var stat: c.struct_statvfs = undefined; - if (c.statvfs(path.ptr, &stat) != 0) { - _ = c.perror("statvfs"); + // Create null-terminated path for C function + const allocator = std.heap.page_allocator; + const null_terminated_path = try allocator.dupeZ(u8, path); + defer allocator.free(null_terminated_path); + + const free_space = get_statvfs_free_space(null_terminated_path.ptr); + if (free_space == 0) { return error.AccessDenied; } - return stat.f_frsize * stat.f_bavail; + return free_space; +} + +extern fn statvfs_get_free_space_impl(path: [*:0]const u8) u64; + +fn get_statvfs_free_space(path: [*:0]const u8) u64 { + // Call the C function that uses statvfs internally to avoid struct issues + return statvfs_get_free_space_impl(path); } pub const Dir = struct { @@ -206,6 +214,7 @@ pub const Dir = struct { const bytes_free = getFreeDiskSpace(path) catch |err| switch (err) { error.AccessDenied => 0, error.NotImplemented => 0, + error.OutOfMemory => 0, }; const formatted_total_bytes = try formatWithCommas(ctx.allocator, total_file_bytes); diff --git a/src/statvfs_helper.c b/src/statvfs_helper.c new file mode 100644 index 0000000..8f6a4fe --- /dev/null +++ b/src/statvfs_helper.c @@ -0,0 +1,19 @@ +#include <stdint.h> + +#ifdef _WIN32 +uint64_t statvfs_get_free_space_impl(const char* path) { + // Windows not implemented + (void)path; + return 0; +} +#else +#include <sys/statvfs.h> + +uint64_t statvfs_get_free_space_impl(const char* path) { + struct statvfs stat; + if (statvfs(path, &stat) != 0) { + return 0; + } + return (uint64_t)stat.f_frsize * (uint64_t)stat.f_bavail; +} +#endif
\ No newline at end of file |