Releases: photostructure/fs-metadata
v1.4.1
Full Changelog: v1.4.0...v1.4.1
v1.4.0
Removed
-
Linux GIO/GLib integration removed. The optional
enable_giobuild-time
flag, thegetGioMountPointsnative binding, and the entiresrc/linux/gio_*
source tree have been deleted. The Linux mount-points and volume-metadata
paths now use/proc/self/mountsparsing 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/mountswithout GIO. The remaining GIO code
path was a thin wrapper aroundg_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-devbuild dependency, no
libgioruntime dependency, simpler Linux build matrix. No public API
changes —getVolumeMountPoints()andgetVolumeMetadata()return the same
data as before.
Changed
- Linux build no longer requires
libglib2.0-dev. Onlylibblkid-dev(and
uuid-devfor the dev environment) is needed when compiling from source. scripts/setup-native.mjsremoved — its only purpose was GIO autodetection.
npm run buildandnpm run build:nativeno longer invoke it.
Commits
Full Changelog: v1.3.0...v1.4.0
v1.3.0
Added
- New optional
mountPointsfield onOptions: pass pre-fetched mount points togetMountPointForPath()andgetVolumeMetadataForPath()to avoid redundant system queries when resolving multiple paths. Obtain viagetVolumeMountPoints({ includeSystemVolumes: true }).
Full Changelog: v1.2.0...v1.3.0
v1.2.0
Added
- New
getMountPointForPath(pathname)function: a lightweight alternative togetVolumeMetadataForPath()that returns only the mount point string without fetching full volume metadata (size, UUID, label, etc.). On macOS, uses a singlefstatfs()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
Added
-
New
getVolumeMetadataForPath(pathname)function: given any file or directory path, returns theVolumeMetadatafor the volume that contains it. Mirrors the behavior ofdf pathname:- Resolves POSIX symlinks via
realpath() - On macOS: uses
fstatfs()f_mntonnameto correctly resolve APFS firmlinks (e.g./Users→/System/Volumes/Data) —stat().devdoes not follow firmlinks and would give the wrong result - On Linux: uses
stat().devdevice 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/mountsreflects the container's mount namespace. - On Windows: uses device ID and path-prefix matching against logical drives
- Resolves POSIX symlinks via
-
New
isReadOnlyfield onMountPoint(and by extensionVolumeMetadata) 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_RDONLYfromstatfsflags - Linux: parses
rofrom mount options in/proc/mounts - Windows: checks
FILE_READ_ONLY_VOLUMEfromGetVolumeInformation
- macOS: reads
Changed
- macOS
isSystemVolumedetection 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 viaDADiskCopyIOMedia()→IORegistryEntryCreateCFProperty("Role"), with aMNT_SNAPSHOTfallback 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.mdfor full details
Security
- macOS: RAII wrapper (
IOObjectGuard) for IOKit objects in APFS volume role detection, preventing Mach port resource leaks if exceptions occur duringGetApfsVolumeRole() - macOS: DiskArbitration operations in
getVolumeMountPoints()now serialize through the sameg_diskArbitrationMutexused bygetVolumeMetadata(), preventing potential data races when both APIs are called concurrently - See
doc/SECURITY_AUDIT_2026.mdfor full audit details
Fixed
- Zero-initialized
VolumeMetadatasize/used/available fields to prevent uninitialized values when volume info retrieval fails early - Windows: eliminated redundant
GetVolumeInformationWcall per drive ingetVolumeMountPoints()
Removed
- Removed macOS
/System/Volumes/*path patterns fromSystemPathPatternsDefault— 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
Full Changelog: v1.0.0...v1.0.1
v1.0.0
Security
- Windows: add
/NXCOMPAT(DEP) and/HIGHENTROPYVA(x64 high-entropy ASLR) linker flags - Windows: add
WarningLevel: 4as structured MSBuild property on x64 and ARM64 targets (avoids/Wflag ordering conflicts with node-gyp defaults) - Linux/macOS: add
-D_FORTIFY_SOURCE=2and-Wformat-securitycompiler 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
Added
- New
networkFsTypesoption for configuring network filesystem detection NetworkFsTypesDefaultandSkipNetworkVolumesDefaultexports
Changed
- Expanded
SystemFsTypesDefaultwithbpf,tracefs,nsfs,ramfs,rpc_pipefs,fuse.lxcfs,fuse.portal - Expanded
SystemPathPatternsDefaultwith macOS metadata paths, kubelet, LXC/LXD, Flatpak paths isRemoteFsType()andextractRemoteInfo()accept optionalnetworkFsTypesparameter
Commits
Full Changelog: v0.8.1...v0.9.0
v0.8.1
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
Added
FS_METADATA_TIMEOUT_MSenvironment 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-basedstat()/chflags()
Fixed
- Added
O_CLOEXECflag toopen()calls to prevent fd leaks on fork/exec - Fixed logic bug attempting to convert invalid CFStringRef in
ProcessNetworkVolume - Fixed inconsistent
statusfield when DiskArbitration returns partial results - Added
noexceptto all RAII destructors to preventstd::terminateduring stack unwinding - Removed
GVolumeMonitorfrom Linux GIO metadata enrichment to fix thread safety issues - Fixed exception safety in Linux GIO metadata loop using RAII smart pointers
- Fixed Windows
FindFirstFileExhandle leak by usingFindCloseinstead ofCloseHandle - Fixed Windows promise race condition and resource leak from detached timeout threads
- Added
CreateEventerror checking in Windows thread pool - Zero-initialized
VolumeInfoandDiskSpaceInfomembers to prevent undefined behavior onERROR_NOT_READY
Changed
- Extracted shared
FdGuardRAII class tocommon/fd_guard.h - Extracted shared
WouldOverflow()utility tocommon/volume_utils.h - Moved
path_security.htocommon/(POSIX-portable) - Simplified CFString null-terminator handling using
strlen() - Documented intentional static dispatch queue singleton pattern
- Consolidated Linux GIO RAII helpers (
GFilePtr,GVolumePtr, etc.) ingio_utils.h - Added move semantics to
BlkidCachefor 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)