1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 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 #include "config-storage.h"
21 #include <android/log.h>
22 #include <iostream>
23 #include <fstream>
24 #include "resmodel.h"
25
26 extern URES res_all;
27 extern char *configfile; // defined in tray-monitor.cpp
28
29 /* Check for \ at the end */
is_str_valid(POOLMEM ** buf,const char * p)30 static char *is_str_valid(POOLMEM **buf, const char *p)
31 {
32 char *p1;
33 if (!p || !*p) {
34 return NULL;
35 }
36 p1 = *buf = check_pool_memory_size(*buf, (strlen(p) + 1));
37 for (; *p ; p++) {
38 if (*p == '\\') {
39 *p1++ = '/';
40
41 } else if (*p == '"') {
42 return NULL;
43
44 } else {
45 *p1++ = *p;
46 }
47 }
48 *p1 = 0;
49 return *buf;
50 }
51
reloadResources()52 bool ConfigStorage::reloadResources()
53 {
54 reloadResources(false);
55 }
56
reloadResources(bool encodePwd)57 bool ConfigStorage::reloadResources(bool encodePwd)
58 {
59 bool ret;
60 config = New(CONFIG());
61 config->encode_password(encodePwd);
62 config->init(configfile, NULL, M_ERROR, (void *)&res_all, res_all_size,
63 r_first, r_last, resources, &rhead);
64 ret = config->parse_config();
65 return ret;
66 }
67
68
getMonitor()69 MONITOR *ConfigStorage::getMonitor() {
70 MONITOR *mon = NULL;
71 mon = (MONITOR *) GetNextRes(rhead, R_MONITOR, NULL);
72 return mon;
73 }
74
saveMonitor(const char * deviceId)75 const char *ConfigStorage::saveMonitor(const char *deviceId) {
76 MONITOR mon;
77 POOLMEM *monName = get_pool_memory(PM_FNAME);
78 Mmsg(monName, "%s-mon", deviceId);
79 mon.hdr.name = monName;
80 const char *err_msg = saveMonitor(&mon);
81 free_and_null_pool_memory(monName);
82 return err_msg;
83 }
84
saveMonitor(MONITOR * mon)85 const char *ConfigStorage::saveMonitor(MONITOR *mon)
86 {
87 const char *error_msg = NULL;
88 POOL_MEM tmp_fname;
89 Mmsg(tmp_fname, "%s.temp", configfile);
90 FILE *fp = fopen(tmp_fname.c_str(), "w");
91
92 if(!fp) {
93 return "Error - unable to open configuration file";
94 }
95
96 writeMonitor(fp, mon);
97
98 QList<RESMON *> *resources = getAllResources();
99 for(RESMON *res : *resources) {
100 writeResource(fp, res, res->code);
101 }
102
103 fclose(fp);
104 unlink(configfile);
105
106 int result = rename(tmp_fname.c_str(), configfile);
107
108 if (result != 0) {
109 error_msg = "Error - unable to write to the configuration file";
110 }
111
112 if(error_msg == NULL) {
113 reloadResources();
114 dump_storage();
115 }
116
117 return error_msg;
118 }
119
getResourceByName(rescode resCode,const char * resName)120 RESMON *ConfigStorage::getResourceByName(rescode resCode, const char* resName) {
121 RESMON *res = NULL;
122 QList<RESMON *> *resources = getResources(resCode);
123
124 for(RESMON *r : *resources) {
125 if(strcmp(r->hdr.name, resName) == 0) {
126 res = r;
127 }
128 }
129
130 return res;
131 }
132
getResources(rescode resCode)133 QList<RESMON *> *ConfigStorage::getResources(rescode resCode) {
134 QList<RESMON *> *resources = new QList<RESMON *>();
135 RESMON *res;
136
137 for(res=NULL; (res=(RESMON *)GetNextRes(rhead, resCode, (RES*)res));) {
138 res->code = resCode;
139 resources->push_back(res);
140 }
141
142 return resources;
143 }
144
getAllResources()145 QList<RESMON *> *ConfigStorage::getAllResources() {
146 QList<RESMON *> *resources = new QList<RESMON *>();
147 RESMON *res;
148
149 for(res=NULL; (res=(RESMON *)GetNextRes(rhead, R_CLIENT, (RES*)res));) {
150 res->code = R_CLIENT;
151 resources->push_back(res);
152 }
153
154 for(res=NULL; (res=(RESMON *)GetNextRes(rhead, R_DIRECTOR, (RES*)res));) {
155 res->code = R_DIRECTOR;
156 resources->push_back(res);
157 }
158
159 for(res=NULL; (res=(RESMON *)GetNextRes(rhead, R_STORAGE, (RES*)res));) {
160 res->code = R_STORAGE;
161 resources->push_back(res);
162 }
163
164 return resources;
165 }
166
saveResources(QList<QObject * > * clients,QList<QObject * > * directors,QList<QObject * > * storages)167 const char *ConfigStorage::saveResources(
168 QList<QObject *> *clients,
169 QList<QObject *> *directors,
170 QList<QObject *> *storages
171 )
172 {
173 const char *error_msg = NULL;
174
175 POOL_MEM tmp_fname;
176 Mmsg(tmp_fname, "%s.temp", configfile);
177 FILE *fp = fopen(tmp_fname.c_str(), "w");
178
179 if(!fp) {
180 return "Unable to open configuration file";
181 }
182
183 MONITOR *mon = getMonitor();
184 writeMonitor(fp, mon);
185
186 for(QObject *obj : *clients) {
187 ResourceModel *model = (ResourceModel *) obj;
188 RESMON *res = model->resource();
189 writeResource(fp, res, R_CLIENT);
190 }
191
192 for(QObject *obj : *directors) {
193 ResourceModel *model = (ResourceModel *) obj;
194 RESMON *res = model->resource();
195 writeResource(fp, res, R_DIRECTOR);
196 }
197
198 for(QObject *obj : *storages) {
199 ResourceModel *model = (ResourceModel *) obj;
200 RESMON *res = model->resource();
201 writeResource(fp, res, R_STORAGE);
202 }
203
204 fclose(fp);
205 unlink(configfile);
206 int result = rename(tmp_fname.c_str(), configfile);
207
208 if (result != 0) {
209 error_msg = "Unable to write to the configuration file";
210 }
211
212 reloadResources();
213 return error_msg;
214 }
215
writeMonitor(FILE * fp,MONITOR * mon)216 void ConfigStorage::writeMonitor(FILE *fp, MONITOR *mon) {
217 fprintf(fp, "Monitor {\n Name = \"%s\"\n", mon->hdr.name);
218 fprintf(fp, " Refresh Interval = %d\n", 120);
219 fprintf(fp, "}\n");
220 }
221
222
addResource(const char * resName,rescode code)223 const char *ConfigStorage::addResource(const char *resName, rescode code) {
224 return addResource(resName, code, false);
225 }
226
addResource(const char * resName,rescode code,bool managed)227 const char *ConfigStorage::addResource(const char *resName, rescode code, bool managed) {
228 RESMON res;
229 res.address = "localhost";
230 res.password = (char *) AndroidFD::devicePwd().toUtf8().constData();
231 res.managed = managed;
232 POOLMEM *pm_resName = get_pool_memory(PM_FNAME);
233
234 switch (code) {
235 case R_CLIENT:
236 Mmsg(pm_resName, "%s-fd", resName);
237 res.port = 9102;
238 res.use_remote = false;
239 break;
240 case R_DIRECTOR:
241 Mmsg(pm_resName, "%s-dir", resName);
242 res.port = 9101;
243 break;
244 case R_STORAGE:
245 Mmsg(pm_resName, "%s-sd", resName);
246 res.port = 9103;
247 break;
248 default:
249 return NULL;
250 }
251
252 res.hdr.name = pm_resName;
253 const char *err_msg = addResource(&res, code);
254 free_and_null_pool_memory(pm_resName);
255 return err_msg;
256 }
257
addResource(RESMON * newRes,rescode code)258 const char *ConfigStorage::addResource(RESMON *newRes, rescode code) {
259 const char *error_msg = validateResource(newRes);
260
261 if(error_msg != NULL) {
262 return error_msg;
263 }
264
265 FILE *fp = fopen(configfile, "a");
266
267 if(!fp) {
268 return "Unable to open configuration file";
269 }
270
271 writeResource(fp, newRes, code);
272 fclose(fp);
273 reloadResources();
274 return error_msg;
275 }
276
editResource(RESMON * oldRes,RESMON * newRes,rescode resCode)277 const char *ConfigStorage::editResource(RESMON *oldRes, RESMON *newRes, rescode resCode) {
278 const char *error_msg = validateResource(newRes);
279
280 if(error_msg != NULL) {
281 return error_msg;
282 }
283
284 POOL_MEM tmp_fname;
285 Mmsg(tmp_fname, "%s.temp", configfile);
286 FILE *fp = fopen(tmp_fname.c_str(), "w");
287
288 if(!fp) {
289 return "Unable to open configuration file";
290 }
291
292 MONITOR *mon = getMonitor();
293 writeMonitor(fp, mon);
294
295 QList<RESMON *> *resources = getAllResources();
296 for(RESMON *res : *resources) {
297 if(strcmp(res->hdr.name, oldRes->hdr.name) == 0) {
298 writeResource(fp, newRes, resCode);
299 }
300 else {
301 writeResource(fp, res, res->code);
302 }
303 }
304
305 fclose(fp);
306 unlink(configfile);
307 int result = rename(tmp_fname.c_str(), configfile);
308
309 if (result != 0) {
310 error_msg = "Unable to write to the configuration file";
311 }
312
313 if(error_msg == NULL) {
314 reloadResources();
315 dump_storage();
316 }
317
318 return error_msg;
319 }
320
validateResource(RESMON * res)321 const char *ConfigStorage::validateResource(RESMON *res) {
322 POOLMEM *buf1 = get_pool_memory(PM_FNAME);
323 POOLMEM *buf2 = get_pool_memory(PM_FNAME);
324 POOLMEM *buf3 = get_pool_memory(PM_FNAME);
325
326 res->hdr.name = is_str_valid(&buf1, res->hdr.name);
327
328 if(!res->hdr.name) {
329 return "The name of the Resource should be set";
330 }
331
332 res->address = is_str_valid(&buf2, res->address);
333
334 if(!res->address) {
335 return "The address of the Resource should be set";
336 }
337
338 res->password = is_str_valid(&buf3, res->password);
339
340 if(!res->password) {
341 return "The password of the Resource should be set";
342 }
343
344 return NULL;
345 }
346
writeResource(FILE * fp,RESMON * res,rescode code)347 void ConfigStorage::writeResource(FILE *fp, RESMON *res, rescode code) {
348 const char *resType;
349
350 switch (code) {
351 case R_CLIENT:
352 resType = "Client";
353 break;
354 case R_DIRECTOR:
355 resType = "Director";
356 break;
357 case R_STORAGE:
358 resType = "Storage";
359 break;
360 default:
361 return;
362 }
363
364 fprintf(fp, "%s {\n Name = \"%s\"\n Address = \"%s\"\n", resType, res->hdr.name, res->address);
365 fprintf(fp, " Password = \"%s\"\n", res->password);
366 fprintf(fp, " Port = %d\n", res->port);
367 fprintf(fp, " Connect Timeout = %d\n", 10);
368
369 if (res->use_remote) {
370 fprintf(fp, " Remote = yes\n");
371 }
372
373 if (res->managed) {
374 fprintf(fp, " Managed = yes\n");
375 }
376
377 fprintf(fp, "}\n");
378 }
379
380
dump_storage()381 void ConfigStorage::dump_storage() {
382 __android_log_write(ANDROID_LOG_DEBUG, "Configuration File:", configfile);
383 std::string line;
384 std::ifstream myfile(configfile);
385 if (myfile.is_open())
386 {
387 __android_log_write(ANDROID_LOG_DEBUG, "Success!", "File was opened");
388 while ( getline (myfile, line) )
389 {
390 __android_log_write(ANDROID_LOG_DEBUG, "Line:", line.c_str());
391 }
392 myfile.close();
393 } else {
394 __android_log_write(ANDROID_LOG_DEBUG, "Error!", "Unable to open file");
395 }
396 }
397
398
399
400