1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
5 Copyright (C) 2014-2015 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22 /*
23 Copyright transferred from MATRIX-Computer GmbH to
24 Kern Sibbald by express permission.
25 Author : Thorsten Engel
26 Created On : Fri May 06 21:44:00 2005
27 */
28 /* @file
29 Interface to Volume Shadow Copies (VSS)
30 */
31
32 #ifdef WIN32_VSS
33
34 #include "include/bareos.h"
35 #include "filed/filed.h"
36
37 #include "ms_atl.h"
38 #include <objbase.h>
39
40 using namespace filedaemon;
41
42 /*
43 * { b5946137-7b9f-4925-af80-51abd60b20d5 }
44 */
45 static const GUID VSS_SWPRV_ProviderID = {
46 0xb5946137, 0x7b9f, 0x4925, { 0xaf, 0x80, 0x51, 0xab, 0xd6, 0x0b, 0x20, 0xd5 }
47 };
48
VSSPathConvert(const char * szFilePath,char * szShadowPath,int nBuflen)49 static bool VSSPathConvert(const char *szFilePath, char *szShadowPath, int nBuflen)
50 {
51 JobControlRecord *jcr = get_jcr_from_tsd();
52
53 if (jcr && jcr->pVSSClient) {
54 return jcr->pVSSClient->GetShadowPath(szFilePath, szShadowPath, nBuflen);
55 }
56
57 return false;
58 }
59
VSSPathConvertW(const wchar_t * szFilePath,wchar_t * szShadowPath,int nBuflen)60 static bool VSSPathConvertW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen)
61 {
62 JobControlRecord *jcr = get_jcr_from_tsd();
63
64 if (jcr && jcr->pVSSClient) {
65 return jcr->pVSSClient->GetShadowPathW(szFilePath, szShadowPath, nBuflen);
66 }
67
68 return false;
69 }
70
VSSInit(JobControlRecord * jcr)71 void VSSInit(JobControlRecord *jcr)
72 {
73 /*
74 * Decide which vss class to initialize
75 */
76 if (g_MajorVersion == 5) {
77 switch (g_MinorVersion) {
78 case 1:
79 jcr->pVSSClient = new VSSClientXP();
80 break;
81 case 2:
82 jcr->pVSSClient = new VSSClient2003();
83 break;
84 }
85 /*
86 * Vista or Longhorn or later
87 */
88 } else if (g_MajorVersion >= 6) {
89 jcr->pVSSClient = new VSSClientVista();
90 }
91
92 /*
93 * Setup the callback functions.
94 */
95 if (!SetVSSPathConvert(VSSPathConvert, VSSPathConvertW)) {
96 Jmsg(jcr, M_FATAL, 0, "Failed to setup VSS Path Conversion callbacks.\n");
97 }
98 }
99
100 /*
101 * Constructor
102 */
VSSClient()103 VSSClient::VSSClient()
104 {
105 memset(this, 0, sizeof(VSSClient));
106 pAlistWriterState_ = New(alist(10, not_owned_by_alist));
107 pAlistWriterInfoText_ = New(alist(10, owned_by_alist));
108 uidCurrentSnapshotSet_ = GUID_NULL;
109 }
110
111 /*
112 * Destructor
113 */
~VSSClient()114 VSSClient::~VSSClient()
115 {
116 /*
117 * Release the IVssBackupComponents interface
118 * WARNING: this must be done BEFORE calling CoUninitialize()
119 */
120 if (pVssObject_) {
121 // pVssObject_->Release();
122 pVssObject_ = NULL;
123 }
124
125 DestroyWriterInfo();
126 delete pAlistWriterState_;
127 delete pAlistWriterInfoText_;
128
129 /*
130 * Call CoUninitialize if the CoInitialize was performed successfully
131 */
132 if (bCoInitializeCalled_) {
133 CoUninitialize();
134 }
135 }
136
InitializeForBackup(JobControlRecord * jcr)137 bool VSSClient::InitializeForBackup(JobControlRecord *jcr)
138 {
139 jcr_ = jcr;
140
141 GeneratePluginEvent(jcr, bEventVssInitializeForBackup);
142
143 return Initialize(0);
144 }
145
InitializeForRestore(JobControlRecord * jcr)146 bool VSSClient::InitializeForRestore(JobControlRecord *jcr)
147 {
148 metadata_ = NULL;
149 jcr_ = jcr;
150
151 GeneratePluginEvent(jcr, bEventVssInitializeForRestore);
152
153 return Initialize(0, true /*=>Restore*/);
154 }
155
GetShadowPath(const char * szFilePath,char * szShadowPath,int nBuflen)156 bool VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nBuflen)
157 {
158 if (!bBackupIsInitialized_)
159 return false;
160
161 /*
162 * Check for valid pathname
163 */
164 bool bIsValidName;
165
166 bIsValidName = strlen(szFilePath) > 3;
167 if (bIsValidName)
168 bIsValidName &= isalpha (szFilePath[0]) &&
169 szFilePath[1]==':' &&
170 szFilePath[2] == '\\';
171
172 if (bIsValidName) {
173 int nDriveIndex = toupper(szFilePath[0])-'A';
174 if (szShadowCopyName_[nDriveIndex][0] != 0) {
175
176 if (WideCharToMultiByte(CP_UTF8,0,szShadowCopyName_[nDriveIndex],-1,szShadowPath,nBuflen-1,NULL,NULL)) {
177 nBuflen -= (int)strlen(szShadowPath);
178 bstrncat(szShadowPath, szFilePath+2, nBuflen);
179 return true;
180 }
181 }
182 }
183
184 bstrncpy(szShadowPath, szFilePath, nBuflen);
185 errno = EINVAL;
186 return false;
187 }
188
GetShadowPathW(const wchar_t * szFilePath,wchar_t * szShadowPath,int nBuflen)189 bool VSSClient::GetShadowPathW(const wchar_t *szFilePath, wchar_t *szShadowPath, int nBuflen)
190 {
191 if (!bBackupIsInitialized_)
192 return false;
193
194 /*
195 * Check for valid pathname
196 */
197 bool bIsValidName;
198
199 bIsValidName = wcslen(szFilePath) > 3;
200 if (bIsValidName)
201 bIsValidName &= iswalpha (szFilePath[0]) &&
202 szFilePath[1]==':' &&
203 szFilePath[2] == '\\';
204
205 if (bIsValidName) {
206 int nDriveIndex = towupper(szFilePath[0])-'A';
207 if (szShadowCopyName_[nDriveIndex][0] != 0) {
208 wcsncpy(szShadowPath, szShadowCopyName_[nDriveIndex], nBuflen);
209 nBuflen -= (int)wcslen(szShadowCopyName_[nDriveIndex]);
210 wcsncat(szShadowPath, szFilePath+2, nBuflen);
211 return true;
212 }
213 }
214
215 wcsncpy(szShadowPath, szFilePath, nBuflen);
216 errno = EINVAL;
217 return false;
218 }
219
GetWriterCount()220 const size_t VSSClient::GetWriterCount()
221 {
222 return pAlistWriterInfoText_->size();
223 }
224
GetWriterInfo(int nIndex)225 const char* VSSClient::GetWriterInfo(int nIndex)
226 {
227 return (char*)pAlistWriterInfoText_->get(nIndex);
228 }
229
GetWriterState(int nIndex)230 const int VSSClient::GetWriterState(int nIndex)
231 {
232 void *item = pAlistWriterState_->get(nIndex);
233
234 /*
235 * Eliminate compiler warnings
236 */
237 #ifdef HAVE_VSS64
238 return (int64_t)(char *)item;
239 #else
240 return (int)(char *)item;
241 #endif
242 }
243
AppendWriterInfo(int nState,const char * pszInfo)244 void VSSClient::AppendWriterInfo(int nState, const char* pszInfo)
245 {
246 pAlistWriterInfoText_->push(bstrdup(pszInfo));
247 pAlistWriterState_->push((void*)nState);
248 }
249
250 /*
251 * Note, this is called at the end of every job, so release all
252 * the items in the alists, but do not delete the alist.
253 */
DestroyWriterInfo()254 void VSSClient::DestroyWriterInfo()
255 {
256 while (!pAlistWriterInfoText_->empty()) {
257 free(pAlistWriterInfoText_->pop());
258 }
259
260 while (!pAlistWriterState_->empty()) {
261 pAlistWriterState_->pop();
262 }
263 }
264 #endif
265
266