Skip to content

Releases: photostructure/fs-metadata

v1.4.1

28 Apr 05:54
Immutable release. Only release title and notes can be modified.
v1.4.1
3e38a64

Choose a tag to compare

v1.4.0

21 Apr 04:21
Immutable release. Only release title and notes can be modified.
v1.4.0
b11dc06

Choose a tag to compare

Removed

  • Linux GIO/GLib integration removed. The optional enable_gio build-time
    flag, the getGioMountPoints native binding, and the entire src/linux/gio_*
    source tree have been deleted. The Linux mount-points and volume-metadata
    paths now use /proc/self/mounts parsing exclusively.

    Background: GIO was originally added to surface auto-mounted volumes (USB
    sticks, external SSDs) that appeared to be missing from /proc/mounts. The
    earlier mount-table read order has since been fixed, and direct verification
    on Ubuntu 24 confirmed that udisks2-mounted devices (/media/$USER/...) are
    fully visible via /proc/self/mounts without GIO. The remaining GIO code
    path was a thin wrapper around g_unix_mounts_get() (which itself reads
    /proc/self/mountinfo) — functionally redundant with the existing mtab
    parser. The GVolumeMonitor enrichment path that originally justified GIO had
    already been removed for thread-safety reasons in an earlier release.

    Net effect: smaller native module, no libglib2.0-dev build dependency, no
    libgio runtime dependency, simpler Linux build matrix. No public API
    changes — getVolumeMountPoints() and getVolumeMetadata() return the same
    data as before.

Changed

  • Linux build no longer requires libglib2.0-dev. Only libblkid-dev (and
    uuid-dev for the dev environment) is needed when compiling from source.
  • scripts/setup-native.mjs removed — its only purpose was GIO autodetection.
    npm run build and npm run build:native no longer invoke it.

Commits

Full Changelog: v1.3.0...v1.4.0

v1.3.0

27 Mar 04:12
Immutable release. Only release title and notes can be modified.
v1.3.0
c6767ae

Choose a tag to compare

Added

  • New optional mountPoints field on Options: pass pre-fetched mount points to getMountPointForPath() and getVolumeMetadataForPath() to avoid redundant system queries when resolving multiple paths. Obtain via getVolumeMountPoints({ includeSystemVolumes: true }).

Full Changelog: v1.2.0...v1.3.0

v1.2.0

27 Mar 00:05
Immutable release. Only release title and notes can be modified.
v1.2.0
19b2c64

Choose a tag to compare

Added

  • New getMountPointForPath(pathname) function: a lightweight alternative to getVolumeMetadataForPath() that returns only the mount point string without fetching full volume metadata (size, UUID, label, etc.). On macOS, uses a single fstatfs() call — no DiskArbitration, IOKit, or space calculations. On Linux/Windows, uses the same device-ID matching logic. Handles symlinks and APFS firmlinks correctly.

Full Changelog: v1.1.0...v1.2.0

v1.1.0

18 Mar 04:30
Immutable release. Only release title and notes can be modified.
v1.1.0
85b3e6f

Choose a tag to compare

Added

  • New getVolumeMetadataForPath(pathname) function: given any file or directory path, returns the VolumeMetadata for the volume that contains it. Mirrors the behavior of df pathname:

    • Resolves POSIX symlinks via realpath()
    • On macOS: uses fstatfs() f_mntonname to correctly resolve APFS firmlinks (e.g. /Users/System/Volumes/Data) — stat().dev does not follow firmlinks and would give the wrong result
    • On Linux: uses stat().dev device ID matching with path-prefix disambiguation for bind mounts and GIO mounts that share a device ID. Also works correctly in Docker containers, where /proc/self/mounts reflects the container's mount namespace.
    • On Windows: uses device ID and path-prefix matching against logical drives
  • New isReadOnly field on MountPoint (and by extension VolumeMetadata) indicating whether a volume is mounted read-only. This is useful for identifying volumes with unstable UUIDs, like the macOS APFS system snapshot at /, whose UUID changes on every OS update. Available on all platforms:

    • macOS: reads MNT_RDONLY from statfs flags
    • Linux: parses ro from mount options in /proc/mounts
    • Windows: checks FILE_READ_ONLY_VOLUME from GetVolumeInformation

Changed

  • macOS isSystemVolume detection now uses APFS volume roles via IOKit instead of path pattern heuristics. Each APFS volume has a role (System, Data, VM, Preboot, Recovery, etc.) stored in its superblock. We read this via DADiskCopyIOMedia()IORegistryEntryCreateCFProperty("Role"), with a MNT_SNAPSHOT fallback if DiskArbitration is unavailable. This is factual (Apple assigns the roles), not heuristic, and correctly distinguishes:
    • / (System role) → isSystemVolume: true — sealed OS snapshot, unstable UUID
    • /System/Volumes/Data (Data role) → isSystemVolume: false — primary user data volume
    • /System/Volumes/VM, Preboot, Update, Hardware, xarts, etc. → isSystemVolume: true
    • See doc/system-volume-detection.md for full details

