2 * Configuration file parser for Bacula Storage daemon
4 * Kern Sibbald, March MM
9 Copyright (C) 2000-2006 Kern Sibbald
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 version 2 as amended with additional clauses defined in the
14 file LICENSE in the main source directory.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 the file LICENSE for additional details.
26 extern int debug_level;
29 /* First and last resource ids */
30 int r_first = R_FIRST;
32 static RES *sres_head[R_LAST - R_FIRST + 1];
33 RES **res_head = sres_head;
36 /* Forward referenced subroutines */
37 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass);
40 /* We build the current resource here statically,
41 * then move it to dynamic memory */
43 int res_all_size = sizeof(res_all);
45 /* Definition of records permitted within each
46 * resource with the routine to process the record
50 /* Globals for the Storage daemon. */
51 static RES_ITEM store_items[] = {
52 {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
53 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
54 {"sdaddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
55 {"sdaddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
56 {"messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
57 {"sdport", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
58 {"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
59 {"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
60 {"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
61 {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
62 {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
63 {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
64 {"tlsenable", store_bit, ITEM(res_store.tls_enable), 1, 0, 0},
65 {"tlsrequire", store_bit, ITEM(res_store.tls_require), 1, 0, 0},
66 {"tlsverifypeer", store_bit, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
67 {"tlscacertificatefile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
68 {"tlscacertificatedir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
69 {"tlscertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
70 {"tlskey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
71 {"tlsdhfile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
72 {"tlsallowedcn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
73 {NULL, NULL, 0, 0, 0, 0}
77 /* Directors that can speak to the Storage daemon */
78 static RES_ITEM dir_items[] = {
79 {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
80 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
81 {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
82 {"monitor", store_bit, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
83 {"tlsenable", store_bit, ITEM(res_dir.tls_enable), 1, 0, 0},
84 {"tlsrequire", store_bit, ITEM(res_dir.tls_require), 1, 0, 0},
85 {"tlsverifypeer", store_bit, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
86 {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
87 {"tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
88 {"tlscertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
89 {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
90 {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
91 {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
92 {NULL, NULL, 0, 0, 0, 0}
95 /* Device definition */
96 static RES_ITEM dev_items[] = {
97 {"name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
98 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
99 {"mediatype", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
100 {"devicetype", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
101 {"archivedevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
102 {"hardwareendoffile", store_bit, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
103 {"hardwareendofmedium", store_bit, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
104 {"backwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
105 {"backwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
106 {"bsfateom", store_bit, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
107 {"twoeof", store_bit, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
108 {"forwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
109 {"forwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
110 {"fastforwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
111 {"removablemedia", store_bit, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
112 {"randomaccess", store_bit, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
113 {"automaticmount", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
114 {"labelmedia", store_bit, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
115 {"alwaysopen", store_bit, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
116 {"autochanger", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
117 {"closeonpoll", store_bit, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
118 {"blockpositioning", store_bit, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
119 {"usemtiocget", store_bit, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
120 {"checklabels", store_bit, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
121 {"requiresmount", store_bit, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
122 {"offlineonunmount", store_bit, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
123 {"autoselect", store_bit, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
124 {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
125 {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
126 {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
127 {"maximumchangerwait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
128 {"maximumopenwait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
129 {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
130 {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
131 {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0},
132 {"maximumrewindwait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
133 {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
134 {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
135 {"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
136 {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
137 {"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
138 {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
139 {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
140 {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
141 {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
142 {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
143 {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
144 {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
145 {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
146 {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
147 {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
148 {"labeltype", store_label, ITEM(res_dev.label_type), 0, 0, 0},
149 {NULL, NULL, 0, 0, 0, 0}
152 /* Autochanger definition */
153 static RES_ITEM changer_items[] = {
154 {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
155 {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
156 {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
157 {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
158 {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
159 {NULL, NULL, 0, 0, 0, 0}
163 // {"mountanonymousvolumes", store_bit, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
166 /* Message resource */
167 extern RES_ITEM msgs_items[];
170 /* This is the master resource definition */
171 RES_TABLE resources[] = {
172 {"director", dir_items, R_DIRECTOR},
173 {"storage", store_items, R_STORAGE},
174 {"device", dev_items, R_DEVICE},
175 {"messages", msgs_items, R_MSGS},
176 {"autochanger", changer_items, R_AUTOCHANGER},
183 * device type device code = token
190 static s_kw dev_types[] = {
191 {"file", B_FILE_DEV},
192 {"tape", B_TAPE_DEV},
194 {"fifo", B_FIFO_DEV},
200 * Store Device Type (File, FIFO, Tape, DVD)
203 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
207 token = lex_get_token(lc, T_NAME);
208 /* Store the label pass 2 so that type is defined */
209 for (i=0; dev_types[i].name; i++) {
210 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
211 *(int *)(item->value) = dev_types[i].token;
217 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
220 set_bit(index, res_all.hdr.item_present);
224 /* Dump contents of resource */
225 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
227 URES *res = (URES *)reshdr;
232 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
235 sendit(sock, _("dump_resource type=%d\n"), type);
236 if (type < 0) { /* no recursion */
242 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
245 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
246 res->res_store.hdr.name,
247 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
248 get_first_port_host_order(res->res_store.sdaddrs),
249 get_first_port_host_order(res->res_store.sddaddrs),
250 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
251 if (res->res_store.sdaddrs) {
252 foreach_dlist(p, res->res_store.sdaddrs) {
253 sendit(sock, " SDaddr=%s SDport=%d\n",
254 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
257 if (res->res_store.sddaddrs) {
258 foreach_dlist(p, res->res_store.sddaddrs) {
259 sendit(sock, " SDDaddr=%s SDDport=%d\n",
260 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
265 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
266 res->res_dev.hdr.name,
267 res->res_dev.media_type, res->res_dev.device_name,
268 res->res_dev.label_type);
269 sendit(sock, " rew_wait=%" lld " min_bs=%d max_bs=%d chgr_wait=%" lld "\n",
270 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
271 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
272 sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
273 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
274 res->res_dev.max_volume_size);
275 sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
276 res->res_dev.max_file_size, res->res_dev.volume_capacity);
277 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
278 sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
279 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
280 if (res->res_dev.changer_res) {
281 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
283 bstrncpy(buf, " ", sizeof(buf));
284 if (res->res_dev.cap_bits & CAP_EOF) {
285 bstrncat(buf, "CAP_EOF ", sizeof(buf));
287 if (res->res_dev.cap_bits & CAP_BSR) {
288 bstrncat(buf, "CAP_BSR ", sizeof(buf));
290 if (res->res_dev.cap_bits & CAP_BSF) {
291 bstrncat(buf, "CAP_BSF ", sizeof(buf));
293 if (res->res_dev.cap_bits & CAP_FSR) {
294 bstrncat(buf, "CAP_FSR ", sizeof(buf));
296 if (res->res_dev.cap_bits & CAP_FSF) {
297 bstrncat(buf, "CAP_FSF ", sizeof(buf));
299 if (res->res_dev.cap_bits & CAP_EOM) {
300 bstrncat(buf, "CAP_EOM ", sizeof(buf));
302 if (res->res_dev.cap_bits & CAP_REM) {
303 bstrncat(buf, "CAP_REM ", sizeof(buf));
305 if (res->res_dev.cap_bits & CAP_RACCESS) {
306 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
308 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
309 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
311 if (res->res_dev.cap_bits & CAP_LABEL) {
312 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
314 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
315 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
317 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
318 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
320 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
321 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
323 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
324 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
326 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
327 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
329 bstrncat(buf, "\n", sizeof(buf));
334 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
335 res->res_changer.hdr.name,
336 res->res_changer.changer_name, res->res_changer.changer_command);
337 foreach_alist(dev, res->res_changer.device) {
338 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
340 bstrncat(buf, "\n", sizeof(buf));
344 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
345 if (res->res_msgs.mail_cmd)
346 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
347 if (res->res_msgs.operator_cmd)
348 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
351 sendit(sock, _("Warning: unknown resource type %d\n"), type);
354 if (recurse && res->res_dir.hdr.next)
355 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
359 * Free memory of resource.
360 * NB, we don't need to worry about freeing any references
361 * to other resources as they will be freed when that
362 * resource chain is traversed. Mainly we worry about freeing
363 * allocated strings (names).
365 void free_resource(RES *sres, int type)
368 URES *res = (URES *)sres;
373 /* common stuff -- free the resource name */
374 nres = (RES *)res->res_dir.hdr.next;
375 if (res->res_dir.hdr.name) {
376 free(res->res_dir.hdr.name);
378 if (res->res_dir.hdr.desc) {
379 free(res->res_dir.hdr.desc);
385 if (res->res_dir.password) {
386 free(res->res_dir.password);
388 if (res->res_dir.address) {
389 free(res->res_dir.address);
391 if (res->res_dir.tls_ctx) {
392 free_tls_context(res->res_dir.tls_ctx);
394 if (res->res_dir.tls_ca_certfile) {
395 free(res->res_dir.tls_ca_certfile);
397 if (res->res_dir.tls_ca_certdir) {
398 free(res->res_dir.tls_ca_certdir);
400 if (res->res_dir.tls_certfile) {
401 free(res->res_dir.tls_certfile);
403 if (res->res_dir.tls_keyfile) {
404 free(res->res_dir.tls_keyfile);
406 if (res->res_dir.tls_dhfile) {
407 free(res->res_dir.tls_dhfile);
409 if (res->res_dir.tls_allowed_cns) {
410 delete res->res_dir.tls_allowed_cns;
414 if (res->res_changer.changer_name) {
415 free(res->res_changer.changer_name);
417 if (res->res_changer.changer_command) {
418 free(res->res_changer.changer_command);
420 if (res->res_changer.device) {
421 delete res->res_changer.device;
425 if (res->res_store.sdaddrs) {
426 free_addresses(res->res_store.sdaddrs);
428 if (res->res_store.sddaddrs) {
429 free_addresses(res->res_store.sddaddrs);
431 if (res->res_store.working_directory) {
432 free(res->res_store.working_directory);
434 if (res->res_store.pid_directory) {
435 free(res->res_store.pid_directory);
437 if (res->res_store.subsys_directory) {
438 free(res->res_store.subsys_directory);
440 if (res->res_store.scripts_directory) {
441 free(res->res_store.scripts_directory);
443 if (res->res_store.tls_ctx) {
444 free_tls_context(res->res_store.tls_ctx);
446 if (res->res_store.tls_ca_certfile) {
447 free(res->res_store.tls_ca_certfile);
449 if (res->res_store.tls_ca_certdir) {
450 free(res->res_store.tls_ca_certdir);
452 if (res->res_store.tls_certfile) {
453 free(res->res_store.tls_certfile);
455 if (res->res_store.tls_keyfile) {
456 free(res->res_store.tls_keyfile);
458 if (res->res_store.tls_dhfile) {
459 free(res->res_store.tls_dhfile);
461 if (res->res_store.tls_allowed_cns) {
462 delete res->res_store.tls_allowed_cns;
466 if (res->res_dev.media_type) {
467 free(res->res_dev.media_type);
469 if (res->res_dev.device_name) {
470 free(res->res_dev.device_name);
472 if (res->res_dev.changer_name) {
473 free(res->res_dev.changer_name);
475 if (res->res_dev.changer_command) {
476 free(res->res_dev.changer_command);
478 if (res->res_dev.alert_command) {
479 free(res->res_dev.alert_command);
481 if (res->res_dev.spool_directory) {
482 free(res->res_dev.spool_directory);
484 if (res->res_dev.mount_point) {
485 free(res->res_dev.mount_point);
487 if (res->res_dev.mount_command) {
488 free(res->res_dev.mount_command);
490 if (res->res_dev.unmount_command) {
491 free(res->res_dev.unmount_command);
493 if (res->res_dev.write_part_command) {
494 free(res->res_dev.write_part_command);
496 if (res->res_dev.free_space_command) {
497 free(res->res_dev.free_space_command);
501 if (res->res_msgs.mail_cmd) {
502 free(res->res_msgs.mail_cmd);
504 if (res->res_msgs.operator_cmd) {
505 free(res->res_msgs.operator_cmd);
507 free_msgs_res((MSGS *)res); /* free message resource */
511 Dmsg1(0, _("Unknown resource type %d\n"), type);
514 /* Common stuff again -- free the resource, recurse to next one */
519 free_resource(nres, type);
523 /* Save the new resource by chaining it into the head list for
524 * the resource. If this is pass 2, we update any resource
527 void save_resource(int type, RES_ITEM *items, int pass)
530 int rindex = type - r_first;
535 * Ensure that all required items are present
537 for (i=0; items[i].name; i++) {
538 if (items[i].flags & ITEM_REQUIRED) {
539 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
540 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
541 items[i].name, resources[rindex]);
544 /* If this triggers, take a look at lib/parse_conf.h */
545 if (i >= MAX_RES_ITEMS) {
546 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
550 /* During pass 2, we looked up pointers to all the resources
551 * referrenced in the current resource, , now we
552 * must copy their address from the static record to the allocated
559 /* Resources not containing a resource */
564 /* Resources containing a resource or an alist */
566 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
567 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
569 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
572 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
573 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
575 res->res_store.messages = res_all.res_store.messages;
576 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
579 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
580 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
581 res_all.res_changer.hdr.name);
583 /* we must explicitly copy the device alist pointer */
584 res->res_changer.device = res_all.res_changer.device;
586 * Now update each device in this resource to point back
587 * to the changer resource.
589 foreach_alist(dev, res->res_changer.device) {
590 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
592 if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
594 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
595 be.strerror(errstat));
599 printf(_("Unknown resource type %d\n"), type);
605 if (res_all.res_dir.hdr.name) {
606 free(res_all.res_dir.hdr.name);
607 res_all.res_dir.hdr.name = NULL;
609 if (res_all.res_dir.hdr.desc) {
610 free(res_all.res_dir.hdr.desc);
611 res_all.res_dir.hdr.desc = NULL;
616 /* The following code is only executed on pass 1 */
619 size = sizeof(DIRRES);
622 size = sizeof(STORES);
625 size = sizeof(DEVRES);
631 size = sizeof(AUTOCHANGER);
634 printf(_("Unknown resource type %d\n"), type);
641 res = (URES *)malloc(size);
642 memcpy(res, &res_all, size);
643 if (!res_head[rindex]) {
644 res_head[rindex] = (RES *)res; /* store first entry */
647 /* Add new res to end of chain */
648 for (next=res_head[rindex]; next->next; next=next->next) {
649 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
650 Emsg2(M_ERROR_TERM, 0,
651 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
652 resources[rindex].name, res->res_dir.hdr.name);
655 next->next = (RES *)res;
656 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
657 res->res_dir.hdr.name);