Building OneDrive-Style File Sync Into Your Own Application
Introduction
"OneDrive-style" sync means placeholder files: everything in a folder looks present and browsable, but the actual data for a file downloads only when something opens it. Windows shows this with the familiar cloud, checkmark, and pinned icons; macOS and Linux have their own equivalents. None of it is exposed through a normal filesystem API. It's a distinct OS-level integration that OneDrive, Dropbox, and Google Drive each built by hooking into platform-specific frameworks meant for exactly this.
If you search for how to build this yourself, you land on Microsoft's Cloud Filter API documentation, which covers Windows only. macOS needs a separate integration with File Provider. Linux has no equivalent OS feature at all and is usually approximated with FUSE. Three platforms, three frameworks, none of which share an API, a data model, or a development pattern.
CBSync, the component at the core of CBFS Sync, is one API over all three. It builds on Cloud Filter API on Windows, File Provider on macOS, and FUSE on Linux, and translates each platform's native placeholder mechanism into the same set of events regardless of which OS your code is running on.
What Building This Yourself Actually Involves
On Windows, the Cloud Filter API requires registering a sync root, implementing a set of callback-style operations for hydration and dehydration, and correctly handling placeholder state transitions that Explorer depends on to show accurate icons. Get the state transitions wrong and files appear synced when they aren't, or won't dehydrate to free up space.
On macOS, the equivalent is a File Provider extension: a separate application extension target, its own entitlements, and packaging and code-signing requirements distinct from the host application. It has to be built and signed with Xcode, even if the rest of your application isn't a macOS-native project.
On Linux, there's no dedicated placeholder API. Tools that offer offline-file behavior there are typically built on FUSE, which projects a virtual filesystem and forwards every file operation to user-space code.
None of these three implementations are transferable to one another. A team building cross-platform sync either learns all three or ships inconsistent behavior across platforms.
What CBSync Handles, and What It Doesn't
CBSync's job is the OS integration layer: registering the sync root, presenting placeholders, firing events when the OS needs a directory listed or a file's data retrieved, and reporting local changes so your code can push them to a remote system.
CBSync does not talk to any remote storage on its own. There's no built-in backend, no bundled protocol client, and no assumption about where or how your data is stored. When the OS asks for a file's contents, your code decides how to get it, whether that's a REST call to your own service, an S3 request, or something else entirely. CBSync's value is that this remote-side logic is the only platform-specific work left. The placeholder mechanics, icons, and OS integration are handled once, the same way, on all three platforms.
Getting Started (.NET)
Set the synchronization root and register it with the OS. On Windows, also set an account and app identifier so the OS can distinguish this sync root from others on the same machine:
cbsync.SyncRootPath = @"C:\Users\Public\MySync";
cbsync.Config("WindowsStorageProviderAccount=MyApp");
cbsync.Config("WindowsStorageProviderId=com.example.myapp");
cbsync.Install();
Install registers the sync root persistently and only needs to run once per sync root. CBSync doesn't support UWP applications on Windows at all, a limitation of the underlying Cloud Filter API that Callback's own documentation states plainly rather than a restriction CBSync adds on top; a Windows product built as UWP needs a different integration approach entirely. MAUI isn't excluded the same way: CBFS Sync's own macOS sample ships as a MAUI application, so that combination is a supported, documented path. On Linux, the same call checks that FUSE is present on the system.
With the sync root registered, activate it and handle the two events every implementation needs: listing a remote directory's contents, and returning a file's data on request.
cbsync.OnListDirectory += (o, e) => {
// Query your backend for what's at e.Path, then report each item.
// created, accessed, and modified are DateTime values (UTC) from your backend's metadata.
cbsync.ListFile(e.TaskId, "report.pdf", 0, 20480, created, accessed, modified);
cbsync.ListFolder(e.TaskId, "Archive", 0, created, accessed, modified);
};
cbsync.OnGetFileData += (o, e) => {
// Fetch e.Length bytes starting at e.Offset from your backend.
byte[] buffer = DownloadRange(e.Path, e.Offset, e.Length);
cbsync.PutFileData(e.TaskId, buffer, 0, buffer.Length);
};
cbsync.Activate(true);
From there, CBSync fires a matching pair of events, one for files and one for folders, for every kind of local change: OnCreateFile/OnCreateFolder, OnUpdateFile/OnUpdateFolder, OnDeleteFile/OnDeleteFolder, and OnRenameFile/OnRenameFolder. Your handlers replicate each one to your backend. Going the other direction, the corresponding CreateFile, CreateFolder, UpdateFile, UpdateFolder, DeleteFile, DeleteFolder, and RenameFile methods push a remote-side change back down to the local sync root. If your backend can't respond within the event handler, complete it later by returning CBFSSYNC_PENDING and calling FinalizeTask once the work is done, so slow network calls never block the OS thread that fired the event.
Platform-Specific Requirements
Windows and Linux need no additional build steps beyond what's shown above, though the Windows sync root has to sit on an NTFS volume; that requirement comes from Cloud Filter API itself, not from CBSync. macOS is the exception: CBFS Sync doesn't ship a pre-built extension, because the File Provider extension has to be signed with your own credentials and identifiers. Instead, it ships the extension's source and a precompiled core framework, and building it requires Xcode and the macOS SDK on a Mac, plus entitlements that grant access to /Library/CloudStorage/, where macOS keeps the local copies of synchronized files.
None of this involves a kernel-mode driver on any platform. CBSync runs entirely on top of OS-provided user-mode frameworks, so there's no driver to sign, no reboot required to install it, and no driver-sharing or versioning to manage across applications.
When This Matters
If your application needs to offer OneDrive-style sync across more than one OS, the alternative to CBSync is learning Cloud Filter API, File Provider, and FUSE separately and keeping their behavior consistent by hand. If you only need this on one platform, and that platform is Windows, building directly against Cloud Filter API is a smaller lift and a reasonable option. CBSync is the shortcut when the requirement is more than one platform, or when consistent placeholder behavior across all of them matters more than owning the integration code yourself.
For the full event reference, error handling, and additional configuration settings, see Getting Started with the CBSync Component.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@callback.com.