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