├── .gitignore ├── .editorconfig ├── .eslintrc ├── index.d.ts ├── src ├── diskusage_posix.cpp ├── diskusage.h ├── main.cpp └── diskusage_win.cpp ├── fallback.js ├── package.json ├── demo └── index.js ├── LICENSE ├── binding.gyp ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | build 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 2 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "browser": false, 5 | "commonjs": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "ecmaVersion": 2018 10 | }, 11 | "rules": { 12 | "semi": ["error", "always"] 13 | } 14 | } -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | type DiskUsage = { 2 | available: number; 3 | free: number; 4 | total: number; 5 | } 6 | 7 | export function check(path: string, callback: (error?: Error, result?: DiskUsage) => void): void; 8 | export function check(path: string): Promise 9 | export function checkSync(path: string): DiskUsage; 10 | -------------------------------------------------------------------------------- /src/diskusage_posix.cpp: -------------------------------------------------------------------------------- 1 | #include "diskusage.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | DiskUsage GetDiskUsage(const char* path) 9 | { 10 | struct statvfs info = {}; 11 | 12 | if (statvfs(path, &info)) { 13 | int errnum = errno; 14 | throw SystemError(errnum, "statvfs", strerror(errnum), path); 15 | } 16 | 17 | DiskUsage result; 18 | result.available = info.f_bavail * info.f_frsize; 19 | result.free = info.f_bfree * info.f_frsize; 20 | result.total = info.f_blocks * info.f_frsize; 21 | 22 | return result; 23 | } 24 | -------------------------------------------------------------------------------- /fallback.js: -------------------------------------------------------------------------------- 1 | var native = require("./build/Release/diskusage.node"); 2 | var promise = typeof Promise !== "undefined" ? Promise : require("es6-promise").Promise; 3 | 4 | exports.check = function(path, callback) { 5 | if (callback) { 6 | return check(path, callback); 7 | } 8 | 9 | return new promise(function (resolve, reject) { 10 | check(path, function (err, result) { 11 | err ? reject(err) : resolve(result); 12 | }); 13 | }); 14 | }; 15 | 16 | exports.checkSync = native.getDiskUsage; 17 | 18 | function check(path, callback) { 19 | var result = undefined; 20 | var error = undefined; 21 | 22 | try { 23 | result = native.getDiskUsage(path); 24 | } catch (error_) { 25 | error = error_; 26 | } 27 | 28 | callback(error, result); 29 | } 30 | -------------------------------------------------------------------------------- /src/diskusage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class SystemError 7 | { 8 | public: 9 | SystemError(int errorno, const std::string& syscall, const std::string& message, const std::string& path) 10 | : m_errorno(errorno), m_syscall(syscall), m_message(message), m_path(path) 11 | {} 12 | 13 | int errorno() const { return m_errorno; } 14 | const char* syscall() const { return m_syscall.c_str(); } 15 | const char* message() const { return m_message.c_str(); } 16 | const char* path() const { return m_path.c_str(); } 17 | 18 | private: 19 | int m_errorno; 20 | std::string m_syscall; 21 | std::string m_message; 22 | std::string m_path; 23 | }; 24 | 25 | struct DiskUsage { 26 | uint64_t available; 27 | uint64_t free; 28 | uint64_t total; 29 | }; 30 | 31 | DiskUsage GetDiskUsage(const char* path); 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "diskusage", 3 | "version": "1.2.0", 4 | "description": "Get total diskspace and free diskspace using bindings around platform specific calls.", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "gypfile": true, 8 | "dependencies": { 9 | "es6-promise": "^4.2.8", 10 | "nan": "^2.18.0" 11 | }, 12 | "devDependencies": { 13 | "eslint": "^8.49.0" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/jduncanator/node-diskusage.git" 18 | }, 19 | "keywords": [ 20 | "disk", 21 | "usage", 22 | "df", 23 | "hdd", 24 | "ssd", 25 | "diskusage", 26 | "df", 27 | "free", 28 | "space" 29 | ], 30 | "author": "jduncanator", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/jduncanator/node-diskusage/issues" 34 | }, 35 | "homepage": "https://github.com/jduncanator/node-diskusage" 36 | } 37 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | const { check, checkSync } = require("../"); 2 | const os = require("os"); 3 | 4 | const targetPath = os.platform() === "win32" ? "c:" : "/"; 5 | 6 | function printResults(type, { available, free, total }) { 7 | console.log(`${type} 8 | Available: ${available} 9 | Free: ${free} 10 | Total: ${total} 11 | `); 12 | } 13 | 14 | async function getFreeSpacePromise(path) { 15 | try { 16 | const info = await check(path); 17 | printResults("PROMISE", info); 18 | } catch (err) { 19 | console.error(err); 20 | } 21 | } 22 | 23 | function getFreeSpaceCallback(path) { 24 | check(path, (err, info) => { 25 | if (err) { 26 | console.error(err); 27 | } else { 28 | printResults("CALLBACK", info); 29 | } 30 | }); 31 | } 32 | 33 | function getFreeSpaceSync(path) { 34 | const info = checkSync(path); 35 | printResults("SYNC", info); 36 | } 37 | 38 | async function start() { 39 | await getFreeSpacePromise(targetPath); 40 | getFreeSpaceCallback(targetPath); 41 | getFreeSpaceSync(targetPath); 42 | } 43 | 44 | start() 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | 'target_name': 'diskusage', 5 | 'include_dirs': [ ' 4 | #include 5 | 6 | static v8::Local ConvertDiskUsage(const DiskUsage& usage) 7 | { 8 | v8::Local obj = Nan::New(); 9 | Nan::Set(obj, Nan::New("available").ToLocalChecked(), Nan::New(static_cast(usage.available))); 10 | Nan::Set(obj, Nan::New("free").ToLocalChecked(), Nan::New(static_cast(usage.free))); 11 | Nan::Set(obj, Nan::New("total").ToLocalChecked(), Nan::New(static_cast(usage.total))); 12 | 13 | return obj; 14 | } 15 | 16 | static v8::Local ConvertSystemError(const SystemError& error) 17 | { 18 | return Nan::ErrnoException(error.errorno(), error.syscall(), error.message(), error.path()); 19 | } 20 | 21 | static NAN_METHOD(GetDiskUsage) 22 | { 23 | Nan::HandleScope scope; 24 | 25 | try { 26 | DiskUsage result = GetDiskUsage(*Nan::Utf8String(info[0])); 27 | info.GetReturnValue().Set(ConvertDiskUsage(result)); 28 | } 29 | catch (const SystemError &error) { 30 | Nan::ThrowError(ConvertSystemError(error)); 31 | } 32 | catch (const std::exception &ex) { 33 | Nan::ThrowError(ex.what()); 34 | } 35 | } 36 | 37 | void Init(v8::Local exports) 38 | { 39 | Nan::SetMethod(exports, "getDiskUsage", GetDiskUsage); 40 | } 41 | 42 | NODE_MODULE(diskusage, Init) 43 | -------------------------------------------------------------------------------- /src/diskusage_win.cpp: -------------------------------------------------------------------------------- 1 | #include "diskusage.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static std::wstring Utf8ToUtf16(const char* str) 8 | { 9 | int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); 10 | if (!size) throw std::runtime_error("MultiByteToWideChar failed"); 11 | 12 | std::wstring result; 13 | result.resize(size); 14 | 15 | size = MultiByteToWideChar(CP_UTF8, 0, str, -1, (LPWSTR)result.data(), result.size()); 16 | if (!size) throw std::runtime_error("MultiByteToWideChar failed"); 17 | 18 | return result; 19 | } 20 | 21 | static std::string Utf16ToUtf8(const char* wstr) 22 | { 23 | int size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)wstr, -1, NULL, 0, NULL, NULL); 24 | if (!size) throw std::runtime_error("WideCharToMultiByte failed"); 25 | 26 | std::string result; 27 | result.resize(size); 28 | 29 | size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)wstr, -1, (LPSTR)result.data(), result.size(), NULL, NULL); 30 | if (!size) throw std::runtime_error("WideCharToMultiByte failed"); 31 | 32 | return result; 33 | } 34 | 35 | DiskUsage GetDiskUsage(const char* path) 36 | { 37 | ULARGE_INTEGER available = {}; 38 | ULARGE_INTEGER total = {}; 39 | ULARGE_INTEGER free = {}; 40 | 41 | if (!GetDiskFreeSpaceExW(Utf8ToUtf16(path).c_str(), &available, &total, &free)) { 42 | LPVOID lpMsgBuf; 43 | DWORD lastError = GetLastError(); 44 | 45 | FormatMessage( 46 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 47 | FORMAT_MESSAGE_FROM_SYSTEM | 48 | FORMAT_MESSAGE_IGNORE_INSERTS, 49 | NULL, 50 | lastError, 51 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 52 | (LPTSTR) &lpMsgBuf, 53 | 0, NULL); 54 | 55 | throw SystemError(lastError, "GetDiskFreeSpaceEx", Utf16ToUtf8((char*)lpMsgBuf), path); 56 | } 57 | 58 | DiskUsage result; 59 | result.available = available.QuadPart; 60 | result.free = free.QuadPart; 61 | result.total = total.QuadPart; 62 | 63 | return result; 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-diskusage 2 | ============== 3 | 4 |

