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 /* First and last resource ids */
27 int r_first = R_FIRST;
29 static RES *sres_head[R_LAST - R_FIRST + 1];
30 RES **res_head = sres_head;
33 /* Forward referenced subroutines */
34 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass);
37 /* We build the current resource here statically,
38 * then move it to dynamic memory */
40 extern "C" { // work around visual compiler mangling variables
46 int res_all_size = sizeof(res_all);
48 /* Definition of records permitted within each
49 * resource with the routine to process the record
53 /* Globals for the Storage daemon. */
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 {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
65 {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
66 {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
67 {"tlsenable", store_bit, ITEM(res_store.tls_enable), 1, 0, 0},
68 {"tlsrequire", store_bit, ITEM(res_store.tls_require), 1, 0, 0},
69 {"tlsverifypeer", store_bit, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
70 {"tlscacertificatefile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
71 {"tlscacertificatedir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
72 {"tlscertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
73 {"tlskey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
74 {"tlsdhfile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
75 {"tlsallowedcn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
76 {NULL, NULL, {0}, 0, 0, 0}
80 /* Directors that can speak to the Storage daemon */
81 static RES_ITEM dir_items[] = {
82 {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
83 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
84 {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
85 {"monitor", store_bit, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
86 {"tlsenable", store_bit, ITEM(res_dir.tls_enable), 1, 0, 0},
87 {"tlsrequire", store_bit, ITEM(res_dir.tls_require), 1, 0, 0},
88 {"tlsverifypeer", store_bit, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
89 {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
90 {"tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
91 {"tlscertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
92 {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
93 {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
94 {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
95 {NULL, NULL, {0}, 0, 0, 0}
98 /* Device definition */
99 static RES_ITEM dev_items[] = {
100 {"name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
101 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
102 {"mediatype", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
103 {"devicetype", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
104 {"archivedevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
105 {"hardwareendoffile", store_bit, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
106 {"hardwareendofmedium", store_bit, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
107 {"backwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
108 {"backwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
109 {"bsfateom", store_bit, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
110 {"twoeof", store_bit, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
111 {"forwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
112 {"forwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
113 {"fastforwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
114 {"removablemedia", store_bit, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
115 {"randomaccess", store_bit, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
116 {"automaticmount", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
117 {"labelmedia", store_bit, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
118 {"alwaysopen", store_bit, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
119 {"autochanger", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
120 {"closeonpoll", store_bit, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
121 {"blockpositioning", store_bit, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
122 {"usemtiocget", store_bit, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
123 {"checklabels", store_bit, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
124 {"requiresmount", store_bit, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
125 {"offlineonunmount", store_bit, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
126 {"autoselect", store_bit, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
127 {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
128 {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
129 {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
130 {"maximumchangerwait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
131 {"maximumopenwait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
132 {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
133 {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
134 {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0},
135 {"maximumrewindwait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
136 {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
137 {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
138 {"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
139 {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
140 {"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
141 {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
142 {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
143 {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
144 {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
145 {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
146 {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
147 {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
148 {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
149 {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
150 {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
151 {"labeltype", store_label, ITEM(res_dev.label_type), 0, 0, 0},
152 {NULL, NULL, {0}, 0, 0, 0}
155 /* Autochanger definition */
156 static RES_ITEM changer_items[] = {
157 {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
158 {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
159 {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
160 {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
161 {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
162 {NULL, NULL, {0}, 0, 0, 0}
166 // {"mountanonymousvolumes", store_bit, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
169 /* Message resource */
170 extern RES_ITEM msgs_items[];
173 /* This is the master resource definition */
174 RES_TABLE resources[] = {
175 {"director", dir_items, R_DIRECTOR},
176 {"storage", store_items, R_STORAGE},
177 {"device", dev_items, R_DEVICE},
178 {"messages", msgs_items, R_MSGS},
179 {"autochanger", changer_items, R_AUTOCHANGER},
186 * device type device code = token
193 static s_kw dev_types[] = {
194 {"file", B_FILE_DEV},
195 {"tape", B_TAPE_DEV},
197 {"fifo", B_FIFO_DEV},
203 * Store Device Type (File, FIFO, Tape, DVD)
206 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
210 token = lex_get_token(lc, T_NAME);
211 /* Store the label pass 2 so that type is defined */
212 for (i=0; dev_types[i].name; i++) {
213 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
214 *(int *)(item->value) = dev_types[i].token;
220 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
223 set_bit(index, res_all.hdr.item_present);
227 /* Dump contents of resource */
228 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
230 URES *res = (URES *)reshdr;
235 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
238 sendit(sock, _("dump_resource type=%d\n"), type);
239 if (type < 0) { /* no recursion */
245 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
248 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
249 res->res_store.hdr.name,
250 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
251 get_first_port_host_order(res->res_store.sdaddrs),
252 get_first_port_host_order(res->res_store.sddaddrs),
253 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
254 if (res->res_store.sdaddrs) {
255 foreach_dlist(p, res->res_store.sdaddrs) {
256 sendit(sock, " SDaddr=%s SDport=%d\n",
257 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
260 if (res->res_store.sddaddrs) {
261 foreach_dlist(p, res->res_store.sddaddrs) {
262 sendit(sock, " SDDaddr=%s SDDport=%d\n",
263 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
268 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
269 res->res_dev.hdr.name,
270 res->res_dev.media_type, res->res_dev.device_name,
271 res->res_dev.label_type);
272 sendit(sock, " rew_wait=%" lld " min_bs=%d max_bs=%d chgr_wait=%" lld "\n",
273 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
274 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
275 sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
276 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
277 res->res_dev.max_volume_size);
278 sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
279 res->res_dev.max_file_size, res->res_dev.volume_capacity);
280 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
281 sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
282 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
283 if (res->res_dev.changer_res) {
284 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
286 bstrncpy(buf, " ", sizeof(buf));
287 if (res->res_dev.cap_bits & CAP_EOF) {
288 bstrncat(buf, "CAP_EOF ", sizeof(buf));
290 if (res->res_dev.cap_bits & CAP_BSR) {
291 bstrncat(buf, "CAP_BSR ", sizeof(buf));
293 if (res->res_dev.cap_bits & CAP_BSF) {
294 bstrncat(buf, "CAP_BSF ", sizeof(buf));
296 if (res->res_dev.cap_bits & CAP_FSR) {
297 bstrncat(buf, "CAP_FSR ", sizeof(buf));
299 if (res->res_dev.cap_bits & CAP_FSF) {
300 bstrncat(buf, "CAP_FSF ", sizeof(buf));
302 if (res->res_dev.cap_bits & CAP_EOM) {
303 bstrncat(buf, "CAP_EOM ", sizeof(buf));
305 if (res->res_dev.cap_bits & CAP_REM) {
306 bstrncat(buf, "CAP_REM ", sizeof(buf));
308 if (res->res_dev.cap_bits & CAP_RACCESS) {
309 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
311 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
312 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
314 if (res->res_dev.cap_bits & CAP_LABEL) {
315 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
317 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
318 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
320 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
321 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
323 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
324 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
326 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
327 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
329 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
330 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
332 bstrncat(buf, "\n", sizeof(buf));
337 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
338 res->res_changer.hdr.name,
339 res->res_changer.changer_name, res->res_changer.changer_command);
340 foreach_alist(dev, res->res_changer.device) {
341 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
343 bstrncat(buf, "\n", sizeof(buf));
347 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
348 if (res->res_msgs.mail_cmd)
349 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
350 if (res->res_msgs.operator_cmd)
351 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
354 sendit(sock, _("Warning: unknown resource type %d\n"), type);
357 if (recurse && res->res_dir.hdr.next)
358 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
362 * Free memory of resource.
363 * NB, we don't need to worry about freeing any references
364 * to other resources as they will be freed when that
365 * resource chain is traversed. Mainly we worry about freeing
366 * allocated strings (names).
368 void free_resource(RES *sres, int type)
371 URES *res = (URES *)sres;
376 /* common stuff -- free the resource name */
377 nres = (RES *)res->res_dir.hdr.next;
378 if (res->res_dir.hdr.name) {
379 free(res->res_dir.hdr.name);
381 if (res->res_dir.hdr.desc) {
382 free(res->res_dir.hdr.desc);
388 if (res->res_dir.password) {
389 free(res->res_dir.password);
391 if (res->res_dir.address) {
392 free(res->res_dir.address);
394 if (res->res_dir.tls_ctx) {
395 free_tls_context(res->res_dir.tls_ctx);
397 if (res->res_dir.tls_ca_certfile) {
398 free(res->res_dir.tls_ca_certfile);
400 if (res->res_dir.tls_ca_certdir) {
401 free(res->res_dir.tls_ca_certdir);
403 if (res->res_dir.tls_certfile) {
404 free(res->res_dir.tls_certfile);
406 if (res->res_dir.tls_keyfile) {
407 free(res->res_dir.tls_keyfile);
409 if (res->res_dir.tls_dhfile) {
410 free(res->res_dir.tls_dhfile);
412 if (res->res_dir.tls_allowed_cns) {
413 delete res->res_dir.tls_allowed_cns;
417 if (res->res_changer.changer_name) {
418 free(res->res_changer.changer_name);
420 if (res->res_changer.changer_command) {
421 free(res->res_changer.changer_command);
423 if (res->res_changer.device) {
424 delete res->res_changer.device;
428 if (res->res_store.sdaddrs) {
429 free_addresses(res->res_store.sdaddrs);
431 if (res->res_store.sddaddrs) {
432 free_addresses(res->res_store.sddaddrs);
434 if (res->res_store.working_directory) {
435 free(res->res_store.working_directory);
437 if (res->res_store.pid_directory) {
438 free(res->res_store.pid_directory);
440 if (res->res_store.subsys_directory) {
441 free(res->res_store.subsys_directory);
443 if (res->res_store.scripts_directory) {
444 free(res->res_store.scripts_directory);
446 if (res->res_store.tls_ctx) {
447 free_tls_context(res->res_store.tls_ctx);
449 if (res->res_store.tls_ca_certfile) {
450 free(res->res_store.tls_ca_certfile);
452 if (res->res_store.tls_ca_certdir) {
453 free(res->res_store.tls_ca_certdir);
455 if (res->res_store.tls_certfile) {
456 free(res->res_store.tls_certfile);
458 if (res->res_store.tls_keyfile) {
459 free(res->res_store.tls_keyfile);
461 if (res->res_store.tls_dhfile) {
462 free(res->res_store.tls_dhfile);
464 if (res->res_store.tls_allowed_cns) {
465 delete res->res_store.tls_allowed_cns;
469 if (res->res_dev.media_type) {
470 free(res->res_dev.media_type);
472 if (res->res_dev.device_name) {
473 free(res->res_dev.device_name);
475 if (res->res_dev.changer_name) {
476 free(res->res_dev.changer_name);
478 if (res->res_dev.changer_command) {
479 free(res->res_dev.changer_command);
481 if (res->res_dev.alert_command) {
482 free(res->res_dev.alert_command);
484 if (res->res_dev.spool_directory) {
485 free(res->res_dev.spool_directory);
487 if (res->res_dev.mount_point) {
488 free(res->res_dev.mount_point);
490 if (res->res_dev.mount_command) {
491 free(res->res_dev.mount_command);
493 if (res->res_dev.unmount_command) {
494 free(res->res_dev.unmount_command);
496 if (res->res_dev.write_part_command) {
497 free(res->res_dev.write_part_command);
499 if (res->res_dev.free_space_command) {
500 free(res->res_dev.free_space_command);
504 if (res->res_msgs.mail_cmd) {
505 free(res->res_msgs.mail_cmd);
507 if (res->res_msgs.operator_cmd) {
508 free(res->res_msgs.operator_cmd);
510 free_msgs_res((MSGS *)res); /* free message resource */
514 Dmsg1(0, _("Unknown resource type %d\n"), type);
517 /* Common stuff again -- free the resource, recurse to next one */
522 free_resource(nres, type);
526 /* Save the new resource by chaining it into the head list for
527 * the resource. If this is pass 2, we update any resource
530 void save_resource(int type, RES_ITEM *items, int pass)
533 int rindex = type - r_first;
538 * Ensure that all required items are present
540 for (i=0; items[i].name; i++) {
541 if (items[i].flags & ITEM_REQUIRED) {
542 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
543 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
544 items[i].name, resources[rindex]);
547 /* If this triggers, take a look at lib/parse_conf.h */
548 if (i >= MAX_RES_ITEMS) {
549 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
553 /* During pass 2, we looked up pointers to all the resources
554 * referrenced in the current resource, , now we
555 * must copy their address from the static record to the allocated
562 /* Resources not containing a resource */
567 /* Resources containing a resource or an alist */
569 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
570 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
572 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
575 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
576 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
578 res->res_store.messages = res_all.res_store.messages;
579 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
582 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
583 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
584 res_all.res_changer.hdr.name);
586 /* we must explicitly copy the device alist pointer */
587 res->res_changer.device = res_all.res_changer.device;
589 * Now update each device in this resource to point back
590 * to the changer resource.
592 foreach_alist(dev, res->res_changer.device) {
593 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
595 if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
597 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
598 be.strerror(errstat));
602 printf(_("Unknown resource type %d\n"), type);
608 if (res_all.res_dir.hdr.name) {
609 free(res_all.res_dir.hdr.name);
610 res_all.res_dir.hdr.name = NULL;
612 if (res_all.res_dir.hdr.desc) {
613 free(res_all.res_dir.hdr.desc);
614 res_all.res_dir.hdr.desc = NULL;
619 /* The following code is only executed on pass 1 */
622 size = sizeof(DIRRES);
625 size = sizeof(STORES);
628 size = sizeof(DEVRES);
634 size = sizeof(AUTOCHANGER);
637 printf(_("Unknown resource type %d\n"), type);
644 res = (URES *)malloc(size);
645 memcpy(res, &res_all, size);
646 if (!res_head[rindex]) {
647 res_head[rindex] = (RES *)res; /* store first entry */
650 /* Add new res to end of chain */
651 for (next=res_head[rindex]; next->next; next=next->next) {
652 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
653 Emsg2(M_ERROR_TERM, 0,
654 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
655 resources[rindex].name, res->res_dir.hdr.name);
658 next->next = (RES *)res;
659 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
660 res->res_dir.hdr.name);