Ticket #13 (new defect)

Opened 3 years ago

Last modified 23 hours ago

Fix file locking on Windows

Reported by: chris Owned by: chris
Priority: normal Milestone: 0.12
Component: bbackupd Version: 0.10
Keywords: windows file locking locked volume shadow copy service vss Cc:

Description

There are two locking issues on Windows: Box cannot back up open files, and while Box is backing up a file, other applications cannot open it for writing.

Changing our access method to Volume Shadow Copy Service is probably the right fix for both of these, but it only works on XP and above, and I cannot install the SDK it on my development machine. I would also like to make it work with MinGW without requiring a restrictively-licensed SDK download from Microsoft.

Please could someone use a Windows machine (XP or above, Windows Activation compliant) to download the SDK and send it to me?

Another option (workaround) might be to use the Windows command-line tools to create a shadow copy and back that up instead of the original. However, I think that would be a kluge, difficult to install, and difficult to detect and handle errors with.

Attachments

ShadowBox.bat (2.9 KB) - added by petej 3 years ago.
ShadowBox?.bat, an example of how to use Shadow Copy, vshadow.exe

Change History

Changed 3 years ago by chris

The SDK can be found here.

Changed 3 years ago by gadlen

I fetched it. It can (for now) be found here. http://lee.org/temp/Volume-Shadow-Copy-Service%20SDK-7.2-setup.exe

:-) Lee http://lee.org

Changed 3 years ago by chris

Got it, thanks.

Changed 3 years ago by petej

ShadowBox?.bat, an example of how to use Shadow Copy, vshadow.exe

Changed 2 years ago by chris

  • milestone changed from 0.11 to 0.12

Not in 0.11, sorry.

Changed 24 hours ago by achim

A good example of how simple VSS-support was added to Cywgin Rsync 3.0.x (check the patch files, they seem straightforward).

I have already checked via e-mail with both Leen Besselink (the author of the page) and Elias Penttilä (the original author) and they are absolutely fine with us using their source either verbatim or as inspiration.

http://www.consolejunky.net/cwrsync-vss/

Changed 24 hours ago by achim

Elias Penttilä's patchset for rsync-2.6.6 http://users.tkk.fi/~epenttil/rsync-vss/

Changed 23 hours ago by achim

First ideas for VSS implementation

First off, the GPL'ed Bacula backup project introduced an abstraction layer "VSSClient" that is used to create the actual VSS depending on the underlying Windows OS, as the APIs seem slightly different for XP, 2K3 and Vista/Windows 7. All VSS code is contained in one vss_generic.cpp which uses #ifdef to include the headers and libs for each OS, such as:

#ifdef B_VSS_XP
// #pragma message("compile VSS for Windows XP")   
   #define VSSClientGeneric VSSClientXP
   
   #include "inc/WinXP/vss.h"
   #include "inc/WinXP/vswriter.h"
   #include "inc/WinXP/vsbackup.h"

#endif

#ifdef B_VSS_W2K3
// #pragma message("compile VSS for Windows 2003")
   #define VSSClientGeneric VSSClient2003
   
   #include "inc/Win2003/vss.h"
   #include "inc/Win2003/vswriter.h"
   #include "inc/Win2003/vsbackup.h"
#endif

This requires that all SDKs to be available in their respective subdirectory, i.e. the XP VSS SDK should be available in boxbackup/win32/vss/inc/WinXP/ and the one for Server 2K3 in boxbackup/win32/vss/inc/Win2003/ (see next step)

For the specific header and code files, please refer to: http://bacula.svn.sourceforge.net/viewvc/bacula/trunk/bacula/src/win32/filed/?pathrev=8346

Using Bacula's approach for VSS in Box Backup

1. Install the required VSS SDKs (see "SDK Download links" below for where to get the various versions):

2. Make sure that MingW can see the VSS files and folders (in this case for Server 2003):

mkdir -p /usr/local/src/boxbackup/win32/vss/
ln -s /cygdrive/c/Program\ Files/Microsoft/VSSSDK72/inc/win2003 /usr/local/src/boxbackup/win32/vss/inc/Win2003
ln -s /cygdrive/c/Program\ Files/Microsoft/VSSSDK72/lib/win2003/obj/i386 /usr/local/src/boxbackup/win32/vss/lib/Win2003
ln -s /cygdrive/c/Program\ Files/MSXML\ 4.0/inc /usr/local/src/boxbackup/win32/inc_xml

3. add this to bin/bbackupd/Makefile to enable linking (in this case for Server 2003)

-lole32 -luuid win32/vss/lib/Win2003/vssapi.lib win32/vss/lib/Win2003/vss_uuid.lib

4. Add VSS code to BB, based on the following functions implemented by the Bacula "API"

