diff options
Diffstat (limited to 'NSCmpts/BackupActions.cpp')
-rw-r--r-- | NSCmpts/BackupActions.cpp | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/NSCmpts/BackupActions.cpp b/NSCmpts/BackupActions.cpp new file mode 100644 index 0000000..0dff71e --- /dev/null +++ b/NSCmpts/BackupActions.cpp @@ -0,0 +1,293 @@ +// BackupActions.cpp: implementation of the CBackupActions class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "BackupActions.h" + +#include "resource.h" +#include <appmisc.h> + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +bool CBackupActions::ArchivePrepare::Do(CActionEngine* pEngine, + HWND hwndUpdates) +{ + // Some Checks + ASSERT(pEngine != NULL); + + if(!m_dest.valid()) + throw CActionError(E_INVALIDARG, IDS_BACKUP_ERR_DEST, m_dest); + + // Create destination folder + HRESULT hr = m_dest.create(); + if(FAILED(hr)) + throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest); + + // This could take a while so message + Update(hwndUpdates, _T("Listing files to backup..."), NULL); + + // Iterate through source folders + string_array::const_iterator iterSrc; + for(iterSrc = m_src.begin(); iterSrc != m_src.end(); iterSrc++) + { + Update(hwndUpdates, NULL, (LPCTSTR)*iterSrc); + + // Variables Used below + file_path srcPath = *iterSrc; + file_path srcFile; + file_path destFile; + + file_iterator fileIter(srcPath.files_begin(file_iterator::sub_folders)); + file_iterator end; + + for( ; fileIter != end; fileIter++) + { + // Check if it has the ARCHIVE attribute set + if(!(fileIter->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) + continue; + + if(fileIter->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + // Make File Paths + srcFile = *iterSrc; + + // Destination is root destination + same folder structure as + // original folder + destFile = m_dest; + + if(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY) + destFile += *(srcFile.end(false) - 1); + + destFile += fileIter->cFileName; + + srcFile = srcFile.folder() + fileIter->cFileName; + + + // Make sure extension is not in list + if(m_asIgnore.find(srcFile.ext().make_lower()) == m_asIgnore.end()) + { + // Add the file + ArchiveCopy* pCopy = new ArchiveCopy(srcFile, destFile); + pEngine->Add(pCopy); + } + } + + // Error from file_iterator (listing folders) + if(fileIter.state() != ERROR_SUCCESS) + throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_BACKUP_ERR_LIST, (file_path)*iterSrc); + } + + return false; +} + +HRESULT CBackupActions::BasePrepare::Initialize(const CPropertyBag& data) +{ + m_dest = data.GetString(NS_BACKUP_REG_DEST, _T("")); + data.GetStringSet(NS_BACKUP_REG_SOURCE, m_src); + + string_array asTemp; + data.GetStringSet(NS_IGNORE_REG_EXT, asTemp); + + // Make them all lower + for_each(asTemp.begin(), asTemp.end(), Lower); + + // And copy them to the set (removes doubles) + copy(asTemp.begin(), asTemp.end(), inserter(m_asIgnore, m_asIgnore.begin())); + + // Remove any blanks from ignore + m_asIgnore.erase(_T("")); + + if(!m_dest.valid()) + return E_INVALIDARG; + + return S_OK; +} + +#define FILETIME_TO_64(ft) \ + ((__int64) (ft.dwLowDateTime | ((__int64)(ft.dwHighDateTime << 32)))) + + +bool CBackupActions::DatePrepare::Do(CActionEngine* pEngine, + HWND hwndUpdates) +{ + // Some Checks + ASSERT(pEngine != NULL); + + if(!m_dest.valid()) + throw CActionError(E_INVALIDARG, IDS_BACKUP_ERR_DEST, m_dest); + + // Create destination folder + HRESULT hr = m_dest.create(); + if(FAILED(hr)) + throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest); + + // This could take a while so message + Update(hwndUpdates, _T("Comparing dates on backup files..."), NULL); + + HANDLE hFile; + FILETIME ftModify; + + // Iterate through source folders + string_array::const_iterator iterSrc; + for(iterSrc = m_src.begin(); iterSrc != m_src.end(); iterSrc++) + { + Update(hwndUpdates, NULL, (LPCTSTR)*iterSrc); + + // Variables Used below + file_path srcPath = *iterSrc; + file_path srcFile; + file_path destFile; + + file_iterator fileIter(srcPath.files_begin(file_iterator::sub_folders)); + file_iterator end; + + for( ; fileIter != end; fileIter++) + { + if(fileIter->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + // Make File Paths + srcFile = *iterSrc; + + // Destination is root destination + same folder structure as + // original folder + destFile = m_dest; + + if(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY) + destFile += *(srcFile.end(false) - 1); + + destFile += fileIter->cFileName; + + srcFile = srcFile.folder() + fileIter->cFileName; + + + // Make sure extension is not in list + if(m_asIgnore.find(srcFile.ext().make_lower()) != m_asIgnore.end()) + continue; + + // Open the file + hFile = CreateFile(destFile, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + + // Check return Value + if(hFile == INVALID_HANDLE_VALUE) + { + // If no file then Backup + switch(::GetLastError()) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + break; + default: + throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_FILE, m_dest); + } + } + else + { + // Get the filetime + ftModify.dwHighDateTime = 0; + ftModify.dwLowDateTime = 0; + + if(!GetFileTime(hFile, NULL, NULL, &ftModify)) + throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_FILE, destFile); + + CloseHandle(hFile); + + // Are we newer? + if(FILETIME_TO_64(fileIter->ftLastWriteTime) <= FILETIME_TO_64(ftModify)) + continue; + } + + // Add the file + ArchiveCopy* pCopy = new ArchiveCopy(srcFile, destFile); + pEngine->Add(pCopy); + + } + + // Error from file_iterator (listing folders) + if(fileIter.state() != ERROR_SUCCESS) + throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_BACKUP_ERR_LIST, (file_path)*iterSrc); + } + + return false; +} + +bool CBackupActions::ArchiveCopy::Do(CActionEngine* pEngine, + HWND hwndUpdates) +{ +start: + try + { + // Update any monitors + Update(hwndUpdates, _T("Copying..."), m_src); + + // Create the folder this file is in + HRESULT hr = m_dest.folder().create(); + if(FAILED(hr)) + throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest.folder()); + + // SetAttributes of the file to make sure it's not read-only + // when read-only CopyFile fails (CopyFile copies attributes) + ::SetFileAttributes(m_dest, FILE_ATTRIBUTE_NORMAL); + + // Copy. Don't worry about overwriting old files + if(!CopyFile(m_src, m_dest, FALSE)) + throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_COPY, m_src); + + // Remove the Archive Attribute of the file + SetFileAttributes(m_src, m_src.attributes() ^ FILE_ATTRIBUTE_ARCHIVE); + + return false; + } + catch(CActionError& err) + { + switch(err.m_hRes) + { + case ERROR_HANDLE_DISK_FULL: + case ERROR_DISK_FULL: + case ERROR_DESTINATION_ELEMENT_FULL: + case STG_E_MEDIUMFULL: + { + string sTemp; + sTemp.format(IDS_BACKUP_ERR_DISKFULL, (LPCTSTR)m_src.root()); + + if(IDYES == MessageBoxTimeout(hwndUpdates, sTemp, _T("Secure Shutdown"), MB_OKCANCEL | MB_ICONQUESTION, 15000, 5000)) + break; + } + default: + throw; + } + + } + + goto start; +} + +bool CBackupActions::DateCopy::Do(CActionEngine* pEngine, + HWND hwndUpdates) +{ + // Update any monitors + Update(hwndUpdates, _T("Copying..."), m_src); + + // Create the folder this file is in + HRESULT hr = m_dest.folder().create(); + if(FAILED(hr)) + throw CActionError(hr, IDS_BACKUP_ERR_CREATE_DEST, m_dest.folder()); + + // SetAttributes of the file to make sure it's not read-only + // when read-only CopyFile fails (CopyFile copies attributes) + ::SetFileAttributes(m_dest, FILE_ATTRIBUTE_NORMAL); + + // Copy. Don't worry about overwriting old files + if(!CopyFile(m_src, m_dest, FALSE)) + throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_BACKUP_ERR_COPY, m_src); + + return false; + + // We don't try to catch disk full errors (and prompt for another disk) + // because that doesn't make any sense in a date based backup +} |