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
file_node_t(char * name,node_t * parent_node)25 file_node_t::file_node_t(char *name, node_t *parent_node) : node_t(name, NODE_TYPE_FILE, parent_node)
26 {
27 backup_file_handle = INVALID_HANDLE_VALUE;
28 restore_file_handle = INVALID_HANDLE_VALUE;
29 restore_at_file_level = FALSE;
30 }
31
~file_node_t()32 file_node_t::~file_node_t()
33 {
34 if (backup_file_handle != INVALID_HANDLE_VALUE)
35 {
36 //_DebugMessage(100, "closing file handle in destructor\n");
37 CloseHandle(backup_file_handle);
38 }
39 if (restore_file_handle != INVALID_HANDLE_VALUE)
40 {
41 //_DebugMessage(100, "closing file handle in destructor\n");
42 if (restore_at_file_level)
43 {
44 CloseHandle(restore_file_handle);
45 }
46 else
47 {
48 // maybe one day
49 }
50 }
51 }
52
53 bRC
startBackupFile(exchange_fd_context_t * context,struct save_pkt * sp)54 file_node_t::startBackupFile(exchange_fd_context_t *context, struct save_pkt *sp)
55 {
56 time_t now = time(NULL);
57 _DebugMessage(100, "startBackupNode_FILE state = %d\n", state);
58
59 if (context->job_level == 'F' || parent->type == NODE_TYPE_STORAGE_GROUP) {
60 sp->fname = full_path;
61 sp->link = full_path;
62 _DebugMessage(100, "fname = %s\n", sp->fname);
63 sp->statp.st_mode = 0700 | S_IFREG;
64 sp->statp.st_ctime = now;
65 sp->statp.st_mtime = now;
66 sp->statp.st_atime = now;
67 sp->statp.st_size = (uint64_t)-1;
68 sp->type = FT_REG;
69 return bRC_OK;
70 } else {
71 bfuncs->setBaculaValue(context->bpContext, bVarFileSeen, (void *)full_path);
72 return bRC_Seen;
73 }
74 }
75
76 bRC
endBackupFile(exchange_fd_context_t * context)77 file_node_t::endBackupFile(exchange_fd_context_t *context)
78 {
79 _DebugMessage(100, "endBackupNode_FILE state = %d\n", state);
80
81 context->current_node = parent;
82
83 return bRC_OK;
84 }
85
86 bRC
createFile(exchange_fd_context_t * context,struct restore_pkt * rp)87 file_node_t::createFile(exchange_fd_context_t *context, struct restore_pkt *rp)
88 {
89 //HrESERestoreOpenFile with name of log file
90
91 _DebugMessage(100, "createFile_FILE state = %d\n", state);
92 rp->create_status = CF_EXTRACT;
93 return bRC_OK;
94 }
95
96 bRC
endRestoreFile(exchange_fd_context_t * context)97 file_node_t::endRestoreFile(exchange_fd_context_t *context)
98 {
99 _DebugMessage(100, "endRestoreFile_FILE state = %d\n", state);
100 context->current_node = parent;
101 return bRC_OK;
102 }
103
104 bRC
pluginIoOpen(exchange_fd_context_t * context,struct io_pkt * io)105 file_node_t::pluginIoOpen(exchange_fd_context_t *context, struct io_pkt *io)
106 {
107 HRESULT result;
108 HANDLE handle;
109 char *tmp = new char[wcslen(filename) + 1];
110 wcstombs(tmp, filename, wcslen(filename) + 1);
111
112 _DebugMessage(100, "pluginIoOpen_FILE - filename = %s\n", tmp);
113 io->status = 0;
114 io->io_errno = 0;
115 if (context->job_type == JOB_TYPE_BACKUP)
116 {
117 _DebugMessage(10, "Calling HrESEBackupOpenFile\n");
118 result = HrESEBackupOpenFile(hccx, filename, 65535, 1, &backup_file_handle, §ion_size);
119 if (result)
120 {
121 _JobMessage(M_FATAL, "HrESEBackupOpenFile failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
122 backup_file_handle = INVALID_HANDLE_VALUE;
123 io->io_errno = 1;
124 return bRC_Error;
125 }
126 }
127 else
128 {
129 _DebugMessage(10, "Calling HrESERestoreOpenFile for '%s'\n", tmp);
130 result = HrESERestoreOpenFile(hccx, filename, 1, &restore_file_handle);
131 if (result == hrRestoreAtFileLevel)
132 {
133 restore_at_file_level = true;
134 _DebugMessage(100, "Calling CreateFileW for '%s'\n", tmp);
135 handle = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
136 if (handle == INVALID_HANDLE_VALUE)
137 {
138 _JobMessage(M_FATAL, "CreateFile failed");
139 return bRC_Error;
140 }
141 restore_file_handle = (void *)handle;
142 return bRC_OK;
143 }
144 else if (result == 0)
145 {
146 _JobMessage(M_FATAL, "Exchange File IO API not yet supported for restore\n");
147 restore_at_file_level = false;
148 return bRC_Error;
149 }
150 else
151 {
152 _JobMessage(M_FATAL, "HrESERestoreOpenFile failed with error 0x%08x - %s\n", result, ESEErrorMessage(result));
153 return bRC_Error;
154 }
155 }
156 return bRC_OK;
157 }
158
159 bRC
pluginIoRead(exchange_fd_context_t * context,struct io_pkt * io)160 file_node_t::pluginIoRead(exchange_fd_context_t *context, struct io_pkt *io)
161 {
162 HRESULT result;
163 uint32_t readLength;
164
165 io->status = 0;
166 io->io_errno = 0;
167 _DebugMessage(200, "Calling HrESEBackupReadFile\n");
168 result = HrESEBackupReadFile(hccx, backup_file_handle, io->buf, io->count, &readLength);
169 if (result)
170 {
171 io->io_errno = 1;
172 return bRC_Error;
173 }
174 io->status = readLength;
175 size += readLength;
176 return bRC_OK;
177 }
178
179 bRC
pluginIoWrite(exchange_fd_context_t * context,struct io_pkt * io)180 file_node_t::pluginIoWrite(exchange_fd_context_t *context, struct io_pkt *io)
181 {
182 DWORD bytes_written;
183
184 io->io_errno = 0;
185 if (!restore_at_file_level)
186 return bRC_Error;
187
188 if (!WriteFile(restore_file_handle, io->buf, io->count, &bytes_written, NULL))
189 {
190 _JobMessage(M_FATAL, "Write Error");
191 return bRC_Error;
192 }
193
194 if (bytes_written != (DWORD)io->count)
195 {
196 _JobMessage(M_FATAL, "Short write");
197 return bRC_Error;
198 }
199 io->status = bytes_written;
200
201 return bRC_OK;
202 }
203
204 bRC
pluginIoClose(exchange_fd_context_t * context,struct io_pkt * io)205 file_node_t::pluginIoClose(exchange_fd_context_t *context, struct io_pkt *io)
206 {
207 if (context->job_type == JOB_TYPE_BACKUP)
208 {
209 _DebugMessage(100, "Calling HrESEBackupCloseFile\n");
210 HrESEBackupCloseFile(hccx, backup_file_handle);
211 backup_file_handle = INVALID_HANDLE_VALUE;
212 return bRC_OK;
213 }
214 else
215 {
216 if (restore_at_file_level)
217 {
218 CloseHandle(restore_file_handle);
219 restore_file_handle = INVALID_HANDLE_VALUE;
220 return bRC_OK;
221 }
222 else
223 {
224 return bRC_OK;
225 }
226 }
227 }
228