2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Configuration file parser for Bacula Storage daemon
22 * Kern Sibbald, March MM
28 /* First and last resource ids */
29 int32_t r_first = R_FIRST;
30 int32_t r_last = R_LAST;
31 static RES *sres_head[R_LAST - R_FIRST + 1];
32 RES **res_head = sres_head;
34 /* We build the current resource here statically,
35 * then move it to dynamic memory */
37 extern "C" { // work around visual compiler mangling variables
43 int32_t res_all_size = sizeof(res_all);
45 /* Definition of records permitted within each
46 * resource with the routine to process the record
51 * Globals for the Storage daemon.
52 * name handler value code flags default_value
54 static RES_ITEM store_items[] = {
55 {"Name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
56 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
57 {"SdAddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
58 {"SdAddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
59 {"Messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
60 {"SdPort", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
61 {"WorkingDirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
62 {"PidDirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
63 {"SubsysDirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
64 {"PluginDirectory", store_dir, ITEM(res_store.plugin_directory), 0, 0, 0},
65 {"ScriptsDirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
66 {"MaximumConcurrentJobs", store_pint32, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 20},
67 {"ClientConnectTimeout", store_time, ITEM(res_store.ClientConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
68 {"HeartbeatInterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 5 * 60},
69 {"TlsAuthenticate", store_bool, ITEM(res_store.tls_authenticate), 0, 0, 0},
70 {"TlsEnable", store_bool, ITEM(res_store.tls_enable), 0, 0, 0},
71 {"TlsRequire", store_bool, ITEM(res_store.tls_require), 0, 0, 0},
72 {"TlsVerifyPeer", store_bool, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
73 {"TlsCaCertificateFile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
74 {"TlsCaCertificateDir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
75 {"TlsCertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
76 {"TlsKey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
77 {"TlsDhFile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
78 {"TlsAllowedCn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
79 {"ClientConnectWait", store_time, ITEM(res_store.client_wait), 0, ITEM_DEFAULT, 30 * 60},
80 {"VerId", store_str, ITEM(res_store.verid), 0, 0, 0},
81 {NULL, NULL, {0}, 0, 0, 0}
85 /* Directors that can speak to the Storage daemon */
86 static RES_ITEM dir_items[] = {
87 {"Name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
88 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
89 {"Password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
90 {"Monitor", store_bool, ITEM(res_dir.monitor), 0, 0, 0},
91 {"TlsAuthenticate", store_bool, ITEM(res_dir.tls_authenticate), 0, 0, 0},
92 {"TlsEnable", store_bool, ITEM(res_dir.tls_enable), 0, 0, 0},
93 {"TlsRequire", store_bool, ITEM(res_dir.tls_require), 0, 0, 0},
94 {"TlsVerifyPeer", store_bool, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
95 {"TlsCaCertificateFile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
96 {"TlsCaCertificateDir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
97 {"TlsCertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
98 {"TlsKey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
99 {"TlsDhFile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
100 {"TlsAllowedCn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
101 {NULL, NULL, {0}, 0, 0, 0}
104 /* Device definition */
105 static RES_ITEM dev_items[] = {
106 {"Name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
107 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
108 {"MediaType", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
109 {"DeviceType", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
110 {"ArchiveDevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
111 {"HardwareEndOfFile", store_bit, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
112 {"HardwareEndOfMedium", store_bit, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
113 {"BackwardSpaceRecord", store_bit, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
114 {"BackwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
115 {"BsfAtEom", store_bit, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
116 {"TwoEof", store_bit, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
117 {"ForwardSpaceRecord", store_bit, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
118 {"ForwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
119 {"FastForwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
120 {"RemovableMedia", store_bit, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
121 {"RandomAccess", store_bit, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
122 {"AutomaticMount", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
123 {"LabelMedia", store_bit, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
124 {"AlwaysOpen", store_bit, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
125 {"Autochanger", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
126 {"CloseOnPoll", store_bit, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
127 {"BlockPositioning", store_bit, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
128 {"UseMtiocGet", store_bit, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
129 {"CheckLabels", store_bit, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
130 {"RequiresMount", store_bit, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
131 {"OfflineOnUnmount", store_bit, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
132 {"BlockChecksum", store_bit, ITEM(res_dev.cap_bits), CAP_BLOCKCHECKSUM, ITEM_DEFAULT, 1},
133 {"Enabled", store_bool, ITEM(res_dev.enabled), 0, ITEM_DEFAULT, 1},
134 {"AutoSelect", store_bool, ITEM(res_dev.autoselect), 0, ITEM_DEFAULT, 1},
135 {"ReadOnly", store_bool, ITEM(res_dev.read_only), 0, ITEM_DEFAULT, 0},
136 {"ChangerDevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
137 {"ControlDevice", store_strname,ITEM(res_dev.control_name), 0, 0, 0},
138 {"ChangerCommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
139 {"AlertCommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
140 {"MaximumChangerWait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
141 {"MaximumOpenWait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
142 {"MaximumNetworkBufferSize", store_pint32, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
143 {"VolumePollInterval", store_time, ITEM(res_dev.vol_poll_interval), 0, ITEM_DEFAULT, 5 * 60},
144 {"MaximumRewindWait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
145 {"MinimumBlockSize", store_size32, ITEM(res_dev.min_block_size), 0, 0, 0},
146 {"MaximumBlockSize", store_maxblocksize, ITEM(res_dev.max_block_size), 0, 0, 0},
147 {"PaddingSize", store_size32, ITEM(res_dev.padding_size), 0, ITEM_DEFAULT, 4096},
148 {"FileAlignment", store_size32, ITEM(res_dev.file_alignment), 0, ITEM_DEFAULT, 4096},
149 {"MaximumVolumeSize", store_size64, ITEM(res_dev.max_volume_size), 0, 0, 0},
150 {"MaximumFileSize", store_size64, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
151 {"VolumeCapacity", store_size64, ITEM(res_dev.volume_capacity), 0, 0, 0},
152 {"MinimumFeeSpace", store_size64, ITEM(res_dev.min_free_space), 0, ITEM_DEFAULT, 5000000},
153 {"MaximumConcurrentJobs", store_pint32, ITEM(res_dev.max_concurrent_jobs), 0, 0, 0},
154 {"SpoolDirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
155 {"MaximumSpoolSize", store_size64, ITEM(res_dev.max_spool_size), 0, 0, 0},
156 {"MaximumJobSpoolSize", store_size64, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
157 {"DriveIndex", store_pint32, ITEM(res_dev.drive_index), 0, 0, 0},
158 {"MaximumPartSize", store_size64, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
159 {"MountPoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
160 {"MountCommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
161 {"UnmountCommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
162 {"WritePartCommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
163 {"FreeSpaceCommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
164 {"LabelType", store_label, ITEM(res_dev.label_type), 0, 0, 0},
165 {NULL, NULL, {0}, 0, 0, 0}
168 /* Autochanger definition */
169 static RES_ITEM changer_items[] = {
170 {"Name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
171 {"Description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
172 {"Device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
173 {"ChangerDevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
174 {"ChangerCommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
175 {NULL, NULL, {0}, 0, 0, 0}
179 // {"mountanonymousvolumes", store_bit, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
182 /* Message resource */
183 extern RES_ITEM msgs_items[];
186 /* This is the master resource definition */
187 RES_TABLE resources[] = {
188 {"Director", dir_items, R_DIRECTOR},
189 {"Storage", store_items, R_STORAGE},
190 {"Device", dev_items, R_DEVICE},
191 {"Messages", msgs_items, R_MSGS},
192 {"Autochanger", changer_items, R_AUTOCHANGER},
199 * device type device code = token
202 {"File", B_FILE_DEV},
203 {"Tape", B_TAPE_DEV},
205 {"Fifo", B_FIFO_DEV},
207 {"VTape", B_VTAPE_DEV},
213 * Store Device Type (File, FIFO, Tape, DVD)
216 void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
220 lex_get_token(lc, T_NAME);
221 /* Store the label pass 2 so that type is defined */
222 for (i=0; dev_types[i].name; i++) {
223 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
224 *(uint32_t *)(item->value) = dev_types[i].token;
230 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
233 set_bit(index, res_all.hdr.item_present);
237 * Store Maximum Block Size, and check it is not greater than MAX_BLOCK_LENGTH
240 void store_maxblocksize(LEX *lc, RES_ITEM *item, int index, int pass)
242 store_size32(lc, item, index, pass);
243 if (*(uint32_t *)(item->value) > MAX_BLOCK_LENGTH) {
244 scan_err2(lc, _("Maximum Block Size configured value %u is greater than allowed maximum: %u"),
245 *(uint32_t *)(item->value), MAX_BLOCK_LENGTH );
249 /* Dump contents of resource */
250 void dump_resource(int type, RES *rres, void sendit(void *sock, const char *fmt, ...), void *sock)
252 URES *res = (URES *)rres;
257 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
260 sendit(sock, _("dump_resource type=%d\n"), type);
261 if (type < 0) { /* no recursion */
267 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
270 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
271 res->res_store.hdr.name,
272 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
273 get_first_port_host_order(res->res_store.sdaddrs),
274 get_first_port_host_order(res->res_store.sddaddrs),
275 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
276 if (res->res_store.sdaddrs) {
277 foreach_dlist(p, res->res_store.sdaddrs) {
278 sendit(sock, " SDaddr=%s SDport=%d\n",
279 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
282 if (res->res_store.sddaddrs) {
283 foreach_dlist(p, res->res_store.sddaddrs) {
284 sendit(sock, " SDDaddr=%s SDDport=%d\n",
285 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
290 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
291 res->res_dev.hdr.name,
292 res->res_dev.media_type, res->res_dev.device_name,
293 res->res_dev.label_type);
294 sendit(sock, " rew_wait=%lld min_bs=%d max_bs=%d chgr_wait=%lld\n",
295 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
296 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
297 sendit(sock, " max_jobs=%d max_files=%lld max_size=%lld\n",
298 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
299 res->res_dev.max_volume_size);
300 sendit(sock, " min_block_size=%lld max_block_size=%lld\n",
301 res->res_dev.min_block_size, res->res_dev.max_block_size);
302 sendit(sock, " max_file_size=%lld capacity=%lld\n",
303 res->res_dev.max_file_size, res->res_dev.volume_capacity);
304 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
305 sendit(sock, " max_spool_size=%lld max_job_spool_size=%lld\n",
306 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
307 if (res->res_dev.changer_res) {
308 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
310 bstrncpy(buf, " ", sizeof(buf));
311 if (res->res_dev.cap_bits & CAP_EOF) {
312 bstrncat(buf, "CAP_EOF ", sizeof(buf));
314 if (res->res_dev.cap_bits & CAP_BSR) {
315 bstrncat(buf, "CAP_BSR ", sizeof(buf));
317 if (res->res_dev.cap_bits & CAP_BSF) {
318 bstrncat(buf, "CAP_BSF ", sizeof(buf));
320 if (res->res_dev.cap_bits & CAP_FSR) {
321 bstrncat(buf, "CAP_FSR ", sizeof(buf));
323 if (res->res_dev.cap_bits & CAP_FSF) {
324 bstrncat(buf, "CAP_FSF ", sizeof(buf));
326 if (res->res_dev.cap_bits & CAP_EOM) {
327 bstrncat(buf, "CAP_EOM ", sizeof(buf));
329 if (res->res_dev.cap_bits & CAP_REM) {
330 bstrncat(buf, "CAP_REM ", sizeof(buf));
332 if (res->res_dev.cap_bits & CAP_RACCESS) {
333 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
335 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
336 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
338 if (res->res_dev.cap_bits & CAP_LABEL) {
339 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
341 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
342 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
344 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
345 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
347 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
348 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
350 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
351 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
353 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
354 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
356 bstrncat(buf, "\n", sizeof(buf));
361 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
362 res->res_changer.hdr.name,
363 res->res_changer.changer_name, res->res_changer.changer_command);
364 foreach_alist(dev, res->res_changer.device) {
365 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
367 bstrncat(buf, "\n", sizeof(buf));
371 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
372 if (res->res_msgs.mail_cmd)
373 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
374 if (res->res_msgs.operator_cmd)
375 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
378 sendit(sock, _("Warning: unknown resource type %d\n"), type);
381 if (recurse && res->res_dir.hdr.next) {
382 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
387 * Free memory of resource.
388 * NB, we don't need to worry about freeing any references
389 * to other resources as they will be freed when that
390 * resource chain is traversed. Mainly we worry about freeing
391 * allocated strings (names).
393 void free_resource(RES *sres, int type)
396 URES *res = (URES *)sres;
401 /* common stuff -- free the resource name */
402 nres = (RES *)res->res_dir.hdr.next;
403 if (res->res_dir.hdr.name) {
404 free(res->res_dir.hdr.name);
406 if (res->res_dir.hdr.desc) {
407 free(res->res_dir.hdr.desc);
413 if (res->res_dir.password) {
414 free(res->res_dir.password);
416 if (res->res_dir.address) {
417 free(res->res_dir.address);
419 if (res->res_dir.tls_ctx) {
420 free_tls_context(res->res_dir.tls_ctx);
422 if (res->res_dir.tls_ca_certfile) {
423 free(res->res_dir.tls_ca_certfile);
425 if (res->res_dir.tls_ca_certdir) {
426 free(res->res_dir.tls_ca_certdir);
428 if (res->res_dir.tls_certfile) {
429 free(res->res_dir.tls_certfile);
431 if (res->res_dir.tls_keyfile) {
432 free(res->res_dir.tls_keyfile);
434 if (res->res_dir.tls_dhfile) {
435 free(res->res_dir.tls_dhfile);
437 if (res->res_dir.tls_allowed_cns) {
438 delete res->res_dir.tls_allowed_cns;
442 if (res->res_changer.changer_name) {
443 free(res->res_changer.changer_name);
445 if (res->res_changer.changer_command) {
446 free(res->res_changer.changer_command);
448 if (res->res_changer.device) {
449 delete res->res_changer.device;
451 rwl_destroy(&res->res_changer.changer_lock);
454 if (res->res_store.sdaddrs) {
455 free_addresses(res->res_store.sdaddrs);
457 if (res->res_store.sddaddrs) {
458 free_addresses(res->res_store.sddaddrs);
460 if (res->res_store.working_directory) {
461 free(res->res_store.working_directory);
463 if (res->res_store.pid_directory) {
464 free(res->res_store.pid_directory);
466 if (res->res_store.subsys_directory) {
467 free(res->res_store.subsys_directory);
469 if (res->res_store.plugin_directory) {
470 free(res->res_store.plugin_directory);
472 if (res->res_store.scripts_directory) {
473 free(res->res_store.scripts_directory);
475 if (res->res_store.tls_ctx) {
476 free_tls_context(res->res_store.tls_ctx);
478 if (res->res_store.tls_ca_certfile) {
479 free(res->res_store.tls_ca_certfile);
481 if (res->res_store.tls_ca_certdir) {
482 free(res->res_store.tls_ca_certdir);
484 if (res->res_store.tls_certfile) {
485 free(res->res_store.tls_certfile);
487 if (res->res_store.tls_keyfile) {
488 free(res->res_store.tls_keyfile);
490 if (res->res_store.tls_dhfile) {
491 free(res->res_store.tls_dhfile);
493 if (res->res_store.tls_allowed_cns) {
494 delete res->res_store.tls_allowed_cns;
496 if (res->res_store.verid) {
497 free(res->res_store.verid);
501 if (res->res_dev.media_type) {
502 free(res->res_dev.media_type);
504 if (res->res_dev.device_name) {
505 free(res->res_dev.device_name);
507 if (res->res_dev.control_name) {
508 free(res->res_dev.control_name);
510 if (res->res_dev.changer_name) {
511 free(res->res_dev.changer_name);
513 if (res->res_dev.changer_command) {
514 free(res->res_dev.changer_command);
516 if (res->res_dev.alert_command) {
517 free(res->res_dev.alert_command);
519 if (res->res_dev.spool_directory) {
520 free(res->res_dev.spool_directory);
522 if (res->res_dev.mount_point) {
523 free(res->res_dev.mount_point);
525 if (res->res_dev.mount_command) {
526 free(res->res_dev.mount_command);
528 if (res->res_dev.unmount_command) {
529 free(res->res_dev.unmount_command);
531 if (res->res_dev.write_part_command) {
532 free(res->res_dev.write_part_command);
534 if (res->res_dev.free_space_command) {
535 free(res->res_dev.free_space_command);
539 if (res->res_msgs.mail_cmd) {
540 free(res->res_msgs.mail_cmd);
542 if (res->res_msgs.operator_cmd) {
543 free(res->res_msgs.operator_cmd);
545 free_msgs_res((MSGS *)res); /* free message resource */
549 Dmsg1(0, _("Unknown resource type %d\n"), type);
552 /* Common stuff again -- free the resource, recurse to next one */
557 free_resource(nres, type);
561 /* Save the new resource by chaining it into the head list for
562 * the resource. If this is pass 2, we update any resource
565 void save_resource(int type, RES_ITEM *items, int pass)
568 int rindex = type - r_first;
573 * Ensure that all required items are present
575 for (i=0; items[i].name; i++) {
576 if (items[i].flags & ITEM_REQUIRED) {
577 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
578 Emsg2(M_ERROR_TERM, 0, _("\"%s\" directive is required in \"%s\" resource, but not found.\n"),
579 items[i].name, resources[rindex].name);
582 /* If this triggers, take a look at lib/parse_conf.h */
583 if (i >= MAX_RES_ITEMS) {
584 Emsg1(M_ERROR_TERM, 0, _("Too many directives in \"%s\" resource\n"), resources[rindex].name);
588 /* During pass 2, we looked up pointers to all the resources
589 * referrenced in the current resource, , now we
590 * must copy their address from the static record to the allocated
597 /* Resources not containing a resource */
602 /* Resources containing a resource or an alist */
604 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
605 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
607 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
610 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
611 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
613 res->res_store.messages = res_all.res_store.messages;
614 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
617 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
618 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
619 res_all.res_changer.hdr.name);
621 /* we must explicitly copy the device alist pointer */
622 res->res_changer.device = res_all.res_changer.device;
624 * Now update each device in this resource to point back
625 * to the changer resource.
627 foreach_alist(dev, res->res_changer.device) {
628 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
630 if ((errstat = rwl_init(&res->res_changer.changer_lock,
631 PRIO_SD_ACH_ACCESS)) != 0)
634 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init lock: ERR=%s\n"),
635 be.bstrerror(errstat));
639 printf(_("Unknown resource type %d\n"), type);
645 if (res_all.res_dir.hdr.name) {
646 free(res_all.res_dir.hdr.name);
647 res_all.res_dir.hdr.name = NULL;
649 if (res_all.res_dir.hdr.desc) {
650 free(res_all.res_dir.hdr.desc);
651 res_all.res_dir.hdr.desc = NULL;
656 /* The following code is only executed on pass 1 */
659 size = sizeof(DIRRES);
662 size = sizeof(STORES);
665 size = sizeof(DEVRES);
671 size = sizeof(AUTOCHANGER);
674 printf(_("Unknown resource type %d\n"), type);
681 res = (URES *)malloc(size);
682 memcpy(res, &res_all, size);
683 if (!res_head[rindex]) {
684 res_head[rindex] = (RES *)res; /* store first entry */
687 /* Add new res to end of chain */
688 for (last=next=res_head[rindex]; next; next=next->next) {
690 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
691 Emsg2(M_ERROR_TERM, 0,
692 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
693 resources[rindex].name, res->res_dir.hdr.name);
696 last->next = (RES *)res;
697 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
698 res->res_dir.hdr.name);
703 bool parse_sd_config(CONFIG *config, const char *configfile, int exit_code)
705 config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
706 r_first, r_last, resources, res_head);
707 return config->parse_config();