Often, you want to have multiple versions of a file, but not rely on Windows NTFS versioning. Here is a simple Win32 class that you can easily use.
The ZIP includes a ready-to-use Notepad which demonstrates the library in a text editor (
Finalize() and keyboard shortcuts are not there yet). A simple 1.stxt file is there to open.
Using the Code
struct alignas(8) FSITEM
CLSID cid = FILESNAP::GUID_HEADER;
unsigned long long DiffAt = 0;
FILETIME created = ti();
FILETIME updated = ti();
unsigned long long i = 0;
unsigned long long at = 0;
unsigned long long sz = 0;
unsigned long long extradatasize = 0;
inline bool BuildMap(vector<FSITEM>& fsx);
FILESNAP(const wchar_t* fi);
inline bool SetSnap(size_t idx,int CommitForce = 0);
inline bool Create(DWORD Access= GENERIC_READ | GENERIC_WRITE, DWORD Share = 0,
LPSECURITY_ATTRIBUTES Atrs = 0, DWORD Disp = CREATE_NEW, DWORD Flags = 0);
inline unsigned long long Size();
inline bool Finalize();
inline bool Commit(size_t At,int Mode);
inline HANDLE GetH();
inline BOOL Write(const char* d, unsigned long long sz2);
inline BOOL Read(char* d, unsigned long long sz2);
inline unsigned long long SetFilePointer(unsigned long long s, DWORD m = FILE_BEGIN);
inline BOOL SetEnd();
inline void Close();
Working with the Class
- You want to create a new file, you simply pass the name to the
- You call
Create() with the
CREATE_NEW to create the file.
- You write to the file using
- When you want to save the current version, you call
Commit(0,0). For the first save,
Commit() ignores the two parameters.
- You keep writing to the file using
- The next
Commit() call will save the current contents as a differential backup. If the
Mode parameter is
Commit() saves as a differential backup to the first commit always. If the
Mode parameter is
Commit() saves as a differential backup to the specified commit number as the
At parameter. This allows you to either use differential or incremental backups.
- You keep writing, reading or else to the current handle using the
GetH() function which returns the current
HANDLE that you can use in other file functions.
- If you want to revert to a specific saving, use
CommitForce can be
0 means that if the file exists already, the function fails.
1 means that if the file exists already, a commit is taken before reverting.
2 does not commit before reverting.
- After you have used
GetH() etc. operate on the reverted data.
Close() will close the file (it does not commit), and delete all temporary files used by the class.
When you open an existing file, the class automatically calls
SetSnap() on the last snapshot found in the file. You can call
BuildMap() to return a
FSITEM array of all snapshots included in the file.
If you build files with mostly differential backups (related to the first snapshot), then the file will be larger, but quicker to open because only one operation will be done (the comparison between the first and the opened snapshot).
If you build files with mostly incremental backups (related to the last snapshot), then the file will be smaller, but slower to open because all snapshots must be processed when a snapshot is loaded.
GetH() with care, because the
HANDLE it returns is not valid anymore when
SetSnap() is called.
- 19/10/2017 - Some typos
- 8/10/2017 - First release