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