@photostructure/fs-metadata 0.0.1 → 0.1.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.
Files changed (39) hide show
  1. package/README.md +68 -200
  2. package/binding.gyp +6 -3
  3. package/package.json +27 -24
  4. package/prebuilds/darwin-arm64/@photostructure+fs-metadata.glibc.node +0 -0
  5. package/prebuilds/linux-arm64/@photostructure+fs-metadata.musl.node +0 -0
  6. package/prebuilds/linux-x64/@photostructure+fs-metadata.glibc.node +0 -0
  7. package/prebuilds/linux-x64/@photostructure+fs-metadata.musl.node +0 -0
  8. package/prebuilds/win32-x64/@photostructure+fs-metadata.glibc.node +0 -0
  9. package/src/binding.cpp +59 -29
  10. package/src/common/debug_log.h +64 -0
  11. package/src/common/hidden.h +12 -0
  12. package/src/common/metadata_worker.h +1 -44
  13. package/src/common/volume_metadata.h +98 -8
  14. package/src/common/volume_mount_points.h +42 -2
  15. package/src/darwin/fs_meta.h +0 -11
  16. package/src/darwin/hidden.cpp +139 -0
  17. package/src/darwin/hidden.h +35 -0
  18. package/src/darwin/volume_metadata.cpp +105 -40
  19. package/src/darwin/volume_mount_points.cpp +88 -29
  20. package/src/linux/blkid_cache.cpp +9 -0
  21. package/src/linux/blkid_cache.h +1 -0
  22. package/src/linux/gio_mount_points.cpp +81 -0
  23. package/src/linux/{gio_worker.h → gio_mount_points.h} +7 -2
  24. package/src/linux/gio_utils.cpp +29 -115
  25. package/src/linux/gio_utils.h +69 -9
  26. package/src/linux/gio_volume_metadata.cpp +90 -0
  27. package/src/linux/gio_volume_metadata.h +20 -0
  28. package/src/linux/volume_metadata.cpp +31 -16
  29. package/src/windows/drive_status.h +227 -0
  30. package/src/windows/error_utils.h +27 -6
  31. package/src/windows/fs_meta.h +3 -33
  32. package/src/windows/hidden.cpp +160 -0
  33. package/src/windows/hidden.h +3 -0
  34. package/src/windows/string.h +48 -0
  35. package/src/windows/system_volume.h +63 -0
  36. package/src/windows/volume_metadata.cpp +171 -138
  37. package/src/windows/volume_mount_points.cpp +102 -26
  38. package/src/common/mount_point.h +0 -13
  39. package/src/linux/gio_worker.cpp +0 -87
@@ -1,5 +1,6 @@
1
1
  // src/darwin/volume_metadata.cpp
2
2
 
3
+ #include "../common/debug_log.h"
3
4
  #include "./fs_meta.h"
4
5
 
5
6
  #include <CoreFoundation/CoreFoundation.h>
@@ -86,37 +87,44 @@ public:
86
87
 
