@photostructure/fs-metadata 0.1.6 → 0.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 +36 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +46 -0
- package/README.md +4 -65
- package/SECURITY.md +9 -0
- package/dist/index.cjs +247 -229
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +245 -227
- package/dist/index.mjs.map +1 -0
- package/dist/types/array.d.ts +0 -5
- package/dist/types/debuglog.d.ts +0 -1
- package/dist/types/exports.d.ts +2 -1
- package/dist/types/mount_point.d.ts +1 -9
- package/dist/types/number.d.ts +0 -4
- package/dist/types/object.d.ts +0 -4
- package/dist/types/options.d.ts +4 -4
- package/dist/types/volume_metadata.d.ts +3 -3
- package/dist/types/volume_mount_points.d.ts +9 -0
- package/package.json +9 -9
- package/prebuilds/darwin-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/src/array.ts +44 -0
- package/src/async.ts +145 -0
- package/src/debuglog.ts +30 -0
- package/src/defer.ts +30 -0
- package/src/error.ts +79 -0
- package/src/exports.ts +156 -0
- package/src/fs.ts +89 -0
- package/src/glob.ts +127 -0
- package/src/hidden.ts +249 -0
- package/src/index.cts +15 -0
- package/src/index.mts +17 -0
- package/src/linux/dev_disk.ts +77 -0
- package/src/linux/mount_points.ts +91 -0
- package/src/linux/mtab.ts +136 -0
- package/src/mount_point.ts +58 -0
- package/src/number.ts +21 -0
- package/src/object.ts +55 -0
- package/src/options.ts +179 -0
- package/src/path.ts +54 -0
- package/src/platform.ts +9 -0
- package/src/random.ts +40 -0
- package/src/remote_info.ts +161 -0
- package/src/setup.ts +69 -0
- package/src/string.ts +99 -0
- package/src/string_enum.ts +41 -0
- package/src/system_volume.ts +75 -0
- package/src/test-utils/assert.ts +69 -0
- package/src/test-utils/hidden-tests.ts +33 -0
- package/src/test-utils/jest-matchers.ts +29 -0
- package/src/test-utils/platform.ts +39 -0
- package/src/types/native_bindings.ts +64 -0
- package/src/types/node-gyp-build.d.ts +6 -0
- package/src/unc.ts +63 -0
- package/src/units.ts +31 -0
- package/src/uuid.ts +24 -0
- package/src/volume_health_status.ts +58 -0
- package/src/volume_metadata.ts +294 -0
- package/src/volume_mount_points.ts +109 -0
- package/tsup.config.ts +8 -0
- package/dist/types/cache.d.ts +0 -4
package/dist/index.mjs
CHANGED
|
@@ -462,20 +462,6 @@ async function setHidden(pathname, hide, method, nativeFn) {
|
|
|
462
462
|
return { pathname: norm, actions };
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
// src/array.ts
|
|
466
|
-
function uniqBy(arr, keyFn) {
|
|
467
|
-
const seen = /* @__PURE__ */ new Set();
|
|
468
|
-
return arr.filter((item) => {
|
|
469
|
-
const key = keyFn(item);
|
|
470
|
-
if (key == null || seen.has(key)) return false;
|
|
471
|
-
seen.add(key);
|
|
472
|
-
return true;
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// src/linux/mount_points.ts
|
|
477
|
-
import { readFile } from "node:fs/promises";
|
|
478
|
-
|
|
479
465
|
// src/options.ts
|
|
480
466
|
import { availableParallelism as availableParallelism2 } from "node:os";
|
|
481
467
|
var TimeoutMsDefault = 5e3;
|
|
@@ -493,6 +479,8 @@ var SystemPathPatternsDefault = [
|
|
|
493
479
|
"/run/user/*/gvfs",
|
|
494
480
|
"/snap/**",
|
|
495
481
|
"/sys/**",
|
|
482
|
+
"**/#snapshot",
|
|
483
|
+
// Synology and Kubernetes volume snapshots
|
|
496
484
|
// windows for linux:
|
|
497
485
|
"/mnt/wslg/distro",
|
|
498
486
|
"/mnt/wslg/doc",
|
|
@@ -510,7 +498,7 @@ var SystemPathPatternsDefault = [
|
|
|
510
498
|
"/System/Volumes/VM",
|
|
511
499
|
"/System/Volumes/xarts"
|
|
512
500
|
];
|
|
513
|
-
var SystemFsTypesDefault =
|
|
501
|
+
var SystemFsTypesDefault = [
|
|
514
502
|
"autofs",
|
|
515
503
|
"binfmt_misc",
|
|
516
504
|
"cgroup",
|
|
@@ -533,7 +521,7 @@ var SystemFsTypesDefault = /* @__PURE__ */ new Set([
|
|
|
533
521
|
"squashfs",
|
|
534
522
|
"sysfs",
|
|
535
523
|
"tmpfs"
|
|
536
|
-
]
|
|
524
|
+
];
|
|
537
525
|
var LinuxMountTablePathsDefault = [
|
|
538
526
|
"/proc/self/mounts",
|
|
539
527
|
"/proc/mounts",
|
|
@@ -544,8 +532,8 @@ var OptionsDefault = {
|
|
|
544
532
|
timeoutMs: TimeoutMsDefault,
|
|
545
533
|
maxConcurrency: availableParallelism2(),
|
|
546
534
|
systemPathPatterns: [...SystemPathPatternsDefault],
|
|
547
|
-
systemFsTypes:
|
|
548
|
-
linuxMountTablePaths: LinuxMountTablePathsDefault,
|
|
535
|
+
systemFsTypes: [...SystemFsTypesDefault],
|
|
536
|
+
linuxMountTablePaths: [...LinuxMountTablePathsDefault],
|
|
549
537
|
includeSystemVolumes: IncludeSystemVolumesDefault
|
|
550
538
|
};
|
|
551
539
|
function optionsWithDefaults(overrides = {}) {
|
|
@@ -560,116 +548,65 @@ function optionsWithDefaults(overrides = {}) {
|
|
|
560
548
|
};
|
|
561
549
|
}
|
|
562
550
|
|
|
563
|
-
// src/
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
551
|
+
// src/linux/dev_disk.ts
|
|
552
|
+
import { readdir, readlink } from "node:fs/promises";
|
|
553
|
+
import { join as join3, resolve as resolve3 } from "node:path";
|
|
554
|
+
async function getUuidFromDevDisk(devicePath) {
|
|
555
|
+
try {
|
|
556
|
+
const result = await getBasenameLinkedTo(
|
|
557
|
+
"/dev/disk/by-uuid",
|
|
558
|
+
resolve3(devicePath)
|
|
559
|
+
);
|
|
560
|
+
debug("[getUuidFromDevDisk] result: %o", result);
|
|
561
|
+
return result;
|
|
562
|
+
} catch (error) {
|
|
563
|
+
debug("[getUuidFromDevDisk] failed: " + error);
|
|
564
|
+
return;
|
|
568
565
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
566
|
+
}
|
|
567
|
+
async function getLabelFromDevDisk(devicePath) {
|
|
568
|
+
try {
|
|
569
|
+
const result = await getBasenameLinkedTo(
|
|
570
|
+
"/dev/disk/by-label",
|
|
571
|
+
resolve3(devicePath)
|
|
572
|
+
);
|
|
573
|
+
debug("[getLabelFromDevDisk] result: %o", result);
|
|
574
|
+
return result;
|
|
575
|
+
} catch (error) {
|
|
576
|
+
debug("[getLabelFromDevDisk] failed: " + error);
|
|
577
|
+
return;
|
|
575
578
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
{
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
cache.set(patternsKey, prior);
|
|
582
|
-
return prior;
|
|
579
|
+
}
|
|
580
|
+
async function getBasenameLinkedTo(linkDir, linkPath) {
|
|
581
|
+
for await (const ea of readLinks(linkDir)) {
|
|
582
|
+
if (ea.linkTarget === linkPath) {
|
|
583
|
+
return decodeEscapeSequences(ea.dirent.name);
|
|
583
584
|
}
|
|
584
585
|
}
|
|
585
|
-
|
|
586
|
-
if (cache.size > 256) {
|
|
587
|
-
cache.clear();
|
|
588
|
-
}
|
|
589
|
-
cache.set(patternsKey, result);
|
|
590
|
-
cache.set(sortedKey, result);
|
|
591
|
-
return result;
|
|
586
|
+
return;
|
|
592
587
|
}
|
|
593
|
-
function
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
if (pattern[i] === "*") {
|
|
607
|
-
regex += "[^/]*";
|
|
608
|
-
i++;
|
|
609
|
-
continue;
|
|
610
|
-
}
|
|
611
|
-
if (pattern[i] === "?") {
|
|
612
|
-
regex += "[^/]";
|
|
613
|
-
i++;
|
|
614
|
-
continue;
|
|
615
|
-
}
|
|
616
|
-
if (pattern[i] === ".") {
|
|
617
|
-
regex += "\\.";
|
|
618
|
-
i++;
|
|
619
|
-
continue;
|
|
620
|
-
}
|
|
621
|
-
if (pattern[i] === "/") {
|
|
622
|
-
if (i === pattern.length - 1) {
|
|
623
|
-
regex += "(?:/|$)";
|
|
624
|
-
i++;
|
|
625
|
-
continue;
|
|
626
|
-
} else if (isWindows) {
|
|
627
|
-
regex += "[\\/\\\\]";
|
|
628
|
-
i++;
|
|
629
|
-
continue;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
if (/[+^${}()|[\]\\]/.test(pattern[i])) {
|
|
633
|
-
regex += "\\" + pattern[i];
|
|
634
|
-
i++;
|
|
635
|
-
continue;
|
|
588
|
+
async function* readLinks(directory) {
|
|
589
|
+
for (const dirent of await readdir(directory, { withFileTypes: true })) {
|
|
590
|
+
if (dirent.isSymbolicLink()) {
|
|
591
|
+
try {
|
|
592
|
+
const linkTarget = resolve3(
|
|
593
|
+
directory,
|
|
594
|
+
await readlink(join3(directory, dirent.name))
|
|
595
|
+
);
|
|
596
|
+
yield { dirent, linkTarget };
|
|
597
|
+
} catch {
|
|
636
598
|
}
|
|
637
|
-
regex += pattern[i];
|
|
638
|
-
i++;
|
|
639
|
-
}
|
|
640
|
-
return regex;
|
|
641
|
-
});
|
|
642
|
-
const final = regexPatterns.filter((ea) => ea.length > 0);
|
|
643
|
-
return final.length === 0 ? (
|
|
644
|
-
// Empty pattern matches nothing
|
|
645
|
-
NeverMatchRE
|
|
646
|
-
) : new RegExp(`^(?:${final.join("|")})$`, "i");
|
|
647
|
-
}
|
|
648
|
-
var NeverMatchRE = /(?!)/;
|
|
649
|
-
|
|
650
|
-
// src/system_volume.ts
|
|
651
|
-
function isSystemVolume(mountPoint, fstype, config = {}) {
|
|
652
|
-
debug("[isSystemVolume] checking %s (fstype: %s)", mountPoint, fstype);
|
|
653
|
-
if (isWindows) {
|
|
654
|
-
const systemDrive = normalizePath(process.env["SystemDrive"]);
|
|
655
|
-
if (systemDrive != null && mountPoint === systemDrive) {
|
|
656
|
-
debug("[isSystemVolume] %s is the Windows system drive", mountPoint);
|
|
657
|
-
return true;
|
|
658
599
|
}
|
|
659
600
|
}
|
|
660
|
-
const result = isNotBlank(fstype) && (config.systemFsTypes ?? SystemFsTypesDefault).has(fstype) || compileGlob(config.systemPathPatterns ?? SystemPathPatternsDefault).test(
|
|
661
|
-
mountPoint
|
|
662
|
-
);
|
|
663
|
-
debug("[isSystemVolume] %s -> %s", mountPoint, result);
|
|
664
|
-
return result;
|
|
665
601
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
602
|
+
|
|
603
|
+
// src/linux/mount_points.ts
|
|
604
|
+
import { readFile } from "node:fs/promises";
|
|
605
|
+
|
|
606
|
+
// src/mount_point.ts
|
|
607
|
+
function isMountPoint(obj) {
|
|
608
|
+
if (!isObject(obj)) return false;
|
|
609
|
+
return "mountPoint" in obj && isNotBlank(obj.mountPoint);
|
|
673
610
|
}
|
|
674
611
|
|
|
675
612
|
// src/remote_info.ts
|
|
@@ -775,6 +712,127 @@ function extractRemoteInfo(fsSpec) {
|
|
|
775
712
|
return;
|
|
776
713
|
}
|
|
777
714
|
|
|
715
|
+
// src/glob.ts
|
|
716
|
+
var cache = /* @__PURE__ */ new Map();
|
|
717
|
+
function compileGlob(patterns) {
|
|
718
|
+
if (patterns == null || patterns.length === 0) {
|
|
719
|
+
return NeverMatchRE;
|
|
720
|
+
}
|
|
721
|
+
const patternsKey = JSON.stringify(patterns);
|
|
722
|
+
{
|
|
723
|
+
const prior = cache.get(patternsKey);
|
|
724
|
+
if (prior != null) {
|
|
725
|
+
return prior;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
const sorted = patterns.slice().filter(isNotBlank).sort();
|
|
729
|
+
const sortedKey = JSON.stringify(sorted);
|
|
730
|
+
{
|
|
731
|
+
const prior = cache.get(sortedKey);
|
|
732
|
+
if (prior != null) {
|
|
733
|
+
cache.set(patternsKey, prior);
|
|
734
|
+
return prior;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
const result = _compileGlob(sorted);
|
|
738
|
+
if (cache.size > 256) {
|
|
739
|
+
cache.clear();
|
|
740
|
+
}
|
|
741
|
+
cache.set(patternsKey, result);
|
|
742
|
+
cache.set(sortedKey, result);
|
|
743
|
+
return result;
|
|
744
|
+
}
|
|
745
|
+
function _compileGlob(patterns) {
|
|
746
|
+
const regexPatterns = patterns.map((pattern) => {
|
|
747
|
+
let regex = "";
|
|
748
|
+
let i = 0;
|
|
749
|
+
while (i < pattern.length) {
|
|
750
|
+
if (pattern[i] === "*" && pattern[i + 1] === "*") {
|
|
751
|
+
regex += ".*";
|
|
752
|
+
i += 2;
|
|
753
|
+
if (pattern[i] === "/") {
|
|
754
|
+
i++;
|
|
755
|
+
}
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
if (pattern[i] === "*") {
|
|
759
|
+
regex += "[^/]*";
|
|
760
|
+
i++;
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
if (pattern[i] === "?") {
|
|
764
|
+
regex += "[^/]";
|
|
765
|
+
i++;
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
if (pattern[i] === ".") {
|
|
769
|
+
regex += "\\.";
|
|
770
|
+
i++;
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
if (pattern[i] === "/") {
|
|
774
|
+
if (i === pattern.length - 1) {
|
|
775
|
+
regex += "(?:/|$)";
|
|
776
|
+
i++;
|
|
777
|
+
continue;
|
|
778
|
+
} else if (isWindows) {
|
|
779
|
+
regex += "[\\/\\\\]";
|
|
780
|
+
i++;
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (/[+^${}()|[\]\\]/.test(pattern[i])) {
|
|
785
|
+
regex += "\\" + pattern[i];
|
|
786
|
+
i++;
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
regex += pattern[i];
|
|
790
|
+
i++;
|
|
791
|
+
}
|
|
792
|
+
return regex;
|
|
793
|
+
});
|
|
794
|
+
const final = regexPatterns.filter((ea) => ea.length > 0);
|
|
795
|
+
return final.length === 0 ? (
|
|
796
|
+
// Empty pattern matches nothing
|
|
797
|
+
NeverMatchRE
|
|
798
|
+
) : new RegExp(`^(?:${final.join("|")})$`, "i");
|
|
799
|
+
}
|
|
800
|
+
var NeverMatchRE = /(?!)/;
|
|
801
|
+
|
|
802
|
+
// src/system_volume.ts
|
|
803
|
+
function isSystemVolume(mountPoint, fstype, config = {}) {
|
|
804
|
+
if (isWindows) {
|
|
805
|
+
const systemDrive = normalizePath(process.env["SystemDrive"]);
|
|
806
|
+
if (systemDrive != null && mountPoint === systemDrive) {
|
|
807
|
+
debug("[isSystemVolume] %s is the Windows system drive", mountPoint);
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const isSystemFsType = isNotBlank(fstype) && (config.systemFsTypes ?? SystemFsTypesDefault).includes(
|
|
812
|
+
fstype
|
|
813
|
+
);
|
|
814
|
+
const hasSystemPath = compileGlob(
|
|
815
|
+
config.systemPathPatterns ?? SystemPathPatternsDefault
|
|
816
|
+
).test(mountPoint);
|
|
817
|
+
const result = isSystemFsType || hasSystemPath;
|
|
818
|
+
debug("[isSystemVolume]", {
|
|
819
|
+
mountPoint,
|
|
820
|
+
fstype,
|
|
821
|
+
result,
|
|
822
|
+
isSystemFsType,
|
|
823
|
+
hasSystemPath
|
|
824
|
+
});
|
|
825
|
+
return result;
|
|
826
|
+
}
|
|
827
|
+
function assignSystemVolume(mp, config) {
|
|
828
|
+
const result = isSystemVolume(mp.mountPoint, mp.fstype, config);
|
|
829
|
+
if (isWindows) {
|
|
830
|
+
mp.isSystemVolume ??= result;
|
|
831
|
+
} else {
|
|
832
|
+
mp.isSystemVolume = result;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
778
836
|
// src/linux/mtab.ts
|
|
779
837
|
function mountEntryToMountPoint(entry) {
|
|
780
838
|
const mountPoint = normalizePosixPath(entry.fs_file);
|
|
@@ -852,7 +910,6 @@ async function getLinuxMountPoints(native, opts) {
|
|
|
852
910
|
const prior = byMountPoint.get(ea.mountPoint);
|
|
853
911
|
const merged = { ...compactValues(prior), ...compactValues(ea) };
|
|
854
912
|
if (isMountPoint(merged)) {
|
|
855
|
-
assignSystemVolume(merged, o);
|
|
856
913
|
byMountPoint.set(merged.mountPoint, merged);
|
|
857
914
|
}
|
|
858
915
|
}
|
|
@@ -863,8 +920,10 @@ async function getLinuxMountPoints(native, opts) {
|
|
|
863
920
|
);
|
|
864
921
|
}
|
|
865
922
|
const results = [...byMountPoint.values()];
|
|
866
|
-
debug("[getLinuxMountPoints]
|
|
867
|
-
|
|
923
|
+
debug("[getLinuxMountPoints] %o", {
|
|
924
|
+
results: results.map((ea) => ea.mountPoint)
|
|
925
|
+
});
|
|
926
|
+
return results;
|
|
868
927
|
}
|
|
869
928
|
async function getLinuxMtabMetadata(mountPoint, opts) {
|
|
870
929
|
let caughtError;
|
|
@@ -887,6 +946,41 @@ async function getLinuxMtabMetadata(mountPoint, opts) {
|
|
|
887
946
|
);
|
|
888
947
|
}
|
|
889
948
|
|
|
949
|
+
// src/unc.ts
|
|
950
|
+
function parseUNCPath(path) {
|
|
951
|
+
if (path == null || isBlank(path) || !isString(path)) {
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (!path.startsWith("\\\\") && !path.startsWith("//")) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
const isForwardSlash = path.startsWith("//");
|
|
958
|
+
const slashChar = isForwardSlash ? "/" : "\\";
|
|
959
|
+
const parts = path.slice(2).split(slashChar);
|
|
960
|
+
if (parts.length < 2) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
const [remoteHost, remoteShare] = parts;
|
|
964
|
+
if (remoteHost == null || isBlank(remoteHost) || remoteShare == null || isBlank(remoteShare)) {
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
const invalidChars = /[<>:"|?*]/;
|
|
968
|
+
if (invalidChars.test(remoteHost) || invalidChars.test(remoteShare)) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
const wrongSlash = isForwardSlash ? "\\" : "/";
|
|
972
|
+
if (path.includes(wrongSlash)) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
return { remoteHost, remoteShare, remote: true };
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// src/uuid.ts
|
|
979
|
+
var uuidRegex = /[a-z0-9][a-z0-9-]{7,}/i;
|
|
980
|
+
function extractUUID(uuid) {
|
|
981
|
+
return toS(uuid).match(uuidRegex)?.[0];
|
|
982
|
+
}
|
|
983
|
+
|
|
890
984
|
// src/string_enum.ts
|
|
891
985
|
function stringEnum(...o) {
|
|
892
986
|
const set = new Set(o);
|
|
@@ -930,18 +1024,25 @@ async function directoryStatus(dir, timeoutMs, canReaddirImpl = canReaddir) {
|
|
|
930
1024
|
return { status: VolumeHealthStatuses.unknown };
|
|
931
1025
|
}
|
|
932
1026
|
|
|
933
|
-
// src/
|
|
934
|
-
function
|
|
935
|
-
|
|
936
|
-
return
|
|
1027
|
+
// src/array.ts
|
|
1028
|
+
function uniqBy(arr, keyFn) {
|
|
1029
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1030
|
+
return arr.filter((item) => {
|
|
1031
|
+
const key = keyFn(item);
|
|
1032
|
+
if (key == null || seen.has(key)) return false;
|
|
1033
|
+
seen.add(key);
|
|
1034
|
+
return true;
|
|
1035
|
+
});
|
|
937
1036
|
}
|
|
1037
|
+
|
|
1038
|
+
// src/volume_mount_points.ts
|
|
938
1039
|
async function getVolumeMountPoints(opts, nativeFn) {
|
|
939
1040
|
const p2 = _getVolumeMountPoints(opts, nativeFn);
|
|
940
1041
|
return isWindows ? p2 : withTimeout({ desc: "getVolumeMountPoints", ...opts, promise: p2 });
|
|
941
1042
|
}
|
|
942
1043
|
async function _getVolumeMountPoints(o, nativeFn) {
|
|
943
1044
|
debug("[getVolumeMountPoints] gathering mount points with options: %o", o);
|
|
944
|
-
const
|
|
1045
|
+
const raw = await (isWindows || isMacOS ? (async () => {
|
|
945
1046
|
debug("[getVolumeMountPoints] using native implementation");
|
|
946
1047
|
const points = await (await nativeFn()).getVolumeMountPoints(o);
|
|
947
1048
|
debug(
|
|
@@ -950,8 +1051,11 @@ async function _getVolumeMountPoints(o, nativeFn) {
|
|
|
950
1051
|
);
|
|
951
1052
|
return points;
|
|
952
1053
|
})() : getLinuxMountPoints(nativeFn, o));
|
|
953
|
-
debug("[getVolumeMountPoints] raw mount points: %o",
|
|
954
|
-
const compacted =
|
|
1054
|
+
debug("[getVolumeMountPoints] raw mount points: %o", raw);
|
|
1055
|
+
const compacted = raw.map((ea) => compactValues(ea)).filter((ea) => isNotBlank(ea.mountPoint));
|
|
1056
|
+
for (const ea of compacted) {
|
|
1057
|
+
assignSystemVolume(ea, o);
|
|
1058
|
+
}
|
|
955
1059
|
const filtered = o.includeSystemVolumes ? compacted : compacted.filter((ea) => !ea.isSystemVolume);
|
|
956
1060
|
const uniq = uniqBy(filtered, (ea) => toNotBlank(ea.mountPoint));
|
|
957
1061
|
debug("[getVolumeMountPoints] found %d unique mount points", uniq.length);
|
|
@@ -962,18 +1066,18 @@ async function _getVolumeMountPoints(o, nativeFn) {
|
|
|
962
1066
|
);
|
|
963
1067
|
await mapConcurrent({
|
|
964
1068
|
maxConcurrency: o.maxConcurrency,
|
|
965
|
-
items: results
|
|
1069
|
+
items: results.filter(
|
|
1070
|
+
// trust but verify
|
|
1071
|
+
(ea) => isBlank(ea.status) || ea.status === "healthy"
|
|
1072
|
+
),
|
|
966
1073
|
fn: async (mp) => {
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
mp.status
|
|
975
|
-
);
|
|
976
|
-
}
|
|
1074
|
+
debug("[getVolumeMountPoints] checking status of %s", mp.mountPoint);
|
|
1075
|
+
mp.status = (await directoryStatus(mp.mountPoint, o.timeoutMs)).status;
|
|
1076
|
+
debug(
|
|
1077
|
+
"[getVolumeMountPoints] status for %s: %s",
|
|
1078
|
+
mp.mountPoint,
|
|
1079
|
+
mp.status
|
|
1080
|
+
);
|
|
977
1081
|
}
|
|
978
1082
|
});
|
|
979
1083
|
debug(
|
|
@@ -983,93 +1087,6 @@ async function _getVolumeMountPoints(o, nativeFn) {
|
|
|
983
1087
|
return results;
|
|
984
1088
|
}
|
|
985
1089
|
|
|
986
|
-
// src/linux/dev_disk.ts
|
|
987
|
-
import { readdir, readlink } from "node:fs/promises";
|
|
988
|
-
import { join as join3, resolve as resolve3 } from "node:path";
|
|
989
|
-
async function getUuidFromDevDisk(devicePath) {
|
|
990
|
-
try {
|
|
991
|
-
const result = await getBasenameLinkedTo(
|
|
992
|
-
"/dev/disk/by-uuid",
|
|
993
|
-
resolve3(devicePath)
|
|
994
|
-
);
|
|
995
|
-
debug("[getUuidFromDevDisk] result: %o", result);
|
|
996
|
-
return result;
|
|
997
|
-
} catch (error) {
|
|
998
|
-
debug("[getUuidFromDevDisk] failed: " + error);
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
async function getLabelFromDevDisk(devicePath) {
|
|
1003
|
-
try {
|
|
1004
|
-
const result = await getBasenameLinkedTo(
|
|
1005
|
-
"/dev/disk/by-label",
|
|
1006
|
-
resolve3(devicePath)
|
|
1007
|
-
);
|
|
1008
|
-
debug("[getLabelFromDevDisk] result: %o", result);
|
|
1009
|
-
return result;
|
|
1010
|
-
} catch (error) {
|
|
1011
|
-
debug("[getLabelFromDevDisk] failed: " + error);
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
async function getBasenameLinkedTo(linkDir, linkPath) {
|
|
1016
|
-
for await (const ea of readLinks(linkDir)) {
|
|
1017
|
-
if (ea.linkTarget === linkPath) {
|
|
1018
|
-
return decodeEscapeSequences(ea.dirent.name);
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
async function* readLinks(directory) {
|
|
1024
|
-
for (const dirent of await readdir(directory, { withFileTypes: true })) {
|
|
1025
|
-
if (dirent.isSymbolicLink()) {
|
|
1026
|
-
try {
|
|
1027
|
-
const linkTarget = resolve3(
|
|
1028
|
-
directory,
|
|
1029
|
-
await readlink(join3(directory, dirent.name))
|
|
1030
|
-
);
|
|
1031
|
-
yield { dirent, linkTarget };
|
|
1032
|
-
} catch {
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
// src/unc.ts
|
|
1039
|
-
function parseUNCPath(path) {
|
|
1040
|
-
if (path == null || isBlank(path) || !isString(path)) {
|
|
1041
|
-
return;
|
|
1042
|
-
}
|
|
1043
|
-
if (!path.startsWith("\\\\") && !path.startsWith("//")) {
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
const isForwardSlash = path.startsWith("//");
|
|
1047
|
-
const slashChar = isForwardSlash ? "/" : "\\";
|
|
1048
|
-
const parts = path.slice(2).split(slashChar);
|
|
1049
|
-
if (parts.length < 2) {
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
const [remoteHost, remoteShare] = parts;
|
|
1053
|
-
if (remoteHost == null || isBlank(remoteHost) || remoteShare == null || isBlank(remoteShare)) {
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
|
-
const invalidChars = /[<>:"|?*]/;
|
|
1057
|
-
if (invalidChars.test(remoteHost) || invalidChars.test(remoteShare)) {
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
const wrongSlash = isForwardSlash ? "\\" : "/";
|
|
1061
|
-
if (path.includes(wrongSlash)) {
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
return { remoteHost, remoteShare, remote: true };
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
// src/uuid.ts
|
|
1068
|
-
var uuidRegex = /[a-z0-9][a-z0-9-]{7,}/i;
|
|
1069
|
-
function extractUUID(uuid) {
|
|
1070
|
-
return toS(uuid).match(uuidRegex)?.[0];
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
1090
|
// src/volume_metadata.ts
|
|
1074
1091
|
async function getVolumeMetadata(o, nativeFn) {
|
|
1075
1092
|
if (isBlank(o.mountPoint)) {
|
|
@@ -1268,3 +1285,4 @@ export {
|
|
|
1268
1285
|
optionsWithDefaults,
|
|
1269
1286
|
setHidden2 as setHidden
|
|
1270
1287
|
};
|
|
1288
|
+
//# sourceMappingURL=index.mjs.map
|