summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-24 06:33:50 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-24 06:33:50 +0200
commit65bdefaf7a0e0299e2a4361d107a9721eac9dd4e (patch)
treeb605c47cb1ca162b1bd9893784938b43bc343f4c /src
parent16e6d5386fecba7895aa64c035eabec664472de6 (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.zig25
-rw-r--r--src/statvfs_helper.c19
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