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, July 2010
21 */
22
23 #include "exchange-fd.h"
24
store_node_t(char * name,node_t * parent_node)25 store_node_t::store_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_STORE, parent_node)
26 {
27 dbi = NULL;
28 hccx = NULL;
29 dbi_node = NULL;
30 file_node = NULL;
31 }
32
~store_node_t()33 store_node_t::~store_node_t()
34 {
35 safe_delete(dbi_node);
36 safe_delete(file_node);
37 }
38
39 bRC
startBackupFile(exchange_fd_context_t * context,struct save_pkt * sp)40 store_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
41 {
42 char *tmp;
43
44 _DebugMessage(100, "startBackupNode_STORE state = %d\n", state);
45
46 switch(state)
47 {
48 case 0:
49 stream_ptr = dbi->wszDatabaseStreams;
50 state = 1;
51 // fall through
52 case 1:
53 dbi_node = new dbi_node_t((char *)"DatabaseBackupInfo", this);
54 dbi_node->dbi = dbi;
55 context->current_node = dbi_node;
56 break;
57 case 2:
58 tmp = new char[wcslen(stream_ptr) + 1];
59 wcstombs(tmp, stream_ptr, wcslen(stream_ptr) + 1);
60 file_node = new file_node_t(tmp, this);
61 file_node->hccx = hccx;
62 file_node->filename = stream_ptr;
63 context->current_node = file_node;
64 break;
65 case 3:
66 if (context->job_level == 'F')
67 {
68 time_t now = time(NULL);
69 sp->fname = full_path;
70 sp->link = full_path;
71 sp->statp.st_mode = 0700 | S_IFDIR;
72 sp->statp.st_ctime = now;
73 sp->statp.st_mtime = now;
74 sp->statp.st_atime = now;
75 sp->statp.st_size = 0;
76 sp->type = FT_DIREND;
77 }
78 else
79 {
80 bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)full_path);
81 return bRC_Seen;
82 }
83 break;
84 }
85
86 return bRC_OK;
87 }
88
89 bRC
endBackupFile(exchange_fd_context_t * context)90 store_node_t::endBackupFile(exchange_fd_context_t *context)
91 {
92 _DebugMessage(100, "endBackupNode_STORE state = %d\n", state);
93 bRC retval = bRC_OK;
94
95 switch(state)
96 {
97 case 0:
98 // should never happen
99 break;
100 case 1:
101 state = 2;
102 retval = bRC_More;
103 break;
104 case 2:
105 safe_delete(file_node);
106 stream_ptr += wcslen(stream_ptr) + 1;
107 if (*stream_ptr == 0)
108 state = 3;
109 retval = bRC_More;
110 break;
111 case 3:
112 //delete dbi_node;
113 context->current_node = parent;
114 break;
115 }
116 return retval;
117 }
118
119 bRC
createFile(exchange_fd_context_t * context,struct restore_pkt * rp)120 store_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
121 {
122 _DebugMessage(0, "createFile_STORE state = %d\n", state);
123
124 if (strcmp(context->path_bits[level - 1], parent->name) != 0)
125 {
126 _DebugMessage(0, "Different storage group - switching back to parent\n", state);
127 context->current_node = parent;
128 return bRC_OK;
129 }
130 for (;;)
131 {
132 switch (state)
133 {
134 case 0:
135 if (strcmp("DatabaseBackupInfo", context->path_bits[level + 1]) != 0)
136 {
137 _JobMessage(M_FATAL, "DatabaseBackupInfo file must exist and must be first in directory\n");
138 state = 999;
139 break;
140 }
141 dbi_node = new dbi_node_t(bstrdup(context->path_bits[level + 1]), this);
142 context->current_node = dbi_node;
143 return bRC_OK;
144 case 1:
145 if (strcmp(context->path_bits[level - 1], parent->name) != 0)
146 {
147 _JobMessage(M_ERROR, "Unexpected Storage Group Change\n");
148 state = 999;
149 break;
150 }
151
152 if (*stream_ptr != 0)
153 {
154 // verify that stream_ptr == context->path_bits[level + 1];
155 _DebugMessage(150, "stream_ptr = %S\n", stream_ptr);
156 _DebugMessage(150, "out_stream_ptr = %S\n", out_stream_ptr);
157 file_node = new file_node_t(bstrdup(context->path_bits[level + 1]), this);
158 file_node->hccx = hccx;
159 file_node->filename = out_stream_ptr;
160 context->current_node = file_node;
161 return bRC_OK;
162 }
163 else
164 {
165 _JobMessage(M_ERROR, "Extra file found '%s'\n", full_path);
166 state = 999;
167 break;
168 }
169 case 2:
170 if (rp->type != FT_DIREND)
171 {
172 _JobMessage(M_ERROR, "Unexpected file '%s'\n", full_path);
173 state = 999;
174 break;
175 }
176 rp->create_status = CF_CREATED;
177 return bRC_OK;
178 case 999:
179 if (strcmp(context->path_bits[level], name) != 0)
180 {
181 _DebugMessage(0, "End of Store when in error state - switching back to parent\n", state);
182 context->current_node = parent;
183 return bRC_OK;
184 }
185 rp->create_status = CF_CREATED;
186 return bRC_OK;
187 }
188 }
189 }
190
191 bRC
endRestoreFile(exchange_fd_context_t * context)192 store_node_t::endRestoreFile(exchange_fd_context_t *context)
193 {
194 HRESULT result;
195
196 _DebugMessage(0, "endRestoreFile_STORE state = %d\n", state);
197 for (;;)
198 {
199 switch (state)
200 {
201 case 0:
202 state = 1;
203 _DebugMessage(0, "Calling HrESERestoreAddDatabase\n");
204 result = HrESERestoreAddDatabase(hccx, dbi_node->restore_display_name, dbi_node->restore_guid, dbi_node->restore_input_streams, &dbi_node->restore_output_streams);
205 if (result != 0)
206 {
207 _JobMessage(M_FATAL, "HrESERestoreAddDatabase failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
208 state = 999;
209 break;
210 }
211 stream_ptr = dbi_node->restore_input_streams;
212 out_stream_ptr = dbi_node->restore_output_streams;
213 return bRC_OK;
214 case 1:
215 if (*stream_ptr != 0)
216 {
217 safe_delete(file_node);
218 file_node = NULL;
219 stream_ptr += wcslen(stream_ptr) + 1;
220 out_stream_ptr += wcslen(out_stream_ptr) + 1;
221 if (*stream_ptr == 0)
222 state = 2;
223 return bRC_OK;
224 }
225 else
226 {
227 state = 999;
228 break;
229 }
230 case 2:
231 context->current_node = parent;
232 return bRC_OK;
233 case 999:
234 return bRC_OK;
235 }
236 }
237 }
238