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, &section_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