Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs: add statfs() functions #46358

Merged
merged 2 commits into from
Jan 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1531,6 +1531,19 @@ changes:
* Returns: {Promise} Fulfills with the {fs.Stats} object for the
given `path`.

### `fsPromises.statfs(path[, options])`

<!-- YAML
added: REPLACEME
-->

* `path` {string|Buffer|URL}
* `options` {Object}
* `bigint` {boolean} Whether the numeric values in the returned
{fs.StatFs} object should be `bigint`. **Default:** `false`.
* Returns: {Promise} Fulfills with the {fs.StatFs} object for the
given `path`.

### `fsPromises.symlink(target, path[, type])`

<!-- YAML
Expand Down Expand Up @@ -4101,6 +4114,26 @@ Stats {
}
```

### `fs.statfs(path[, options], callback)`

<!-- YAML
added: REPLACEME
-->

* `path` {string|Buffer|URL}
* `options` {Object}
* `bigint` {boolean} Whether the numeric values in the returned
{fs.StatFs} object should be `bigint`. **Default:** `false`.
* `callback` {Function}
* `err` {Error}
* `stats` {fs.StatFs}

Asynchronous statfs(2). Returns information about the mounted file system which
contains `path`. The callback gets two arguments `(err, stats)` where `stats`
is an {fs.StatFs} object.

In case of an error, the `err.code` will be one of [Common System Errors][].

### `fs.symlink(target, path[, type], callback)`

<!-- YAML
Expand Down Expand Up @@ -5852,6 +5885,23 @@ changes:

Retrieves the {fs.Stats} for the path.

### `fs.statfsSync(path[, options])`

<!-- YAML
added: REPLACEME
-->

* `path` {string|Buffer|URL}
* `options` {Object}
* `bigint` {boolean} Whether the numeric values in the returned
{fs.StatFs} object should be `bigint`. **Default:** `false`.
* Returns: {fs.StatFs}

Synchronous statfs(2). Returns information about the mounted file system which
contains `path`.

In case of an error, the `err.code` will be one of [Common System Errors][].

### `fs.symlinkSync(target, path[, type])`

<!-- YAML
Expand Down Expand Up @@ -6944,6 +6994,114 @@ The times in the stat object have the following semantics:
Prior to Node.js 0.12, the `ctime` held the `birthtime` on Windows systems. As
of 0.12, `ctime` is not "creation time", and on Unix systems, it never was.

### Class: `fs.StatFs`

<!-- YAML
added: REPLACEME
-->

Provides information about a mounted file system.

Objects returned from [`fs.statfs()`][] and its synchronous counterpart are of
this type. If `bigint` in the `options` passed to those methods is `true`, the
numeric values will be `bigint` instead of `number`.

```console
StatFs {
type: 1397114950,
bsize: 4096,
blocks: 121938943,
bfree: 61058895,
bavail: 61058895,
files: 999,
ffree: 1000000
}
```

`bigint` version:

```console
StatFs {
type: 1397114950n,
bsize: 4096n,
blocks: 121938943n,
bfree: 61058895n,
bavail: 61058895n,
files: 999n,
ffree: 1000000n
}
```

#### `statfs.bavail`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Free blocks available to unprivileged users.

#### `statfs.bfree`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Free blocks in file system.

#### `statfs.blocks`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Total data blocks in file system.

#### `statfs.bsize`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Optimal transfer block size.

#### `statfs.ffree`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Free file nodes in file system.

#### `statfs.files`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Total file nodes in file system.

#### `statfs.type`

<!-- YAML
added: REPLACEME
-->

* {number|bigint}

Type of file system.

### Class: `fs.WriteStream`

<!-- YAML
Expand Down Expand Up @@ -7787,6 +7945,7 @@ the file contents.
[`fs.rmSync()`]: #fsrmsyncpath-options
[`fs.rmdir()`]: #fsrmdirpath-options-callback
[`fs.stat()`]: #fsstatpath-options-callback
[`fs.statfs()`]: #fsstatfspath-options-callback
[`fs.symlink()`]: #fssymlinktarget-path-type-callback
[`fs.utimes()`]: #fsutimespath-atime-mtime-callback
[`fs.watch()`]: #fswatchfilename-options-listener
Expand Down
30 changes: 30 additions & 0 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const {
nullCheck,
preprocessSymlinkDestination,
Stats,
getStatFsFromBinding,
getStatsFromBinding,
realpathCacheKey,
stringToFlags,
Expand Down Expand Up @@ -1509,6 +1510,24 @@ function stat(path, options = { bigint: false }, callback) {
binding.stat(pathModule.toNamespacedPath(path), options.bigint, req);
}

function statfs(path, options = { bigint: false }, callback) {
if (typeof options === 'function') {
callback = options;
options = kEmptyObject;
}
callback = maybeCallback(callback);
path = getValidatedPath(path);
const req = new FSReqCallback(options.bigint);
req.oncomplete = (err, stats) => {
if (err) {
return callback(err);
}

callback(err, getStatFsFromBinding(stats));
};
binding.statfs(pathModule.toNamespacedPath(path), options.bigint, req);
}

function hasNoEntryError(ctx) {
if (ctx.errno) {
const uvErr = uvErrmapGet(ctx.errno);
Expand Down Expand Up @@ -1583,6 +1602,15 @@ function statSync(path, options = { bigint: false, throwIfNoEntry: true }) {
return getStatsFromBinding(stats);
}

function statfsSync(path, options = { bigint: false }) {
path = getValidatedPath(path);
const ctx = { path };
const stats = binding.statfs(pathModule.toNamespacedPath(path),
options.bigint, undefined, ctx);
handleErrorFromBinding(ctx);
return getStatFsFromBinding(stats);
}

/**
* Reads the contents of a symbolic link
* referred to by `path`.
Expand Down Expand Up @@ -3013,7 +3041,9 @@ module.exports = fs = {
rmdir,
rmdirSync,
stat,
statfs,
statSync,
statfsSync,
symlink,
symlinkSync,
truncate,
Expand Down
9 changes: 9 additions & 0 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const {
emitRecursiveRmdirWarning,
getDirents,
getOptions,
getStatFsFromBinding,
getStatsFromBinding,
getValidatedPath,
getValidMode,
Expand Down Expand Up @@ -781,6 +782,13 @@ async function stat(path, options = { bigint: false }) {
return getStatsFromBinding(result);
}

async function statfs(path, options = { bigint: false }) {
path = getValidatedPath(path);
const result = await binding.statfs(pathModule.toNamespacedPath(path),
options.bigint, kUsePromises);
return getStatFsFromBinding(result);
}

async function link(existingPath, newPath) {
existingPath = getValidatedPath(existingPath, 'existingPath');
newPath = getValidatedPath(newPath, 'newPath');
Expand Down Expand Up @@ -953,6 +961,7 @@ module.exports = {
symlink,
lstat,
stat,
statfs,
link,
unlink,
chmod,
Expand Down
19 changes: 19 additions & 0 deletions lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,24 @@ function getStatsFromBinding(stats, offset = 0) {
);
}

class StatFs {
constructor(type, bsize, blocks, bfree, bavail, files, ffree) {
this.type = type;
this.bsize = bsize;
this.blocks = blocks;
this.bfree = bfree;
this.bavail = bavail;
this.files = files;
this.ffree = ffree;
}
}

function getStatFsFromBinding(stats) {
return new StatFs(
stats[0], stats[1], stats[2], stats[3], stats[4], stats[5], stats[6]
);
}

function stringToFlags(flags, name = 'flags') {
if (typeof flags === 'number') {
validateInt32(flags, name);
Expand Down Expand Up @@ -912,6 +930,7 @@ module.exports = {
nullCheck,
preprocessSymlinkDestination,
realpathCacheKey: Symbol('realpathCacheKey'),
getStatFsFromBinding,
getStatsFromBinding,
stringToFlags,
stringToSymlinkType,
Expand Down
Loading