Filesystem Compatibility & Conformance
Swarmfile mounts as a real drive - ~/Swarmfile on macOS and Linux, a drive letter on Windows - through FUSE/FUSE-T and WinFsp, not through a synced local folder. The exact location is per-machine and can be configured (the engine's mount_point; Windows picks its drive letter at runtime), so read yours from the Desktop App's Status pill rather than hard-coding a path. That distinction matters for exactly the kind of file your native apps care about: does a rename actually rename, does a lock actually stop a second writer, does opening a 200 GB file touch the whole thing or just the bytes you read.
This page states plainly what works today, per platform, and what's a known gap.
What's verified#
Most rows below are exercised by automated write-semantics tests that drive the mounted filesystem the way an application does - not the internal storage code directly - on a live mount per platform. A few rows (adapter capabilities and platform-specific behavior) are covered by targeted tests instead; the Notes column says when.
| Capability | macOS | Linux | Windows | Notes |
|---|---|---|---|---|
| Create / read / write | Verified | Verified | Verified | |
| Delete (file & directory) | Verified | Verified | Verified | On Windows, verified via Win32 RemoveDirectory, cmd rmdir /s and .NET's recursive Directory.Delete, including on empty folders. PowerShell's Remove-Item -Recurse fails through the mount (known limitation - use one of the above instead) |
| Rename - same directory | Verified | Verified | Verified | |
| Rename - cross-directory (move) | Asserted | Asserted | Verified | Entry identity, history, comments, and locks move with the file - this is not a copy-then-delete. Windows verified on a live mount; macOS/Linux covered by the conformance suite |
Exclusive create (O_EXCL / Win32 CREATE_NEW) | Verified | Verified | Verified | A create that races an existing name is refused (EEXIST / STATUS_OBJECT_NAME_COLLISION), enforced at our layer - so it holds even offline, not just when the OS routes the open |
| Overwrite / truncate an existing file | Verified | Verified | Verified | Content-checksummed, not just size-checked |
| Directory listing at scale | Verified | Verified | Verified | Wildcard/exact-name filters are verified on Windows only - POSIX shells and apps glob client-side over a plain readdir, so there's no equivalent operation to assert there |
| Case handling | Case-preserving | Case-preserving | Case-insensitive | Matches each platform's native convention. Names also resolve across Unicode forms on every platform: café.txt created as NFC opens when asked for the NFD spelling, an ASCII-case-only difference resolves, and the Turkish dotted/dotless I family (İ/ı vs i) is treated as one name - the store keeps the spelling you created with. Verified live on Windows in both request directions and unit-tested cross-platform; the WinFsp boundary reports the requested spelling when the stored one differs by more than case, which is what lets the open succeed |
Free-space reporting (statfs) | Verified | Verified | Verified | |
fsync durability | Verified | Verified | Verified | A write is not reported durable until it actually is; on Windows this is the FlushFileBuffers path |
| Extended attributes (get/set/list/remove) | Local-only, via macOS's ._ files (see below) | Implemented | Not implemented | Windows EA specifically - see below. Not the same thing as alternate data streams, the row below. On Linux the adapter implements all four operations; nothing on a Linux mount creates them the way macOS does, so end-to-end use isn't exercised |
| Alternate data streams - create/read/write/enumerate/delete | N/A | N/A | Verified, incl. sync between two clients | Windows-only concept (file.ext:streamname). A stream also survives a copy through the mount rather than being silently dropped, the way most non-native sync tools drop it. The Zone.Identifier stream (Windows' Mark of the Web) stays on the machine that wrote it and never syncs - see Sync Exclusions. Every other stream's content travels the same hub upload/commit pipeline as file content. Verified on real Windows mounts: these operations, and sync between two clients through the hub. A stream written or changed on one client reads back identical on the other, a stream deletion reaches the other client, and a Zone.Identifier never leaves the client that wrote it |
| Alternate data streams - rename | N/A | N/A | Not supported (see below) | |
| Symlinks - create | Verified | Verified | Not supported (see below) | |
| Symlinks - read / follow / list / delete | Verified | Verified | Read, follow & list | On Windows, readlink (reparse-point resolution), following a link to its target, and listing it as a reparse point are all verified; delete-through-the-mount isn't verified on Windows |
Executable bit (chmod +x / -x) | Verified | Verified | Preserved (no executable bit) | Any x bit sets the project's per-file executable flag; the drive reports 0755 / 0644. A create with mode 0755 (including git checkout of a 100755 file) comes out executable. Windows has no mode bit: edits and safe-saves there keep the flag, and swarmfile chmod sets it from any platform |
| Byte-range locking (API) | Verified | Verified | Verified | Hub-enforced acquire/release/overlap-detection, driven over the engine control socket - the same primitive a native worksharing plugin (e.g. for Revit) would call. Release is always an explicit unlock call over that socket; on Windows in particular, a lock is not auto-released when the OS closes the file handle, so a caller must unlock explicitly. Revit/SolidWorks worksharing itself needs no plugin on Windows - Swarmfile honors the native OS file lock those apps already take and turns it into a hub-enforced claim across machines; on macOS/Linux only cooperative locks apply. A deployment that needs an open refused whenever the hub can't be reached can enable that (see Environment Variables). This byte-range API is the lower-level primitive for finer, element-level integrations beyond that. See Swarmfile vs. LucidLink for how the underlying lock guarantee compares |
| Folder/file ACL enforcement | Verified | Verified | Verified, incl. Explorer-visible permissions | Enforced hub-side for every client; only Windows additionally enforces and presents ACLs at the mount itself (Explorer-visible DACL). On macOS and Linux, Finder and ls show the mode bits from getattr, not the project's ACLs |
Declared gaps#
Each of these is a documented limitation:
-
Hard links. Not supported on any platform. Our metadata model is one entry = one path = one content id; a hard link needs a content-identity indirection the schema doesn't have.
-
Symlink creation on Windows. Windows mounts read and follow symlinks correctly but refuse to create one. Creating a Windows symlink as an unprivileged process requires Developer Mode or a specific privilege - support would work for some users and silently fail for others on the same drive, so we refuse consistently instead.
-
Renaming an alternate data stream itself. Renaming the base file that carries a stream works normally, and the stream travels with it. Renaming just the stream -
file.txt:secrettofile.txt:hidden- is out of scope and refused outright, not silently mishandled: we won't rename the base file when you only asked to rename one of its streams, and we won't leave the stream qualifier in a request that no path would ever resolve to. -
Extended attributes on Windows. Not implemented - a deliberate scope decision, separate from alternate data streams (see the verified-capabilities table above, which streams are supported).
-
A save the hub refuses reaches the app as
EIO. When a save is refused (a file held elsewhere, a plan or policy refusal, a root-create restriction, quarantine), the application only sees a generic I/O error; the reason is written under Why did my save fail? in the tray and printed byswarmfile sync stuck. The errno is deliberately generic, so read the reason there rather than from the app's error dialog. -
fallocate/copy_file_range/lseek(SEEK_HOLE). Not implemented on the POSIX adapters. -
fcntl()byte-range advisory locks are kernel-local only. They don't coordinate across machines - that's a different mechanism from the hub-enforced byte-range locking API above. An app that relies on plain POSIX advisory locks for multi-writer coordination (rather than calling into the lock API) gets locking that looks like it works but only protects against other processes on the same machine. -
Windows: a memory-mapped view can outlive the handle for reads, not for writes. Reading through a memory-mapped view works, including when an application closes the file handle before reading the map -
gitdoes exactly that with.git/config, which is whygit init/commit/statuswork on the mount. Writing through a mapping is only served while a file handle is open: an application that maps a file read-write, closes the handle, and then writes through the view can have those write-backs fail. Keep the handle open until the mapping is unmapped, or write through the handle. Read-only mappings (the common case, git included) are unaffected. -
A file isn't readable the instant it's written - for about a second, on Windows. The engine itself publishes the new content synchronously as the flush completes (the local metadata row, size included, is updated before close returns), so a script that opens the file through a fresh handle gets the new bytes on macOS and Linux. Windows can still report the old attributes (0 bytes for a new file, the previous size for an overwrite) for up to its 1-second Cache Manager revalidation timeout, because the kernel caches file info between revalidations. It matters for any workflow that writes a file and immediately reads it back - a save-then-verify step, a render job that re-opens its own output, or an app that reloads the file right after saving. A person clicking around is usually slower than the one-second window, but not always: reopening a just-saved file within that second can still see the old size. If you need certainty, wait on the engine rather than the clock:
swarmfile uploads --waitblocks until the upload queue is empty, andswarmfile statussplits the rest -pending uploads(blocks still going up),commits pending(bytes up, commit not landed; a plan-held commit shows underquota-held commits). (A plainsyncforces pending writes to flush locally but does not wait for the hub upload and commit, so use the counters, notsync, when that distinction matters.) -
access()/faccessat()aren't enforced locally. Permission is decided hub-side by the ACL system, not by local file mode bits, so a pre-flightaccess()check reports success even for a write the hub will later refuse. -
A read can WAIT, for a file that is still uploading. A file that has never finished uploading can be opened - it reports the size it is going to be, and reads work. A read into a range that has not arrived yet waits for it, bounded at 15 s by default, and returns a retryable error -
EAGAINon macOS and Linux,STATUS_IO_TIMEOUTon Windows - rather than an I/O error if the wait times out, because an application that sees an I/O error part way through a file usually decides the file is damaged and discards your document. A stall is the correct answer for a player; a corrupt-file error is not. It only ever applies to a file with no committed version yet, so nothing you are already reading changes behavior. -
macOS:
dittoworks. Plaincp/cp -R,rsync, Finder, and the installers and build scripts that reach fordittoall work. -
macOS extended attributes are local-only. The drive is mounted without NFS named attributes, so macOS keeps Finder tags, comments, and the like the way it does on any such volume: in an AppleDouble
._namefile beside the original. Swarmfile keeps those._files, and.DS_Store, on the machine that wrote them and never syncs them (see Sync Exclusions) -cp -p,ditto, andxattrwork with them on that machine, but a teammate (or that machine after a fresh install) won't see them. Windows alternate data streams are the exception and do travel (except theZone.IdentifierMark of the Web, which stays local); POSIX xattrs crossing machines would be a hub-side format addition, not a mount fix.
How we verify this#
Each platform has its own conformance suite driving the live mount, and a shared manifest keeps the three platforms' coverage aligned - a capability missing on one platform is caught rather than left for you to find. Known gaps are listed above.
How this compares to typical cloud storage clients#
Most general-purpose cloud storage clients - the kind built primarily for syncing documents and photos - are sync engines wearing a filesystem's clothing: a background process reconciling a local folder against the cloud, not a filesystem driver with defined semantics for the operations above. That's a fine model for a folder of PDFs. It tends to fall over for exactly the workloads Swarmfile targets: whole-file download before an app can open anything, no cross-process byte-range locking, and "two people edited it" resolved by keeping both files rather than by a lock.
This isn't a hypothetical concern - it shows up in vendor documentation for the professional tools this product is built for. Autodesk's own support article on using cloud-synced services with Revit files states that file-based worksharing isn't supported on common cloud-sync storage, and names corruption of the central model and lost work as the consequence. Esri's knowledge base similarly documents common problems running ArcGIS Pro against cloud storage services. If you're evaluating any filesystem - including this one - for this kind of workload, the questions worth asking are the ones this page answers: is locking enforced per byte range or just per whole file, is it enforced on every platform your team actually uses, and is any of it independently verified rather than asserted.