import assert from 'node:assert'; import BoxError from './boxerror.js'; import debugModule from 'debug'; import safe from 'safetydance'; import shellModule from './shell.js'; const debug = debugModule('box:df'); const shell = shellModule('df'); // binary units (non SI) 1024 based function prettyBytes(bytes) { assert.strictEqual(typeof bytes, 'number'); const i = Math.floor(Math.log(bytes) / Math.log(1024)), sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; return (bytes / Math.pow(1024, i)).toFixed(2) * 1 + '' + sizes[i]; } function parseLine(line) { const parts = line.split(/\s+/, 7); // this way the mountpoint can have spaces in it return { filesystem: parts[0], type: parts[1], size: Number.parseInt(parts[2], 10), used: Number.parseInt(parts[3], 10), available: Number.parseInt(parts[4], 10), capacity: Number.parseInt(parts[5], 10) / 100, // note: this has a trailing % mountpoint: parts[6] }; } async function filesystems() { const [error, output] = await safe(shell.spawn('df', ['-B1', '--output=source,fstype,size,used,avail,pcent,target'], { encoding: 'utf8', timeout: 5000 })); if (error) { debug(`filesystems: df command failed. error: ${error}\n stdout: ${error.stdout}\n stderr: ${error.stderr}`); throw new BoxError(BoxError.FS_ERROR, `Error running df: ${error.message}`); } const lines = output.trim().split('\n').slice(1); // discard header const result = []; for (const line of lines) { result.push(parseLine(line)); } return result; } async function file(filename) { assert.strictEqual(typeof filename, 'string'); if (!safe.fs.existsSync(filename)) throw new BoxError(BoxError.NOT_FOUND, `Path ${filename} does not exist`); const [error, output] = await safe(shell.spawn('df', ['-B1', '--output=source,fstype,size,used,avail,pcent,target', filename], { encoding: 'utf8', timeout: 5000 })); if (error) { debug(`file: df command failed. error: ${error}\n stdout: ${error.stdout}\n stderr: ${error.stderr}`); throw new BoxError(BoxError.FS_ERROR, `Error running df: ${error.message}`); } const lines = output.trim().split('\n').slice(1); // discard header return parseLine(lines[0]); } export default { filesystems, file, prettyBytes };