2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Configuration file parser for Bacula Storage daemon
23 * Kern Sibbald, March MM
29 /* First and last resource ids */
30 int32_t r_first = R_FIRST;
31 int32_t r_last = R_LAST;
32 static RES *sres_head[R_LAST - R_FIRST + 1];
33 RES **res_head = sres_head;
35 /* We build the current resource here statically,
36 * then move it to dynamic memory */
38 extern "C" { // work around visual compiler mangling variables
44 int32_t res_all_size = sizeof(res_all);
46 /* Definition of records permitted within each
47 * resource with the routine to process the record
52 * Globals for the Storage daemon.
53 * name handler value code flags default_value
55 static RES_ITEM store_items[] = {
56 {"Name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
57 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
58 {"SdAddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
59 {"SdAddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
60 {"Messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
61 {"SdPort", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
62 {"WorkingDirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
63 {"PidDirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
64 {"SubsysDirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
65 {"PluginDirectory", store_dir, ITEM(res_store.plugin_directory), 0, 0, 0},
66 {"ScriptsDirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
67 {"MaximumConcurrentJobs", store_pint32, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 20},
68 {"ClientConnectTimeout", store_time, ITEM(res_store.ClientConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
69 {"HeartbeatInterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 5 * 60},
70 {"TlsAuthenticate", store_bool, ITEM(res_store.tls_authenticate), 0, 0, 0},
71 {"TlsEnable", store_bool, ITEM(res_store.tls_enable), 0, 0, 0},
72 {"TlsRequire", store_bool, ITEM(res_store.tls_require), 0, 0, 0},
73 {"TlsVerifyPeer", store_bool, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
74 {"TlsCaCertificateFile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
75 {"TlsCaCertificateDir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
76 {"TlsCertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
77 {"TlsKey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
78 {"TlsDhFile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
79 {"TlsAllowedCn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
80 {"ClientConnectWait", store_time, ITEM(res_store.client_wait), 0, ITEM_DEFAULT, 30 * 60},
81 {"VerId", store_str, ITEM(res_store.verid), 0, 0, 0},
82 {NULL, NULL, {0}, 0, 0, 0}
86 /* Directors that can speak to the Storage daemon */
87 static RES_ITEM dir_items[] = {
88 {"Name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
89 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
90 {"Password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
91 {"Monitor", store_bool, ITEM(res_dir.monitor), 0, 0, 0},
92 {"TlsAuthenticate", store_bool, ITEM(res_dir.tls_authenticate), 0, 0, 0},
93 {"TlsEnable", store_bool, ITEM(res_dir.tls_enable), 0, 0, 0},
94 {"TlsRequire", store_bool, ITEM(res_dir.tls_require), 0, 0, 0},
95 {"TlsVerifyPeer", store_bool, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
96 {"TlsCaCertificateFile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
97 {"TlsCaCertificateDir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
98 {"TlsCertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
99 {"TlsKey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
100 {"TlsDhFile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
101 {"TlsAllowedCn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
102 {NULL, NULL, {0}, 0, 0, 0}
105 /* Device definition */
106 static RES_ITEM dev_items[] = {
107 {"Name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
108 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
109 {"MediaType", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
110 {"DeviceType", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
111 {"ArchiveDevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
112 {"HardwareEndOfFile", store_bit, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
113 {"HardwareEndOfMedium", store_bit, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
114 {"BackwardSpaceRecord", store_bit, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
115 {"BackwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
116 {"BsfAtEom", store_bit, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
117 {"TwoEof", store_bit, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
118 {"ForwardSpaceRecord", store_bit, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
119 {"ForwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
120 {"FastForwardSpaceFile", store_bit, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
121 {"RemovableMedia", store_bit, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
122 {"RandomAccess", store_bit, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
123 {"AutomaticMount", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
124 {"LabelMedia", store_bit, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
125 {"AlwaysOpen", store_bit, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
126 {"Autochanger", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
127 {"CloseOnPoll", store_bit, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
128 {"BlockPositioning", store_bit, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
129 {"UseMtiocGet", store_bit, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
130 {"CheckLabels", store_bit, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
131 {"RequiresMount", store_bit, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
132 {"OfflineOnUnmount", store_bit, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
133 {"BlockChecksum", store_bit, ITEM(res_dev.cap_bits), CAP_BLOCKCHECKSUM, ITEM_DEFAULT, 1},
134 {"Enabled", store_bool, ITEM(res_dev.enabled), 0, ITEM_DEFAULT, 1},
135 {"AutoSelect", store_bool, ITEM(res_dev.autoselect), 0, ITEM_DEFAULT, 1},
136 {"ReadOnly", store_bool, ITEM(res_dev.read_only), 0, ITEM_DEFAULT, 0},
137 {"ChangerDevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
138 {"ControlDevice", store_strname,ITEM(res_dev.control_name), 0, 0, 0},
139 {"ChangerCommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
140 {"AlertCommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
141 {"MaximumChangerWait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
142 {"MaximumOpenWait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
143 {"MaximumNetworkBufferSize", store_pint32, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
144 {"VolumePollInterval", store_time, ITEM(res_dev.vol_poll_interval), 0, ITEM_DEFAULT, 5 * 60},
145 {"MaximumRewindWait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
146 {"MinimumBlockSize", store_size32, ITEM(res_dev.min_block_size), 0, 0, 0},
147 {"MaximumBlockSize", store_maxblocksize, ITEM(res_dev.max_block_size), 0, 0, 0},
148 {"PaddingSize", store_size32, ITEM(res_dev.padding_size), 0, ITEM_DEFAULT, 4096},
149 {"FileAlignment", store_size32, ITEM(res_dev.file_alignment), 0, ITEM_DEFAULT, 4096},
150 {"MaximumVolumeSize", store_size64, ITEM(res_dev.max_volume_size), 0, 0, 0},
151 {"MaximumFileSize", store_size64, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
152 {"VolumeCapacity", store_size64, ITEM(res_dev.volume_capacity), 0, 0, 0},
153 {"MinimumFeeSpace", store_size64, ITEM(res_dev.min_free_space), 0, ITEM_DEFAULT, 5000000},
154 {"MaximumConcurrentJobs", store_pint32, ITEM(res_dev.max_concurrent_jobs), 0, 0, 0},
155 {"SpoolDirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
156 {"MaximumSpoolSize", store_size64, ITEM(res_dev.max_spool_size), 0, 0, 0},
157 {"MaximumJobSpoolSize", store_size64, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
158 {"DriveIndex", store_pint32, ITEM(res_dev.drive_index), 0, 0, 0},
159 {"MaximumPartSize", store_size64, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
160 {"MountPoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
161 {"MountCommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
162 {"UnmountCommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
163 {"WritePartCommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
164 {"FreeSpaceCommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
165 {"LabelType", store_label, ITEM(res_dev.label_type), 0, 0, 0},
166 {NULL, NULL, {0}, 0, 0, 0}
169 /* Autochanger definition */
170 static RES_ITEM changer_items[] = {
171 {"Name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
172 {"Description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
173 {"Device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
174 {"ChangerDevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
175 {"ChangerCommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
176 {NULL, NULL, {0}, 0, 0, 0}
180 // {"mountanonymousvolumes", store_bit, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
183 /* Message resource */
184 extern RES_ITEM msgs_items[];
187 /* This is the master resource definition */
188 RES_TABLE resources[] = {
189 {"Director", dir_items, R_DIRECTOR},
190 {"Storage", store_items, R_STORAGE},
191 {"Device", dev_items, R_DEVICE},
192 {"Messages", msgs_items, R_MSGS},
193 {"Autochanger", changer_items, R_AUTOCHANGER},
200 * device type device code = token
203 {"File", B_FILE_DEV},
204 {"Tape", B_TAPE_DEV},
206 {"Fifo", B_FIFO_DEV},
208 {"VTape", B_VTAPE_DEV},
214 * Store Device Type (File, FIFO, Tape, DVD)
217 void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
221 lex_get_token(lc, T_NAME);
222 /* Store the label pass 2 so that type is defined */
223 for (i=0; dev_types[i].name; i++) {
224 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
225 *(uint32_t *)(item->value) = dev_types[i].token;
231 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
234 set_bit(index, res_all.hdr.item_present);
238 * Store Maximum Block Size, and check it is not greater than MAX_BLOCK_LENGTH
241 void store_maxblocksize(LEX *lc, RES_ITEM *item, int index, int pass)
243 store_size32(lc, item, index, pass);
244 if (*(uint32_t *)(item->value) > MAX_BLOCK_LENGTH) {
245 scan_err2(lc, _("Maximum Block Size configured value %u is greater than allowed maximum: %u"),
246 *(uint32_t *)(item->value), MAX_BLOCK_LENGTH );
250 /* Dump contents of resource */
251 void dump_resource(int type, RES *rres, void sendit(void *sock, const char *fmt, ...), void *sock)
253 URES *res = (URES *)rres;
258 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
261 sendit(sock, _("dump_resource type=%d\n"), type);
262 if (type < 0) { /* no recursion */
268 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
271 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
272 res->res_store.hdr.name,
273 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
274 get_first_port_host_order(res->res_store.sdaddrs),
275 get_first_port_host_order(res->res_store.sddaddrs),
276 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
277 if (res->res_store.sdaddrs) {
278 foreach_dlist(p, res->res_store.sdaddrs) {
279 sendit(sock, " SDaddr=%s SDport=%d\n",
280 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
283 if (res->res_store.sddaddrs) {
284 foreach_dlist(p, res->res_store.sddaddrs) {
285 sendit(sock, " SDDaddr=%s SDDport=%d\n",
286 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
291 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
292 res->res_dev.hdr.name,
293 res->res_dev.media_type, res->res_dev.device_name,
294 res->res_dev.label_type);
295 sendit(sock, " rew_wait=%lld min_bs=%d max_bs=%d chgr_wait=%lld\n",
296 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
297 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
298 sendit(sock, " max_jobs=%d max_files=%lld max_size=%lld\n",
299 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
300 res->res_dev.max_volume_size);
301 sendit(sock, " min_block_size=%lld max_block_size=%lld\n",
302 res->res_dev.min_block_size, res->res_dev.max_block_size);
303 sendit(sock, " max_file_size=%lld capacity=%lld\n",
304 res->res_dev.max_file_size, res->res_dev.volume_capacity);
305 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
306 sendit(sock, " max_spool_size=%lld max_job_spool_size=%lld\n",
307 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
308 if (res->res_dev.changer_res) {
309 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
311 bstrncpy(buf, " ", sizeof(buf));
312 if (res->res_dev.cap_bits & CAP_EOF) {
313 bstrncat(buf, "CAP_EOF ", sizeof(buf));
315 if (res->res_dev.cap_bits & CAP_BSR) {
316 bstrncat(buf, "CAP_BSR ", sizeof(buf));
318 if (res->res_dev.cap_bits & CAP_BSF) {
319 bstrncat(buf, "CAP_BSF ", sizeof(buf));
321 if (res->res_dev.cap_bits & CAP_FSR) {
322 bstrncat(buf, "CAP_FSR ", sizeof(buf));
324 if (res->res_dev.cap_bits & CAP_FSF) {
325 bstrncat(buf, "CAP_FSF ", sizeof(buf));
327 if (res->res_dev.cap_bits & CAP_EOM) {
328 bstrncat(buf, "CAP_EOM ", sizeof(buf));
330 if (res->res_dev.cap_bits & CAP_REM) {
331 bstrncat(buf, "CAP_REM ", sizeof(buf));
333 if (res->res_dev.cap_bits & CAP_RACCESS) {
334 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
336 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
337 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
339 if (res->res_dev.cap_bits & CAP_LABEL) {
340 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
342 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
343 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
345 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
346 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
348 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
349 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
351 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
352 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
354 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
355 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
357 bstrncat(buf, "\n", sizeof(buf));
362 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
363 res->res_changer.hdr.name,
364 res->res_changer.changer_name, res->res_changer.changer_command);
365 foreach_alist(dev, res->res_changer.device) {
366 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
368 bstrncat(buf, "\n", sizeof(buf));
372 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
373 if (res->res_msgs.mail_cmd)
374 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
375 if (res->res_msgs.operator_cmd)
376 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
379 sendit(sock, _("Warning: unknown resource type %d\n"), type);
382 if (recurse && res->res_dir.hdr.next) {
383 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
388 * Free memory of resource.
389 * NB, we don't need to worry about freeing any references
390 * to other resources as they will be freed when that
391 * resource chain is traversed. Mainly we worry about freeing
392 * allocated strings (names).
394 void free_resource(RES *sres, int type)
397 URES *res = (URES *)sres;
402 /* common stuff -- free the resource name */
403 nres = (RES *)res->res_dir.hdr.next;
404 if (res->res_dir.hdr.name) {
405 free(res->res_dir.hdr.name);
407 if (res->res_dir.hdr.desc) {
408 free(res->res_dir.hdr.desc);
414 if (res->res_dir.password) {
415 free(res->res_dir.password);
417 if (res->res_dir.address) {
418 free(res->res_dir.address);
420 if (res->res_dir.tls_ctx) {
421 free_tls_context(res->res_dir.tls_ctx);
423 if (res->res_dir.tls_ca_certfile) {
424 free(res->res_dir.tls_ca_certfile);
426 if (res->res_dir.tls_ca_certdir) {
427 free(res->res_dir.tls_ca_certdir);
429 if (res->res_dir.tls_certfile) {
430 free(res->res_dir.tls_certfile);
432 if (res->res_dir.tls_keyfile) {
433 free(res->res_dir.tls_keyfile);
435 if (res->res_dir.tls_dhfile) {
436 free(res->res_dir.tls_dhfile);
438 if (res->res_dir.tls_allowed_cns) {
439 delete res->res_dir.tls_allowed_cns;
443 if (res->res_changer.changer_name) {
444 free(res->res_changer.changer_name);
446 if (res->res_changer.changer_command) {
447 free(res->res_changer.changer_command);
449 if (res->res_changer.device) {
450 delete res->res_changer.device;
452 rwl_destroy(&res->res_changer.changer_lock);
455 if (res->res_store.sdaddrs) {
456 free_addresses(res->res_store.sdaddrs);
458 if (res->res_store.sddaddrs) {
459 free_addresses(res->res_store.sddaddrs);
461 if (res->res_store.working_directory) {
462 free(res->res_store.working_directory);
464 if (res->res_store.pid_directory) {
465 free(res->res_store.pid_directory);
467 if (res->res_store.subsys_directory) {
468 free(res->res_store.subsys_directory);
470 if (res->res_store.plugin_directory) {
471 free(res->res_store.plugin_directory);
473 if (res->res_store.scripts_directory) {
474 free(res->res_store.scripts_directory);
476 if (res->res_store.tls_ctx) {
477 free_tls_context(res->res_store.tls_ctx);
479 if (res->res_store.tls_ca_certfile) {
480 free(res->res_store.tls_ca_certfile);
482 if (res->res_store.tls_ca_certdir) {
483 free(res->res_store.tls_ca_certdir);
485 if (res->res_store.tls_certfile) {
486 free(res->res_store.tls_certfile);
488 if (res->res_store.tls_keyfile) {
489 free(res->res_store.tls_keyfile);
491 if (res->res_store.tls_dhfile) {
492 free(res->res_store.tls_dhfile);
494 if (res->res_store.tls_allowed_cns) {
495 delete res->res_store.tls_allowed_cns;
497 if (res->res_store.verid) {
498 free(res->res_store.verid);
502 if (res->res_dev.media_type) {
503 free(res->res_dev.media_type);
505 if (res->res_dev.device_name) {
506 free(res->res_dev.device_name);
508 if (res->res_dev.control_name) {
509 free(res->res_dev.control_name);
511 if (res->res_dev.changer_name) {
512 free(res->res_dev.changer_name);
514 if (res->res_dev.changer_command) {
515 free(res->res_dev.changer_command);
517 if (res->res_dev.alert_command) {
518 free(res->res_dev.alert_command);
520 if (res->res_dev.spool_directory) {
521 free(res->res_dev.spool_directory);
523 if (res->res_dev.mount_point) {
524 free(res->res_dev.mount_point);
526 if (res->res_dev.mount_command) {
527 free(res->res_dev.mount_command);
529 if (res->res_dev.unmount_command) {
530 free(res->res_dev.unmount_command);
532 if (res->res_dev.write_part_command) {
533 free(res->res_dev.write_part_command);
535 if (res->res_dev.free_space_command) {
536 free(res->res_dev.free_space_command);
540 if (res->res_msgs.mail_cmd) {
541 free(res->res_msgs.mail_cmd);
543 if (res->res_msgs.operator_cmd) {
544 free(res->res_msgs.operator_cmd);
546 free_msgs_res((MSGS *)res); /* free message resource */
550 Dmsg1(0, _("Unknown resource type %d\n"), type);
553 /* Common stuff again -- free the resource, recurse to next one */
558 free_resource(nres, type);
562 /* Save the new resource by chaining it into the head list for
563 * the resource. If this is pass 2, we update any resource
566 void save_resource(int type, RES_ITEM *items, int pass)
569 int rindex = type - r_first;
574 * Ensure that all required items are present
576 for (i=0; items[i].name; i++) {
577 if (items[i].flags & ITEM_REQUIRED) {
578 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
579 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
580 items[i].name, resources[rindex]);
583 /* If this triggers, take a look at lib/parse_conf.h */
584 if (i >= MAX_RES_ITEMS) {
585 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
589 /* During pass 2, we looked up pointers to all the resources
590 * referrenced in the current resource, , now we
591 * must copy their address from the static record to the allocated
598 /* Resources not containing a resource */
603 /* Resources containing a resource or an alist */
605 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
606 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
608 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
611 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
612 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
614 res->res_store.messages = res_all.res_store.messages;
615 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
618 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
619 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
620 res_all.res_changer.hdr.name);
622 /* we must explicitly copy the device alist pointer */
623 res->res_changer.device = res_all.res_changer.device;
625 * Now update each device in this resource to point back
626 * to the changer resource.
628 foreach_alist(dev, res->res_changer.device) {
629 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
631 if ((errstat = rwl_init(&res->res_changer.changer_lock,
632 PRIO_SD_ACH_ACCESS)) != 0)
635 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init lock: ERR=%s\n"),
636 be.bstrerror(errstat));
640 printf(_("Unknown resource type %d\n"), type);
646 if (res_all.res_dir.hdr.name) {
647 free(res_all.res_dir.hdr.name);
648 res_all.res_dir.hdr.name = NULL;
650 if (res_all.res_dir.hdr.desc) {
651 free(res_all.res_dir.hdr.desc);
652 res_all.res_dir.hdr.desc = NULL;
657 /* The following code is only executed on pass 1 */
660 size = sizeof(DIRRES);
663 size = sizeof(STORES);
666 size = sizeof(DEVRES);
672 size = sizeof(AUTOCHANGER);
675 printf(_("Unknown resource type %d\n"), type);
682 res = (URES *)malloc(size);
683 memcpy(res, &res_all, size);
684 if (!res_head[rindex]) {
685 res_head[rindex] = (RES *)res; /* store first entry */
688 /* Add new res to end of chain */
689 for (last=next=res_head[rindex]; next; next=next->next) {
691 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
692 Emsg2(M_ERROR_TERM, 0,
693 _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
694 resources[rindex].name, res->res_dir.hdr.name);
697 last->next = (RES *)res;
698 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
699 res->res_dir.hdr.name);
704 bool parse_sd_config(CONFIG *config, const char *configfile, int exit_code)
706 config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
707 r_first, r_last, resources, res_head);
708 return config->parse_config();