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