@photostructure/fs-metadata 0.8.0 → 0.9.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 CHANGED
@@ -14,6 +14,25 @@ Fixed for any bug fixes.
14
14
  Security in case of vulnerabilities.
15
15
  -->
16
16
 
17
+ ## 0.9.0 - 2025-12-28
18
+
19
+ ### Added
20
+
21
+ - New `networkFsTypes` option for configuring network filesystem detection
22
+ - `NetworkFsTypesDefault` and `SkipNetworkVolumesDefault` exports
23
+
24
+ ### Changed
25
+
26
+ - Expanded `SystemFsTypesDefault` with `bpf`, `tracefs`, `nsfs`, `ramfs`, `rpc_pipefs`, `fuse.lxcfs`, `fuse.portal`
27
+ - Expanded `SystemPathPatternsDefault` with macOS metadata paths, kubelet, LXC/LXD, Flatpak paths
28
+ - `isRemoteFsType()` and `extractRemoteInfo()` accept optional `networkFsTypes` parameter
29
+
30
+ ## 0.8.1 - 2025-12-28
31
+
32
+ ### Changed
33
+
34
+ - Added container runtime paths to the default set of system paths. See SystemPathPatternsDefault
35
+
17
36
  ## 0.8.0 - 2025-12-01
18
37
 
19
38
  ### Added
@@ -98,9 +117,9 @@ Security in case of vulnerabilities.
98
117
 
