Skip to content

Commit d78bf11

Browse files
authored
os: add disk_usage/1 (#23634)
1 parent d4298ca commit d78bf11

5 files changed

Lines changed: 70 additions & 0 deletions

File tree

‎vlib/builtin/cfns.c.v‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ fn C.stat(&char, voidptr) int
142142

143143
fn C.lstat(path &char, buf &C.stat) int
144144

145+
fn C.statvfs(const_path &char, buf &C.statvfs) int
146+
145147
fn C.rename(old_filename &char, new_filename &char) int
146148

147149
fn C.fgets(str &char, n int, stream &C.FILE) int
@@ -513,3 +515,5 @@ fn C.WrappedNSLog(str &u8)
513515
// absolute value
514516
@[trusted]
515517
fn C.abs(number int) int
518+
519+
fn C.GetDiskFreeSpaceExA(const_path &char, free_bytes_available_to_caller &u64, total_number_of_bytes &u64, total_number_of_free_bytes &u64) bool

‎vlib/os/os.c.v‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,3 +1073,10 @@ pub fn error_win32(e SystemError) IError {
10731073
panic('Win32 API not available on this platform.')
10741074
}
10751075
}
1076+
1077+
pub struct DiskUsage {
1078+
pub:
1079+
total u64
1080+
available u64
1081+
used u64
1082+
}

‎vlib/os/os_nix.c.v‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import strings
77
#include <fcntl.h>
88
#include <sys/utsname.h>
99
#include <sys/types.h>
10+
#include <sys/statvfs.h>
1011
#include <utime.h>
1112

1213
// path_separator is the platform specific separator string, used between the folders
@@ -530,3 +531,31 @@ fn C.sysconf(name int) i64
530531
pub fn page_size() int {
531532
return int(C.sysconf(C._SC_PAGESIZE))
532533
}
534+
535+
struct C.statvfs {
536+
f_bsize usize
537+
f_blocks usize
538+
f_bfree usize
539+
f_bavail usize
540+
}
541+
542+
// disk_usage returns disk usage of `path`
543+
@[manualfree]
544+
pub fn disk_usage(path string) !DiskUsage {
545+
mpath := if path == '' { '.' } else { path }
546+
defer { unsafe { mpath.free() } }
547+
mut vfs := C.statvfs{}
548+
ret := unsafe { C.statvfs(&char(mpath.str), &vfs) }
549+
if ret == -1 {
550+
return error('cannot get disk usage of path')
551+
}
552+
f_bsize := u64(vfs.f_bsize)
553+
f_blocks := u64(vfs.f_blocks)
554+
f_bavail := u64(vfs.f_bavail)
555+
f_bfree := u64(vfs.f_bfree)
556+
return DiskUsage{
557+
total: f_bsize * f_blocks
558+
available: f_bsize * f_bavail
559+
used: f_bsize * (f_blocks - f_bfree)
560+
}
561+
}

‎vlib/os/os_test.c.v‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,3 +1110,10 @@ fn test_mkdir_at_file_dst() {
11101110
}
11111111
assert false
11121112
}
1113+
1114+
fn test_disk_usage() {
1115+
usage := os.disk_usage('.')!
1116+
assert usage.total > 0
1117+
assert usage.available > 0
1118+
assert usage.used > 0
1119+
}

‎vlib/os/os_windows.c.v‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,26 @@ pub fn page_size() int {
601601
C.GetSystemInfo(&sinfo)
602602
return int(sinfo.dwPageSize)
603603
}
604+
605+
// disk_usage returns disk usage of `path`
606+
pub fn disk_usage(path string) !DiskUsage {
607+
mut free_bytes_available_to_caller := u64(0)
608+
mut total := u64(0)
609+
mut available := u64(0)
610+
mut ret := false
611+
if path == '.' || path == '' {
612+
ret = C.GetDiskFreeSpaceExA(&char(0), &free_bytes_available_to_caller, &total,
613+
&available)
614+
} else {
615+
ret = C.GetDiskFreeSpaceExA(&char(path.str), &free_bytes_available_to_caller,
616+
&total, &available)
617+
}
618+
if ret == false {
619+
return error('cannot get disk usage of path')
620+
}
621+
return DiskUsage{
622+
total: total
623+
available: available
624+
used: total - available
625+
}
626+
}

0 commit comments

Comments
 (0)