Would be nice to have a function that returns the available disk space on a given path (file, directory, server share). Something like this: ``` // Returns ulong.max when the available disk space could not be determined. ulong getAvailableDiskSpace(string path) { import std.string: toStringz; version (WINDOWS) { import core.sys.windows.winbase; ULARGE_INTEGER freeBytesAvailable; auto pathCstr = (driveName(path) ~ dirSeparator).toStringz(); bool success = GetDiskFreeSpaceExW(path, &freeBytesAvailable, null, null); return success ? free_bytes.QuadPart : ulong.max; } else { import core.sys.posix.sys.statvfs; statvfs_t stats; int err = statvfs(path.toStringz(), &stats); return !err ? stats.f_bavail * stats.f_frsize : ulong.max; } } ```
NTFS supports symbolic links too, so GetDiskFreeSpaceExW should receive the folder path because it can reside on a different partition than the disk it's accessed through.
Indeed, I misread GetDiskFreeSpaceEx's documentation. Thanks.
Version that actually compiles on Windows too: ``` // Returns ulong.max when the available disk space could not be determined. ulong getAvailableDiskSpace(string path) { import std.string: toStringz; version (Windows) { import std.path; import core.sys.windows.winbase; import core.sys.windows.winnt; import std.internal.cstring; ULARGE_INTEGER freeBytesAvailable; path ~= dirSeparator; auto success = GetDiskFreeSpaceExW(path.tempCStringW(), &freeBytesAvailable, null, null); return success ? freeBytesAvailable.QuadPart : ulong.max; } else { import core.sys.posix.sys.statvfs; statvfs_t stats; int err = statvfs(path.toStringz(), &stats); return !err ? stats.f_bavail * stats.f_frsize : ulong.max; } } ```
(In reply to Johan Engelen from comment #3) > Version that actually compiles on Windows too: > ``` > // Returns ulong.max when the available disk space could not be determined. > ulong getAvailableDiskSpace(string path) > { > import std.string: toStringz; > version (Windows) > { > import std.path; > import core.sys.windows.winbase; > import core.sys.windows.winnt; > import std.internal.cstring; > > ULARGE_INTEGER freeBytesAvailable; > path ~= dirSeparator; > auto success = GetDiskFreeSpaceExW(path.tempCStringW(), > &freeBytesAvailable, null, null); > return success ? freeBytesAvailable.QuadPart : ulong.max; > } > else > { > import core.sys.posix.sys.statvfs; > > statvfs_t stats; > int err = statvfs(path.toStringz(), &stats); > return !err ? stats.f_bavail * stats.f_frsize : ulong.max; > } > } > ``` what I would say if it'd be a PR: 1. change declaration to ulong getAvailableDiskSpace(const(char)[] path) because const(char)[] acts as a wildcard and takes all char[] variants. 2. returns -1 on failure. ulong.max: No way !!! 3. linux version: don't need to init the target so statvfs_t stats = void; Otherwise let's get the merge ;)
(In reply to b2.temp from comment #4) > 2. returns -1 on failure. ulong.max: No way !!! The return type is _unsigned_. Throwing an exception is also a possibility.
(In reply to Johan Engelen from comment #5) > (In reply to b2.temp from comment #4) > > 2. returns -1 on failure. ulong.max: No way !!! > > The return type is _unsigned_. Oops, sorry , i must be blind ^^ Anyway...Wouldn't 0 be a possible return type in case of error ? It would allow: if (auto space = getAvailableDiskSpace(root)) { } else { throw new Exception("either the disk is full or inaccessible"); } > Throwing an exception is also a possibility. No, seriously, delegate this option to the user.
(In reply to b2.temp from comment #6) > Anyway...Wouldn't 0 be a possible return type in case of error No. What if there's no more space in the drive? Would you return something other than zero?
In both cases I 'd return 0. statvfs_t stats; int err = statvfs(path.toStringz(), &stats); return err ? 0 : stats.f_bavail * stats.f_frsize; > "either the disk is full or inaccessible" Because in both cases you can do nothing. By the way HDD are never full. Only removable media can be full (bootable USB key, DVD/CD rom, etc).
@Johan: As you have already prepared a nice function & no one disagrees that it wouldn't be useful - I assigned this to you. Looking forward to your PR ;-)
Unassigning myself. I'm not going to work on this any time soon.
Hi, I'd like to take this task. In which part of the std do you think it would be best to put this function? Thanks, Alex
std.file makes more sense. User wants available disk space to know if it can create a file or how many byte in disk a cache can use (or whatever else). Much less useful in std.path. ideally there would be: std.filesystem.file std.filesystem.path std.filesystem.package <-- i would put it here but since it's not the case std.file is the best ooption.
See https://github.com/ldc-developers/ldc/blob/f5b05878de6df2ea4a77c37128ad2eae0266b690/driver/cache_pruning.d#L47-L71
@jercaianu updated dlang/phobos pull request #5776 "Fix Issue 16487 - Add function to obtain the available disk space" fixing this issue: - Fix Issue 16487 - Add function to obtain the available disk space - Fix Issue 16487 - Add function to obtain the available disk space https://github.com/dlang/phobos/pull/5776
dlang/phobos pull request #5776 "Fix Issue 16487 - Add function to obtain the available disk space" was merged into master: - d38cbf90cbd66685efa51b5c9a553ff253c7c1a5 by Alexandru Jercaianu: Fix Issue 16487 - Add function to obtain the available disk space https://github.com/dlang/phobos/pull/5776