87
88
  class GetVolumeMetadataWorker : public MetadataWorkerBase {
88
89
  public:
89
- GetVolumeMetadataWorker(const std::string &path,
90
+ GetVolumeMetadataWorker(const std::string &mountPoint,
91
+ const VolumeMetadataOptions &options,
90
92
  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
- }
93
+ : MetadataWorkerBase(mountPoint, deferred), options_(options) {}
97
94
 
98
95
  void Execute() override {
96
+ DEBUG_LOG("[GetVolumeMetadataWorker] Executing for mount point: %s",
97
+ mountPoint.c_str());
99
98
  try {
100
99
  if (!GetBasicVolumeInfo()) {
101
100
  return;
102
101
  }
103
102
  GetDiskArbitrationInfo();
104
103
  } catch (const std::exception &e) {
104
+ DEBUG_LOG("[GetVolumeMetadataWorker] Exception: %s", e.what());
105
105
  SetError(e.what());
106
106
  }
107
107
  }
108
108
 
109
109
  private:
110
+ VolumeMetadataOptions options_;
111
+
110
112
  bool GetBasicVolumeInfo() {
113
+ DEBUG_LOG("[GetVolumeMetadataWorker] Getting basic volume info for: %s",
114
+ mountPoint.c_str());
111
115
  struct statvfs vfs;
112
116
  struct statfs fs;
113
117
 
114
118
  if (statvfs(mountPoint.c_str(), &vfs) != 0) {
119
+ DEBUG_LOG("[GetVolumeMetadataWorker] statvfs failed: %s (%d)",
120
+ strerror(errno), errno);
115
121
  SetError(CreateErrorMessage("statvfs", errno));
116
122
  return false;
117
123
  }
118
124
 
119
125
  if (statfs(mountPoint.c_str(), &fs) != 0) {
126
+ DEBUG_LOG("[GetVolumeMetadataWorker] statfs failed: %s (%d)",
127
+ strerror(errno), errno);
120
128
  SetError(CreateErrorMessage("statfs", errno));
121
129
  return false;
122
130
  }
@@ -138,53 +146,96 @@ private:
138
146
  metadata.available = static_cast<double>(blockSize * availBlocks);
139
147
  metadata.used = static_cast<double>(blockSize * (totalBlocks - freeBlocks));
140
148
 
141
- metadata.fileSystem = fs.f_fstypename;
149
+ metadata.fstype = fs.f_fstypename;
142
150
  metadata.mountFrom = fs.f_mntfromname;
143
151
  metadata.mountName = fs.f_mntonname;
144
152
  metadata.status = "ready";
145
153
 
154
+ DEBUG_LOG("[GetVolumeMetadataWorker] Volume info - size: %f, available: "
155
+ "%f, used: %f",
156
+ metadata.size, metadata.available, metadata.used);
146
157
  return true;
147
158
  }
148
159
 
149
160
  void GetDiskArbitrationInfo() {
161
+ DEBUG_LOG("[GetVolumeMetadataWorker] Getting Disk Arbitration info for: %s",
162
+ mountPoint.c_str());
163
+
164
+ // Check if this is a network filesystem
165
+ if (metadata.fstype == "smbfs" || metadata.fstype == "nfs" ||
166
+ metadata.fstype == "afpfs" || metadata.fstype == "webdav") {
167
+ // For network filesystems, we consider them healthy even without DA info
168
+ metadata.remote = true;
169
+ metadata.status = "healthy";
170
+ return;
171
+ }
172
+
150
173
  CFReleaser<DASessionRef> session(DASessionCreate(kCFAllocatorDefault));
151
174
  if (!session.isValid()) {
175
+ DEBUG_LOG("[GetVolumeMetadataWorker] Failed to create DA session");
152
176
  metadata.status = "partial";
177
+ metadata.error = "Failed to create DA session";
153
178
  return;
154
179
  }
155
180
 
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);
181
+ try {
182
+ // RAII cleanup for RunLoop scheduling
183
+ struct RunLoopCleaner {
184
+ DASessionRef session;
185
+ explicit RunLoopCleaner(DASessionRef s) : session(s) {}
186
+ ~RunLoopCleaner() {
187
+ DASessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(),
188
+ kCFRunLoopDefaultMode);
189
+ }
190
+ };
191
+
192
+ // Schedule session with RunLoop
193
+ DASessionScheduleWithRunLoop(session.get(), CFRunLoopGetCurrent(),
194
+ kCFRunLoopDefaultMode);
195
+
196
+ auto scopeGuard = std::make_unique<RunLoopCleaner>(session.get());
197
+
198
+ CFReleaser<DADiskRef> disk(DADiskCreateFromBSDName(
199
+ kCFAllocatorDefault, session.get(), metadata.mountFrom.c_str()));
200
+
201
+ if (!disk.isValid()) {
202
+ DEBUG_LOG("[GetVolumeMetadataWorker] Failed to create disk reference");
203
+ metadata.status = "partial";
204
+ metadata.error = "Failed to create disk reference";
205
+ return;
167
206
  }
168
- } runLoopCleaner(session.get());
169
207
 
170
- CFReleaser<DADiskRef> disk(DADiskCreateFromBSDName(
171
- kCFAllocatorDefault, session.get(), metadata.mountFrom.c_str()));
208
+ CFReleaser<CFDictionaryRef> description(
209
+ DADiskCopyDescription(disk.get()));
210
+ if (!description.isValid()) {
211
+ DEBUG_LOG("[GetVolumeMetadataWorker] Failed to get disk description");
212
+ metadata.status = "partial";
213
+ metadata.error = "Failed to get disk description";
214
+ return;
215
+ }
172
216
 
173
- if (!disk.isValid()) {
174
- metadata.status = "partial";
175
- return;
217
+ ProcessDiskDescription(description.get());
218
+
219
+ // Only set ready if we got this far without errors
220
+ if (metadata.status != "partial") {
221
+ metadata.status = "healthy";
222
+ }
223
+ } catch (const std::exception &e) {
224
+ DEBUG_LOG("[GetVolumeMetadataWorker] Exception: %s", e.what());
225
+ metadata.status = "error";
226
+ metadata.error = e.what();
176
227
  }
228
+ }
177
229
 