Security

  • macOS: RAII wrapper (IOObjectGuard) for IOKit objects in APFS volume role detection, preventing Mach port resource leaks if exceptions occur during GetApfsVolumeRole()
  • macOS: DiskArbitration operations in getVolumeMountPoints() now serialize through the same g_diskArbitrationMutex used by getVolumeMetadata(), preventing potential data races when both APIs are called concurrently
  • See doc/SECURITY_AUDIT_2026.md for full audit details

Fixed

  • Zero-initialized VolumeMetadata size/used/available fields to prevent uninitialized values when volume info retrieval fails early
  • Windows: eliminated redundant GetVolumeInformationW call per drive in getVolumeMountPoints()

Removed

  • Removed macOS /System/Volumes/* path patterns from SystemPathPatternsDefault — these are now handled natively via APFS volume roles. The Spotlight, FSEvents, and Trashes glob patterns (**/.Spotlight-V100, **/.fseventsd, etc.) were also removed as they matched directories within volumes, not mount points.

Full Changelog

v1.0.1...v1.1.0

v1.0.1

02 Mar 05:09
Immutable release. Only release title and notes can be modified.
v1.0.1
7284122

Choose a tag to compare

Full Changelog: v1.0.0...v1.0.1

v1.0.0

24 Feb 05:55
Immutable release. Only release title and notes can be modified.
v1.0.0
7b86217

Choose a tag to compare

Security

  • Windows: add /NXCOMPAT (DEP) and /HIGHENTROPYVA (x64 high-entropy ASLR) linker flags
  • Windows: add WarningLevel: 4 as structured MSBuild property on x64 and ARM64 targets (avoids /W flag ordering conflicts with node-gyp defaults)
  • Linux/macOS: add -D_FORTIFY_SOURCE=2 and -Wformat-security compiler flags
  • Linux x64: add -fcf-protection=full (Intel CET); Linux ARM64: add -mbranch-protection=standard (PAC+BTI)

Full Changelog: v0.9.0...v1.0.0

v0.9.0

29 Dec 00:18
Immutable release. Only release title and notes can be modified.
v0.9.0
36190aa

Choose a tag to compare

Added

  • New networkFsTypes option for configuring network filesystem detection
  • NetworkFsTypesDefault and SkipNetworkVolumesDefault exports

Changed

  • Expanded SystemFsTypesDefault with bpf, tracefs, nsfs, ramfs, rpc_pipefs, fuse.lxcfs, fuse.portal
  • Expanded SystemPathPatternsDefault with macOS metadata paths, kubelet, LXC/LXD, Flatpak paths
  • isRemoteFsType() and extractRemoteInfo() accept optional networkFsTypes parameter

Commits

Full Changelog: v0.8.1...v0.9.0

v0.8.1

28 Dec 23:32
Immutable release. Only release title and notes can be modified.
v0.8.1
b897039

Choose a tag to compare

Changed

  • Added container runtime paths to the default set of system paths. See SystemPathPatternsDefault

Commits

Full Changelog: v0.8.0...v0.8.1

Release 0.8.0

02 Dec 06:14
v0.8.0
699af21

Choose a tag to compare

Added

  • FS_METADATA_TIMEOUT_MS environment variable for configuring operation timeout (see gotchas.md)

Security

  • Fixed TOCTOU race condition in macOS hidden file operations by using fstat()/fchflags() with file descriptors instead of path-based stat()/chflags()

Fixed

  • Added O_CLOEXEC flag to open() calls to prevent fd leaks on fork/exec
  • Fixed logic bug attempting to convert invalid CFStringRef in ProcessNetworkVolume
  • Fixed inconsistent status field when DiskArbitration returns partial results
  • Added noexcept to all RAII destructors to prevent std::terminate during stack unwinding
  • Removed GVolumeMonitor from Linux GIO metadata enrichment to fix thread safety issues
  • Fixed exception safety in Linux GIO metadata loop using RAII smart pointers
  • Fixed Windows FindFirstFileEx handle leak by using FindClose instead of CloseHandle
  • Fixed Windows promise race condition and resource leak from detached timeout threads
  • Added CreateEvent error checking in Windows thread pool
  • Zero-initialized VolumeInfo and DiskSpaceInfo members to prevent undefined behavior on ERROR_NOT_READY

