2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2018 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Written by James Harper, October 2008
23 #include "exchange-fd.h"
25 dbi_node_t::dbi_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_DATABASE_INFO, parent_node)
27 restore_display_name = NULL;
28 restore_input_streams = NULL;
32 dbi_node_t::~dbi_node_t()
36 if (restore_input_streams != NULL)
37 delete restore_input_streams;
38 if (restore_display_name != NULL)
39 delete restore_display_name;
43 dbi_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
45 time_t now = time(NULL);
47 _DebugMessage(100, "startBackupNode_DBI state = %d\n", state);
49 if (context->job_level == 'F') {
50 sp->fname = full_path;
52 sp->statp.st_mode = 0700 | S_IFREG;
53 sp->statp.st_ctime = now;
54 sp->statp.st_mtime = now;
55 sp->statp.st_atime = now;
56 sp->statp.st_size = (uint64_t)-1;
62 bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)full_path);
68 dbi_node_t::endBackupFile(exchange_fd_context_t *context)
70 _DebugMessage(100, "endBackupNode_DBI state = %d\n", state);
72 context->current_node = parent;
78 dbi_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
80 _DebugMessage(100, "createFile_DBI state = %d\n", state);
82 rp->create_status = CF_EXTRACT;
88 dbi_node_t::endRestoreFile(exchange_fd_context_t *context)
90 _DebugMessage(100, "endRestoreFile_DBI state = %d\n", state);
92 context->current_node = parent;
98 dbi_node_t::pluginIoOpen(exchange_fd_context_t *context, struct io_pkt *io)
107 buffer = new char[buffer_size];
109 if (context->job_type == JOB_TYPE_BACKUP)
111 ptr = (WCHAR *)buffer;
112 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"DatabaseBackupInfo\n");
115 buffer_pos += len * 2;
118 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%d\n", EXCHANGE_PLUGIN_VERSION);
121 buffer_pos += len * 2;
124 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", dbi->wszDatabaseDisplayName);
127 buffer_pos += len * 2;
130 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
131 dbi->rguidDatabase.Data1, dbi->rguidDatabase.Data2, dbi->rguidDatabase.Data3,
132 dbi->rguidDatabase.Data4[0], dbi->rguidDatabase.Data4[1],
133 dbi->rguidDatabase.Data4[2], dbi->rguidDatabase.Data4[3],
134 dbi->rguidDatabase.Data4[4], dbi->rguidDatabase.Data4[5],
135 dbi->rguidDatabase.Data4[6], dbi->rguidDatabase.Data4[7]);
138 buffer_pos += len * 2;
141 stream = dbi->wszDatabaseStreams;
144 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", stream);
147 buffer_pos += len * 2;
149 stream += wcslen(stream) + 1;
152 buffer_size = buffer_pos;
167 dbi_node_t::pluginIoRead(exchange_fd_context_t *context, struct io_pkt *io)
172 io->status = MIN(io->count, (int)(buffer_size - buffer_pos));
175 memcpy(io->buf, buffer + buffer_pos, io->status);
176 buffer_pos += io->status;
182 dbi_node_t::pluginIoWrite(exchange_fd_context_t *context, struct io_pkt *io)
184 memcpy(&buffer[buffer_pos], io->buf, io->count);
185 buffer_pos += io->count;
186 io->status = io->count;
192 dbi_node_t::pluginIoClose(exchange_fd_context_t *context, struct io_pkt *io)
199 int stream_buf_count;
200 WCHAR *streams_start;
202 if (context->job_type == JOB_TYPE_RESTORE)
204 // need to think about making this buffer overflow proof...
205 _DebugMessage(100, "analyzing DatabaseBackupInfo\n");
206 ptr = (WCHAR *)buffer;
208 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
211 _DebugMessage(150, "Header = %S\n", tmp);
212 // verify that header == "DatabaseBackupInfo"
214 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
216 if (swscanf(tmp, L"%d%c", &version, &eol) != 1)
219 _DebugMessage(150, "Version = 0 (inferred)\n");
224 _DebugMessage(150, "Version = %d\n", version);
225 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
228 restore_display_name = new WCHAR[wchars_read];
229 swscanf(ptr, L"%127[^\n]", restore_display_name);
230 _DebugMessage(150, "Database Display Name = %S\n", restore_display_name);
233 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
236 if (swscanf(ptr, L"%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
237 &restore_guid.Data1, &restore_guid.Data2, &restore_guid.Data3,
238 &restore_guid.Data4[0], &restore_guid.Data4[1],
239 &restore_guid.Data4[2], &restore_guid.Data4[3],
240 &restore_guid.Data4[4], &restore_guid.Data4[5],
241 &restore_guid.Data4[6], &restore_guid.Data4[7]) != 11)
245 _DebugMessage(150, "GUID = %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
246 restore_guid.Data1, restore_guid.Data2, restore_guid.Data3,
247 restore_guid.Data4[0], restore_guid.Data4[1],
248 restore_guid.Data4[2], restore_guid.Data4[3],
249 restore_guid.Data4[4], restore_guid.Data4[5],
250 restore_guid.Data4[6], restore_guid.Data4[7]);
254 stream_buf_count = 1;
256 while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
258 _DebugMessage(150, "File = %S\n", tmp);
260 stream_buf_count += wchars_read;
262 restore_input_streams = new WCHAR[stream_buf_count];
264 stream_buf_count = 0;
265 while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
267 snwprintf(&restore_input_streams[stream_buf_count], 65535, L"%s", tmp);
269 stream_buf_count += wchars_read;
271 restore_input_streams[stream_buf_count] = 0;
273 _DebugMessage(100, "done analyzing DatabasePluginInfo\n");
279 _JobMessage(M_FATAL, "Format of %s is incorrect", full_path);