178
- CFReleaser<CFDictionaryRef> description(DADiskCopyDescription(disk.get()));
179
- if (!description.isValid()) {
230
+ void ProcessDiskDescription(CFDictionaryRef description) {
231
+ DEBUG_LOG("[GetVolumeMetadataWorker] Processing disk description");
232
+ if (!description) {
233
+ DEBUG_LOG("[GetVolumeMetadataWorker] Invalid disk description");
180
234
  metadata.status = "partial";
235
+ metadata.error = "Invalid disk description";
181
236
  return;
182
237
  }
183
238
 
184
- ProcessDiskDescription(description.get());
185
- }
186
-
187
- void ProcessDiskDescription(CFDictionaryRef description) {
188
239
  // Get volume name/label
189
240
  if (CFStringRef volumeName = (CFStringRef)CFDictionaryGetValue(
190
241
  description, kDADiskDescriptionVolumeNameKey)) {
@@ -205,29 +256,43 @@ private:
205
256
  }
206
257
 
207
258
  void ProcessNetworkVolume(CFDictionaryRef description) {
259
+ DEBUG_LOG("[GetVolumeMetadataWorker] Processing network volume");
208
260
  CFBooleanRef isNetworkVolume = (CFBooleanRef)CFDictionaryGetValue(
209
261
  description, kDADiskDescriptionVolumeNetworkKey);
210
-
211
262
  metadata.remote = CFBooleanGetValue(isNetworkVolume);
263
+
212
264
  CFURLRef url = (CFURLRef)CFDictionaryGetValue(
213
265
  description, kDADiskDescriptionVolumePathKey);
214
266
  if (!url) {
267
+ metadata.error = "Invalid URL";
215
268
  return;
216
269
  }
217
-
218
- CFStringRef urlString = CFURLGetString(url);
219
- if (!urlString) {
270
+ CFReleaser<CFStringRef> urlString(
271
+ CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle));
272
+ if (!urlString.isValid()) {
273
+ metadata.error = std::string("Invalid URL string: ") +
274
+ CFStringToString(urlString.get());
220
275
  return;
221
276
  }
222
- metadata.uri = CFStringToString(urlString);
277
+
278
+ DEBUG_LOG("[GetVolumeMetadataWorker] URL path: %s",
279
+ CFStringToString(urlString.get()).c_str());
280
+ metadata.uri = CFStringToString(urlString.get());
223
281
  }
224
282
  };
225
283
 
226
- Napi::Value GetVolumeMetadata(const Napi::Env &env,
227
- const std::string &mountPoint,
228
- const Napi::Object &options) {
284
+ Napi::Value GetVolumeMetadata(const Napi::CallbackInfo &info) {
285
+ auto env = info.Env();
286
+ DEBUG_LOG("[GetVolumeMetadata] called");
287
+
288
+ VolumeMetadataOptions options;
289
+ if (info.Length() > 0 && info[0].IsObject()) {
290
+ options = VolumeMetadataOptions::FromObject(info[0].As<Napi::Object>());
291
+ }
292
+
229
293
  auto deferred = Napi::Promise::Deferred::New(env);
230
- auto *worker = new GetVolumeMetadataWorker(mountPoint, deferred);
294
+ auto *worker =
295
+ new GetVolumeMetadataWorker(options.mountPoint, options, deferred);
231
296
  worker->Queue();
232
297
  return deferred.Promise();
233
298
  }
@@ -1,19 +1,30 @@
1
1
  // src/darwin/volume_mount_points.cpp
2
-
3
- #include "./fs_meta.h"
2
+ #include "../common/volume_mount_points.h"
3
+ #include "../common/debug_log.h"
4
+ #include "fs_meta.h"
5
+ #include <chrono>
6
+ #include <future>
4
7
  #include <sys/mount.h>
5
- #include <sys/param.h>
6
- #include <vector>
8
+ #include <unistd.h>
7
9
 
8
10
  namespace FSMeta {
9
11
 
10
12
  class GetVolumeMountPointsWorker : public Napi::AsyncWorker {
13
+ private:
14
+ Napi::Promise::Deferred deferred_;
15
+ std::vector<MountPoint> mountPoints_;
16
+ uint32_t timeoutMs_;
17
+
11
18
  public:
12
- GetVolumeMountPointsWorker(const Napi::Promise::Deferred &deferred)
13
- : Napi::AsyncWorker(deferred.Env()), deferred_(deferred) {}
19
+ GetVolumeMountPointsWorker(const Napi::Promise::Deferred &deferred,
20
+ uint32_t timeoutMs = 5000)
21
+ : Napi::AsyncWorker(deferred.Env()), deferred_(deferred),
22
+ timeoutMs_(timeoutMs) {}
14
23
 
15
24
  void Execute() override {
25
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Executing");
16
26
  try {
27
+ // Get mount list - this is fast
17
28
  struct statfs *mntbufp;
18
29
  int count = getmntinfo(&mntbufp, MNT_WAIT);
19
30
 
@@ -22,42 +33,90 @@ public:
22
33
  }
23
34
 
24
35
  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);
36
+ MountPoint mp;
37
+ mp.mountPoint = mntbufp[i].f_mntonname;
38
+ mp.fstype = mntbufp[i].f_fstypename;
39
+ mp.error = ""; // Initialize error field
40
+
41
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Checking mount point: %s",
42
+ mp.mountPoint.c_str());
43
+
44
+ try {
45
+ // Use shared_future to allow multiple gets
46
+ std::shared_future<bool> future =
47
+ std::async(std::launch::async, [path = mp.mountPoint]() {
48
+ return access(path.c_str(), R_OK) == 0;
49
+ }).share();
50
+
51
+ auto status = future.wait_for(std::chrono::milliseconds(timeoutMs_));
52
+
53
+ if (status == std::future_status::timeout) {
54
+ mp.status = "disconnected";
55
+ mp.error = "Access check timed out";
56
+ DEBUG_LOG(
57
+ "[GetVolumeMountPointsWorker] Access check timed out for: %s",
58
+ mp.mountPoint.c_str());
59
+ } else if (status == std::future_status::ready) {
60
+ try {
61
+ bool isAccessible = future.get();
62
+ mp.status = isAccessible ? "healthy" : "inaccessible";
63
+ if (!isAccessible) {
64
+ mp.error = "Path is not accessible";
65
+ }
66
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Access check %s for: %s",
67
+ isAccessible ? "succeeded" : "failed",
68
+ mp.mountPoint.c_str());
69
+ } catch (const std::exception &e) {
70
+ mp.status = "error";
71
+ mp.error = std::string("Access check failed: ") + e.what();
72
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Exception: %s", e.what());
73
+ }
74
+ } else {
75
+ mp.status = "error";
76
+ mp.error = "Unexpected future status";
77
+ DEBUG_LOG(
78
+ "[GetVolumeMountPointsWorker] Unexpected future status for: %s",
79
+ mp.mountPoint.c_str());
80
+ }
81
+ } catch (const std::exception &e) {
82
+ mp.status = "error";
83
+ mp.error = std::string("Mount point check failed: ") + e.what();
84
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Exception: %s", e.what());
85
+ }
86
+
87
+ mountPoints_.push_back(std::move(mp));
29
88
  }
30
89
  } catch (const std::exception &e) {
31
- SetError(e.what());
90
+ SetError(std::string("Failed to process mount points: ") + e.what());
91
+ DEBUG_LOG("[GetVolumeMountPointsWorker] Exception: %s", e.what());
32
92
  }
