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