5 | npm Version 6 | npm Downloads 7 |

8 | 9 | This module implements platform specific bindings to obtain disk usage information on Windows and POSIX platforms. Windows support is backed by [GetDiskFreeSpaceEx](http://msdn.microsoft.com/en-us/library/windows/desktop/aa364937/) and POSIX is implemented with [statvfs](http://www.freebsd.org/cgi/man.cgi?query=statvfs). 10 | 11 | Installation 12 | ------------ 13 | 14 | Install with `npm`: 15 | 16 | ``` bash 17 | $ npm install diskusage 18 | ``` 19 | 20 | Usage 21 | -------- 22 | 23 | The module exposes two functions. `check` takes a path/mount point as the first argument and a callback as the second. The callback takes two arguments `err` and `info`. `err` will be an `Error` if something went wrong. `info` contains three members: `available`, `free` and `total` in bytes. 24 | 25 | If no callback is supplied `check` will instead return a `Promise` that you can await. 26 | 27 | - `available`: Disk space available to the current user (i.e. Linux reserves 5% for root) 28 | - `free`: Disk space physically free 29 | - `total`: Total disk space (free + used) 30 | 31 | `checkSync` only takes the path argument. It returns the same `info` on success, throws an `Error` on failure. 32 | 33 | Examples 34 | -------- 35 | 36 | ``` js 37 | const disk = require('diskusage'); 38 | const os = require('os'); 39 | 40 | let path = os.platform() === 'win32' ? 'c:' : '/'; 41 | 42 | // Callbacks 43 | disk.check(path, function(err, info) { 44 | if (err) { 45 | console.log(err); 46 | } else { 47 | console.log(info.available); 48 | console.log(info.free); 49 | console.log(info.total); 50 | } 51 | }); 52 | 53 | // Promise 54 | async function getFreeSpace(path) { 55 | try { 56 | const { free } = await disk.check(path); 57 | console.log(`Free space: ${free}`); 58 | return free 59 | } catch (err) { 60 | console.error(err) 61 | return 0 62 | } 63 | } 64 | 65 | // Or without using async/await 66 | disk.check(path) 67 | .then(info => console.log(`free: ${info.free}`)) 68 | .catch(err => console.error(err)) 69 | 70 | // Synchronous 71 | try { 72 | let info = disk.checkSync(path); 73 | console.log(info.available); 74 | console.log(info.free); 75 | console.log(info.total); 76 | } 77 | catch (err) { 78 | console.log(err); 79 | } 80 | ``` 81 | 82 | TypeScript 83 | ---------- 84 | 85 | The module has an embedded .d.ts file. You can use `import * as diskusage from 'diskusage'`. 86 | 87 | ```ts 88 | type DiskUsage = { 89 | available: number; 90 | free: number; 91 | total: number; 92 | } 93 | 94 | export function check(path: string, callback: (error?: Error, result?: DiskUsage) => void): void; 95 | export function check(path: string): Promise 96 | export function checkSync(path: string): DiskUsage; 97 | ``` 98 | 99 | Demo 100 | ---- 101 | 102 | To see a demo of this library see the `demo/` folder. 103 | 104 | You can run it with node: (node 8+ required) 105 | 106 | ```bash 107 | node ./demo/ 108 | ``` 109 | --------------------------------------------------------------------------------