@photostructure/fs-metadata 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/binding.gyp +1 -0
- package/dist/index.cjs +169 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -2
- package/dist/index.d.mts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.mjs +168 -121
- package/dist/index.mjs.map +1 -1
- package/doc/SECURITY_AUDIT_2026.md +1 -0
- package/package.json +5 -5
- package/prebuilds/darwin-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/darwin-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/src/binding.cpp +11 -0
- package/src/darwin/get_mount_point.cpp +96 -0
- package/src/darwin/get_mount_point.h +13 -0
- package/src/index.ts +32 -1
- package/src/mount_point_for_path.ts +54 -0
- package/src/types/native_bindings.ts +7 -0
- package/src/types/options.ts +14 -0
- package/src/volume_metadata.ts +32 -10
|
@@ -190,6 +190,7 @@ A caller could theoretically provide a malicious pattern causing ReDoS.
|
|
|
190
190
|
**Files**: `src/windows/volume_mount_points.cpp`, `src/windows/volume_metadata.cpp`, `src/windows/system_volume.h`
|
|
191
191
|
|
|
192
192
|
**Issue**: `GetVolumeInformationW` was called redundantly:
|
|
193
|
+
|
|
193
194
|
- In `volume_mount_points.cpp`: once for `fstype`/`isReadOnly`, then again inside `IsSystemVolume()`
|
|
194
195
|
- In `volume_metadata.cpp`: `IsSystemVolume()` queried the API, then `VolumeInfo` queried it again 5 lines later
|
|
195
196
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photostructure/fs-metadata",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Cross-platform native filesystem metadata retrieval for Node.js",
|
|
5
5
|
"homepage": "https://photostructure.github.io/fs-metadata/",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"cross-platform"
|
|
92
92
|
],
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"node-addon-api": "^8.
|
|
94
|
+
"node-addon-api": "^8.7.0",
|
|
95
95
|
"node-gyp-build": "^4.8.4"
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"jest-environment-node": "^30.3.0",
|
|
109
109
|
"jest-extended": "^7.0.0",
|
|
110
110
|
"node-gyp": "^12.2.0",
|
|
111
|
-
"npm-check-updates": "^19.6.
|
|
111
|
+
"npm-check-updates": "^19.6.6",
|
|
112
112
|
"npm-run-all2": "8.0.4",
|
|
113
113
|
"prebuildify": "^6.0.1",
|
|
114
114
|
"prettier": "^3.8.1",
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"ts-jest": "^29.4.6",
|
|
118
118
|
"tsup": "^8.5.1",
|
|
119
119
|
"tsx": "^4.21.0",
|
|
120
|
-
"typedoc": "^0.28.
|
|
120
|
+
"typedoc": "^0.28.18",
|
|
121
121
|
"typescript": "^5.9.3",
|
|
122
|
-
"typescript-eslint": "^8.57.
|
|
122
|
+
"typescript-eslint": "^8.57.2"
|
|
123
123
|
}
|
|
124
124
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/binding.cpp
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "windows/hidden.h"
|
|
9
9
|
#elif defined(__APPLE__)
|
|
10
10
|
#include "darwin/fs_meta.h"
|
|
11
|
+
#include "darwin/get_mount_point.h"
|
|
11
12
|
#include "darwin/hidden.h"
|
|
12
13
|
#elif defined(__linux__)
|
|
13
14
|
#include "common/volume_metadata.h"
|
|
@@ -60,6 +61,12 @@ Napi::Value GetVolumeMetadata(const Napi::CallbackInfo &info) {
|
|
|
60
61
|
return FSMeta::GetVolumeMetadata(info);
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
#if defined(__APPLE__)
|
|
65
|
+
Napi::Value GetMountPointForPath(const Napi::CallbackInfo &info) {
|
|
66
|
+
return FSMeta::GetMountPoint(info);
|
|
67
|
+
}
|
|
68
|
+
#endif
|
|
69
|
+
|
|
63
70
|
#if defined(_WIN32) || defined(__APPLE__)
|
|
64
71
|
Napi::Value GetHiddenAttribute(const Napi::CallbackInfo &info) {
|
|
65
72
|
return FSMeta::GetHiddenAttribute(info);
|
|
@@ -81,6 +88,10 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
|
81
88
|
|
|
82
89
|
exports.Set("getVolumeMetadata", Napi::Function::New(env, GetVolumeMetadata));
|
|
83
90
|
|
|
91
|
+
#if defined(__APPLE__)
|
|
92
|
+
exports.Set("getMountPoint", Napi::Function::New(env, GetMountPointForPath));
|
|
93
|
+
#endif
|
|
94
|
+
|
|
84
95
|
#ifdef ENABLE_GIO
|
|
85
96
|
exports.Set("getGioMountPoints", Napi::Function::New(env, GetGioMountPoints));
|
|
86
97
|
#endif
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/darwin/get_mount_point.cpp
|
|
2
|
+
// Lightweight mount point lookup using fstatfs() only.
|
|
3
|
+
// Returns f_mntonname without DiskArbitration, IOKit, or space calculations.
|
|
4
|
+
|
|
5
|
+
#include "./get_mount_point.h"
|
|
6
|
+
#include "../common/debug_log.h"
|
|
7
|
+
#include "../common/error_utils.h"
|
|
8
|
+
#include "../common/fd_guard.h"
|
|
9
|
+
#include "../common/path_security.h"
|
|
10
|
+
|
|
11
|
+
#include <fcntl.h>
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <sys/mount.h>
|
|
14
|
+
#include <sys/param.h>
|
|
15
|
+
#include <unistd.h>
|
|
16
|
+
|
|
17
|
+
namespace FSMeta {
|
|
18
|
+
|
|
19
|
+
class GetMountPointWorker : public Napi::AsyncWorker {
|
|
20
|
+
public:
|
|
21
|
+
GetMountPointWorker(const std::string &path,
|
|
22
|
+
const Napi::Promise::Deferred &deferred)
|
|
23
|
+
: Napi::AsyncWorker(deferred.Env()), path_(path), deferred_(deferred) {}
|
|
24
|
+
|
|
25
|
+
void Execute() override {
|
|
26
|
+
DEBUG_LOG("[GetMountPointWorker] Executing for path: %s", path_.c_str());
|
|
27
|
+
try {
|
|
28
|
+
std::string error;
|
|
29
|
+
std::string validated = ValidatePathForRead(path_, error);
|
|
30
|
+
if (validated.empty()) {
|
|
31
|
+
SetError(error);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
DEBUG_LOG("[GetMountPointWorker] Using validated path: %s",
|
|
36
|
+
validated.c_str());
|
|
37
|
+
|
|
38
|
+
int fd = open(validated.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
|
39
|
+
if (fd < 0) {
|
|
40
|
+
int err = errno;
|
|
41
|
+
DEBUG_LOG("[GetMountPointWorker] open failed: %s (%d)", strerror(err),
|
|
42
|
+
err);
|
|
43
|
+
SetError(CreatePathErrorMessage("open", path_, err));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
FdGuard guard(fd);
|
|
48
|
+
|
|
49
|
+
struct statfs fs;
|
|
50
|
+
if (fstatfs(fd, &fs) != 0) {
|
|
51
|
+
int err = errno;
|
|
52
|
+
DEBUG_LOG("[GetMountPointWorker] fstatfs failed: %s (%d)",
|
|
53
|
+
strerror(err), err);
|
|
54
|
+
SetError(CreatePathErrorMessage("fstatfs", path_, err));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
result_ = fs.f_mntonname;
|
|
59
|
+
DEBUG_LOG("[GetMountPointWorker] mount point: %s", result_.c_str());
|
|
60
|
+
} catch (const std::exception &e) {
|
|
61
|
+
DEBUG_LOG("[GetMountPointWorker] Exception: %s", e.what());
|
|
62
|
+
SetError(e.what());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void OnOK() override {
|
|
67
|
+
Napi::HandleScope scope(Env());
|
|
68
|
+
deferred_.Resolve(Napi::String::New(Env(), result_));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void OnError(const Napi::Error &error) override {
|
|
72
|
+
deferred_.Reject(error.Value());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private:
|
|
76
|
+
std::string path_;
|
|
77
|
+
std::string result_;
|
|
78
|
+
Napi::Promise::Deferred deferred_;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
Napi::Value GetMountPoint(const Napi::CallbackInfo &info) {
|
|
82
|
+
auto env = info.Env();
|
|
83
|
+
DEBUG_LOG("[GetMountPoint] called");
|
|
84
|
+
|
|
85
|
+
if (info.Length() < 1 || !info[0].IsString()) {
|
|
86
|
+
throw Napi::TypeError::New(env, "String argument expected");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
std::string path = info[0].As<Napi::String>().Utf8Value();
|
|
90
|
+
auto deferred = Napi::Promise::Deferred::New(env);
|
|
91
|
+
auto *worker = new GetMountPointWorker(path, deferred);
|
|
92
|
+
worker->Queue();
|
|
93
|
+
return deferred.Promise();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
} // namespace FSMeta
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/darwin/get_mount_point.h
|
|
2
|
+
// Lightweight mount point lookup using fstatfs() only.
|
|
3
|
+
// Returns f_mntonname without DiskArbitration, IOKit, or space calculations.
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include <napi.h>
|
|
8
|
+
|
|
9
|
+
namespace FSMeta {
|
|
10
|
+
|
|
11
|
+
Napi::Value GetMountPoint(const Napi::CallbackInfo &info);
|
|
12
|
+
|
|
13
|
+
} // namespace FSMeta
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
isHiddenRecursiveImpl,
|
|
13
13
|
setHiddenImpl,
|
|
14
14
|
} from "./hidden";
|
|
15
|
+
import { getMountPointForPathImpl } from "./mount_point_for_path";
|
|
15
16
|
import {
|
|
16
17
|
getTimeoutMsDefault,
|
|
17
18
|
IncludeSystemVolumesDefault,
|
|
@@ -121,7 +122,9 @@ export function getVolumeMetadata(
|
|
|
121
122
|
*/
|
|
122
123
|
export function getVolumeMetadataForPath(
|
|
123
124
|
pathname: string,
|
|
124
|
-
opts?: Partial<
|
|
125
|
+
opts?: Partial<
|
|
126
|
+
Pick<Options, "timeoutMs" | "linuxMountTablePaths" | "mountPoints">
|
|
127
|
+
>,
|
|
125
128
|
): Promise<VolumeMetadata> {
|
|
126
129
|
return getVolumeMetadataForPathImpl(
|
|
127
130
|
pathname,
|
|
@@ -130,6 +133,34 @@ export function getVolumeMetadataForPath(
|
|
|
130
133
|
);
|
|
131
134
|
}
|
|
132
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Get the mount point path for an arbitrary file or directory path.
|
|
138
|
+
*
|
|
139
|
+
* This is a lightweight alternative to {@link getVolumeMetadataForPath} when
|
|
140
|
+
* you only need the mount point string. On macOS it uses a single fstatfs()
|
|
141
|
+
* call (no DiskArbitration, IOKit, or space calculations). On Linux/Windows
|
|
142
|
+
* it uses device ID matching against the mount table.
|
|
143
|
+
*
|
|
144
|
+
* Symlinks are resolved, and macOS APFS firmlinks (e.g. `/Users` →
|
|
145
|
+
* `/System/Volumes/Data`) are handled correctly.
|
|
146
|
+
*
|
|
147
|
+
* @param pathname Path to any file or directory
|
|
148
|
+
* @param opts Optional settings (timeoutMs, linuxMountTablePaths)
|
|
149
|
+
* @returns The mount point path (e.g., "/", "/System/Volumes/Data", "C:\\")
|
|
150
|
+
*/
|
|
151
|
+
export function getMountPointForPath(
|
|
152
|
+
pathname: string,
|
|
153
|
+
opts?: Partial<
|
|
154
|
+
Pick<Options, "timeoutMs" | "linuxMountTablePaths" | "mountPoints">
|
|
155
|
+
>,
|
|
156
|
+
): Promise<string> {
|
|
157
|
+
return getMountPointForPathImpl(
|
|
158
|
+
pathname,
|
|
159
|
+
optionsWithDefaults(opts),
|
|
160
|
+
nativeFn,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
133
164
|
/**
|
|
134
165
|
* Retrieves metadata for all mounted volumes with optional filtering and
|
|
135
166
|
* concurrency control.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/mount_point_for_path.ts
|
|
2
|
+
|
|
3
|
+
import { realpath } from "node:fs/promises";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
import { withTimeout } from "./async";
|
|
6
|
+
import { debug } from "./debuglog";
|
|
7
|
+
import { statAsync } from "./fs";
|
|
8
|
+
import { isMacOS } from "./platform";
|
|
9
|
+
import { isBlank, isNotBlank } from "./string";
|
|
10
|
+
import type { NativeBindingsFn } from "./types/native_bindings";
|
|
11
|
+
import type { Options } from "./types/options";
|
|
12
|
+
import { findMountPointByDeviceId } from "./volume_metadata";
|
|
13
|
+
|
|
14
|
+
export async function getMountPointForPathImpl(
|
|
15
|
+
pathname: string,
|
|
16
|
+
opts: Options,
|
|
17
|
+
nativeFn: NativeBindingsFn,
|
|
18
|
+
): Promise<string> {
|
|
19
|
+
if (isBlank(pathname)) {
|
|
20
|
+
throw new TypeError("Invalid pathname: got " + JSON.stringify(pathname));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// realpath() resolves POSIX symlinks. APFS firmlinks are NOT resolved by
|
|
24
|
+
// realpath(), but fstatfs() follows them — handled below on macOS.
|
|
25
|
+
const resolved = await realpath(pathname);
|
|
26
|
+
|
|
27
|
+
const resolvedStat = await statAsync(resolved);
|
|
28
|
+
const dir = resolvedStat.isDirectory() ? resolved : dirname(resolved);
|
|
29
|
+
|
|
30
|
+
if (isMacOS) {
|
|
31
|
+
// Use the lightweight native getMountPoint which only does fstatfs —
|
|
32
|
+
// no DiskArbitration, IOKit, or space calculations.
|
|
33
|
+
const native = await nativeFn();
|
|
34
|
+
if (native.getMountPoint) {
|
|
35
|
+
debug("[getMountPointForPath] using native getMountPoint for %s", dir);
|
|
36
|
+
const p = native.getMountPoint(dir);
|
|
37
|
+
const mountPoint = await withTimeout({
|
|
38
|
+
desc: "getMountPoint()",
|
|
39
|
+
timeoutMs: opts.timeoutMs,
|
|
40
|
+
promise: p,
|
|
41
|
+
});
|
|
42
|
+
if (isNotBlank(mountPoint)) {
|
|
43
|
+
debug("[getMountPointForPath] resolved to %s", mountPoint);
|
|
44
|
+
return mountPoint;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Fallback: should not happen on macOS, but defensive
|
|
48
|
+
throw new Error("getMountPoint native function unavailable");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Linux/Windows: device ID matching + path prefix tiebreaker
|
|
52
|
+
debug("[getMountPointForPath] using device matching for %s", resolved);
|
|
53
|
+
return findMountPointByDeviceId(resolved, resolvedStat, opts, nativeFn);
|
|
54
|
+
}
|
|
@@ -54,6 +54,13 @@ export interface NativeBindings {
|
|
|
54
54
|
* subsequent parsing and extraction logic.
|
|
55
55
|
*/
|
|
56
56
|
getVolumeMetadata(options: GetVolumeMetadataOptions): Promise<VolumeMetadata>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* macOS only: lightweight mount point lookup using fstatfs().
|
|
60
|
+
* Returns the f_mntonname for the given directory path without fetching
|
|
61
|
+
* full volume metadata (no DiskArbitration, no IOKit, no space calculation).
|
|
62
|
+
*/
|
|
63
|
+
getMountPoint?(path: string): Promise<string>;
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
export type GetVolumeMetadataOptions = {
|
package/src/types/options.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/types/options.ts
|
|
2
2
|
|
|
3
|
+
import type { MountPoint } from "./mount_point";
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Configuration options for filesystem operations.
|
|
5
7
|
*
|
|
@@ -7,6 +9,18 @@
|
|
|
7
9
|
* @see {@link OptionsDefault} for the default values
|
|
8
10
|
*/
|
|
9
11
|
export interface Options {
|
|
12
|
+
/**
|
|
13
|
+
* Pre-fetched mount points to use instead of querying the system.
|
|
14
|
+
*
|
|
15
|
+
* When provided, functions like {@link getMountPointForPath} and
|
|
16
|
+
* {@link getVolumeMetadataForPath} will use these mount points for device ID
|
|
17
|
+
* matching instead of calling {@link getVolumeMountPoints} internally. This
|
|
18
|
+
* avoids redundant system queries when resolving multiple paths.
|
|
19
|
+
*
|
|
20
|
+
* Obtain via `getVolumeMountPoints({ includeSystemVolumes: true })` — system
|
|
21
|
+
* volumes must be included for device ID matching to work correctly.
|
|
22
|
+
*/
|
|
23
|
+
mountPoints?: MountPoint[];
|
|
10
24
|
/**
|
|
11
25
|
* Timeout in milliseconds for filesystem operations.
|
|
12
26
|
*
|
package/src/volume_metadata.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/volume_metadata.ts
|
|
2
2
|
|
|
3
|
+
import type { Stats } from "node:fs";
|
|
3
4
|
import { realpath } from "node:fs/promises";
|
|
4
5
|
import { dirname } from "node:path";
|
|
5
6
|
import { mapConcurrent, withTimeout } from "./async";
|
|
@@ -209,12 +210,38 @@ export async function getVolumeMetadataForPathImpl(
|
|
|
209
210
|
// Linux/Windows: stat().dev is reliable (no firmlinks). Find the mount point
|
|
210
211
|
// by comparing device IDs, using path prefix as a tiebreaker for bind mounts
|
|
211
212
|
// or GIO mounts that share the same device id.
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
const mountPoint = await findMountPointByDeviceId(
|
|
214
|
+
resolved,
|
|
215
|
+
resolvedStat,
|
|
216
|
+
opts,
|
|
215
217
|
nativeFn,
|
|
216
218
|
);
|
|
217
219
|
|
|
220
|
+
return getVolumeMetadataImpl({ ...opts, mountPoint }, nativeFn);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Find the mount point for a resolved path using device ID matching.
|
|
225
|
+
* Used on Linux and Windows where stat().dev is reliable (no firmlinks).
|
|
226
|
+
*
|
|
227
|
+
* Compares device IDs of mount points against the target path's device ID,
|
|
228
|
+
* using path prefix as a tiebreaker for bind mounts or GIO mounts that share
|
|
229
|
+
* the same device id. The longest prefix match wins.
|
|
230
|
+
*/
|
|
231
|
+
export async function findMountPointByDeviceId(
|
|
232
|
+
resolved: string,
|
|
233
|
+
resolvedStat: Stats,
|
|
234
|
+
opts: Options,
|
|
235
|
+
nativeFn: NativeBindingsFn,
|
|
236
|
+
): Promise<string> {
|
|
237
|
+
const targetDev = resolvedStat.dev;
|
|
238
|
+
const mountPoints =
|
|
239
|
+
opts.mountPoints ??
|
|
240
|
+
(await getVolumeMountPointsImpl(
|
|
241
|
+
{ ...opts, includeSystemVolumes: true },
|
|
242
|
+
nativeFn,
|
|
243
|
+
));
|
|
244
|
+
|
|
218
245
|
const prefixMatches: string[] = [];
|
|
219
246
|
const deviceMatches: string[] = [];
|
|
220
247
|
|
|
@@ -234,18 +261,13 @@ export async function getVolumeMetadataForPathImpl(
|
|
|
234
261
|
}),
|
|
235
262
|
);
|
|
236
263
|
|
|
237
|
-
// Longest prefix match wins; fall back to device-only match.
|
|
238
264
|
const candidates = prefixMatches.length > 0 ? prefixMatches : deviceMatches;
|
|
239
265
|
if (candidates.length === 0) {
|
|
240
266
|
throw new Error(
|
|
241
|
-
"No mount point found for path: " + JSON.stringify(
|
|
267
|
+
"No mount point found for path: " + JSON.stringify(resolved),
|
|
242
268
|
);
|
|
243
269
|
}
|
|
244
|
-
|
|
245
|
-
a.length >= b.length ? a : b,
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
return getVolumeMetadataImpl({ ...opts, mountPoint }, nativeFn);
|
|
270
|
+
return candidates.reduce((a, b) => (a.length >= b.length ? a : b));
|
|
249
271
|
}
|
|
250
272
|
|
|
251
273
|
export async function getAllVolumeMetadataImpl(
|