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);
39 /* We build the current resource here statically,
40 * then move it to dynamic memory */
42 int res_all_size = sizeof(res_all);
44 /* Definition of records permitted within each
45 * resource with the routine to process the record
49 /* Globals for the Storage daemon. */
50 static RES_ITEM store_items[] = {
51 {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
52 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
53 {"sdaddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
54 {"sdaddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
55 {"messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
56 {"sdport", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
57 {"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
58 {"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
59 {"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
60 {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
61 {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
62 {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
63 {"tlsenable", store_yesno, ITEM(res_store.tls_enable), 1, 0, 0},
64 {"tlsrequire", store_yesno, ITEM(res_store.tls_require), 1, 0, 0},
65 {"tlsverifypeer", store_yesno, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 1},
66 {"tlscacertificatefile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
67 {"tlscacertificatedir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
68 {"tlscertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
69 {"tlskey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
70 {"tlsdhfile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
71 {"tlsallowedcn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
72 {NULL, NULL, 0, 0, 0, 0}
76 /* Directors that can speak to the Storage daemon */
77 static RES_ITEM dir_items[] = {
78 {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
79 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
80 {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
81 {"monitor", store_yesno, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
82 {"tlsenable", store_yesno, ITEM(res_dir.tls_enable), 1, 0, 0},
83 {"tlsrequire", store_yesno, ITEM(res_dir.tls_require), 1, 0, 0},
84 {"tlsverifypeer", store_yesno, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 1},
85 {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
86 {"tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
87 {"tlscertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
88 {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
89 {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
90 {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
91 {NULL, NULL, 0, 0, 0, 0}
94 /* Device definition */
95 static RES_ITEM dev_items[] = {
96 {"name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
97 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
98 {"mediatype", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
99 {"devicetype", store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
100 {"archivedevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
101 {"hardwareendoffile", store_yesno, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
102 {"hardwareendofmedium", store_yesno, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
103 {"backwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
104 {"backwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
105 {"bsfateom", store_yesno, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
106 {"twoeof", store_yesno, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
107 {"forwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
108 {"forwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
109 {"fastforwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
110 {"removablemedia", store_yesno, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
111 {"randomaccess", store_yesno, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
112 {"automaticmount", store_yesno, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
113 {"labelmedia", store_yesno, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
114 {"alwaysopen", store_yesno, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
115 {"autochanger", store_yesno, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
116 {"closeonpoll", store_yesno, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
117 {"blockpositioning", store_yesno, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
118 {"usemtiocget", store_yesno, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
119 {"checklabels", store_yesno, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
120 {"requiresmount", store_yesno, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
121 {"offlineonunmount", store_yesno, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
122 {"autoselect", store_yesno, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
123 {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
124 {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
125 {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
126 {"maximumchangerwait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
127 {"maximumopenwait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
128 {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
129 {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
130 {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0},
131 {"maximumrewindwait", store_time, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
132 {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
133 {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
134 {"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
135 {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
136 {"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
137 {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
138 {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
139 {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
140 {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
141 {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
142 {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
143 {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
144 {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
145 {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
146 {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
147 {"labeltype", store_label, ITEM(res_dev.label_type), 0, 0, 0},
148 {NULL, NULL, 0, 0, 0, 0}
151 /* Autochanger definition */
152 static RES_ITEM changer_items[] = {
153 {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
154 {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
155 {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
156 {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
157 {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
158 {NULL, NULL, 0, 0, 0, 0}
162 // {"mountanonymousvolumes", store_yesno, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
165 /* Message resource */
166 extern RES_ITEM msgs_items[];
169 /* This is the master resource definition */
170 RES_TABLE resources[] = {
171 {"director", dir_items, R_DIRECTOR},
172 {"storage", store_items, R_STORAGE},
173 {"device", dev_items, R_DEVICE},
174 {"messages", msgs_items, R_MSGS},
175 {"autochanger", changer_items, R_AUTOCHANGER},
182 * device type device code = token
189 static s_kw dev_types[] = {
190 {"file", B_FILE_DEV},
191 {"tape", B_TAPE_DEV},
193 {"fifo", B_FIFO_DEV},
199 * Store Device Type (File, FIFO, Tape, DVD)
202 static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
206 token = lex_get_token(lc, T_NAME);
207 /* Store the label pass 2 so that type is defined */
208 for (i=0; dev_types[i].name; i++) {
209 if (strcasecmp(lc->str, dev_types[i].name) == 0) {
210 *(int *)(item->value) = dev_types[i].token;
216 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
219 set_bit(index, res_all.hdr.item_present);
223 /* Dump contents of resource */
224 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
226 URES *res = (URES *)reshdr;
231 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
234 sendit(sock, _("dump_resource type=%d\n"), type);
235 if (type < 0) { /* no recursion */
241 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
244 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
245 res->res_store.hdr.name,
246 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
247 get_first_port_host_order(res->res_store.sdaddrs),
248 get_first_port_host_order(res->res_store.sddaddrs),
249 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
250 if (res->res_store.sdaddrs) {
251 foreach_dlist(p, res->res_store.sdaddrs) {
252 sendit(sock, " SDaddr=%s SDport=%d\n",
253 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
256 if (res->res_store.sddaddrs) {
257 foreach_dlist(p, res->res_store.sddaddrs) {
258 sendit(sock, " SDDaddr=%s SDDport=%d\n",
259 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
264 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
265 res->res_dev.hdr.name,
266 res->res_dev.media_type, res->res_dev.device_name,
267 res->res_dev.label_type);
268 sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d chgr_wait=%d\n",
269 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
270 res->res_dev.max_block_size, res->res_dev.max_changer_wait);
271 sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
272 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
273 res->res_dev.max_volume_size);
274 sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
275 res->res_dev.max_file_size, res->res_dev.volume_capacity);
276 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
277 sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
278 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
279 if (res->res_dev.changer_res) {
280 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
282 bstrncpy(buf, " ", sizeof(buf));
283 if (res->res_dev.cap_bits & CAP_EOF) {
284 bstrncat(buf, "CAP_EOF ", sizeof(buf));
286 if (res->res_dev.cap_bits & CAP_BSR) {
287 bstrncat(buf, "CAP_BSR ", sizeof(buf));
289 if (res->res_dev.cap_bits & CAP_BSF) {
290 bstrncat(buf, "CAP_BSF ", sizeof(buf));
292 if (res->res_dev.cap_bits & CAP_FSR) {
293 bstrncat(buf, "CAP_FSR ", sizeof(buf));
295 if (res->res_dev.cap_bits & CAP_FSF) {
296 bstrncat(buf, "CAP_FSF ", sizeof(buf));
298 if (res->res_dev.cap_bits & CAP_EOM) {
299 bstrncat(buf, "CAP_EOM ", sizeof(buf));
301 if (res->res_dev.cap_bits & CAP_REM) {
302 bstrncat(buf, "CAP_REM ", sizeof(buf));
304 if (res->res_dev.cap_bits & CAP_RACCESS) {
305 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
307 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
308 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
310 if (res->res_dev.cap_bits & CAP_LABEL) {
311 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
313 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
314 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
316 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
317 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
319 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
320 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
322 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
323 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
325 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
326 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
328 bstrncat(buf, "\n", sizeof(buf));
333 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
334 res->res_changer.hdr.name,
335 res->res_changer.changer_name, res->res_changer.changer_command);
336 foreach_alist(dev, res->res_changer.device) {
337 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
339 bstrncat(buf, "\n", sizeof(buf));
343 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
344 if (res->res_msgs.mail_cmd)
345 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
346 if (res->res_msgs.operator_cmd)
347 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
350 sendit(sock, _("Warning: unknown resource type %d\n"), type);
353 if (recurse && res->res_dir.hdr.next)
354 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
358 * Free memory of resource.
359 * NB, we don't need to worry about freeing any references
360 * to other resources as they will be freed when that
361 * resource chain is traversed. Mainly we worry about freeing
362 * allocated strings (names).
364 void free_resource(RES *sres, int type)
367 URES *res = (URES *)sres;
372 /* common stuff -- free the resource name */
373 nres = (RES *)res->res_dir.hdr.next;
374 if (res->res_dir.hdr.name) {
375 free(res->res_dir.hdr.name);
377 if (res->res_dir.hdr.desc) {
378 free(res->res_dir.hdr.desc);
384 if (res->res_dir.password) {
385 free(res->res_dir.password);
387 if (res->res_dir.address) {
388 free(res->res_dir.address);
390 if (res->res_dir.tls_ctx) {
391 free_tls_context(res->res_dir.tls_ctx);
393 if (res->res_dir.tls_ca_certfile) {
394 free(res->res_dir.tls_ca_certfile);
396 if (res->res_dir.tls_ca_certdir) {
397 free(res->res_dir.tls_ca_certdir);
399 if (res->res_dir.tls_certfile) {
400 free(res->res_dir.tls_certfile);
402 if (res->res_dir.tls_keyfile) {
403 free(res->res_dir.tls_keyfile);
405 if (res->res_dir.tls_dhfile) {
406 free(res->res_dir.tls_dhfile);
408 if (res->res_dir.tls_allowed_cns) {
409 delete res->res_dir.tls_allowed_cns;
413 if (res->res_changer.changer_name) {
414 free(res->res_changer.changer_name);
416 if (res->res_changer.changer_command) {
417 free(res->res_changer.changer_command);
419 if (res->res_changer.device) {
420 delete res->res_changer.device;
424 if (res->res_store.sdaddrs) {
425 free_addresses(res->res_store.sdaddrs);
427 if (res->res_store.sddaddrs) {
428 free_addresses(res->res_store.sddaddrs);
430 if (res->res_store.working_directory) {
431 free(res->res_store.working_directory);
433 if (res->res_store.pid_directory) {
434 free(res->res_store.pid_directory);
436 if (res->res_store.subsys_directory) {
437 free(res->res_store.subsys_directory);
439 if (res->res_store.scripts_directory) {
440 free(res->res_store.scripts_directory);
442 if (res->res_store.tls_ctx) {
443 free_tls_context(res->res_store.tls_ctx);
445 if (res->res_store.tls_ca_certfile) {
446 free(res->res_store.tls_ca_certfile);
448 if (res->res_store.tls_ca_certdir) {
449 free(res->res_store.tls_ca_certdir);
451 if (res->res_store.tls_certfile) {
452 free(res->res_store.tls_certfile);
454 if (res->res_store.tls_keyfile) {
455 free(res->res_store.tls_keyfile);
457 if (res->res_store.tls_dhfile) {
458 free(res->res_store.tls_dhfile);
460 if (res->res_store.tls_allowed_cns) {
461 delete res->res_store.tls_allowed_cns;
465 if (res->res_dev.media_type) {
466 free(res->res_dev.media_type);
468 if (res->res_dev.device_name) {
469 free(res->res_dev.device_name);
471 if (res->res_dev.changer_name) {
472 free(res->res_dev.changer_name);
474 if (res->res_dev.changer_command) {
475 free(res->res_dev.changer_command);
477 if (res->res_dev.alert_command) {
478 free(res->res_dev.alert_command);
480 if (res->res_dev.spool_directory) {
481 free(res->res_dev.spool_directory);
483 if (res->res_dev.mount_point) {
484 free(res->res_dev.mount_point);
486 if (res->res_dev.mount_command) {
487 free(res->res_dev.mount_command);
489 if (res->res_dev.unmount_command) {
490 free(res->res_dev.unmount_command);
492 if (res->res_dev.write_part_command) {
493 free(res->res_dev.write_part_command);
495 if (res->res_dev.free_space_command) {
496 free(res->res_dev.free_space_command);
500 if (res->res_msgs.mail_cmd) {
501 free(res->res_msgs.mail_cmd);
503 if (res->res_msgs.operator_cmd) {
504 free(res->res_msgs.operator_cmd);
506 free_msgs_res((MSGS *)res); /* free message resource */
510 Dmsg1(0, _("Unknown resource type %d\n"), type);
513 /* Common stuff again -- free the resource, recurse to next one */
518 free_resource(nres, type);
522 /* Save the new resource by chaining it into the head list for
523 * the resource. If this is pass 2, we update any resource
526 void save_resource(int type, RES_ITEM *items, int pass)
529 int rindex = type - r_first;
534 * Ensure that all required items are present
536 for (i=0; items[i].name; i++) {
537 if (items[i].flags & ITEM_REQUIRED) {
538 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
539 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
540 items[i].name, resources[rindex]);
543 /* If this triggers, take a look at lib/parse_conf.h */
544 if (i >= MAX_RES_ITEMS) {
545 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
549 /* During pass 2, we looked up pointers to all the resources
550 * referrenced in the current resource, , now we
551 * must copy their address from the static record to the allocated
558 /* Resources not containing a resource */
563 /* Resources containing a resource or an alist */
565 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
566 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
568 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
571 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
572 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"), res_all.res_dir.hdr.name);
574 res->res_store.messages = res_all.res_store.messages;
575 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
578 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
579 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
580 res_all.res_changer.hdr.name);
582 /* we must explicitly copy the device alist pointer */
583 res->res_changer.device = res_all.res_changer.device;
585 * Now update each device in this resource to point back
586 * to the changer resource.
588 foreach_alist(dev, res->res_changer.device) {
589 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
591 if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
593 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
594 be.strerror(errstat));
598 printf(_("Unknown resource type %d\n"), type);
604 if (res_all.res_dir.hdr.name) {
605 free(res_all.res_dir.hdr.name);
606 res_all.res_dir.hdr.name = NULL;
608 if (res_all.res_dir.hdr.desc) {
609 free(res_all.res_dir.hdr.desc);
610 res_all.res_dir.hdr.desc = NULL;
615 /* The following code is only executed on pass 1 */
618 size = sizeof(DIRRES);
621 size = sizeof(STORES);
624 size = sizeof(DEVRES);
630 size = sizeof(AUTOCHANGER);
633 printf(_("Unknown resource type %d\n"), type);
640 res = (URES *)malloc(size);
641 memcpy(res, &res_all, size);
642 if (!res_head[rindex]) {
643 res_head[rindex] = (RES *)res; /* store first entry */
646 /* Add new res to end of chain */
647 for (next=res_head[rindex]; next->next; next=next->next) {
648 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
649 Emsg2(M_ERROR_TERM, 0,
650 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
651 resources[rindex].name, res->res_dir.hdr.name);
654 next->next = (RES *)res;
655 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
656 res->res_dir.hdr.name);