Changed

  • Extracted shared FdGuard RAII class to common/fd_guard.h
  • Extracted shared WouldOverflow() utility to common/volume_utils.h
  • Moved path_security.h to common/ (POSIX-portable)
  • Simplified CFString null-terminator handling using strlen()
  • Documented intentional static dispatch queue singleton pattern
  • Consolidated Linux GIO RAII helpers (GFilePtr, GVolumePtr, etc.) in gio_utils.h
  • Added move semantics to BlkidCache for proper resource transfer

Commits

  • fix(changelog): add FS_METADATA_TIMEOUT_MS environment variable for operation timeout configuration (ac78b2d)
  • Merge pull request #153 from photostructure/dependabot/npm_and_yarn/dev-dependencies-65f50cb316 (c902196)
  • fix: add additional directory for node-sqlite in settings (1ddda96)
  • fix(workflow): consolidate macOS and Windows test jobs into a single test-mac-win job (0c9756a)
  • fix(workflow): replace QEMU with native ARM runners (2f9f6d0)
  • fix(workflow): change C/C++ build mode to manual and add Node.js setup step (0331d82)
  • fix: update timeout handling to use new getTimeoutMsDefault() function instead of const (which proved hard to test) (5eaaed8)
  • fix: initialize bufferSize in WNetConnection constructor for consistency (6cd065c)
  • fix: replace NULL with nullptr for better type safety in Windows code (b3aeee6)
  • fix(tests): use tsx CLI directly to avoid Windows npx ENOENT errors (1396b71)
  • fix(tests): replace execSync with execFileSync to avoid shell quoting issues (c53478c)
  • docs(build): add reference link for macOS Intel runner in workflow (1c6618a)
  • fix(test): ensure FS_METADATA_TIMEOUT_MS is removed from env vars for default value test (9e5dc8f)
  • test: GHA Alpine is glacial. Extend the timeout to 15s to deflake the test (ef07599)
  • feat(timeout): add FS_METADATA_TIMEOUT_MS environment variable support for configurable timeout (28a5313)
  • chore(deps-dev): bump eslint (99d6f0b)
  • docs: update Linux API Reference to clarify GVolumeMonitor thread safety and usage (27bf59d)
  • fix(gio_volume_metadata): remove GVolumeMonitor to fix thread safety (bca4ba7)
  • chore(fmt) (a10ecb8)
  • docs: add comprehensive Linux API Reference Guide (6fac02d)
  • docs: add CreateEvent API details to Windows API Reference (fffa210)
  • docs: update Windows API Reference with FindFirstFileExA and FindClose details (35e9181)
  • chore: update CHANGELOG for version 0.8.0 with Windows handle leak fixes and resource management improvements (2932d17)
  • chore: update CHANGELOG for version 0.8.0 with Linux GIO memory leak fixes and exception safety improvements (370e360)
  • docs: enhance macOS API Reference with additional sections and usage examples (fd32c50)
  • chore: update CHANGELOG for version 0.8.0 with macos-specific security fixes and enhancements (7ad992b)
  • chore(fmt) (8bb2261)
  • test: add comprehensive tests for Windows native code fixes (4a3657d)
  • chore: initialize members in VolumeInfo and DiskSpaceInfo to prevent uninitialized memory access (d9cd7eb)
  • chore: add FindHandleGuard for safe management of FindFirstFile handles (036192b)
  • chore: enhance WorkQueue constructor with error handling and initialization check (0c7ccfc)
  • chore: refactor CheckDriveAsync to improve exception handling and remove timeout management from the thread (fcb755b)
  • chore(line endings): ensure windows doesn't crlf the world (e6d04e8)
  • chore: simplify cache release logic and enhance move semantics in BlkidCache (479117c)
  • chore: use validated mount point for GIO metadata collection and error logging (c522517)
  • chore: enhance RAII management in GIO utilities and volume metadata handling (7b2f1b0)
  • chore: update CodeQL action to version 4.31.6 (cadf90f)
  • chore: implement secure path validation in volume metadata handling on linux and macos (c51dd3f)
  • chore: add volume utilities for safe multiplication and overflow checking (35521d0)
  • chore: add noexcept specifier to RAII destructors and methods for improved exception safety (5cd7628)
  • chore: implement file descriptor-based approach in GetHiddenWorker and SetHiddenWorker to prevent TOCTOU race conditions (fb34c20)
  • chore: add shared FdGuard RAII wrapper for POSIX file descriptors to ensure proper resource management (e3c3261)
  • chore: update ts-jest to version 29.4.6 (e4d872a)
  • chore(fmt) (96d24b9)
  • chore: update dependencies for prettier, tsx, and typedoc (639a550)
  • chore: add security configuration to disable npm lifecycle scripts by default (91de079)
  • chore: update devDependencies to latest versions (7207bf9)
  • chore(workflows): update actions/checkout and CodeQL action versions (1adfe35)
  • chore(deps): work around broken eslint (62a60da)
  • chore(dependencies): update package versions (559dec3)