99
118
  - `Packaging`: Improved ESM/CJS support with common `__dirname` implementation thanks to `tsup` [shims](https://tsup.egoist.dev/#inject-cjs-and-esm-shims).
100
119
 
101
- This change simplifies the implementation and improves inline jsdocs as the exported code and docs have been inlined.
120
+ This change simplifies the implementation and improves inline js docs as the exported code and docs have been inlined.
102
121
 
103
- - `Packaging`: Re-enabled test coverage assertions (after finding the magicks to get istanbul to see what the tests were exercising)
122
+ - `Packaging`: Re-enabled test coverage assertions (after finding the magics to get istanbul to see what the tests were exercising)
104
123
 
105
124
  - `Packaging`: Added debuglog tests
106
125
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ![PhotoStructure fs-metadata logo](https://raw.githubusercontent.com/photostructure/fs-metadata/main/doc/logo.svg)
2
2
 
3
- Cross-platform native Node.js module for filesystem metadata, mount points, and volume information.
3
+ Cross-platform native Node.js module for filesystem metadata, mount points, and volume information. Built for and supported by [PhotoStructure](https://photostructure.com).
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@photostructure/fs-metadata.svg)](https://www.npmjs.com/package/@photostructure/fs-metadata)
6
6
  [![Build](https://github.com/photostructure/fs-metadata/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/photostructure/fs-metadata/actions/workflows/build.yml)
@@ -48,10 +48,11 @@ console.log(metadata);
48
48
 
49
49
  ## Documentation
50
50
 
51
- - 📖 [API Reference](https://photostructure.github.io/fs-metadata/modules.html)
52
- - 💡 [Examples](./doc/examples.md) - Common usage patterns and recipes
53
- - ⚠️ [Gotchas](./doc/gotchas.md) - Platform quirks, timeouts, and troubleshooting
54
- - 🔧 [Contributing](./CONTRIBUTING.md) - Build instructions and development guide
51
+ - [Security reporting](./SECURITY.md) - How to report security issues
52
+ - [API Reference](https://photostructure.github.io/fs-metadata/modules.html)
53
+ - [Examples](./doc/examples.md) - Common usage patterns and recipes
54
+ - [Gotchas](./doc/gotchas.md) - Platform quirks, timeouts, and troubleshooting
55
+ - [Contributing](./CONTRIBUTING.md) - Build instructions and development guide
55
56
 
56
57
  ### Options
57
58
 
@@ -60,10 +61,6 @@ console.log(metadata);
60
61
  - Set `FS_METADATA_TIMEOUT_MS` environment variable to override the default (5000ms)
61
62
  - **System Volumes**: Control [system volume filtering](https://photostructure.github.io/fs-metadata/interfaces/Options.html)
62
63
 
63
- ## Support
64
+ ## Development
64
65
 
65
- Built and supported by [PhotoStructure](https://photostructure.com)
66
-
67
- - [GitHub Issues](https://github.com/photostructure/fs-metadata/issues)
68
- - [Security Policy](./SECURITY.md)
69
- - [MIT License](./LICENSE.txt)
66
+ Development of this library was assisted by AI coding tools. All changes are human-reviewed and tested.
package/binding.gyp CHANGED
@@ -31,11 +31,13 @@
31
31
  "-lblkid"
32
32
  ],
33
33
  "cflags": [
34
- "-fPIC"
34
+ "-fPIC",
35
+ "-fstack-protector-strong"
35
36
  ],
36
37
  "cflags_cc": [
37
38
  "-fexceptions",
38
- "-fPIC"
39
+ "-fPIC",
40
+ "-fstack-protector-strong"
39
41
  ],
40
42
  "conditions": [
41
43
  [
@@ -179,14 +181,19 @@
179
181
  "CLANG_CXX_LANGUAGE_STANDARD": "c++17",
180
182
  "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
181
183
  "CLANG_CXX_LIBRARY": "libc++",
182
- "MACOSX_DEPLOYMENT_TARGET": "10.15"
184
+ "MACOSX_DEPLOYMENT_TARGET": "10.15",
185
+ "OTHER_CFLAGS": [
186
+ "-fstack-protector-strong"
187
+ ]
183
188
  },
184
189
  "cflags": [
185
190
  "-fexceptions",
186
- "-fPIC"
191
+ "-fPIC",
192
+ "-fstack-protector-strong"
187
193
  ],
188
194
  "cflags_cc": [
189
- "-fexceptions"
195
+ "-fexceptions",
196
+ "-fstack-protector-strong"
190
197
  ],
191
198
  "link_settings": {
192
199
  "libraries": [
package/dist/index.cjs CHANGED
@@ -32,7 +32,9 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  IncludeSystemVolumesDefault: () => IncludeSystemVolumesDefault,
34
34
  LinuxMountTablePathsDefault: () => LinuxMountTablePathsDefault,
35
+ NetworkFsTypesDefault: () => NetworkFsTypesDefault,
35
36
  OptionsDefault: () => OptionsDefault,
37
+ SkipNetworkVolumesDefault: () => SkipNetworkVolumesDefault,
36
38
  SystemFsTypesDefault: () => SystemFsTypesDefault,
37
39
  SystemPathPatternsDefault: () => SystemPathPatternsDefault,
38
40
  VolumeHealthStatuses: () => VolumeHealthStatuses,
@@ -628,6 +630,7 @@ var SystemPathPatternsDefault = [
628
630
  "/proc/**",
629
631
  "/run",
630
632
  "/run/credentials/**",
633
+ "/run/flatpak/**",
631
634
  "/run/lock",
632
635
  "/run/snapd/**",
633
636
  "/run/user/*/doc",
@@ -639,12 +642,39 @@ var SystemPathPatternsDefault = [
639
642
  // we aren't including /tmp/**, as some people temporarily mount volumes there, like /tmp/project.
640
643
  "**/#snapshot",
641
644
  // Synology and Kubernetes volume snapshots
642
- // windows for linux:
645
+ // Container runtime paths - these are internal infrastructure paths that are
646
+ // inaccessible to non-root processes and should never be scanned.
647
+ //
648
+ // Docker: https://docs.docker.com/engine/storage/drivers/overlayfs-driver/
649
+ // - /var/lib/docker contains overlay2 filesystems, container layers, images
650
+ // - /run/docker contains runtime data like network namespaces
651
+ "/run/docker/**",
652
+ "/var/lib/docker/**",
653
+ //
654
+ // containerd: https://github.com/containerd/containerd/blob/main/docs/ops.md
655
+ // - Used by Kubernetes, Docker (as backend), and standalone
656
+ "/run/containerd/**",
657
+ "/var/lib/containerd/**",
658
+ //
659
+ // Podman/CRI-O: https://podman.io/docs/installation#storage
660
+ // - Rootless and rootful container storage
661
+ "/run/containers/**",
662
+ "/var/lib/containers/**",
663
+ //
664
+ // Kubernetes: https://kubernetes.io/docs/reference/node/kubelet-files/
665
+ // - kubelet stores pod data, device plugins, and seccomp profiles
666
+ "/var/lib/kubelet/**",
667
+ //
668
+ // LXC/LXD: https://linuxcontainers.org/
669
+ // - Linux container storage and configuration
670
+ "/var/lib/lxc/**",
671
+ "/var/lib/lxd/**",
672
+ // WSL (Windows Subsystem for Linux):
643
673
  "/mnt/wslg/distro",
644
674
  "/mnt/wslg/doc",
645
675
  "/mnt/wslg/versions.txt",
646
676
  "/usr/lib/wsl/drivers",
647
- // MacOS stuff:
677
+ // macOS system paths:
648
678
  "/private/var/vm",
649
679
  // macOS swap
650
680
  "/System/Volumes/Hardware",
@@ -654,11 +684,20 @@ var SystemPathPatternsDefault = [
654
684
  "/System/Volumes/Reserved",
655
685
  "/System/Volumes/Update",
656
686
  "/System/Volumes/VM",
657
- "/System/Volumes/xarts"
687
+ "/System/Volumes/xarts",
688
+ // macOS per-volume metadata (Spotlight, FSEvents, versioning, Trash):
689
+ // https://eclecticlight.co/2021/01/28/spotlight-on-search-how-spotlight-works/
690
+ "**/.DocumentRevisions-V100",
691
+ "**/.fseventsd",
692
+ "**/.Spotlight-V100",
693
+ "**/.Trashes"
658
694
  ];
659
695
  var SystemFsTypesDefault = [
660
696
  "autofs",
661
697
  "binfmt_misc",
698
+ // BPF filesystem for persistent BPF objects
699
+ // https://docs.kernel.org/bpf/
700
+ "bpf",
662
701
  "cgroup",
663
702
  "cgroup2",
664
703
  "configfs",
@@ -667,24 +706,98 @@ var SystemFsTypesDefault = [
667
706
  "devtmpfs",
668
707
  "efivarfs",
669
708
  "fusectl",
709
+ // LXC container filesystem virtualization
710
+ // https://linuxcontainers.org/lxcfs/
711
+ "fuse.lxcfs",
712
+ // XDG Desktop Portal for Flatpak sandboxed app file access
713
+ // https://flatpak.github.io/xdg-desktop-portal/
714
+ "fuse.portal",
670
715
  "fuse.snapfuse",
671
716
  "hugetlbfs",
672
717
  "mqueue",
673
718
  "none",
719
+ // Linux namespace filesystem (internal kernel use)
720
+ // https://man7.org/linux/man-pages/man7/namespaces.7.html
721
+ "nsfs",
674
722
  "proc",
675
723
  "pstore",
724
+ // RAM-based filesystem (predecessor to tmpfs)
725
+ // https://www.kernel.org/doc/html/latest/filesystems/ramfs-rootfs-initramfs.html
726
+ "ramfs",
676
727
  "rootfs",
728
+ // NFS RPC communication pipe filesystem
729
+ // https://man7.org/linux/man-pages/man8/rpc.gssd.8.html
730
+ "rpc_pipefs",
677
731
  "securityfs",
678
732
  "snap*",
679
733
  "squashfs",
680
734
  "sysfs",
681
- "tmpfs"
735
+ "tmpfs",
736
+ // Kernel function tracing filesystem
737
+ // https://www.kernel.org/doc/html/latest/trace/ftrace.html
738
+ "tracefs"
682
739
  ];
683
740
  var LinuxMountTablePathsDefault = [
684
741
  "/proc/self/mounts",
685
742
  "/proc/mounts",
686
743
  "/etc/mtab"
687
744
  ];
745
+ var NetworkFsTypesDefault = [
746
+ // Plan 9 filesystem (VM host-guest, also network)
747
+ // https://www.kernel.org/doc/html/latest/filesystems/9p.html
748
+ "9p",
749
+ // Apple Filing Protocol (legacy macOS/netatalk)
750
+ "afp",
751
+ // Andrew File System (distributed) - not to be confused with Apple's APFS
752
+ // https://www.openafs.org/
753
+ "afs",
754
+ // BeeGFS parallel filesystem (HPC)
755
+ // https://www.beegfs.io/
756
+ "beegfs",
757
+ // Ceph distributed filesystem
758
+ // https://docs.ceph.com/
759
+ "ceph",
760
+ // Windows/Samba shares (SMB/CIFS)
761
+ // https://www.samba.org/
762
+ "cifs",
763
+ // FTP filesystem mount
764
+ "ftp",
765
+ // Generic FUSE (often remote, treated conservatively)
766
+ "fuse",
767
+ // rclone cloud storage mount (Google Drive, S3, etc.)
768
+ // https://rclone.org/commands/rclone_mount/
769
+ "fuse.rclone",
770
+ // Amazon S3 FUSE mount
771
+ // https://github.com/s3fs-fuse/s3fs-fuse
772
+ "fuse.s3fs",
773
+ // SSH filesystem
774
+ // https://github.com/libfuse/sshfs
775
+ "fuse.sshfs",
776
+ // Red Hat Global File System (cluster)
777
+ "gfs",
778
+ "gfs2",
779
+ // GlusterFS distributed filesystem
780
+ // https://www.gluster.org/
781
+ "glusterfs",
782
+ // Lustre parallel filesystem (HPC)
783
+ // https://www.lustre.org/
784
+ "lustre",
785
+ // Novell NetWare (legacy)
786
+ "ncpfs",
787
+ "ncp",
788
+ // Network File System
789
+ // https://man7.org/linux/man-pages/man5/nfs.5.html
790
+ "nfs",
791
+ "nfs4",
792
+ // SMB filesystem
793
+ "smb",
794
+ "smbfs",
795
+ // SSH filesystem (non-FUSE variant)
796
+ "sshfs",
797
+ // WebDAV filesystem
798
+ // https://savannah.nongnu.org/projects/davfs2
799
+ "webdav"
800
+ ];
688
801
  var IncludeSystemVolumesDefault = isWindows;
689
802
  var SkipNetworkVolumesDefault = false;
690
803
  var OptionsDefault = {
@@ -693,6 +806,7 @@ var OptionsDefault = {
693
806
  systemPathPatterns: [...SystemPathPatternsDefault],
694
807
  systemFsTypes: [...SystemFsTypesDefault],
695
808
  linuxMountTablePaths: [...LinuxMountTablePathsDefault],
809
+ networkFsTypes: [...NetworkFsTypesDefault],
696
810
  includeSystemVolumes: IncludeSystemVolumesDefault,
697
811
  skipNetworkVolumes: SkipNetworkVolumesDefault
698
812
  };
@@ -817,38 +931,15 @@ function isRemoteInfo(obj) {
817
931
  const { remoteHost, remoteShare } = obj;
818
932
  return isNotBlank(remoteHost) && isNotBlank(remoteShare);
819
933
  }
820
- var NETWORK_FS_TYPE_ARRAY = [
821
- "9p",
822
- "afp",
823
- "afs",
824
- "beegfs",
825
- "ceph",
826
- "cifs",
827
- "ftp",
828
- "fuse",
829
- "gfs2",
830
- "glusterfs",
831
- "lustre",
832
- "ncpfs",
833
- "nfs",
834
- "nfs4",
835
- "smb",
836
- "smbfs",
837
- "sshfs",
838
- "webdav"
839
- ];
840
- var NETWORK_FS_TYPES = new Set(NETWORK_FS_TYPE_ARRAY);
841
934
  var FS_TYPE_ALIASES = /* @__PURE__ */ new Map([
842
935
  ["nfs1", "nfs"],
843
936
  ["nfs2", "nfs"],
844
937
  ["nfs3", "nfs"],
845
- ["nfs4", "nfs4"],
846
938
  ["fuse.sshfs", "sshfs"],
847
939
  ["sshfs.fuse", "sshfs"],
848
940
  ["davfs2", "webdav"],
849
941
  ["davfs", "webdav"],
850
942
  ["cifs.smb", "cifs"],
851
- ["smbfs", "cifs"],
852
943
  ["cephfs", "ceph"],
853
944
  ["fuse.ceph", "ceph"],
854
945
  ["fuse.cephfs", "ceph"],
@@ -859,8 +950,12 @@ function normalizeFsType(fstype) {
859
950
  const norm = toS(fstype).toLowerCase().replace(/:$/, "");
860
951
  return FS_TYPE_ALIASES.get(norm) ?? norm;
861
952
  }
862
- function isRemoteFsType(fstype) {
863
- return isNotBlank(fstype) && NETWORK_FS_TYPES.has(normalizeFsType(fstype));
953
+ function isRemoteFsType(fstype, networkFsTypes = NetworkFsTypesDefault) {
954
+ if (!isNotBlank(fstype)) return false;
955
+ const normalized = normalizeFsType(fstype);
956
+ return networkFsTypes.some(
957
+ (nft) => nft === normalized || normalized.startsWith(nft + ".")
958
+ );
864
959
  }
865
960
  function parseURL(s) {
866
961
  try {
@@ -869,7 +964,7 @@ function parseURL(s) {
869
964
  return;
870
965
  }
871
966
  }
872
- function extractRemoteInfo(fsSpec) {
967
+ function extractRemoteInfo(fsSpec, networkFsTypes = NetworkFsTypesDefault) {
873
968
  if (fsSpec == null || isBlank(fsSpec)) return;
874
969
  if (isWindows) {
875
970
  fsSpec = fsSpec.replace(/\\/g, "/");
@@ -918,7 +1013,7 @@ function extractRemoteInfo(fsSpec) {
918
1013
  if (parsed != null) {
919
1014
  debug("[extractRemoteInfo] parsed URL: %o", parsed);
920
1015
  const fstype = normalizeFsType(parsed.protocol);
921
- if (!isRemoteFsType(fstype)) {
1016
+ if (!isRemoteFsType(fstype, networkFsTypes)) {
922
1017
  return {
923
1018
  uri: fsSpec,
924
1019
  remote: false
@@ -1071,6 +1166,7 @@ function mountEntryToMountPoint(entry) {
1071
1166
  };
1072
1167
  }
1073
1168
  function mountEntryToPartialVolumeMetadata(entry, options = {}) {
1169
+ const networkFsTypes = options.networkFsTypes ?? NetworkFsTypesDefault;
1074
1170
  return {
1075
1171
  mountPoint: entry.fs_file,
1076
1172
  fstype: entry.fs_vfstype,
@@ -1078,7 +1174,7 @@ function mountEntryToPartialVolumeMetadata(entry, options = {}) {
1078
1174
  isSystemVolume: isSystemVolume(entry.fs_file, entry.fs_vfstype, options),
1079
1175
  remote: false,
1080
1176
  // < default to false, but it may be overridden by extractRemoteInfo
1081
- ...extractRemoteInfo(entry.fs_spec)
1177
+ ...extractRemoteInfo(entry.fs_spec, networkFsTypes)
1082
1178
  };
1083
1179
  }
1084
1180
  function parseMtab(content) {
@@ -1330,9 +1426,9 @@ async function _getVolumeMetadata(o, nativeFn2) {
1330
1426
  debug("[getVolumeMetadata] requesting native metadata");
1331
1427
  const metadata = await (await nativeFn2()).getVolumeMetadata(o);
1332
1428
  debug("[getVolumeMetadata] native metadata: %o", metadata);
1333
- const remoteInfo = mtabInfo ?? extractRemoteInfo(metadata.uri) ?? extractRemoteInfo(metadata.mountFrom) ?? (isWindows ? parseUNCPath(o.mountPoint) : void 0);
1429
+ const remoteInfo = mtabInfo ?? extractRemoteInfo(metadata.uri, o.networkFsTypes) ?? extractRemoteInfo(metadata.mountFrom, o.networkFsTypes) ?? (isWindows ? parseUNCPath(o.mountPoint) : void 0);
1334
1430
  debug("[getVolumeMetadata] extracted remote info: %o", remoteInfo);
1335
- remote ||= isRemoteFsType(metadata.fstype) || (remoteInfo?.remote ?? metadata.remote ?? false);
1431
+ remote ||= isRemoteFsType(metadata.fstype, o.networkFsTypes) || (remoteInfo?.remote ?? metadata.remote ?? false);
1336
1432
  debug("[getVolumeMetadata] assembling: %o", {
1337
1433
  status,
1338
1434
  mtabInfo,
@@ -1460,7 +1556,9 @@ function setHidden(pathname, hidden, method = "auto") {
1460
1556
  0 && (module.exports = {
1461
1557
  IncludeSystemVolumesDefault,
1462
1558
  LinuxMountTablePathsDefault,
1559
+ NetworkFsTypesDefault,
1463
1560
  OptionsDefault,
1561
+ SkipNetworkVolumesDefault,
1464
1562
  SystemFsTypesDefault,
1465
1563
  SystemPathPatternsDefault,
1466
1564
  VolumeHealthStatuses,