33
93
  }
34
94
 
35
95
  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);
96
+ DEBUG_LOG("[GetVolumeMountPointsWorker] OnOK");
97
+ auto env = Env();
98
+ auto result = Napi::Array::New(env, mountPoints_.size());
99
+
100
+ for (size_t i = 0; i < mountPoints_.size(); i++) {
101
+ result[i] = mountPoints_[i].ToObject(env);
44
102
  }
45
103
 
46
104
  deferred_.Resolve(result);
47
105
  }
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
106
  };
57
107
 
58
- Napi::Value GetVolumeMountPoints(Napi::Env env) {
108
+ Napi::Promise GetVolumeMountPoints(const Napi::CallbackInfo &info) {
109
+ auto env = info.Env();
110
+ DEBUG_LOG("[GetVolumeMountPoints] called");
111
+
59
112
  auto deferred = Napi::Promise::Deferred::New(env);
60
- auto *worker = new GetVolumeMountPointsWorker(deferred);
113
+
114
+ MountPointOptions options;
115
+ if (info.Length() > 0 && info[0].IsObject()) {
116
+ options = MountPointOptions::FromObject(info[0].As<Napi::Object>());
117
+ }
118
+
119
+ auto *worker = new GetVolumeMountPointsWorker(deferred, options.timeoutMs);
61
120
  worker->Queue();
62
121
  return deferred.Promise();
63
122
  }
@@ -1,5 +1,7 @@
1
1
  // src/linux/blkid_cache.cpp
2
+
2
3
  #include "blkid_cache.h"
4
+ #include "../common/debug_log.h"
3
5
  #include <stdexcept>
4
6
 
5
7
  namespace FSMeta {
@@ -10,19 +12,25 @@ std::mutex BlkidCache::mutex_;
10
12
  // Constructor: Initializes the blkid cache with proper error handling
11
13
  BlkidCache::BlkidCache() : cache_(nullptr) {
12
14
  std::lock_guard<std::mutex> lock(mutex_);
15
+ DEBUG_LOG("[BlkidCache] initializing cache");
13
16
  if (blkid_get_cache(&cache_, nullptr) != 0) {
17
+ DEBUG_LOG("[BlkidCache] failed to initialize cache");
14
18
  throw std::runtime_error("Failed to initialize blkid cache");
15
19
  }
20
+ DEBUG_LOG("[BlkidCache] cache initialized successfully");
16
21
  }
17
22
 
18
23
  // Destructor: Safely releases the blkid cache resource
19
24
  BlkidCache::~BlkidCache() {
20
25
  if (cache_) {
21
26
  std::lock_guard<std::mutex> lock(mutex_);
27
+ DEBUG_LOG("[BlkidCache] releasing cache");
22
28
  try {
23
29
  blkid_put_cache(cache_);
24
30
  cache_ = nullptr; // Avoid double-release
31
+ DEBUG_LOG("[BlkidCache] cache released successfully");
25
32
  } catch (const std::exception &e) {
33
+ DEBUG_LOG("[BlkidCache] error releasing cache: %s", e.what());
26
34
  // Optional: Log error during cache cleanup
27
35
  // std::cerr << "Error while releasing blkid cache: " << e.what()
28
36
  // << std::endl;
@@ -33,6 +41,7 @@ BlkidCache::~BlkidCache() {
33
41
  // Accessor for blkid cache
34
42
  blkid_cache BlkidCache::get() {
35
43
  if (!cache_) {
44
+ DEBUG_LOG("[BlkidCache] attempted to access uninitialized cache");
36
45
  throw std::runtime_error(
37
46
  "blkid cache is uninitialized or has been released");
38
47
  }
@@ -1,4 +1,5 @@
1
1
  // src/linux/blkid_cache.h
2
+
2
3
  #pragma once
3
4
  #include <blkid/blkid.h>
4
5
  #include <mutex>
@@ -0,0 +1,81 @@
1
+ // src/linux/gio_mount_points.cpp
2
+ #ifdef ENABLE_GIO
3
+
4
+ #include "gio_mount_points.h"
5
+ #include "../common/debug_log.h"
6
+ #include "gio_utils.h"
7
+ #include <gio/gio.h>
8
+ #include <memory>
9
+ #include <stdexcept>
10
+
11
+ namespace FSMeta {
12
+ namespace gio {
13
+
14
+ GioMountPointsWorker::GioMountPointsWorker(
15
+ const Napi::Promise::Deferred &deferred)
16
+ : Napi::AsyncWorker(deferred.Env()), deferred_(deferred) {}
17
+
18
+ GioMountPointsWorker::~GioMountPointsWorker() { mountPoints.clear(); }
19
+
20
+ void GioMountPointsWorker::Execute() {
21
+ try {
22
+ DEBUG_LOG("[GioMountPoints] processing mounts");
23
+
24
+ MountIterator::forEachMount([this](GMount *mount, GFile *root) {
25
+ GCharPtr path(g_file_get_path(root));
26
+ if (path) {
27
+ GFileInfoPtr info(g_file_query_filesystem_info(
28
+ root, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, nullptr, nullptr));
29
+ if (info) {
30
+ const char *fs_type_str = g_file_info_get_attribute_string(
31
+ info.get(), G_FILE_ATTRIBUTE_FILESYSTEM_TYPE);
32
+ if (fs_type_str) {
33
+ GCharPtr fs_type(g_strdup(fs_type_str));
34
+ DEBUG_LOG("[GioMountPoints] found {mountPoint: %s, fsType: %s}",
35
+ path.get(), fs_type.get());
36
+ MountPoint point{};
37
+ point.mountPoint = path.get();
38
+ point.fstype = fs_type.get();
39
+ mountPoints.push_back(point);
40
+ }
41
+ }
42
+ }
43
+ return true; // Continue iteration
44
+ });
45
+
46
+ DEBUG_LOG("[GioMountPoints] found %zu mount points", mountPoints.size());
47
+ } catch (const std::exception &e) {
48
+ DEBUG_LOG("[GioMountPoints] error: %s", e.what());
49
+ SetError(e.what());
50
+ }
51
+ }
52
+
53
+ void GioMountPointsWorker::OnOK() {
54
+ Napi::HandleScope scope(Env());
55
+ Napi::Array result = Napi::Array::New(Env());
56
+
57
+ for (size_t i = 0; i < mountPoints.size(); i++) {
58
+ Napi::Object point = Napi::Object::New(Env());
59
+ point.Set("mountPoint", mountPoints[i].mountPoint);
60
+ point.Set("fstype", mountPoints[i].fstype);
61
+ result.Set(i, point);
62
+ }
63
+
64
+ deferred_.Resolve(result);
65
+ }
66
+
67
+ void GioMountPointsWorker::OnError(const Napi::Error &error) {
68
+ deferred_.Reject(error.Value());
69
+ }
70
+
71
+ Napi::Value GetMountPoints(Napi::Env env) {
72
+ auto deferred = Napi::Promise::Deferred::New(env);
73
+ auto *worker = new GioMountPointsWorker(deferred);
74
+ worker->Queue();
75
+ return deferred.Promise();
76
+ }
77
+
78
+ } // namespace gio
79
+ } // namespace FSMeta
80
+
81
+ #endif // ENABLE_GIO
@@ -1,10 +1,10 @@
1
- // src/linux/gio_worker.h
1
+ // src/linux/gio_mount_points.h
2
2
 
3
3
  #pragma once
4
4
 
5
5
  #ifdef ENABLE_GIO
6
6
 
7
- #include "../common/mount_point.h"
7
+ #include "../common/volume_mount_points.h"
8
8
  #include <napi.h>
9
9
  #include <string>
10
10
  #include <vector>
@@ -12,6 +12,11 @@
12
12
  namespace FSMeta {
13
13
  namespace gio {
14
14
 
15
+ /**
16
+ * Get mount points asynchronously using GIO
17
+ */
18
+ Napi::Value GetMountPoints(Napi::Env env);
19
+
15
20
  class GioMountPointsWorker : public Napi::AsyncWorker {
16
21
  public:
17
22
  explicit GioMountPointsWorker(const Napi::Promise::Deferred &deferred);