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
dbi_node_t(char * name,node_t * parent_node)25 dbi_node_t::dbi_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_DATABASE_INFO, parent_node)
26 {
27 restore_display_name = NULL;
28 restore_input_streams = NULL;
29 buffer = NULL;
30 }
31
~dbi_node_t()32 dbi_node_t::~dbi_node_t()
33 {
34 if (buffer != NULL)
35 delete buffer;
36 if (restore_input_streams != NULL)
37 delete restore_input_streams;
38 if (restore_display_name != NULL)
39 delete restore_display_name;
40 }
41
42 bRC
startBackupFile(exchange_fd_context_t * context,struct save_pkt * sp)43 dbi_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
44 {
45 time_t now = time(NULL);
46
47 _DebugMessage(100, "startBackupNode_DBI state = %d\n", state);
48
49 if (context->job_level == 'F') {
50 sp->fname = full_path;
51 sp->link = 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;
57 sp->type = FT_REG;
58 return bRC_OK;
59 }
60 else
61 {
62 bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)full_path);
63 return bRC_Seen;
64 }
65 }
66
67 bRC
endBackupFile(exchange_fd_context_t * context)68 dbi_node_t::endBackupFile(exchange_fd_context_t *context)
69 {
70 _DebugMessage(100, "endBackupNode_DBI state = %d\n", state);
71
72 context->current_node = parent;
73
74 return bRC_OK;
75 }
76
77 bRC
createFile(exchange_fd_context_t * context,struct restore_pkt * rp)78 dbi_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
79 {
80 _DebugMessage(100, "createFile_DBI state = %d\n", state);
81
82 rp->create_status = CF_EXTRACT;
83
84 return bRC_OK;
85 }
86
87 bRC
endRestoreFile(exchange_fd_context_t * context)88 dbi_node_t::endRestoreFile(exchange_fd_context_t *context)
89 {
90 _DebugMessage(100, "endRestoreFile_DBI state = %d\n", state);
91
92 context->current_node = parent;
93
94 return bRC_OK;
95 }
96
97 bRC
pluginIoOpen(exchange_fd_context_t * context,struct io_pkt * io)98 dbi_node_t::pluginIoOpen(exchange_fd_context_t *context, struct io_pkt *io)
99 {
100 uint32_t len;
101 WCHAR *ptr;
102 WCHAR *stream;
103 //char tmp[512];
104
105 buffer_pos = 0;
106 buffer_size = 65536;
107 buffer = new char[buffer_size];
108
109 if (context->job_type == JOB_TYPE_BACKUP)
110 {
111 ptr = (WCHAR *)buffer;
112 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"DatabaseBackupInfo\n");
113 if (len < 0)
114 goto fail;
115 buffer_pos += len * 2;
116 ptr += len;
117
118 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%d\n", EXCHANGE_PLUGIN_VERSION);
119 if (len < 0)
120 goto fail;
121 buffer_pos += len * 2;
122 ptr += len;
123
124 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", dbi->wszDatabaseDisplayName);
125 if (len < 0)
126 goto fail;
127 buffer_pos += len * 2;
128 ptr += len;
129
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]);
136 if (len < 0)
137 goto fail;
138 buffer_pos += len * 2;
139 ptr += len;
140
141 stream = dbi->wszDatabaseStreams;
142 while (*stream)
143 {
144 len = snwprintf(ptr, (buffer_size - buffer_pos) / 2, L"%s\n", stream);
145 if (len < 0)
146 goto fail;
147 buffer_pos += len * 2;
148 ptr += len;
149 stream += wcslen(stream) + 1;
150 }
151
152 buffer_size = buffer_pos;
153 buffer_pos = 0;
154 }
155
156 io->status = 0;
157 io->io_errno = 0;
158 return bRC_OK;
159
160 fail:
161 io->status = 0;
162 io->io_errno = 1;
163 return bRC_Error;
164 }
165
166 bRC
pluginIoRead(exchange_fd_context_t * context,struct io_pkt * io)167 dbi_node_t::pluginIoRead(exchange_fd_context_t *context, struct io_pkt *io)
168 {
169 io->status = 0;
170 io->io_errno = 0;
171
172 io->status = MIN(io->count, (int)(buffer_size - buffer_pos));
173 if (io->status == 0)
174 return bRC_OK;
175 memcpy(io->buf, buffer + buffer_pos, io->status);
176 buffer_pos += io->status;
177
178 return bRC_OK;
179 }
180
181 bRC
pluginIoWrite(exchange_fd_context_t * context,struct io_pkt * io)182 dbi_node_t::pluginIoWrite(exchange_fd_context_t *context, struct io_pkt *io)
183 {
184 memcpy(&buffer[buffer_pos], io->buf, io->count);
185 buffer_pos += io->count;
186 io->status = io->count;
187 io->io_errno = 0;
188 return bRC_OK;
189 }
190
191 bRC
pluginIoClose(exchange_fd_context_t * context,struct io_pkt * io)192 dbi_node_t::pluginIoClose(exchange_fd_context_t *context, struct io_pkt *io)
193 {
194 WCHAR tmp[128];
195 WCHAR *ptr;
196 WCHAR eol;
197 int wchars_read;
198 int version;
199 int stream_buf_count;
200 WCHAR *streams_start;
201
202 if (context->job_type == JOB_TYPE_RESTORE)
203 {
204 // need to think about making this buffer overflow proof...
205 _DebugMessage(100, "analyzing DatabaseBackupInfo\n");
206 ptr = (WCHAR *)buffer;
207
208 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
209 goto restore_fail;
210 ptr += wchars_read;
211 _DebugMessage(150, "Header = %S\n", tmp);
212 // verify that header == "DatabaseBackupInfo"
213
214 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
215 goto restore_fail;
216 if (swscanf(tmp, L"%d%c", &version, &eol) != 1)
217 {
218 version = 0;
219 _DebugMessage(150, "Version = 0 (inferred)\n");
220 }
221 else
222 {
223 ptr += wchars_read;
224 _DebugMessage(150, "Version = %d\n", version);
225 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
226 goto restore_fail;
227 }
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);
231 ptr += wchars_read;
232
233 if (swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) != 2)
234 goto restore_fail;
235
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)
242 {
243 goto restore_fail;
244 }
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]);
251
252 ptr += wchars_read;
253
254 stream_buf_count = 1;
255 streams_start = ptr;
256 while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
257 {
258 _DebugMessage(150, "File = %S\n", tmp);
259 ptr += wchars_read;
260 stream_buf_count += wchars_read;
261 }
262 restore_input_streams = new WCHAR[stream_buf_count];
263 ptr = streams_start;
264 stream_buf_count = 0;
265 while (ptr < (WCHAR *)(buffer + buffer_pos) && swscanf(ptr, L"%127[^\n]%c%n", tmp, &eol, &wchars_read) == 2)
266 {
267 snwprintf(&restore_input_streams[stream_buf_count], 65535, L"%s", tmp);
268 ptr += wchars_read;
269 stream_buf_count += wchars_read;
270 }
271 restore_input_streams[stream_buf_count] = 0;
272
273 _DebugMessage(100, "done analyzing DatabasePluginInfo\n");
274 }
275 delete buffer;
276 buffer = NULL;
277 return bRC_OK;
278 restore_fail:
279 _JobMessage(M_FATAL, "Format of %s is incorrect", full_path);
280 delete buffer;
281 buffer = NULL;
282 return bRC_Error;
283 }
284