2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2010 Free Software Foundation Europe e.V.
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.
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.
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
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.
29 * Written by James Harper, October 2008
32 #include "exchange-fd.h"
34 storage_group_node_t::storage_group_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_STORAGE_GROUP, parent_node)
39 restore_environment = NULL;
40 saved_log_path = NULL;
44 storage_group_node_t::~storage_group_node_t()
50 if (file_node != NULL)
56 storage_group_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
60 WCHAR *tmp_logfiles, *tmp_logfile_ptr;
65 _DebugMessage(100, "startBackupNode_STORAGE_GROUP state = %d, name = %s\n", state, name);
72 if (context->job_level == 'F')
74 _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_FULL)\n");
75 result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_FULL);
80 _DebugMessage(100, "Calling HrESEBackupSetup (BACKUP_TYPE_LOGS_ONLY)\n");
81 result = HrESEBackupSetup(hccx, ibi->hInstanceId, BACKUP_TYPE_LOGS_ONLY);
82 if (context->accurate)
89 _JobMessage(M_FATAL, "HrESEBackupSetup failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
95 if (context->path_bits[level + 1] == NULL)
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;
108 DATABASE_BACKUP_INFO *dbi = NULL;
110 for (current_dbi = 0; current_dbi < ibi->cDatabase; current_dbi++)
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)
119 if (current_dbi == ibi->cDatabase)
121 _JobMessage(M_FATAL, "Invalid Database '%s'\n", context->path_bits[level + 1]);
124 store_node = new store_node_t(tmp, this);
125 _DebugMessage(100, "Database name = %s\n", store_node->name);
127 store_node->hccx = hccx;
128 store_node->dbi = dbi;
129 context->current_node = store_node;
133 _DebugMessage(100, "Calling HrESEBackupGetLogAndPatchFiles\n");
134 result = HrESEBackupGetLogAndPatchFiles(hccx, &tmp_logfiles);
137 _JobMessage(M_FATAL, "HrESEBackupGetLogAndPatchFiles failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
140 for (len = 0, tmp_logfile_ptr = tmp_logfiles; *tmp_logfile_ptr != 0; tmp_logfile_ptr += wcslen(tmp_logfile_ptr) + 1)
142 len += wcslen(tmp_logfile_ptr) + 1;
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)
148 // check file modification date
150 FILETIME modified_time;
154 include_file = false;
155 handle = INVALID_HANDLE_VALUE;
156 if (context->job_since == 0)
160 handle = CreateFileW(tmp_logfile_ptr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
161 if (handle == INVALID_HANDLE_VALUE)
163 //_JobMessage(M_WARNING, "Could not open '%S' to check last modified date (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
169 if (GetFileTime(handle, NULL, NULL, &modified_time) == 0)
171 //_JobMessage(M_WARNING, "Could not check last modified date for '%S' (0x%08x), including anyway\n", tmp_logfile_ptr, GetLastError());
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)
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);
192 /* this is handled via checkFile now */
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);
205 if (handle != INVALID_HANDLE_VALUE)
210 logfile_ptr = logfiles;
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);
218 file_node->hccx = hccx;
219 file_node->filename = logfile_ptr;
220 context->current_node = file_node;
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;
240 storage_group_node_t::endBackupFile(exchange_fd_context_t *context)
243 bRC retval = bRC_Error;
245 _DebugMessage(100, "endBackupNode_STORAGE_GROUP state = %d\n", state);
250 // should never happen
253 // free node->storage_group_node
254 if (context->path_bits[level + 1] == NULL)
257 if (current_dbi == ibi->cDatabase)
265 // should never happen
269 logfile_ptr += wcslen(logfile_ptr) + 1;
270 if (*logfile_ptr == 0)
275 if (context->truncate_logs)
277 _DebugMessage(100, "Calling HrESEBackupTruncateLogs\n");
278 result = HrESEBackupTruncateLogs(hccx);
281 _JobMessage(M_FATAL, "HrESEBackupTruncateLogs failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
285 _JobMessage(M_INFO, "Truncated database logs for Storage Group %s\n", name);
290 _JobMessage(M_INFO, "Did NOT truncate database logs for Storage Group %s\n", name);
292 _DebugMessage(100, "Calling HrESEBackupInstanceEnd\n");
293 result = HrESEBackupInstanceEnd(hccx, ESE_BACKUP_INSTANCE_END_SUCCESS);
296 _JobMessage(M_FATAL, "HrESEBackupInstanceEnd failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
300 context->current_node = parent;
307 storage_group_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
312 _DebugMessage(100, "createFile_STORAGE_GROUP state = %d\n", state);
314 if (strcmp(context->path_bits[level], name) != 0)
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);
323 _JobMessage(M_FATAL, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
325 rp->create_status = CF_CREATED;
328 _DebugMessage(100, "Calling HrESERestoreClose\n");
329 result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
332 _JobMessage(M_FATAL, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
334 rp->create_status = CF_CREATED;
337 context->current_node = parent;
340 if (saved_log_path != NULL)
342 _DebugMessage(100, "Calling HrESERestoreReopen\n");
343 result = HrESERestoreReopen(context->computer_name, service_name, saved_log_path, &hccx);
346 _JobMessage(M_FATAL, "HrESERestoreReopen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
348 saved_log_path = NULL;
349 rp->create_status = CF_CREATED;
352 _DebugMessage(100, "Calling HrESERestoreGetEnvironment\n");
353 result = HrESERestoreGetEnvironment(hccx, &restore_environment);
356 _JobMessage(M_FATAL, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
358 saved_log_path = NULL;
359 rp->create_status = CF_CREATED;
362 saved_log_path = NULL;
370 if (context->path_bits[level + 2] == NULL)
372 _JobMessage(M_ERROR, "Unexpected log file '%s%s' - expecting database\n", full_path, context->path_bits[level + 1]);
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);
384 _JobMessage(M_FATAL, "HrESERestoreOpen failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
388 _DebugMessage(100, "Calling HrESERestoreGetEnvironment\n");
389 result = HrESERestoreGetEnvironment(hccx, &restore_environment);
392 _JobMessage(M_FATAL, "HrESERestoreGetEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
399 if (context->path_bits[level + 2] == NULL)
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;
409 if (context->path_bits[level + 2] != NULL)
411 _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
415 if (context->path_bits[level + 1] == NULL)
421 file_node = new file_node_t(bstrdup(context->path_bits[level + 1]), this);
422 file_node->hccx = hccx;
424 for (i = strlen(file_node->name) - 1; i >= 0; i--)
426 if (file_node->name[i] == '\\')
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;
440 if (rp->type != FT_DIREND)
442 _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
446 // must be the storage group node
447 _DebugMessage(100, "Calling HrESERestoreSaveEnvironment\n");
448 result = HrESERestoreSaveEnvironment(hccx);
451 _JobMessage(M_FATAL, "HrESERestoreSaveEnvironment failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
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);
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);
469 _JobMessage(M_INFO, "Storage Group '%s' restored successfully\n", name);
472 _DebugMessage(100, "Calling HrESERestoreClose\n");
473 result = HrESERestoreClose(hccx, RESTORE_CLOSE_NORMAL);
476 _JobMessage(M_FATAL, "HrESERestoreClose failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
481 rp->create_status = CF_CREATED;
484 rp->create_status = CF_CREATED;
491 storage_group_node_t::endRestoreFile(exchange_fd_context_t *context)
493 _DebugMessage(100, "endRestoreFile_STORAGE_GROUP state = %d\n", state);
503 context->current_node = parent;
506 context->current_node = parent;