1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979) 2 // Box Backup, http://www.boxbackup.org/ 3 // 4 // Copyright (c) 2003-2010, Ben Summers and contributors. 5 // All rights reserved. 6 // 7 // Note that this project uses mixed licensing. Any file with this license 8 // attached, or where the code LICENSE-GPL appears on the first line, falls 9 // under the "Box Backup GPL" license. See the file COPYING.txt for more 10 // information about this license. 11 // 12 // --------------------------------------------------------------------- 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of the GNU General Public License 15 // as published by the Free Software Foundation; either version 2 16 // of the License, or (at your option) any later version. 17 // 18 // This program is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU General Public License for more details. 22 // 23 // You should have received a copy of the GNU General Public License 24 // along with this program; if not, write to the Free Software 25 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 // 27 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4] 28 // 29 // As a special exception to the GPLv2, the Box Backup Project gives 30 // permission to link any code falling under this license (the Box Backup 31 // GPL) with any software that can be downloaded from 32 // the OpenSSL website [http://www.openssl.org] under either the 33 // "OpenSSL License" or the "Original SSLeay License", and to distribute 34 // the linked executables under the terms of the "Box Backup GPL" license. 35 // 36 // As a special exception to the GPLv2, the Box Backup Project gives 37 // permission to link any code falling under this license (the Box Backup 38 // GPL) with any version of Microsoft's Volume Shadow Copy Service 7.2 SDK 39 // or Microsoft Windows Software Development Kit (SDK), including 40 // vssapi.lib, that can be downloaded from the Microsoft website 41 // [*.microsoft.com], and to distribute the linked executables under the 42 // terms of the "Box Backup GPL" license. 43 // -------------------------------------------------------------------------- 44 // 45 // File 46 // Name: BackupDaemon.h 47 // Purpose: Backup daemon 48 // Created: 2003/10/08 49 // 50 // -------------------------------------------------------------------------- 51 52 #ifndef BACKUPDAEMON__H 53 #define BACKUPDAEMON__H 54 55 #include <vector> 56 #include <string> 57 #include <memory> 58 59 #include "BackupClientContext.h" 60 #include "BackupClientDirectoryRecord.h" 61 #include "BoxTime.h" 62 #include "Daemon.h" 63 #include "Logging.h" 64 #include "Socket.h" 65 #include "SocketListen.h" 66 #include "SocketStream.h" 67 #include "TLSContext.h" 68 69 #include "autogen_BackupProtocolClient.h" 70 71 #ifdef WIN32 72 #include "WinNamedPipeListener.h" 73 #include "WinNamedPipeStream.h" 74 #endif 75 76 #ifdef ENABLE_VSS 77 # include <comdef.h> 78 # include <Vss.h> 79 # include <VsWriter.h> 80 # include <VsBackup.h> 81 #endif 82 83 class BackupClientDirectoryRecord; 84 class BackupClientContext; 85 class Configuration; 86 class BackupClientInodeToIDMap; 87 class ExcludeList; 88 class IOStreamGetLine; 89 class Archive; 90 91 // -------------------------------------------------------------------------- 92 // 93 // Class 94 // Name: BackupDaemon 95 // Purpose: Backup daemon 96 // Created: 2003/10/08 97 // 98 // -------------------------------------------------------------------------- 99 class BackupDaemon : public Daemon, ProgressNotifier, LocationResolver, 100 RunStatusProvider, SysadminNotifier 101 { 102 public: 103 BackupDaemon(); 104 ~BackupDaemon(); 105 106 private: 107 // methods below do partial (specialized) serialization of 108 // client state only 109 bool SerializeStoreObjectInfo(box_time_t theLastSyncTime, 110 box_time_t theNextSyncTime) const; 111 bool DeserializeStoreObjectInfo(box_time_t & theLastSyncTime, 112 box_time_t & theNextSyncTime); 113 bool DeleteStoreObjectInfo() const; 114 BackupDaemon(const BackupDaemon &); 115 116 public: 117 #ifdef WIN32 118 // add command-line options to handle Windows services 119 std::string GetOptionString(); 120 int ProcessOption(signed int option); 121 int Main(const std::string &rConfigFileName); 122 123 // This shouldn't be here, but apparently gcc on 124 // Windows has no idea about inherited methods... Main(const char * DefaultConfigFile,int argc,const char * argv[])125 virtual int Main(const char *DefaultConfigFile, int argc, 126 const char *argv[]) 127 { 128 return Daemon::Main(DefaultConfigFile, argc, argv); 129 } 130 #endif 131 132 void Run(); 133 virtual const char *DaemonName() const; 134 virtual std::string DaemonBanner() const; 135 virtual void Usage(); 136 const ConfigurationVerify *GetConfigVerify() const; 137 138 bool FindLocationPathName(const std::string &rLocationName, std::string &rPathOut) const; 139 140 enum 141 { 142 // Add stuff to this, make sure the textual equivalents in SetState() are changed too. 143 State_Initialising = -1, 144 State_Idle = 0, 145 State_Connected = 1, 146 State_Error = 2, 147 State_StorageLimitExceeded = 3 148 }; 149 GetState()150 int GetState() {return mState;} 151 152 // Allow other classes to call this too 153 void NotifySysadmin(SysadminNotifier::EventCode Event); 154 155 private: 156 void Run2(); 157 158 public: 159 void InitCrypto(); 160 void RunSyncNowWithExceptionHandling(); 161 void RunSyncNow(); 162 void OnBackupStart(); 163 void OnBackupFinish(); 164 // TouchFileInWorkingDir is only here for use by Boxi. 165 // This does NOT constitute an API! 166 void TouchFileInWorkingDir(const char *Filename); 167 168 private: 169 void DeleteAllLocations(); 170 void SetupLocations(BackupClientContext &rClientContext, const Configuration &rLocationsConf); 171 172 void DeleteIDMapVector(std::vector<BackupClientInodeToIDMap *> &rVector); DeleteAllIDMaps()173 void DeleteAllIDMaps() 174 { 175 DeleteIDMapVector(mCurrentIDMaps); 176 DeleteIDMapVector(mNewIDMaps); 177 } 178 void FillIDMapVector(std::vector<BackupClientInodeToIDMap *> &rVector, bool NewMaps); 179 180 void SetupIDMapsForSync(); 181 void CommitIDMapsAfterSync(); 182 void DeleteCorruptBerkelyDbFiles(); 183 184 void MakeMapBaseName(unsigned int MountNumber, std::string &rNameOut) const; 185 186 void SetState(int State); 187 188 void WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut); 189 void CloseCommandConnection(); 190 void SendSyncStartOrFinish(bool SendStart); 191 192 void DeleteUnusedRootDirEntries(BackupClientContext &rContext); 193 194 #ifdef PLATFORM_CANNOT_FIND_PEER_UID_OF_UNIX_SOCKET 195 // For warning user about potential security hole 196 virtual void SetupInInitialProcess(); 197 #endif 198 199 int UseScriptToSeeIfSyncAllowed(); 200 201 public: 202 class Location 203 { 204 public: 205 Location(); 206 ~Location(); 207 208 void Deserialize(Archive & rArchive); 209 void Serialize(Archive & rArchive) const; 210 private: 211 Location(const Location &); // copy not allowed 212 Location &operator=(const Location &); 213 public: 214 std::string mName; 215 std::string mPath; 216 std::auto_ptr<BackupClientDirectoryRecord> mpDirectoryRecord; 217 int mIDMapIndex; 218 ExcludeList *mpExcludeFiles; 219 ExcludeList *mpExcludeDirs; 220 221 #ifdef ENABLE_VSS 222 bool mIsSnapshotCreated; 223 VSS_ID mSnapshotVolumeId; 224 std::string mSnapshotPath; 225 #endif 226 }; 227 228 typedef const std::vector<Location *> Locations; GetLocations()229 Locations GetLocations() { return mLocations; } 230 231 private: 232 int mState; // what the daemon is currently doing 233 234 std::vector<Location *> mLocations; 235 236 std::vector<std::string> mIDMapMounts; 237 std::vector<BackupClientInodeToIDMap *> mCurrentIDMaps; 238 std::vector<BackupClientInodeToIDMap *> mNewIDMaps; 239 240 int mDeleteRedundantLocationsAfter; 241 242 // For the command socket 243 class CommandSocketInfo 244 { 245 public: 246 CommandSocketInfo(); 247 ~CommandSocketInfo(); 248 private: 249 CommandSocketInfo(const CommandSocketInfo &); // no copying 250 CommandSocketInfo &operator=(const CommandSocketInfo &); 251 public: 252 #ifdef WIN32 253 WinNamedPipeListener<1 /* listen backlog */> mListeningSocket; 254 std::auto_ptr<WinNamedPipeStream> mpConnectedSocket; 255 #else 256 SocketListen<SocketStream, 1 /* listen backlog */> mListeningSocket; 257 std::auto_ptr<SocketStream> mpConnectedSocket; 258 #endif 259 IOStreamGetLine *mpGetLine; 260 }; 261 262 // Using a socket? 263 std::auto_ptr<CommandSocketInfo> mapCommandSocketInfo; 264 265 // Stop notifications being repeated. 266 SysadminNotifier::EventCode mLastNotifiedEvent; 267 268 // Unused entries in the root directory wait a while before being deleted 269 box_time_t mDeleteUnusedRootDirEntriesAfter; // time to delete them 270 std::vector<std::pair<int64_t,std::string> > mUnusedRootDirEntries; 271 272 int64_t mClientStoreMarker; 273 bool mStorageLimitExceeded; 274 bool mReadErrorsOnFilesystemObjects; 275 box_time_t mLastSyncTime, mNextSyncTime; 276 box_time_t mCurrentSyncStartTime, mUpdateStoreInterval; 277 TLSContext mTlsContext; 278 bool mDeleteStoreObjectInfoFile; 279 bool mDoSyncForcedByPreviousSyncError; 280 281 public: StopRun()282 bool StopRun() { return this->Daemon::StopRun(); } StorageLimitExceeded()283 bool StorageLimitExceeded() { return mStorageLimitExceeded; } 284 285 private: 286 bool mLogAllFileAccess; 287 288 public: GetProgressNotifier()289 ProgressNotifier* GetProgressNotifier() { return mpProgressNotifier; } GetLocationResolver()290 LocationResolver* GetLocationResolver() { return mpLocationResolver; } GetRunStatusProvider()291 RunStatusProvider* GetRunStatusProvider() { return mpRunStatusProvider; } GetSysadminNotifier()292 SysadminNotifier* GetSysadminNotifier() { return mpSysadminNotifier; } SetProgressNotifier(ProgressNotifier * p)293 void SetProgressNotifier (ProgressNotifier* p) { mpProgressNotifier = p; } SetLocationResolver(LocationResolver * p)294 void SetLocationResolver (LocationResolver* p) { mpLocationResolver = p; } SetRunStatusProvider(RunStatusProvider * p)295 void SetRunStatusProvider(RunStatusProvider* p) { mpRunStatusProvider = p; } SetSysadminNotifier(SysadminNotifier * p)296 void SetSysadminNotifier (SysadminNotifier* p) { mpSysadminNotifier = p; } 297 298 private: 299 ProgressNotifier* mpProgressNotifier; 300 LocationResolver* mpLocationResolver; 301 RunStatusProvider* mpRunStatusProvider; 302 SysadminNotifier* mpSysadminNotifier; 303 304 /* ProgressNotifier implementation */ 305 public: NotifyIDMapsSetup(BackupClientContext & rContext)306 virtual void NotifyIDMapsSetup(BackupClientContext& rContext) { } 307 NotifyScanDirectory(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)308 virtual void NotifyScanDirectory( 309 const BackupClientDirectoryRecord* pDirRecord, 310 const std::string& rLocalPath) 311 { 312 if (mLogAllFileAccess) 313 { 314 BOX_INFO("Scanning directory: " << rLocalPath); 315 } 316 } NotifyDirStatFailed(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,const std::string & rErrorMsg)317 virtual void NotifyDirStatFailed( 318 const BackupClientDirectoryRecord* pDirRecord, 319 const std::string& rLocalPath, 320 const std::string& rErrorMsg) 321 { 322 BOX_WARNING("Failed to access directory: " << rLocalPath 323 << ": " << rErrorMsg); 324 } NotifyFileStatFailed(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,const std::string & rErrorMsg)325 virtual void NotifyFileStatFailed( 326 const BackupClientDirectoryRecord* pDirRecord, 327 const std::string& rLocalPath, 328 const std::string& rErrorMsg) 329 { 330 BOX_WARNING("Failed to access file: " << rLocalPath 331 << ": " << rErrorMsg); 332 } NotifyDirListFailed(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,const std::string & rErrorMsg)333 virtual void NotifyDirListFailed( 334 const BackupClientDirectoryRecord* pDirRecord, 335 const std::string& rLocalPath, 336 const std::string& rErrorMsg) 337 { 338 BOX_WARNING("Failed to list directory: " << rLocalPath 339 << ": " << rErrorMsg); 340 } NotifyMountPointSkipped(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)341 virtual void NotifyMountPointSkipped( 342 const BackupClientDirectoryRecord* pDirRecord, 343 const std::string& rLocalPath) 344 { 345 #ifdef WIN32 346 BOX_WARNING("Ignored directory: " << rLocalPath << 347 ": is an NTFS junction/reparse point; create " 348 "a new location if you want to back it up"); 349 #else 350 BOX_WARNING("Ignored directory: " << rLocalPath << 351 ": is a mount point; create a new location " 352 "if you want to back it up"); 353 #endif 354 } NotifyFileExcluded(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)355 virtual void NotifyFileExcluded( 356 const BackupClientDirectoryRecord* pDirRecord, 357 const std::string& rLocalPath) 358 { 359 if (mLogAllFileAccess) 360 { 361 BOX_INFO("Skipping excluded file: " << rLocalPath); 362 } 363 } NotifyDirExcluded(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)364 virtual void NotifyDirExcluded( 365 const BackupClientDirectoryRecord* pDirRecord, 366 const std::string& rLocalPath) 367 { 368 if (mLogAllFileAccess) 369 { 370 BOX_INFO("Skipping excluded directory: " << rLocalPath); 371 } 372 } NotifyUnsupportedFileType(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)373 virtual void NotifyUnsupportedFileType( 374 const BackupClientDirectoryRecord* pDirRecord, 375 const std::string& rLocalPath) 376 { 377 BOX_WARNING("Ignoring file of unknown type: " << rLocalPath); 378 } NotifyFileReadFailed(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,const std::string & rErrorMsg)379 virtual void NotifyFileReadFailed( 380 const BackupClientDirectoryRecord* pDirRecord, 381 const std::string& rLocalPath, 382 const std::string& rErrorMsg) 383 { 384 BOX_WARNING("Error reading file: " << rLocalPath 385 << ": " << rErrorMsg); 386 } NotifyFileModifiedInFuture(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)387 virtual void NotifyFileModifiedInFuture( 388 const BackupClientDirectoryRecord* pDirRecord, 389 const std::string& rLocalPath) 390 { 391 BOX_WARNING("Some files have modification times excessively " 392 "in the future. Check clock synchronisation. " 393 "Example file (only one shown): " << rLocalPath); 394 } NotifyFileSkippedServerFull(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)395 virtual void NotifyFileSkippedServerFull( 396 const BackupClientDirectoryRecord* pDirRecord, 397 const std::string& rLocalPath) 398 { 399 BOX_WARNING("Skipped file: server is full: " << rLocalPath); 400 } NotifyFileUploadException(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,const BoxException & rException)401 virtual void NotifyFileUploadException( 402 const BackupClientDirectoryRecord* pDirRecord, 403 const std::string& rLocalPath, 404 const BoxException& rException) 405 { 406 if (rException.GetType() == CommonException::ExceptionType && 407 rException.GetSubType() == CommonException::AccessDenied) 408 { 409 BOX_ERROR("Failed to upload file: " << rLocalPath 410 << ": Access denied"); 411 } 412 else 413 { 414 BOX_ERROR("Failed to upload file: " << rLocalPath 415 << ": caught exception: " << rException.what() 416 << " (" << rException.GetType() 417 << "/" << rException.GetSubType() << ")"); 418 } 419 } NotifyFileUploadServerError(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,int type,int subtype)420 virtual void NotifyFileUploadServerError( 421 const BackupClientDirectoryRecord* pDirRecord, 422 const std::string& rLocalPath, 423 int type, int subtype) 424 { 425 std::ostringstream msgs; 426 if (type != BackupProtocolClientError::ErrorType) 427 { 428 msgs << "unknown error type " << type; 429 } 430 else 431 { 432 switch(subtype) 433 { 434 case BackupProtocolClientError::Err_WrongVersion: 435 msgs << "WrongVersion"; 436 break; 437 case BackupProtocolClientError::Err_NotInRightProtocolPhase: 438 msgs << "NotInRightProtocolPhase"; 439 break; 440 case BackupProtocolClientError::Err_BadLogin: 441 msgs << "BadLogin"; 442 break; 443 case BackupProtocolClientError::Err_CannotLockStoreForWriting: 444 msgs << "CannotLockStoreForWriting"; 445 break; 446 case BackupProtocolClientError::Err_SessionReadOnly: 447 msgs << "SessionReadOnly"; 448 break; 449 case BackupProtocolClientError::Err_FileDoesNotVerify: 450 msgs << "FileDoesNotVerify"; 451 break; 452 case BackupProtocolClientError::Err_DoesNotExist: 453 msgs << "DoesNotExist"; 454 break; 455 case BackupProtocolClientError::Err_DirectoryAlreadyExists: 456 msgs << "DirectoryAlreadyExists"; 457 break; 458 case BackupProtocolClientError::Err_CannotDeleteRoot: 459 msgs << "CannotDeleteRoot"; 460 break; 461 case BackupProtocolClientError::Err_TargetNameExists: 462 msgs << "TargetNameExists"; 463 break; 464 case BackupProtocolClientError::Err_StorageLimitExceeded: 465 msgs << "StorageLimitExceeded"; 466 break; 467 case BackupProtocolClientError::Err_DiffFromFileDoesNotExist: 468 msgs << "DiffFromFileDoesNotExist"; 469 break; 470 case BackupProtocolClientError::Err_DoesNotExistInDirectory: 471 msgs << "DoesNotExistInDirectory"; 472 break; 473 case BackupProtocolClientError::Err_PatchConsistencyError: 474 msgs << "PatchConsistencyError"; 475 break; 476 default: 477 msgs << "unknown error subtype " << subtype; 478 } 479 } 480 481 BOX_ERROR("Failed to upload file: " << rLocalPath 482 << ": server error: " << msgs.str()); 483 } NotifyFileUploading(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)484 virtual void NotifyFileUploading( 485 const BackupClientDirectoryRecord* pDirRecord, 486 const std::string& rLocalPath) 487 { 488 if (mLogAllFileAccess) 489 { 490 BOX_NOTICE("Uploading complete file: " << rLocalPath); 491 } 492 } NotifyFileUploadingPatch(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)493 virtual void NotifyFileUploadingPatch( 494 const BackupClientDirectoryRecord* pDirRecord, 495 const std::string& rLocalPath) 496 { 497 if (mLogAllFileAccess) 498 { 499 BOX_NOTICE("Uploading patch to file: " << rLocalPath); 500 } 501 } NotifyFileUploadingAttributes(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath)502 virtual void NotifyFileUploadingAttributes( 503 const BackupClientDirectoryRecord* pDirRecord, 504 const std::string& rLocalPath) 505 { 506 if (mLogAllFileAccess) 507 { 508 BOX_NOTICE("Uploading new file attributes: " << 509 rLocalPath); 510 } 511 } NotifyFileUploaded(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,int64_t FileSize,int64_t UploadedSize)512 virtual void NotifyFileUploaded( 513 const BackupClientDirectoryRecord* pDirRecord, 514 const std::string& rLocalPath, 515 int64_t FileSize, int64_t UploadedSize) 516 { 517 if (mLogAllFileAccess) 518 { 519 BOX_NOTICE("Uploaded file: " << rLocalPath << ", " 520 "total size = " << FileSize << ", " 521 "uploaded size = " << UploadedSize); 522 } 523 } NotifyFileSynchronised(const BackupClientDirectoryRecord * pDirRecord,const std::string & rLocalPath,int64_t FileSize)524 virtual void NotifyFileSynchronised( 525 const BackupClientDirectoryRecord* pDirRecord, 526 const std::string& rLocalPath, 527 int64_t FileSize) 528 { 529 if (mLogAllFileAccess) 530 { 531 BOX_INFO("Synchronised file: " << rLocalPath); 532 } 533 } NotifyDirectoryDeleted(int64_t ObjectID,const std::string & rRemotePath)534 virtual void NotifyDirectoryDeleted( 535 int64_t ObjectID, 536 const std::string& rRemotePath) 537 { 538 if (mLogAllFileAccess) 539 { 540 BOX_NOTICE("Deleted directory: " << rRemotePath << 541 " (ID " << BOX_FORMAT_OBJECTID(ObjectID) << 542 ")"); 543 } 544 } NotifyFileDeleted(int64_t ObjectID,const std::string & rRemotePath)545 virtual void NotifyFileDeleted( 546 int64_t ObjectID, 547 const std::string& rRemotePath) 548 { 549 if (mLogAllFileAccess) 550 { 551 BOX_NOTICE("Deleted file: " << rRemotePath << 552 " (ID " << BOX_FORMAT_OBJECTID(ObjectID) << 553 ")"); 554 } 555 } NotifyReadProgress(int64_t readSize,int64_t offset,int64_t length,box_time_t elapsed,box_time_t finish)556 virtual void NotifyReadProgress(int64_t readSize, int64_t offset, 557 int64_t length, box_time_t elapsed, box_time_t finish) 558 { 559 BOX_TRACE("Read " << readSize << " bytes at " << offset << 560 ", " << (length - offset) << " remain, eta " << 561 BoxTimeToSeconds(finish - elapsed) << "s"); 562 } NotifyReadProgress(int64_t readSize,int64_t offset,int64_t length)563 virtual void NotifyReadProgress(int64_t readSize, int64_t offset, 564 int64_t length) 565 { 566 BOX_TRACE("Read " << readSize << " bytes at " << offset << 567 ", " << (length - offset) << " remain"); 568 } NotifyReadProgress(int64_t readSize,int64_t offset)569 virtual void NotifyReadProgress(int64_t readSize, int64_t offset) 570 { 571 BOX_TRACE("Read " << readSize << " bytes at " << offset << 572 ", unknown bytes remaining"); 573 } 574 575 #ifdef WIN32 576 private: 577 bool mInstallService, mRemoveService, mRunAsService; 578 std::string mServiceName; 579 #endif 580 581 #ifdef ENABLE_VSS 582 IVssBackupComponents* mpVssBackupComponents; 583 void CreateVssBackupComponents(); 584 bool WaitForAsync(IVssAsync *pAsync, const std::string& description); 585 typedef HRESULT (__stdcall IVssBackupComponents::*AsyncMethod)(IVssAsync**); 586 bool CallAndWaitForAsync(AsyncMethod method, 587 const std::string& description); 588 void CleanupVssBackupComponents(); 589 #endif 590 }; 591 592 #endif // BACKUPDAEMON__H 593