waseigo
DiskSpace
Hi everyone, I needed this for a project I’ve been working on, and couldn’t find a simple solution that would work. The solutions in Check disk space inside elixir didn’t work for me.
Looking at how Exqlite deals with NIFs, I wrote a Makefile and then used Grok 3 with numerous rounds to generate the C file for a NIF. I then had GPT-5 and Gemini 2.5 Flash review it, then back to Grok 3 for implementing the suggested improvements, as Grok’s license permits licensing generated code permissively. Back and forth, again and again.
It should work on everything POSIX and on Windows, though I have only tested it on Debian 12. I don’t have Apple computers, and currently don’t run FreeBSD or NetBSD anywhere to try it out there.
What it does
It returns information about total, used, free, and available disk space, using native system calls for accuracy and performance. Optionally converts the results into human-readable strings with kibibytes etc. or kilobytes etc.
Returns disk space metrics as a map with keys:
:total— total size of the filesystem:used— bytes currently used:free— bytes free on the filesystem:available— bytes available to the current user (may be less than free due to permissions)
Provides both safe (stat/2) and bang (stat!/2) variants (with opts keyword-list options for human-readable output), the latter raising on errors.
Provides a humanize/2 function to which you can pipe the output of stat/2 and stat!/2 to generate human-readable output, if you don’t want to pass opts to those functions.
Usage example
iex(1)> DiskSpace.stat!("/tmp")
%{
available: 32389640192,
free: 43895349248,
total: 225035927552,
used: 181140578304
}
iex(2)> DiskSpace.stat("/tmp")
{:ok,
%{
available: 32389599232,
free: 43895308288,
total: 225035927552,
used: 181140619264
}}
iex(3)> DiskSpace.stat("/tmp", humanize: true)
{:ok,
%{
available: "30.17 GiB",
free: "40.88 GiB",
total: "209.58 GiB",
used: "168.70 GiB"
}}
iex(4)> DiskSpace.stat("/tmp", humanize: true, base: :decimal)
{:ok,
%{
available: "32.39 GB",
free: "43.90 GB",
total: "225.04 GB",
used: "181.14 GB"
}}
iex(5)> DiskSpace.stat!("/yolo/swag")
** (DiskSpace.Error) DiskSpace error: :realpath_failed
(disk_space 0.1.0) lib/disk_space.ex:86: DiskSpace.stat!/2
iex:5: (file)
Error-handling
stat/2returns{:ok, stats_map}or{:error, reason}stat!/2returnsstats_mapor raisesDiskSpace.Error
Reporting issues and opening PRs welcome.
- Package: disk_space | Hex
- Documentation: README — DiskSpace v1.0.0
- License: Apache-2.0
- Git repo:
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










First 8 of 8 Posts
hauleth
Why not use
os_mon’sdisksup? How does your solution differs?waseigo
I couldn’t get os_mon/disksup to start!
waseigo
Actually, I just got
disksupworking. I had to add:os_monto the:extra_applicationsinmix.exs… Oh well, live and learn!To answer your question:
:disksup.get_disk_info/1disk_space.stat/2andstat!/2:os_mon’s:disksup):os_monin:extra_applicationsinmix.exs{:ok, stats_map}or{:error, reason}(stat/2),stats_mapor raises exception (stat!/2), wherestats_mapis a plain Elixir map with atom keys with: integer values (bytes) if option:humanizeis false (default), string values (KiB, kB, etc.) if:humanizeis truehumanize: true, either as KiB etc. (base: :binary, default) or kB etc. (base: :decimal)disk_space_check_intervalDiskSpace.humanize/2:alarm_handler, signal:disk_almost_full, via:os_monwaseigo
Just published v0.2.1 and deprecated v0.1.0 and v0.2.0.
v0.2.0 reshapes
{:error, reason}and{:error, reason, info}tuples coming from the NIF to{:error, %{reason: reason, info: info}for easier pattern-matching on always 2-element error tuples.v0.2.1 actually works as a dependency… I had forgotten to include
c_srcin the packageAlso added the earlier comparison table to
README.md, as it was a great question, thanks @hauleth!NobbZ
Of course there is a runtime requirement… You have to add an entry to the applications
depslist, and unless you setruntime: falseyour app will be loaded and started at runtime.Please be aware that this is implicit, and compare it to the explicit adding to
applicationsback before elixir 1.5.waseigo
Aha, I was not aware of that, thanks!
waseigo
Version 0.3.0 is up on Hex.pm.
Supported Elixir and OTP versions
mix testpasses?Apologies to those behind the 40+ downloads of the prior versions, for whom it was only working on Linux. First time I’m dealing with a NIF (or GitHub Actions, for that matter)!
waseigo
v0.4.0 is on Hex.pm, I bumped the minimum Elixir version to 1.15, though it’s really the OTP version that determines things, and using DiskSpace on Windows requires OTP 27 and above, therefore Elixir 1.17.
I deprecated the previous versions.
Also, I wrote down my experience with having Grok 3 write the C source and Makefile (and the build.yml for GitHub Actions) with code reviews by Gemini 2.5 Flash and GPT-5 in a blog post: