@photostructure/fs-metadata 0.0.1

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.
@@ -0,0 +1,69 @@
1
+ // src/common/metadata_worker.h
2
+ #pragma once
3
+ #include "./volume_metadata.h"
4
+ #include <napi.h>
5
+
6
+ namespace FSMeta {
7
+
8
+ class MetadataWorkerBase : public Napi::AsyncWorker {
9
+ protected:
10
+ std::string mountPoint;
11
+ VolumeMetadata metadata;
12
+ Napi::Promise::Deferred deferred_;
13
+
14
+ MetadataWorkerBase(const std::string &path,
15
+ const Napi::Promise::Deferred &deferred)
16
+ : Napi::AsyncWorker(deferred.Env()), mountPoint(path),
17
+ deferred_(deferred) {}
18
+
19
+ void OnError(const Napi::Error &error) override {
20
+ deferred_.Reject(error.Value());
21
+ }
22
+
23
+ // Creates a JavaScript object from VolumeMetadata
24
+ Napi::Object CreateResultObject() {
25
+ auto env = Env();
26
+ auto result = Napi::Object::New(env);
27
+
28
+ // Match the current VolumeMetadata struct members
29
+ result.Set("label", metadata.label.empty()
30
+ ? env.Null()
31
+ : Napi::String::New(env, metadata.label));
32
+ result.Set("fileSystem", metadata.fileSystem.empty()
33
+ ? env.Null()
34
+ : Napi::String::New(env, metadata.fileSystem));
35
+ result.Set("size", Napi::Number::New(env, metadata.size));
36
+ result.Set("used", Napi::Number::New(env, metadata.used));
37
+ result.Set("available", Napi::Number::New(env, metadata.available));
38
+ result.Set("uuid", metadata.uuid.empty()
39
+ ? env.Null()
40
+ : Napi::String::New(env, metadata.uuid));
41
+ result.Set("mountFrom", metadata.mountFrom.empty()
42
+ ? env.Null()
43
+ : Napi::String::New(env, metadata.mountFrom));
44
+ result.Set("mountName", metadata.mountName.empty()
45
+ ? env.Null()
46
+ : Napi::String::New(env, metadata.mountName));
47
+ result.Set("uri", metadata.uri.empty()
48
+ ? env.Null()
49
+ : Napi::String::New(env, metadata.uri));
50
+ result.Set("status", Napi::String::New(env, metadata.status));
51
+
52
+ if (metadata.remote) {
53
+ result.Set("remote", Napi::Boolean::New(env, metadata.remote));
54
+ }
55
+ result.Set("remoteHost", metadata.remoteHost.empty()
56
+ ? env.Null()
57
+ : Napi::String::New(env, metadata.remoteHost));
58
+ result.Set("remoteShare",
59
+ metadata.remoteShare.empty()
60
+ ? env.Null()
61
+ : Napi::String::New(env, metadata.remoteShare));
62
+
63
+ return result;
64
+ };
65
+
66
+ void OnOK() override { deferred_.Resolve(CreateResultObject()); }
67
+ }; // class MetadataWorkerBase
68
+
69
+ } // namespace FSMeta
@@ -0,0 +1,13 @@
1
+ // src/common/mount_point.h
2
+ #pragma once
3
+ #include <napi.h>
4
+ #include <string>
5
+
6
+ namespace FSMeta {
7
+
8
+ struct MountPoint {
9
+ std::string mountPoint;
10
+ std::string fstype;
11
+ };
12
+
13
+ } // namespace FSMeta
@@ -0,0 +1,34 @@
1
+ // src/common/volume_metadata.h
2
+ #pragma once
3
+ #include <napi.h>
4
+ #include <string>
5
+
6
+ namespace FSMeta {
7
+
8
+ // Volume metadata structure
9
+ struct VolumeMetadata {
10
+ std::string label;
11
+ std::string fileSystem;
12
+ double size;
13
+ double used;
14
+ double available;
15
+ std::string uuid;
16
+ std::string mountFrom;
17
+ std::string mountName;
18
+ std::string uri;
19
+ std::string status;
20
+ bool remote = false;
21
+ std::string remoteHost;
22
+ std::string remoteShare;
23
+ };
24
+
25
+ struct VolumeMetadataOptions {
26
+ uint32_t timeoutMs = 5000;
27
+ std::string device;
28
+ };
29
+
30
+ Napi::Value GetVolumeMetadata(const Napi::Env &env,
31
+ const std::string &mountPoint,
32
+ const Napi::Object &options);
33
+
34
+ } // namespace FSMeta
@@ -0,0 +1,8 @@
1
+ // src/common/volume_mount_points.h
2
+ #pragma once
3
+ #include <napi.h>
4
+ #include <string>
5
+
6
+ namespace FSMeta {
7
+ Napi::Value GetVolumeMountPoints(Napi::Env env);
8
+ }
@@ -0,0 +1,18 @@
1
+ // src/darwin/fs_meta.h
2
+
3
+ #pragma once
4
+
5
+ #include "../common/error_utils.h"
6
+ #include "../common/metadata_worker.h"
7
+ #include "../common/mount_point.h"
8
+ #include "../common/volume_mount_points.h"
9
+
10
+ namespace FSMeta {
11
+
12
+ // Forward declarations of the main interface functions
13
+ Napi::Value GetVolumeMountPoints(Napi::Env env);
14
+ Napi::Value GetVolumeMetadata(const Napi::Env &env,
15
+ const std::string &mountPoint,
16
+ const Napi::Object &options);
17
+
18
+ } // namespace FSMeta
@@ -0,0 +1,235 @@
1
+ // src/darwin/volume_metadata.cpp
2
+
3
+ #include "./fs_meta.h"
4
+
5
+ #include <CoreFoundation/CoreFoundation.h>
6
+ #include <DiskArbitration/DiskArbitration.h>
7
+ #include <IOKit/IOBSD.h>
8
+ #include <IOKit/storage/IOMedia.h>
9
+ #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
10
+ #include <memory>
11
+ #include <string>
12
+ #include <sys/mount.h>
13
+ #include <sys/param.h>
14
+ #include <sys/statvfs.h>
15
+
16
+ namespace FSMeta {
17
+
18
+ // Helper function to convert CFString to std::string
19
+ static std::string CFStringToString(CFStringRef cfString) {
20
+ if (!cfString) {
21
+ return "";
22
+ }
23
+
24
+ CFIndex length = CFStringGetLength(cfString);
25
+ CFIndex maxSize =
26
+ CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
27
+ std::string result(maxSize, '\0');
28
+
29
+ if (!CFStringGetCString(cfString, &result[0], maxSize,
30
+ kCFStringEncodingUTF8)) {
31
+ return "";
32
+ }
33
+
34
+ result.resize(strlen(result.c_str()));
35
+ return result;
36
+ }
37
+
38
+ // Improved CFReleaser with proper Core Foundation support
39
+ template <typename T> class CFReleaser {
40
+ private:
41
+ T ref_;
42
+
43
+ public:
44
+ explicit CFReleaser(T ref = nullptr) noexcept : ref_(ref) {}
45
+
46
+ // Delete copy operations
47
+ CFReleaser(const CFReleaser &) = delete;
48
+ CFReleaser &operator=(const CFReleaser &) = delete;
49
+
50
+ // Move operations
51
+ CFReleaser(CFReleaser &&other) noexcept : ref_(other.ref_) {
52
+ other.ref_ = nullptr;
53
+ }
54
+
55
+ CFReleaser &operator=(CFReleaser &&other) noexcept {
56
+ if (this != &other) {
57
+ reset();
58
+ ref_ = other.ref_;
59
+ other.ref_ = nullptr;
60
+ }
61
+ return *this;
62
+ }
63
+
64
+ ~CFReleaser() { reset(); }
65
+
66
+ void reset(T ref = nullptr) {
67
+ if (ref_) {
68
+ CFRelease(ref_);
69
+ }
70
+ ref_ = ref;
71
+ }
72
+
73
+ // Implicit conversion operator for Core Foundation APIs
74
+ operator T() const noexcept { return ref_; }
75
+
76
+ T get() const noexcept { return ref_; }
77
+ bool isValid() const noexcept { return ref_ != nullptr; }
78
+
79
+ // Release ownership
80
+ T release() noexcept {
81
+ T temp = ref_;
82
+ ref_ = nullptr;
83
+ return temp;
84
+ }
85
+ };
86
+
87
+ class GetVolumeMetadataWorker : public MetadataWorkerBase {
88
+ public:
89
+ GetVolumeMetadataWorker(const std::string &path,
90
+ const Napi::Promise::Deferred &deferred)
91
+ : MetadataWorkerBase(path, deferred) {
92
+
93
+ if (path.empty()) {
94
+ throw FSException("Mount point path cannot be empty");
95
+ }
96
+ }
97
+
98
+ void Execute() override {
99
+ try {
100
+ if (!GetBasicVolumeInfo()) {
101
+ return;
102
+ }
103
+ GetDiskArbitrationInfo();
104
+ } catch (const std::exception &e) {
105
+ SetError(e.what());
106
+ }
107
+ }
108
+
109
+ private:
110
+ bool GetBasicVolumeInfo() {
111
+ struct statvfs vfs;
112
+ struct statfs fs;
113
+
114
+ if (statvfs(mountPoint.c_str(), &vfs) != 0) {
115
+ SetError(CreateErrorMessage("statvfs", errno));
116
+ return false;
117
+ }
118
+
119
+ if (statfs(mountPoint.c_str(), &fs) != 0) {
120
+ SetError(CreateErrorMessage("statfs", errno));
121
+ return false;
122
+ }
123
+
124
+ // Calculate sizes using uint64_t to prevent overflow
125
+ const uint64_t blockSize = vfs.f_frsize ? vfs.f_frsize : vfs.f_bsize;
126
+ const uint64_t totalBlocks = vfs.f_blocks;
127
+ const uint64_t availBlocks = vfs.f_bavail;
128
+ const uint64_t freeBlocks = vfs.f_bfree;
129
+
130
+ // Check for overflow before multiplication
131
+ if (blockSize > 0 &&
132
+ totalBlocks > std::numeric_limits<uint64_t>::max() / blockSize) {
133
+ SetError("Volume size calculation would overflow");
134
+ return false;
135
+ }
136
+
137
+ metadata.size = static_cast<double>(blockSize * totalBlocks);
138
+ metadata.available = static_cast<double>(blockSize * availBlocks);
139
+ metadata.used = static_cast<double>(blockSize * (totalBlocks - freeBlocks));
140
+
141
+ metadata.fileSystem = fs.f_fstypename;
142
+ metadata.mountFrom = fs.f_mntfromname;
143
+ metadata.mountName = fs.f_mntonname;
144
+ metadata.status = "ready";
145
+
146
+ return true;
147
+ }
148
+
149
+ void GetDiskArbitrationInfo() {
150
+ CFReleaser<DASessionRef> session(DASessionCreate(kCFAllocatorDefault));
151
+ if (!session.isValid()) {
152
+ metadata.status = "partial";
153
+ return;
154
+ }
155
+
156
+ // Schedule session with RunLoop
157
+ DASessionScheduleWithRunLoop(session.get(), CFRunLoopGetCurrent(),
158
+ kCFRunLoopDefaultMode);
159
+
160
+ // RAII cleanup for RunLoop scheduling
161
+ struct RunLoopCleaner {
162
+ DASessionRef session;
163
+ explicit RunLoopCleaner(DASessionRef s) : session(s) {}
164
+ ~RunLoopCleaner() {
165
+ DASessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(),
166
+ kCFRunLoopDefaultMode);
167
+ }
168
+ } runLoopCleaner(session.get());
169
+
170
+ CFReleaser<DADiskRef> disk(DADiskCreateFromBSDName(
171
+ kCFAllocatorDefault, session.get(), metadata.mountFrom.c_str()));
172
+
173
+ if (!disk.isValid()) {
174
+ metadata.status = "partial";
175
+ return;
176
+ }
177
+
178
+ CFReleaser<CFDictionaryRef> description(DADiskCopyDescription(disk.get()));
179
+ if (!description.isValid()) {
180
+ metadata.status = "partial";
181
+ return;
182
+ }
183
+
184
+ ProcessDiskDescription(description.get());
185
+ }
186
+
187
+ void ProcessDiskDescription(CFDictionaryRef description) {
188
+ // Get volume name/label
189
+ if (CFStringRef volumeName = (CFStringRef)CFDictionaryGetValue(
190
+ description, kDADiskDescriptionVolumeNameKey)) {
191
+ metadata.label = CFStringToString(volumeName);
192
+ }
193
+
194
+ // Get UUID
195
+ if (CFUUIDRef uuid = (CFUUIDRef)CFDictionaryGetValue(
196
+ description, kDADiskDescriptionVolumeUUIDKey)) {
197
+ CFReleaser<CFStringRef> uuidString(
198
+ CFUUIDCreateString(kCFAllocatorDefault, uuid));
199
+ if (uuidString.isValid()) {
200
+ metadata.uuid = CFStringToString(uuidString.get());
201
+ }
202
+ }
203
+
204
+ ProcessNetworkVolume(description);
205
+ }
206
+
207
+ void ProcessNetworkVolume(CFDictionaryRef description) {
208
+ CFBooleanRef isNetworkVolume = (CFBooleanRef)CFDictionaryGetValue(
209
+ description, kDADiskDescriptionVolumeNetworkKey);
210
+
211
+ metadata.remote = CFBooleanGetValue(isNetworkVolume);
212
+ CFURLRef url = (CFURLRef)CFDictionaryGetValue(
213
+ description, kDADiskDescriptionVolumePathKey);
214
+ if (!url) {
215
+ return;
216
+ }
217
+
218
+ CFStringRef urlString = CFURLGetString(url);
219
+ if (!urlString) {
220
+ return;
221
+ }
222
+ metadata.uri = CFStringToString(urlString);
223
+ }
224
+ };
225
+
226
+ Napi::Value GetVolumeMetadata(const Napi::Env &env,
227
+ const std::string &mountPoint,
228
+ const Napi::Object &options) {
229
+ auto deferred = Napi::Promise::Deferred::New(env);
230
+ auto *worker = new GetVolumeMetadataWorker(mountPoint, deferred);
231
+ worker->Queue();
232
+ return deferred.Promise();
233
+ }
234
+
235
+ } // namespace FSMeta
@@ -0,0 +1,65 @@
1
+ // src/darwin/volume_mount_points.cpp
2
+
3
+ #include "./fs_meta.h"
4
+ #include <sys/mount.h>
5
+ #include <sys/param.h>
6
+ #include <vector>
7
+
8
+ namespace FSMeta {
9
+
10
+ class GetVolumeMountPointsWorker : public Napi::AsyncWorker {
11
+ public:
12
+ GetVolumeMountPointsWorker(const Napi::Promise::Deferred &deferred)
13
+ : Napi::AsyncWorker(deferred.Env()), deferred_(deferred) {}
14
+
15
+ void Execute() override {
16
+ try {
17
+ struct statfs *mntbufp;
18
+ int count = getmntinfo(&mntbufp, MNT_WAIT);
19
+
20
+ if (count <= 0) {
21
+ throw std::runtime_error("Failed to get mount information");
22
+ }
23
+
24
+ for (int i = 0; i < count; i++) {
25
+ MountPoint point;
26
+ point.mountPoint = mntbufp[i].f_mntonname;
27
+ point.fstype = mntbufp[i].f_fstypename;
28
+ mountPoints.push_back(point);
29
+ }
30
+ } catch (const std::exception &e) {
31
+ SetError(e.what());
32
+ }
33
+ }
34
+
35
+ void OnOK() override {
36
+ Napi::HandleScope scope(Env());
37
+ Napi::Array result = Napi::Array::New(Env());
38
+
39
+ for (size_t i = 0; i < mountPoints.size(); i++) {
40
+ Napi::Object point = Napi::Object::New(Env());
41
+ point.Set("mountPoint", mountPoints[i].mountPoint);
42
+ point.Set("fstype", mountPoints[i].fstype);
43
+ result.Set(i, point);
44
+ }
45
+
46
+ deferred_.Resolve(result);
47
+ }
48
+
49
+ void OnError(const Napi::Error &error) override {
50
+ deferred_.Reject(error.Value());
51
+ }
52
+
53
+ private:
54
+ std::vector<MountPoint> mountPoints;
55
+ Napi::Promise::Deferred deferred_;
56
+ };
57
+
58
+ Napi::Value GetVolumeMountPoints(Napi::Env env) {
59
+ auto deferred = Napi::Promise::Deferred::New(env);
60
+ auto *worker = new GetVolumeMountPointsWorker(deferred);
61
+ worker->Queue();
62
+ return deferred.Promise();
63
+ }
64
+
65
+ } // namespace FSMeta
@@ -0,0 +1,42 @@
1
+ // src/linux/blkid_cache.cpp
2
+ #include "blkid_cache.h"
3
+ #include <stdexcept>
4
+
5
+ namespace FSMeta {
6
+
7
+ // Define the static mutex
8
+ std::mutex BlkidCache::mutex_;
9
+
10
+ // Constructor: Initializes the blkid cache with proper error handling
11
+ BlkidCache::BlkidCache() : cache_(nullptr) {
12
+ std::lock_guard<std::mutex> lock(mutex_);
13
+ if (blkid_get_cache(&cache_, nullptr) != 0) {
14
+ throw std::runtime_error("Failed to initialize blkid cache");
15
+ }
16
+ }
17
+
18
+ // Destructor: Safely releases the blkid cache resource
19
+ BlkidCache::~BlkidCache() {
20
+ if (cache_) {
21
+ std::lock_guard<std::mutex> lock(mutex_);
22
+ try {
23
+ blkid_put_cache(cache_);
24
+ cache_ = nullptr; // Avoid double-release
25
+ } catch (const std::exception &e) {
26
+ // Optional: Log error during cache cleanup
27
+ // std::cerr << "Error while releasing blkid cache: " << e.what()
28
+ // << std::endl;
29
+ }
30
+ }
31
+ }
32
+
33
+ // Accessor for blkid cache
34
+ blkid_cache BlkidCache::get() {
35
+ if (!cache_) {
36
+ throw std::runtime_error(
37
+ "blkid cache is uninitialized or has been released");
38
+ }
39
+ return cache_;
40
+ }
41
+
42
+ } // namespace FSMeta
@@ -0,0 +1,27 @@
1
+ // src/linux/blkid_cache.h
2
+ #pragma once
3
+ #include <blkid/blkid.h>
4
+ #include <mutex>
5
+
6
+ namespace FSMeta {
7
+
8
+ // Thread-safe helper class for RAII handling of blkid cache
9
+ class BlkidCache {
10
+ private:
11
+ static std::mutex mutex_;
12
+ blkid_cache cache_;
13
+
14
+ public:
15
+ BlkidCache();
16
+ ~BlkidCache();
17
+
18
+ // Returns the blkid cache pointer
19
+ blkid_cache get();
20
+
21
+ operator bool() const { return cache_ != nullptr; }
22
+
23
+ BlkidCache(const BlkidCache &) = delete;
24
+ BlkidCache &operator=(const BlkidCache &) = delete;
25
+ };
26
+
27
+ } // namespace FSMeta
@@ -0,0 +1,151 @@
1
+ #ifdef ENABLE_GIO
2
+
3
+ #include "gio_utils.h"
4
+ #include "gio_worker.h"
5
+ #include <gio/gio.h>
6
+ #include <iostream>
7
+ #include <memory>
8
+ #include <stdexcept>
9
+
10
+ namespace FSMeta {
11
+ namespace gio {
12
+
13
+ // Custom deleter for GObject types
14
+ struct GObjectDeleter {
15
+ void operator()(void *ptr) const {
16
+ if (ptr) {
17
+ g_object_unref(ptr);
18
+ }
19
+ }
20
+ };
21
+
22
+ // Type aliases for common GObject smart pointers
23
+ using GVolumeMonitorPtr = std::unique_ptr<GVolumeMonitor, GObjectDeleter>;
24
+ using GObjectPtr = std::unique_ptr<GObject, GObjectDeleter>;
25
+ using GFilePtr = std::unique_ptr<GFile, GObjectDeleter>;
26
+ using GVolumePtr = std::unique_ptr<GVolume, GObjectDeleter>;
27
+ using GMountPtr = std::unique_ptr<GMount, GObjectDeleter>;
28
+ using GUriPtr = std::unique_ptr<GUri, GObjectDeleter>;
29
+
30
+ Napi::Value GetMountPoints(Napi::Env env) {
31
+ auto deferred = Napi::Promise::Deferred::New(env);
32
+ auto *worker = new GioMountPointsWorker(deferred);
33
+ worker->Queue();
34
+ return deferred.Promise();
35
+ }
36
+
37
+ void addMountMetadata(const std::string &mountPoint, VolumeMetadata &metadata) {
38
+
39
+ GVolumeMonitor *monitor = g_volume_monitor_get();
40
+ if (!monitor) {
41
+ return;
42
+ }
43
+
44
+ std::unique_ptr<GVolumeMonitor, GObjectDeleter> monitor_guard(monitor);
45
+ GList *mounts = g_volume_monitor_get_mounts(monitor);
46
+ if (!mounts) {
47
+ return;
48
+ }
49
+
50
+ for (GList *l = mounts; l != nullptr; l = l->next) {
51
+ GMount *mount = G_MOUNT(l->data);
52
+ if (!mount) {
53
+ continue;
54
+ }
55
+
56
+ GFile *root = g_mount_get_root(mount);
57
+ if (!root) {
58
+ continue;
59
+ }
60
+
61
+ char *path = g_file_get_path(root);
62
+
63
+ if (path && mountPoint == path) {
64
+
65
+ // Get volume name
66
+ GVolume *volume = g_mount_get_volume(mount);
67
+ if (volume) {
68
+ char *name = g_volume_get_name(volume);
69
+ if (name) {
70
+ metadata.label = name;
71
+ g_free(name);
72
+ }
73
+ g_object_unref(volume);
74
+ }
75
+
76
+ // Get mount name (can include filesystem type info)
77
+ char *mount_name = g_mount_get_name(mount);
78
+ if (mount_name) {
79
+ g_free(mount_name);
80
+ }
81
+
82
+ // Get location and URI
83
+ GFile *location = g_mount_get_default_location(mount);
84
+ if (location) {
85
+
86
+ // Try different URI methods
87
+ char *uri = g_file_get_uri(location);
88
+ char *parse_name = g_file_get_parse_name(location);
89
+
90
+ if (uri) {
91
+ metadata.uri = uri;
92
+
93
+ // Parse URI for remote details
94
+ GError *error = nullptr;
95
+ GUri *parsed_uri = g_uri_parse(uri, G_URI_FLAGS_NONE, &error);
96
+ if (parsed_uri) {
97
+ const char *scheme = g_uri_get_scheme(parsed_uri);
98
+
99
+ if (scheme && strcmp(scheme, "file") != 0) {
100
+ metadata.remote = true;
101
+ metadata.fileSystem = scheme;
102
+
103
+ const char *host = g_uri_get_host(parsed_uri);
104
+ const char *path = g_uri_get_path(parsed_uri);
105
+
106
+ if (host)
107
+ metadata.remoteHost = host;
108
+ if (path && path[0] == '/')
109
+ metadata.remoteShare = path + 1;
110
+ }
111
+ g_uri_unref(parsed_uri);
112
+ } else {
113
+ if (error) {
114
+ g_error_free(error);
115
+ }
116
+ }
117
+ g_free(uri);
118
+ }
119
+
120
+ if (parse_name) {
121
+ g_free(parse_name);
122
+ }
123
+ g_object_unref(location);
124
+ }
125
+
126
+ // Try additional methods to get filesystem info
127
+ if (metadata.fileSystem.empty()) {
128
+ GDrive *drive = g_mount_get_drive(mount);
129
+ if (drive) {
130
+ // Try to get unix device path
131
+ char *unix_device = g_drive_get_identifier(
132
+ drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE);
133
+ if (unix_device) {
134
+ g_free(unix_device);
135
+ }
136
+ g_object_unref(drive);
137
+ }
138
+ }
139
+ break;
140
+ }
141
+ g_object_unref(root);
142
+ g_free(path);
143
+ }
144
+
145
+ g_list_free_full(mounts, g_object_unref);
146
+ }
147
+
148
+ } // namespace gio
149
+ } // namespace FSMeta
150
+
151
+ #endif // ENABLE_GIO
@@ -0,0 +1,27 @@
1
+ // src/linux/gio_utils.h
2
+ #pragma once
3
+
4
+ #ifdef ENABLE_GIO
5
+
6
+ #include "../common/volume_metadata.h"
7
+ #include <napi.h>
8
+ #include <string>
9
+ #include <vector>
10
+
11
+ namespace FSMeta {
12
+ namespace gio {
13
+
14
+ /**
15
+ * Get mount points asynchronously using GIO
16
+ */
17
+ Napi::Value GetMountPoints(Napi::Env env);
18
+
19
+ /**
20
+ * Add metadata from GIO to the volume metadata
21
+ */
22
+ void addMountMetadata(const std::string &mountPoint, VolumeMetadata &metadata);
23
+
24
+ } // namespace gio
25
+ } // namespace FSMeta
26
+
27
+ #endif // ENABLE_GIO