From d38cbf90cbd66685efa51b5c9a553ff253c7c1a5 Mon Sep 17 00:00:00 2001 From: Alexandru Jercaianu Date: Tue, 10 Oct 2017 18:35:21 +0300 Subject: [PATCH 1/4] Fix Issue 16487 - Add function to obtain the available disk space --- changelog/std-file-getAvailableDiskSpace.dd | 17 +++++ std/file.d | 72 +++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 changelog/std-file-getAvailableDiskSpace.dd diff --git a/changelog/std-file-getAvailableDiskSpace.dd b/changelog/std-file-getAvailableDiskSpace.dd new file mode 100644 index 00000000000..763db9ef481 --- /dev/null +++ b/changelog/std-file-getAvailableDiskSpace.dd @@ -0,0 +1,17 @@ +Added the `std.file.getAvailableDiskSpace` functionality. + +$(REF getAvailableDiskSpace, std,file) receives as a parameter the path of a file or +directory in the file system, and returns the available disk space on the mounted filesystem. +If the given path is nonexistent, an exception is thrown. + +--- +import std.file; +ulong size = getAvailableDiskSpace("."); +assert(size > 0); +--- + +--- +import std.file; +assertThrown(getAvailableDiskSpace("NonExistentFile")); +--- + diff --git a/std/file.d b/std/file.d index b8930d95e51..095b17e3900 100644 --- a/std/file.d +++ b/std/file.d @@ -62,6 +62,7 @@ $(TR $(TD Other) $(TD $(LREF FileException) $(LREF PreserveAttributes) $(LREF SpanMode) + $(LREF getAvailableDiskSpace) )) ) @@ -5232,3 +5233,74 @@ string tempDir() @trusted myFile.write("hello"); assert(myFile.readText == "hello"); } + +/** +Returns the available disk space based on a given path. +On Windows, `path` must be a directory; on Posix systems, it can be a file or directory. + +Params: + path = on Windows, it must be a directory; on Posix it can be a file or directory +Returns: + Available space in bytes + +Throws: + $(LREF FileException) in case of failure +*/ +ulong getAvailableDiskSpace(string path) @safe +{ + version (Windows) + { + import core.sys.windows.winbase : GetDiskFreeSpaceExW; + import core.sys.windows.winnt : ULARGE_INTEGER; + import std.internal.cstring : tempCStringW; + + ULARGE_INTEGER freeBytesAvailable; + auto err = () @trusted { + return GetDiskFreeSpaceExW(path.tempCStringW(), &freeBytesAvailable, null, null); + } (); + cenforce(err != 0, "Cannot get available disk space"); + + return freeBytesAvailable.QuadPart; + } + else version (Posix) + { + import std.string : toStringz; + + version (FreeBSD) + { + import core.sys.posix.sys.statvfs : statfs, statfs_t; + + statfs_t stats; + auto err = () @trusted { + return statfs(path.toStringz(), &stats); + } (); + cenforce(err == 0, "Cannot get available disk space"); + + return stats.f_bavail * stats.f_bsize; + } + else + { + import core.sys.posix.sys.statvfs : statvfs, statvfs_t; + + statvfs_t stats; + auto err = () @trusted { + return statvfs(path.toStringz(), &stats); + } (); + cenforce(err == 0, "Cannot get available disk space"); + + return stats.f_bavail * stats.f_frsize; + } + } + else static assert(0, "Unsupported platform"); +} + +/// +@safe unittest +{ + import std.exception : assertThrown; + + auto space = getAvailableDiskSpace("."); + assert(space > 0); + + assertThrown!FileException(getAvailableDiskSpace("ThisFileDoesNotExist123123")); +} From d0f19603a1e738b5b8cc0dbf3cff054faaf70c2c Mon Sep 17 00:00:00 2001 From: Alexandru Jercaianu Date: Wed, 11 Apr 2018 13:25:02 +0300 Subject: [PATCH 2/4] Changed getAvailableDiskSpace signature --- std/file.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/file.d b/std/file.d index 095b17e3900..0d689a01a67 100644 --- a/std/file.d +++ b/std/file.d @@ -5246,7 +5246,7 @@ Returns: Throws: $(LREF FileException) in case of failure */ -ulong getAvailableDiskSpace(string path) @safe +ulong getAvailableDiskSpace(scope const(char)[] path) @safe { version (Windows) { From 8082e7de7ad32ddbc0c92660856fe67cd0c2cae4 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Tue, 18 Jun 2019 23:05:42 -0400 Subject: [PATCH 3/4] Fix FreeBSD deprecated import --- std/file.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/file.d b/std/file.d index 0d689a01a67..f874a70dcd1 100644 --- a/std/file.d +++ b/std/file.d @@ -5268,7 +5268,7 @@ ulong getAvailableDiskSpace(scope const(char)[] path) @safe version (FreeBSD) { - import core.sys.posix.sys.statvfs : statfs, statfs_t; + import core.sys.freebsd.sys.mount : statfs, statfs_t; statfs_t stats; auto err = () @trusted { From 425eeb3abcec8476f992de9b64ad62f8124bde24 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Sun, 23 Jun 2019 09:40:56 -0400 Subject: [PATCH 4/4] getAvailableDiskSpace: toStringz -> tempCString --- std/file.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/std/file.d b/std/file.d index f874a70dcd1..31a626814f8 100644 --- a/std/file.d +++ b/std/file.d @@ -5264,7 +5264,7 @@ ulong getAvailableDiskSpace(scope const(char)[] path) @safe } else version (Posix) { - import std.string : toStringz; + import std.internal.cstring : tempCString; version (FreeBSD) { @@ -5272,7 +5272,7 @@ ulong getAvailableDiskSpace(scope const(char)[] path) @safe statfs_t stats; auto err = () @trusted { - return statfs(path.toStringz(), &stats); + return statfs(path.tempCString(), &stats); } (); cenforce(err == 0, "Cannot get available disk space"); @@ -5284,7 +5284,7 @@ ulong getAvailableDiskSpace(scope const(char)[] path) @safe statvfs_t stats; auto err = () @trusted { - return statvfs(path.toStringz(), &stats); + return statvfs(path.tempCString(), &stats); } (); cenforce(err == 0, "Cannot get available disk space");