BOOL InitializeForBackup();
virtual BOOL CreateSnapshots(char* szDriveLetters) = 0;
virtual BOOL CloseBackup() = 0;
virtual const char* GetDriverName() = 0;
BOOL GetShadowPath  (const char* szFilePath, char* szShadowPath, int nBuflen);
BOOL GetShadowPathW (const wchar_t* szFilePath, wchar_t* szShadowPath, int nBuflen); /* nBuflen in characters */
BOOL CloseBackup()

On a high level, we need to a. Create the shadow copy and receive a (global) handle to a VSSClient object b. Substitute all paths that are used for backup with the corresponding VSS path as generated by our VSSClient object c. Deinit the shadow copy once the backup is done.

Note: There is also the AlphaVSS, "a .NET class library written in C++/CLI aiming to provide a managed interface to this API. The goal is to provide an interface that is simple to use from a C# or VB.NET application, yet providing the full functionality of VSS." http://alphavss.codeplex.com/ Not sure if we can use that somehow in stock C++?

Anyway, I detected the following places in the code where Box Backup interacts with the local file system paths:

lib/common/BoxPlatform.h

// Add VSS for Win32 clients
#ifdef WIN32
#ifndef USE_VSS
#define USE_VSS
#endif
#endif

bin/bbackupd/BackupDaemon.cpp

RunSyncNow()
#ifdef USE_VSS
	InitializeForBackup();
#endif
               // Sync the directory
               (*i)->mpDirectoryRecord->SyncDirectory(
                       params,
                       BackupProtocolClientListDirectory::RootDirectory,
                       (*i)->mPath, std::string("/") + (*i)->mName);

Local path is stored in (*i)->mPath

for(std::vector<Location *>::const_iterator
        i(mLocations.begin());
        i != mLocations.end(); ++i)
// add at the end of RunSyncNow()
#ifdef USE_VSS
	CloseBackup();
#endif

Now we need to make sure that the local path used by SyncDirectory? above is actually the VSS path:

bin/bbackupd/BackupClientDirectoryRecord.cpp

SyncDirectory
Purpose: Recursively synchronise a local directory with the server.

        BackupClientDirectoryRecord::SyncParams &rParams,
        int64_t ContainingDirectoryID,
        const std::string &rLocalPath,
        const std::string &rRemotePath,
        bool ThisDirHasJustBeenCreated)

Makes use of these other funcions:

UpdateItems
Purpose: Update the items stored on the server. The rFiles vector will be erased after it's used to save space.
Returns true if all items were updated successfully. (If not, the failures will have been logged).

UploadFile
Purpose: Update the items stored on the server. The rFiles vector will be erased after it's used to save space.
Returns true if all items were updated successfully. (If not, the failures will have been logged).
struct dirent *en = 0;
EMU_STRUCT_STAT file_st;
std::string filename;
while((en = ::readdir(dirHandle)) != 0)

uses MakeFullPath?

filename = MakeFullPath(rLocalPath, en->d_name);

lib/common/PathUtils.cpp

Name:    PathUtils.cpp
Purpose: Platform-independent path manipulation

Name:    MakeFullPath(const std::string& rDir, const std::string& rFile)
Purpose: Combine directory and file name

is where we need to add calls to and use the result to return the correct VSS-based FullPath?:

BOOL GetShadowPath  (const char* szFilePath, char* szShadowPath, int nBuflen);
BOOL GetShadowPathW (const wchar_t* szFilePath, wchar_t* szShadowPath, int nBuflen); /* nBuflen in characters */

SDK Download links

For Windows XP and 2003 users, you can download Microsoft’s Volume Shadow Copy Service SDK.

http://www.microsoft.com/downloads/details.aspx?FamilyID=0B4F56E4-0CCC-4626-826A-ED2C4C95C871&displaylang=en

http://www.microsoft.com/downloads/details.aspx?FamilyID=0b4f56e4-0ccc-4626-826a-ed2c4c95c871&displaylang=en&Hash=XbJaz6J077EdJjQS1kvwkBx2hOhvwBFCTsP8QUwEqEoyk5xpijF%2ftKvdCP7mZPNC2HnBGRcuuT5luN2TuMLTqA%3d%3d

Vista user’s need to download the Windows Vista SDK Update V6.0 (Microsoft Windows SDK Update for Windows Vista and .NET Framework 3.0)

http://msdn.microsoft.com/en-us/windows/bb980924.aspx

http://www.microsoft.com/downloads/details.aspx?FamilyID=4377F86D-C913-4B5C-B87E-EF72E5B4E065&displaylang=en

2008 Server

http://www.microsoft.com/downloads/details.aspx?FamilyID=F26B1AA4-741A-433A-9BE5-FA919850BDBF&displaylang=en

Windows 7 needs SDK 7.0

http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en

Note: See TracTickets for help on using tickets.