]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/filed/plugins/exch_storage_group_node.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / filed / plugins / exch_storage_group_node.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /* 
20  *  Written by James Harper, July 2010
21  *  
22  *  Used only in "old Exchange plugin" now deprecated.
23  */
24
25 #include "exchange-fd.h"
26
27 storage_group_node_t::storage_group_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_STORAGE_GROUP, parent_node)
28 {
29    ibi = NULL;
30    store_node = NULL;
31    current_dbi = 0;
32    restore_environment = NULL;
33    saved_log_path = NULL;
34    next = NULL;
35 }
36
37 storage_group_node_t::~storage_group_node_t()
38 {
39 /*
40    safe_delete(dbi_node);
41    safe_delete(file_node);
42 */
43 }
44
45 bRC
46 storage_group_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
47 {
48    HRESULT result;
49    int len;
50    WCHAR *tmp_logfiles, *tmp_logfile_ptr;
51    char *tmp;
52
53    for(;;)
54    {
55       _DebugMessage(100, "startBackupNode_STORAGE_GROUP state = %d, name = %s\n", state, name);
56       switch(state)
57       {
58       case 0:
59          current_dbi = 0;
60          store_node = NULL;
61          logfile_ptr = NULL;
62          if (context->job_level == 'F')
63          {
64             _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_FULL)\n");
65             result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_FULL);
66             state = 1;
67          }
68          else
69          {
70             _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_LOGS_ONLY)\n");
71             result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_LOGS_ONLY);
72             if (context->accurate)
73                state = 1;
74             else
75                state = 2;
76          }
77          if (result != 0)
78          {
79             _JobMessage(M_FATAL, "HrESEBackupSetup failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
80             state = 999;
81             return bRC_Error;
82          }
83          break;
84       case 1:
85          if (context->path_bits[level + 1] == NULL)
86          {
87             _DebugMessage(100, "No specific database specified - backing them all up\n");
88             DATABASE_BACKUP_INFO *dbi = &ibi->rgDatabase[current_dbi];
89             char *tmp = new char[wcslen(dbi->wszDatabaseDisplayName) + 1];
90             wcstombs(tmp, dbi->wszDatabaseDisplayName, wcslen(dbi->wszDatabaseDisplayName) + 1);
91             store_node = new store_node_t(tmp, this);
92             store_node->dbi = dbi;
93             store_node->hccx = hccx;
94             context->current_node = store_node;
95          }
96          else
97          {
98             DATABASE_BACKUP_INFO *dbi = NULL;
99             char *tmp = NULL;
100             for (current_dbi = 0; current_dbi < ibi->cDatabase; current_dbi++)
101             {
102                dbi = &ibi->rgDatabase[current_dbi];
103                char *tmp = new char[wcslen(dbi->wszDatabaseDisplayName) + 1];
104                wcstombs(tmp, dbi->wszDatabaseDisplayName, wcslen(dbi->wszDatabaseDisplayName) + 1);
105                if (stricmp(tmp, context->path_bits[level + 1]) == 0)
106                   break;
107                safe_delete(tmp);
108             }
109             if (current_dbi == ibi->cDatabase)
110             {
111                _JobMessage(M_FATAL, "Invalid Database '%s'\n", context->path_bits[level + 1]);
112                return bRC_Error;
113             }
114             store_node = new store_node_t(tmp, this);
115             _DebugMessage(100, "Database name = %s\n", store_node->name);
116             safe_delete(tmp);
117             store_node->hccx = hccx;
118             store_node->dbi = dbi;
119             context->current_node = store_node;
120          }
121          return bRC_OK;
122       case 2:
123          _DebugMessage(100, "Calling HrESEBackupGetLogAndPatchFiles\n");
124          result = HrESEBackupGetLogAndPatchFiles(hccx, &tmp_logfiles);
125          if (result != 0)
126          {
127             _JobMessage(M_FATAL, "HrESEBackupGetLogAndPatchFiles failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
128             return bRC_Error;
129          }
130          for (len = 0, tmp_logfile_ptr = tmp_logfiles; *tmp_logfile_ptr != 0; tmp_logfile_ptr += wcslen(tmp_logfile_ptr) + 1)
131          {
132             len += wcslen(tmp_logfile_ptr) + 1;
133          }
134          logfiles = new WCHAR[len + 1];
135          logfile_ptr = logfiles;
136          for (tmp_logfile_ptr = tmp_logfiles; *tmp_logfile_ptr != 0; tmp_logfile_ptr += wcslen(tmp_logfile_ptr) + 1)
137          {
138             // check file modification date
139             HANDLE handle;
140             FILETIME modified_time;
141             //int64_t tmp_time;
142             __int64 tmp_time;
143             bool include_file;
144             include_file = false;
145             handle = INVALID_HANDLE_VALUE;
146             if (context->job_since == 0)
147                include_file = true;
148             if (!include_file)
149             {
150                handle = CreateFileW(tmp_logfile_ptr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
151                if (handle == INVALID_HANDLE_VALUE)
152                {
153                   //_JobMessage(M_WARNING, "Could not open '%S' to check last modified date (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
154                   include_file = true;
155                }
156             }
157             if (!include_file)
158             {
159                if (GetFileTime(handle, NULL, NULL, &modified_time) == 0)
160                {
161                   //_JobMessage(M_WARNING, "Could not check last modified date for '%S' (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
162                   include_file = true;
163                }
164             }
165             if (!include_file)
166             {
167                tmp_time = (((int64_t)modified_time.dwHighDateTime) << 32) | modified_time.dwLowDateTime;
168                tmp_time -= 116444736000000000LL;
169                tmp_time /= 10000000;
170                if (tmp_time > context->job_since)
171                {
172                   include_file = true;
173                }
174             }
175             if (include_file)
176             {
177                memcpy(logfile_ptr, tmp_logfile_ptr, (wcslen(tmp_logfile_ptr) + 1) * 2);
178                logfile_ptr += wcslen(logfile_ptr) + 1;
179                //_DebugMessage(100, "Including file %S\n", logfile_ptr);
180             }
181 #if 0
182 /* this is handled via checkFile now */
183             else
184             {
185                if (context->accurate) {
186                   tmp = new char[strlen(full_path) + wcslen(tmp_logfile_ptr) + 1];
187                   strcpy(tmp, full_path);
188                   wcstombs(tmp + strlen(full_path), tmp_logfile_ptr, wcslen(tmp_logfile_ptr) + 1);
189                   bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)tmp);
190                   delete tmp;
191                }
192             }
193 #endif
194
195             if (handle != INVALID_HANDLE_VALUE)
196                CloseHandle(handle);
197
198          }
199          *logfile_ptr = 0;
200          logfile_ptr = logfiles;
201          state = 3;
202          break;
203       case 3:
204          tmp = new char[wcslen(logfile_ptr) + 1];
205          wcstombs(tmp, logfile_ptr, wcslen(logfile_ptr) + 1);
206          file_node = new file_node_t(tmp, this);
207          delete tmp;
208          file_node->hccx = hccx;
209          file_node->filename = logfile_ptr;
210          context->current_node = file_node;
211          return bRC_OK;
212       case 4:
213          time_t now = time(NULL);
214          sp->fname = full_path;
215          sp->link = full_path;
216          _DebugMessage(100, "fname = %s\n", sp->fname);
217          sp->statp.st_mode = 0700 | S_IFDIR;
218          sp->statp.st_ctime = now;
219          sp->statp.st_mtime = now;
220          sp->statp.st_atime = now;
221          sp->statp.st_size = 0;
222          //sp->statp.st_blocks = 0;
223          sp->type = FT_DIREND;
224          return bRC_OK;
225       }
226    }
227 }
228
229 bRC
230 storage_group_node_t::endBackupFile(exchange_fd_context_t *context)
231 {
232    HRESULT result;
233    bRC retval = bRC_Error;
234
235    _DebugMessage(100, "endBackupNode_STORAGE_GROUP state = %d\n", state);
236
237    switch(state)
238    {
239    case 0:
240       // should never happen
241       break;
242    case 1:
243       // free node->storage_group_node
244       if (context->path_bits[level + 1] == NULL)
245       {
246          current_dbi++;
247          if (current_dbi == ibi->cDatabase)
248             state = 2;
249       }
250       else
251          state = 2;
252       retval = bRC_More;
253       break;
254    case 2:
255       // should never happen
256       break;
257    case 3:
258       safe_delete(file_node);
259       logfile_ptr += wcslen(logfile_ptr) + 1;
260       if (*logfile_ptr == 0)
261          state = 4;
262       retval = bRC_More;
263       break;
264    case 4:
265       if (context->truncate_logs) {
266          _DebugMessage(100, "Calling HrESEBackupTruncateLogs\n");
267          result = HrESEBackupTruncateLogs(hccx);
268          if (result != 0) {
269             _JobMessage(M_FATAL, "HrESEBackupTruncateLogs failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
270          } else {
271             _JobMessage(M_INFO, "Truncated database logs for Storage Group %s\n", name);
272          }
273       } else {
274          _JobMessage(M_INFO, "Did NOT truncate database logs for Storage Group %s\n", name);
275       }
276       _DebugMessage(100, "Calling HrESEBackupInstanceEnd\n");
277       result = HrESEBackupInstanceEnd(hccx, ESE_BACKUP_INSTANCE_END_SUCCESS);
278       if (result != 0) {
279          _JobMessage(M_FATAL, "HrESEBackupInstanceEnd failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
280          return bRC_Error;
281       }
282       retval = bRC_OK;
283       context->current_node = parent;
284       break;
285    }
286    return retval;
287 }
288
289 bRC
290 storage_group_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
291 {
292    HRESULT result;
293    int len;
294
295    _DebugMessage(0, "createFile_STORAGE_GROUP state = %d\n", state);
296
297    if (strcmp(context->path_bits[level], name) != 0) {
298       _DebugMessage(0, "Different storage group - switching back to parent\n", state);
299       saved_log_path = new WCHAR[wcslen(restore_environment->m_wszRestoreLogPath) + 1];
300       wcscpy(saved_log_path, restore_environment->m_wszRestoreLogPath);
301       _DebugMessage(100, "Calling HrESERestoreSaveEnvironment\n");
302       result = HrESERestoreSaveEnvironment(hccx);
303       if (result != 0) {
304          _JobMessage(M_FATAL, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
305          state = 999;
306          rp->create_status = CF_CREATED;
307          return bRC_OK;
308       }
309       _DebugMessage(100, "Calling HrESERestoreClose\n");
310       result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
311       if (result != 0) {
312          _JobMessage(M_FATAL, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
313          state = 999;
314          rp->create_status = CF_CREATED;
315          return bRC_OK;
316       }
317       context->current_node = parent;
318       return bRC_OK;
319    }
320    if (saved_log_path != NULL) {
321       _DebugMessage(0, "Calling HrESERestoreReopen\n");
322       result = HrESERestoreReopen(context->computer_name, service_name, saved_log_path, &hccx);
323       if (result != 0) {
324          _JobMessage(M_FATAL, "HrESERestoreReopen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
325          state = 999;
326          saved_log_path = NULL;
327          rp->create_status = CF_CREATED;
328          return bRC_OK;
329       }
330       _DebugMessage(0, "Calling HrESERestoreGetEnvironment\n");
331       result = HrESERestoreGetEnvironment(hccx, &restore_environment);
332       if (result != 0) {
333          _JobMessage(M_FATAL, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
334          state = 999;
335          saved_log_path = NULL;
336          rp->create_status = CF_CREATED;
337          return bRC_OK;
338       }
339       saved_log_path = NULL;
340    }
341
342    for (;;) {
343       switch (state) {
344       case 0:
345          if (context->path_bits[level + 2] == NULL) {
346             _JobMessage(M_ERROR, "Unexpected log file '%s%s' - expecting database\n", full_path, context->path_bits[level + 1]);
347             state = 999;
348             break;
349          }
350          service_name = new WCHAR[strlen(parent->name) + 1];
351          storage_group_name = new WCHAR[strlen(name) + 1];
352          mbstowcs(service_name, parent->name, strlen(parent->name) + 1);
353          mbstowcs(storage_group_name, name, strlen(name) + 1);
354          _DebugMessage(0, "Calling HrESERestoreOpen\n");
355          result = HrESERestoreOpen(context->computer_name, service_name, storage_group_name, NULL, &hccx);
356          if (result != 0) {
357             _JobMessage(M_FATAL, "HrESERestoreOpen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
358             state = 999;
359             break;
360          }
361          _DebugMessage(0, "Calling HrESERestoreGetEnvironment\n");
362          result = HrESERestoreGetEnvironment(hccx, &restore_environment);
363          if (result != 0) {
364             _JobMessage(M_FATAL, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
365             state = 999;
366             break;
367          }
368          state = 1;
369          break;
370       case 1:
371          if (context->path_bits[level + 2] == NULL) {
372             state = 2;
373             break;
374          }
375          store_node = new store_node_t(bstrdup(context->path_bits[level + 1]), this);
376          store_node->hccx = hccx;
377          context->current_node = store_node;
378          return bRC_OK;
379       case 2:
380          if (context->path_bits[level + 2] != NULL) {
381             _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
382             state = 999;
383             break;
384          }
385          if (context->path_bits[level + 1] == NULL) {
386             state = 3;
387             break;
388          }
389          state = 2;
390          file_node = new file_node_t(bstrdup(context->path_bits[level + 1]), this);
391          file_node->hccx = hccx;
392          int i;
393          for (i = strlen(file_node->name) - 1; i >= 0; i--) {
394             if (file_node->name[i] == '\\') {
395                i++;
396                break;
397             }
398          }
399          len = wcslen(restore_environment->m_wszRestoreLogPath) + strlen(file_node->name + i) + 1 + 1;
400          file_node->filename = new WCHAR[len];
401          wcscpy(file_node->filename, restore_environment->m_wszRestoreLogPath);
402          wcscat(file_node->filename, L"\\");
403          mbstowcs(&file_node->filename[wcslen(file_node->filename)], file_node->name + i, strlen(file_node->name + i) + 1);
404          context->current_node = file_node;
405          return bRC_OK;
406       case 3:
407          if (rp->type != FT_DIREND) {
408             _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
409             state = 999;
410             break;
411          }
412          // must be the storage group node
413          _DebugMessage(100, "Calling HrESERestoreSaveEnvironment\n");
414          result = HrESERestoreSaveEnvironment(hccx);
415          if (result != 0) {
416             _JobMessage(M_FATAL, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
417             state = 999;
418             break;
419          }
420
421          _DebugMessage(100, "Calling HrESERestoreComplete\n");
422          result = HrESERestoreComplete(hccx, restore_environment->m_wszRestoreLogPath,
423             restore_environment->m_wszRestoreLogPath, storage_group_name, ESE_RESTORE_COMPLETE_ATTACH_DBS);
424          if (result != 0) {
425             _JobMessage(M_FATAL, "HrESERestoreComplete failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
426             _DebugMessage(100, "Calling HrESERestoreClose\n");
427             result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
428             state = 999;
429             break;
430          } else {
431             _JobMessage(M_INFO, "Storage Group '%s' restored successfully\n", name);
432          }
433
434          _DebugMessage(100, "Calling HrESERestoreClose\n");
435          result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
436          if (result != 0) {
437             _JobMessage(M_FATAL, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
438             state = 999;
439             break;
440          }
441
442          rp->create_status = CF_CREATED;
443          return bRC_OK;
444       case 999:
445          rp->create_status = CF_CREATED;
446          return bRC_OK;
447       }
448    }
449 }
450
451 bRC
452 storage_group_node_t::endRestoreFile(exchange_fd_context_t *context)
453 {
454    _DebugMessage(0, "endRestoreFile_STORAGE_GROUP state = %d\n", state);
455    switch (state) {
456    case 0:
457       return bRC_Error;
458    case 1:
459       return bRC_OK;
460    case 2:
461       return bRC_OK;
462    case 3:
463       context->current_node = parent;
464       return bRC_OK;
465    case 999:
466       context->current_node = parent;
467       return bRC_OK;
468    }
469
470    return bRC_Error;
471 }