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 extern "C" { // work around visual compiler mangling variables
49 int res_all_size = sizeof(res_all);
51 /* Definition of records permitted within each
52 * resource with the routine to process the record
56 /* Globals for the Storage daemon. */
57 static RES_ITEM store_items[] = {
58 {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
59 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
60 {"sdaddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
61 {"sdaddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
62 {"messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
63 {"sdport", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
64 {"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
65 {"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
66 {"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
67 {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
68 {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
69 {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
70 {"tlsenable", store_bit, ITEM(res_store.tls_enable), 1, 0, 0},
71 {"tlsrequire", store_bit, ITEM(res_store.tls_require), 1, 0, 0},
72 {"tlsverifypeer", store_bit, 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 {NULL, NULL, {0}, 0, 0, 0}
83 /* Directors that can speak to the Storage daemon */
84 static RES_ITEM dir_items[] = {
85 {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
86 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
87 {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
88 {"monitor", store_bit, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
89 {"tlsenable", store_bit, ITEM(res_dir.tls_enable), 1, 0, 0},
90 {"tlsrequire", store_bit, ITEM(res_dir.tls_require), 1, 0, 0},
91 {"tlsverifypeer", store_bit, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
92 {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
93 {"tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
94 {"tlscertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
95 {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
96 {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
97 {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
98 {NULL, NULL, {0}, 0, 0, 0}
101 /* Device definition */
102 static RES_ITEM dev_items[] = {
103 {"name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
104 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
105 {"mediatype", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
106 {"devicetype", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
107 {"archivedevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
108 {"hardwareendoffile", store_bit, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
109 {"hardwareendofmedium", store_bit, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
110 {"backwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
111 {"backwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
112 {"bsfateom", store_bit, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
113 {"twoeof", store_bit, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
114 {"forwardspacerecord", store_bit, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
115 {"forwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
116 {"fastforwardspacefile", store_bit, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
117 {"removablemedia", store_bit, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
118 {"randomaccess", store_bit, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
119 {"automaticmount", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
120 {"labelmedia", store_bit, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
121 {"alwaysopen", store_bit, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
122 {"autochanger", store_bit, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
123 {"closeonpoll", store_bit, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
124 {"blockpositioning", store_bit, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
125 {"usemtiocget", store_bit, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
126 {"checklabels", store_bit, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
127 {"requiresmount", store_bit, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
128 {"offlineonunmount", store_bit, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
129 {"autoselect", store_bit, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
130 {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
131 {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
132 {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
133 {"maximumchangerwait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
134 {"maximumopenwait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
135 {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
136 {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
137 {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0},
138 {"maximumrewindwait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
139 {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
140 {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
141 {"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
142 {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
143 {"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
144 {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
145 {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
146 {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
147 {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
148 {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
149 {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
150 {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
151 {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
152 {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
153 {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
154 {"labeltype", store_label, ITEM(res_dev.label_type), 0, 0, 0},
155 {NULL, NULL, {0}, 0, 0, 0}
158 /* Autochanger definition */
159 static RES_ITEM changer_items[] = {
160 {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
161 {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
162 {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
163 {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
164 {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
165 {NULL, NULL, {0}, 0, 0, 0}
169 // {"mountanonymousvolumes", store_bit, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
172 /* Message resource */
173 extern RES_ITEM msgs_items[];
176 /* This is the master resource definition */
177 RES_TABLE resources[] = {
178 {"director", dir_items, R_DIRECTOR},
179 {"storage", store_items, R_STORAGE},
180 {"device", dev_items, R_DEVICE},
181 {"messages", msgs_items, R_MSGS},
182 {"autochanger", changer_items, R_AUTOCHANGER},
189 * device type device code = token
196 static s_kw dev_types[] = {
197 {"file", B_FILE_DEV},
198 {"tape", B_TAPE_DEV},
200 {"fifo", B_FIFO_DEV},
206 * Store Device Type (File, FIFO, Tape, DVD)
209 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
213 token = lex_get_token(lc, T_NAME);
214 /* Store the label pass 2 so that type is defined */
215 for (i=0; dev_types[i].name; i++) {
216 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
217 *(int *)(item->value) = dev_types[i].token;
223 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
226 set_bit(index, res_all.hdr.item_present);
230 /* Dump contents of resource */
231 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
233 URES *res = (URES *)reshdr;
238 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
241 sendit(sock, _("dump_resource type=%d\n"), type);
242 if (type < 0) { /* no recursion */
248 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
251 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
252 res->res_store.hdr.name,
253 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
254 get_first_port_host_order(res->res_store.sdaddrs),
255 get_first_port_host_order(res->res_store.sddaddrs),
256 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
257 if (res->res_store.sdaddrs) {
258 foreach_dlist(p, res->res_store.sdaddrs) {
259 sendit(sock, " SDaddr=%s SDport=%d\n",
260 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
263 if (res->res_store.sddaddrs) {
264 foreach_dlist(p, res->res_store.sddaddrs) {
265 sendit(sock, " SDDaddr=%s SDDport=%d\n",
266 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
271 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
272 res->res_dev.hdr.name,
273 res->res_dev.media_type, res->res_dev.device_name,
274 res->res_dev.label_type);
275 sendit(sock, " rew_wait=%" lld " min_bs=%d max_bs=%d chgr_wait=%" lld "\n",
276 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
277 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
278 sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
279 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
280 res->res_dev.max_volume_size);
281 sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
282 res->res_dev.max_file_size, res->res_dev.volume_capacity);
283 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
284 sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
285 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
286 if (res->res_dev.changer_res) {
287 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
289 bstrncpy(buf, " ", sizeof(buf));
290 if (res->res_dev.cap_bits & CAP_EOF) {
291 bstrncat(buf, "CAP_EOF ", sizeof(buf));
293 if (res->res_dev.cap_bits & CAP_BSR) {
294 bstrncat(buf, "CAP_BSR ", sizeof(buf));
296 if (res->res_dev.cap_bits & CAP_BSF) {
297 bstrncat(buf, "CAP_BSF ", sizeof(buf));
299 if (res->res_dev.cap_bits & CAP_FSR) {
300 bstrncat(buf, "CAP_FSR ", sizeof(buf));
302 if (res->res_dev.cap_bits & CAP_FSF) {
303 bstrncat(buf, "CAP_FSF ", sizeof(buf));
305 if (res->res_dev.cap_bits & CAP_EOM) {
306 bstrncat(buf, "CAP_EOM ", sizeof(buf));
308 if (res->res_dev.cap_bits & CAP_REM) {
309 bstrncat(buf, "CAP_REM ", sizeof(buf));
311 if (res->res_dev.cap_bits & CAP_RACCESS) {
312 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
314 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
315 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
317 if (res->res_dev.cap_bits & CAP_LABEL) {
318 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
320 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
321 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
323 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
324 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
326 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
327 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
329 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
330 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
332 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
333 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
335 bstrncat(buf, "\n", sizeof(buf));
340 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
341 res->res_changer.hdr.name,
342 res->res_changer.changer_name, res->res_changer.changer_command);
343 foreach_alist(dev, res->res_changer.device) {
344 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
346 bstrncat(buf, "\n", sizeof(buf));
350 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
351 if (res->res_msgs.mail_cmd)
352 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
353 if (res->res_msgs.operator_cmd)
354 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
357 sendit(sock, _("Warning: unknown resource type %d\n"), type);
360 if (recurse && res->res_dir.hdr.next)
361 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
365 * Free memory of resource.
366 * NB, we don't need to worry about freeing any references
367 * to other resources as they will be freed when that
368 * resource chain is traversed. Mainly we worry about freeing
369 * allocated strings (names).
371 void free_resource(RES *sres, int type)
374 URES *res = (URES *)sres;
379 /* common stuff -- free the resource name */
380 nres = (RES *)res->res_dir.hdr.next;
381 if (res->res_dir.hdr.name) {
382 free(res->res_dir.hdr.name);
384 if (res->res_dir.hdr.desc) {
385 free(res->res_dir.hdr.desc);
391 if (res->res_dir.password) {
392 free(res->res_dir.password);
394 if (res->res_dir.address) {
395 free(res->res_dir.address);
397 if (res->res_dir.tls_ctx) {
398 free_tls_context(res->res_dir.tls_ctx);
400 if (res->res_dir.tls_ca_certfile) {
401 free(res->res_dir.tls_ca_certfile);
403 if (res->res_dir.tls_ca_certdir) {
404 free(res->res_dir.tls_ca_certdir);
406 if (res->res_dir.tls_certfile) {
407 free(res->res_dir.tls_certfile);
409 if (res->res_dir.tls_keyfile) {
410 free(res->res_dir.tls_keyfile);
412 if (res->res_dir.tls_dhfile) {
413 free(res->res_dir.tls_dhfile);
415 if (res->res_dir.tls_allowed_cns) {
416 delete res->res_dir.tls_allowed_cns;
420 if (res->res_changer.changer_name) {
421 free(res->res_changer.changer_name);
423 if (res->res_changer.changer_command) {
424 free(res->res_changer.changer_command);
426 if (res->res_changer.device) {
427 delete res->res_changer.device;
431 if (res->res_store.sdaddrs) {
432 free_addresses(res->res_store.sdaddrs);
434 if (res->res_store.sddaddrs) {
435 free_addresses(res->res_store.sddaddrs);
437 if (res->res_store.working_directory) {
438 free(res->res_store.working_directory);
440 if (res->res_store.pid_directory) {
441 free(res->res_store.pid_directory);
443 if (res->res_store.subsys_directory) {
444 free(res->res_store.subsys_directory);
446 if (res->res_store.scripts_directory) {
447 free(res->res_store.scripts_directory);
449 if (res->res_store.tls_ctx) {
450 free_tls_context(res->res_store.tls_ctx);
452 if (res->res_store.tls_ca_certfile) {
453 free(res->res_store.tls_ca_certfile);
455 if (res->res_store.tls_ca_certdir) {
456 free(res->res_store.tls_ca_certdir);
458 if (res->res_store.tls_certfile) {
459 free(res->res_store.tls_certfile);
461 if (res->res_store.tls_keyfile) {
462 free(res->res_store.tls_keyfile);
464 if (res->res_store.tls_dhfile) {
465 free(res->res_store.tls_dhfile);
467 if (res->res_store.tls_allowed_cns) {
468 delete res->res_store.tls_allowed_cns;
472 if (res->res_dev.media_type) {
473 free(res->res_dev.media_type);
475 if (res->res_dev.device_name) {
476 free(res->res_dev.device_name);
478 if (res->res_dev.changer_name) {
479 free(res->res_dev.changer_name);
481 if (res->res_dev.changer_command) {
482 free(res->res_dev.changer_command);
484 if (res->res_dev.alert_command) {
485 free(res->res_dev.alert_command);
487 if (res->res_dev.spool_directory) {
488 free(res->res_dev.spool_directory);
490 if (res->res_dev.mount_point) {
491 free(res->res_dev.mount_point);
493 if (res->res_dev.mount_command) {
494 free(res->res_dev.mount_command);
496 if (res->res_dev.unmount_command) {
497 free(res->res_dev.unmount_command);
499 if (res->res_dev.write_part_command) {
500 free(res->res_dev.write_part_command);
502 if (res->res_dev.free_space_command) {
503 free(res->res_dev.free_space_command);
507 if (res->res_msgs.mail_cmd) {
508 free(res->res_msgs.mail_cmd);
510 if (res->res_msgs.operator_cmd) {
511 free(res->res_msgs.operator_cmd);
513 free_msgs_res((MSGS *)res); /* free message resource */
517 Dmsg1(0, _("Unknown resource type %d\n"), type);
520 /* Common stuff again -- free the resource, recurse to next one */
525 free_resource(nres, type);
529 /* Save the new resource by chaining it into the head list for
530 * the resource. If this is pass 2, we update any resource
533 void save_resource(int type, RES_ITEM *items, int pass)
536 int rindex = type - r_first;
541 * Ensure that all required items are present
543 for (i=0; items[i].name; i++) {
544 if (items[i].flags & ITEM_REQUIRED) {
545 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
546 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
547 items[i].name, resources[rindex]);
550 /* If this triggers, take a look at lib/parse_conf.h */
551 if (i >= MAX_RES_ITEMS) {
552 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
556 /* During pass 2, we looked up pointers to all the resources
557 * referrenced in the current resource, , now we
558 * must copy their address from the static record to the allocated
565 /* Resources not containing a resource */
570 /* Resources containing a resource or an alist */
572 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
573 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
575 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
578 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
579 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
581 res->res_store.messages = res_all.res_store.messages;
582 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
585 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
586 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
587 res_all.res_changer.hdr.name);
589 /* we must explicitly copy the device alist pointer */
590 res->res_changer.device = res_all.res_changer.device;
592 * Now update each device in this resource to point back
593 * to the changer resource.
595 foreach_alist(dev, res->res_changer.device) {
596 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
598 if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
600 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
601 be.strerror(errstat));
605 printf(_("Unknown resource type %d\n"), type);
611 if (res_all.res_dir.hdr.name) {
612 free(res_all.res_dir.hdr.name);
613 res_all.res_dir.hdr.name = NULL;
615 if (res_all.res_dir.hdr.desc) {
616 free(res_all.res_dir.hdr.desc);
617 res_all.res_dir.hdr.desc = NULL;
622 /* The following code is only executed on pass 1 */
625 size = sizeof(DIRRES);
628 size = sizeof(STORES);
631 size = sizeof(DEVRES);
637 size = sizeof(AUTOCHANGER);
640 printf(_("Unknown resource type %d\n"), type);
647 res = (URES *)malloc(size);
648 memcpy(res, &res_all, size);
649 if (!res_head[rindex]) {
650 res_head[rindex] = (RES *)res; /* store first entry */
653 /* Add new res to end of chain */
654 for (next=res_head[rindex]; next->next; next=next->next) {
655 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
656 Emsg2(M_ERROR_TERM, 0,
657 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
658 resources[rindex].name, res->res_dir.hdr.name);
661 next->next = (RES *)res;
662 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
663 res->res_dir.hdr.name);