2 * Configuration file parser for Bacula Storage daemon
4 * Kern Sibbald, March MM
9 Copyright (C) 2000-2005 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 */
38 /* We build the current resource here statically,
39 * then move it to dynamic memory */
41 int res_all_size = sizeof(res_all);
43 /* Definition of records permitted within each
44 * resource with the routine to process the record
48 /* Globals for the Storage daemon. */
49 static RES_ITEM store_items[] = {
50 {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
51 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
52 {"sdaddress", store_addresses_address, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
53 {"sdaddresses", store_addresses, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
54 {"messages", store_res, ITEM(res_store.messages), R_MSGS, 0, 0},
55 {"sdport", store_addresses_port, ITEM(res_store.sdaddrs), 0, ITEM_DEFAULT, 9103},
56 {"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
57 {"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
58 {"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, 0, 0},
59 {"scriptsdirectory", store_dir, ITEM(res_store.scripts_directory), 0, 0, 0},
60 {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 10},
61 {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
62 {"tlsenable", store_yesno, ITEM(res_store.tls_enable), 1, ITEM_DEFAULT, 0},
63 {"tlsrequire", store_yesno, ITEM(res_store.tls_require), 1, ITEM_DEFAULT, 0},
64 {"tlsverifypeer", store_yesno, ITEM(res_store.tls_verify_peer), 1, ITEM_DEFAULT, 0},
65 {"tlscacertificatefile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0},
66 {"tlscacertificatedir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0},
67 {"tlscertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0},
68 {"tlskey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0},
69 {"tlsdhfile", store_dir, ITEM(res_store.tls_dhfile), 0, 0, 0},
70 {"tlsallowedcn", store_alist_str, ITEM(res_store.tls_allowed_cns), 0, 0, 0},
71 {NULL, NULL, 0, 0, 0, 0}
75 /* Directors that can speak to the Storage daemon */
76 static RES_ITEM dir_items[] = {
77 {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
78 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
79 {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
80 {"monitor", store_yesno, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
81 {"tlsenable", store_yesno, ITEM(res_dir.tls_enable), 1, ITEM_DEFAULT, 0},
82 {"tlsrequire", store_yesno, ITEM(res_dir.tls_require), 1, ITEM_DEFAULT, 0},
83 {"tlsverifypeer", store_yesno, ITEM(res_dir.tls_verify_peer), 1, ITEM_DEFAULT, 0},
84 {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
85 {"tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
86 {"tlscertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
87 {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
88 {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
89 {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
90 {NULL, NULL, 0, 0, 0, 0}
93 /* Device definition */
94 static RES_ITEM dev_items[] = {
95 {"name", store_name, ITEM(res_dev.hdr.name), 0, ITEM_REQUIRED, 0},
96 {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
97 {"mediatype", store_strname,ITEM(res_dev.media_type), 0, ITEM_REQUIRED, 0},
98 {"archivedevice", store_strname,ITEM(res_dev.device_name), 0, ITEM_REQUIRED, 0},
99 {"hardwareendoffile", store_yesno, ITEM(res_dev.cap_bits), CAP_EOF, ITEM_DEFAULT, 1},
100 {"hardwareendofmedium", store_yesno, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1},
101 {"backwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1},
102 {"backwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1},
103 {"bsfateom", store_yesno, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0},
104 {"twoeof", store_yesno, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0},
105 {"forwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1},
106 {"forwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1},
107 {"fastforwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1},
108 {"removablemedia", store_yesno, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1},
109 {"randomaccess", store_yesno, ITEM(res_dev.cap_bits), CAP_RACCESS, 0, 0},
110 {"automaticmount", store_yesno, ITEM(res_dev.cap_bits), CAP_AUTOMOUNT, ITEM_DEFAULT, 0},
111 {"labelmedia", store_yesno, ITEM(res_dev.cap_bits), CAP_LABEL, ITEM_DEFAULT, 0},
112 {"alwaysopen", store_yesno, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
113 {"autochanger", store_yesno, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
114 {"closeonpoll", store_yesno, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
115 {"blockpositioning", store_yesno, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
116 {"usemtiocget", store_yesno, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
117 {"checklabels", store_yesno, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
118 {"requiresmount", store_yesno, ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
119 {"offlineonunmount", store_yesno, ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
120 {"autoselect", store_yesno, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
121 {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
122 {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
123 {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
124 {"maximumchangerwait", store_pint, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
125 {"maximumopenwait", store_pint, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
126 {"maximumopenvolumes", store_pint, ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
127 {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
128 {"volumepollinterval", store_time, ITEM(res_dev.vol_poll_interval), 0, 0, 0},
129 {"maximumrewindwait", store_pint, ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
130 {"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
131 {"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
132 {"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
133 {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
134 {"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
135 {"spooldirectory", store_dir, ITEM(res_dev.spool_directory), 0, 0, 0},
136 {"maximumspoolsize", store_size, ITEM(res_dev.max_spool_size), 0, 0, 0},
137 {"maximumjobspoolsize", store_size, ITEM(res_dev.max_job_spool_size), 0, 0, 0},
138 {"driveindex", store_pint, ITEM(res_dev.drive_index), 0, 0, 0},
139 {"maximumpartsize", store_size, ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
140 {"mountpoint", store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
141 {"mountcommand", store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
142 {"unmountcommand", store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
143 {"writepartcommand", store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
144 {"freespacecommand", store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
145 {"labeltype", store_label, ITEM(res_dev.label_type), 0, 0, 0},
146 {NULL, NULL, 0, 0, 0, 0}
149 /* Autochanger definition */
150 static RES_ITEM changer_items[] = {
151 {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0},
152 {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0},
153 {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0},
154 {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0},
155 {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
156 {NULL, NULL, 0, 0, 0, 0}
160 // {"mountanonymousvolumes", store_yesno, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0},
163 /* Message resource */
164 extern RES_ITEM msgs_items[];
167 /* This is the master resource definition */
168 RES_TABLE resources[] = {
169 {"director", dir_items, R_DIRECTOR},
170 {"storage", store_items, R_STORAGE},
171 {"device", dev_items, R_DEVICE},
172 {"messages", msgs_items, R_MSGS},
173 {"autochanger", changer_items, R_AUTOCHANGER},
180 /* Dump contents of resource */
181 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
183 URES *res = (URES *)reshdr;
188 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type);
191 sendit(sock, "dump_resource type=%d\n", type);
192 if (type < 0) { /* no recursion */
198 sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
201 sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
202 res->res_store.hdr.name,
203 NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
204 get_first_port_host_order(res->res_store.sdaddrs),
205 get_first_port_host_order(res->res_store.sddaddrs),
206 edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
207 if (res->res_store.sdaddrs) {
208 foreach_dlist(p, res->res_store.sdaddrs) {
209 sendit(sock, " SDaddr=%s SDport=%d\n",
210 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
213 if (res->res_store.sddaddrs) {
214 foreach_dlist(p, res->res_store.sddaddrs) {
215 sendit(sock, " SDDaddr=%s SDDport=%d\n",
216 p->get_address(buf, sizeof(buf)), p->get_port_host_order());
221 sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
222 res->res_dev.hdr.name,
223 res->res_dev.media_type, res->res_dev.device_name,
224 res->res_dev.label_type);
225 sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n",
226 res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
227 res->res_dev.max_block_size);
228 sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
229 res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
230 res->res_dev.max_volume_size);
231 sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n",
232 res->res_dev.max_file_size, res->res_dev.volume_capacity);
233 sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
234 sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
235 res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
236 if (res->res_dev.changer_res) {
237 sendit(sock, " changer=%p\n", res->res_dev.changer_res);
239 bstrncpy(buf, " ", sizeof(buf));
240 if (res->res_dev.cap_bits & CAP_EOF) {
241 bstrncat(buf, "CAP_EOF ", sizeof(buf));
243 if (res->res_dev.cap_bits & CAP_BSR) {
244 bstrncat(buf, "CAP_BSR ", sizeof(buf));
246 if (res->res_dev.cap_bits & CAP_BSF) {
247 bstrncat(buf, "CAP_BSF ", sizeof(buf));
249 if (res->res_dev.cap_bits & CAP_FSR) {
250 bstrncat(buf, "CAP_FSR ", sizeof(buf));
252 if (res->res_dev.cap_bits & CAP_FSF) {
253 bstrncat(buf, "CAP_FSF ", sizeof(buf));
255 if (res->res_dev.cap_bits & CAP_EOM) {
256 bstrncat(buf, "CAP_EOM ", sizeof(buf));
258 if (res->res_dev.cap_bits & CAP_REM) {
259 bstrncat(buf, "CAP_REM ", sizeof(buf));
261 if (res->res_dev.cap_bits & CAP_RACCESS) {
262 bstrncat(buf, "CAP_RACCESS ", sizeof(buf));
264 if (res->res_dev.cap_bits & CAP_AUTOMOUNT) {
265 bstrncat(buf, "CAP_AUTOMOUNT ", sizeof(buf));
267 if (res->res_dev.cap_bits & CAP_LABEL) {
268 bstrncat(buf, "CAP_LABEL ", sizeof(buf));
270 if (res->res_dev.cap_bits & CAP_ANONVOLS) {
271 bstrncat(buf, "CAP_ANONVOLS ", sizeof(buf));
273 if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
274 bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
276 if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
277 bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
279 if (res->res_dev.cap_bits & CAP_REQMOUNT) {
280 bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
282 if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
283 bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
285 bstrncat(buf, "\n", sizeof(buf));
290 sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n",
291 res->res_changer.hdr.name,
292 res->res_changer.changer_name, res->res_changer.changer_command);
293 foreach_alist(dev, res->res_changer.device) {
294 sendit(sock, " --->Device: name=%s\n", dev->hdr.name);
296 bstrncat(buf, "\n", sizeof(buf));
300 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
301 if (res->res_msgs.mail_cmd)
302 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
303 if (res->res_msgs.operator_cmd)
304 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
307 sendit(sock, _("Warning: unknown resource type %d\n"), type);
310 if (recurse && res->res_dir.hdr.next)
311 dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock);
315 * Free memory of resource.
316 * NB, we don't need to worry about freeing any references
317 * to other resources as they will be freed when that
318 * resource chain is traversed. Mainly we worry about freeing
319 * allocated strings (names).
321 void free_resource(RES *sres, int type)
324 URES *res = (URES *)sres;
329 /* common stuff -- free the resource name */
330 nres = (RES *)res->res_dir.hdr.next;
331 if (res->res_dir.hdr.name) {
332 free(res->res_dir.hdr.name);
334 if (res->res_dir.hdr.desc) {
335 free(res->res_dir.hdr.desc);
341 if (res->res_dir.password) {
342 free(res->res_dir.password);
344 if (res->res_dir.address) {
345 free(res->res_dir.address);
347 if (res->res_dir.tls_ctx) {
348 free_tls_context(res->res_dir.tls_ctx);
350 if (res->res_dir.tls_ca_certfile) {
351 free(res->res_dir.tls_ca_certfile);
353 if (res->res_dir.tls_ca_certdir) {
354 free(res->res_dir.tls_ca_certdir);
356 if (res->res_dir.tls_certfile) {
357 free(res->res_dir.tls_certfile);
359 if (res->res_dir.tls_keyfile) {
360 free(res->res_dir.tls_keyfile);
362 if (res->res_dir.tls_dhfile) {
363 free(res->res_dir.tls_dhfile);
365 if (res->res_dir.tls_allowed_cns) {
366 delete res->res_dir.tls_allowed_cns;
370 if (res->res_changer.changer_name) {
371 free(res->res_changer.changer_name);
373 if (res->res_changer.changer_command) {
374 free(res->res_changer.changer_command);
376 if (res->res_changer.device) {
377 delete res->res_changer.device;
381 if (res->res_store.sdaddrs) {
382 free_addresses(res->res_store.sdaddrs);
384 if (res->res_store.sddaddrs) {
385 free_addresses(res->res_store.sddaddrs);
387 if (res->res_store.working_directory) {
388 free(res->res_store.working_directory);
390 if (res->res_store.pid_directory) {
391 free(res->res_store.pid_directory);
393 if (res->res_store.subsys_directory) {
394 free(res->res_store.subsys_directory);
396 if (res->res_store.scripts_directory) {
397 free(res->res_store.scripts_directory);
399 if (res->res_store.tls_ctx) {
400 free_tls_context(res->res_store.tls_ctx);
402 if (res->res_store.tls_ca_certfile) {
403 free(res->res_store.tls_ca_certfile);
405 if (res->res_store.tls_ca_certdir) {
406 free(res->res_store.tls_ca_certdir);
408 if (res->res_store.tls_certfile) {
409 free(res->res_store.tls_certfile);
411 if (res->res_store.tls_keyfile) {
412 free(res->res_store.tls_keyfile);
414 if (res->res_store.tls_dhfile) {
415 free(res->res_store.tls_dhfile);
417 if (res->res_store.tls_allowed_cns) {
418 delete res->res_store.tls_allowed_cns;
422 if (res->res_dev.media_type) {
423 free(res->res_dev.media_type);
425 if (res->res_dev.device_name) {
426 free(res->res_dev.device_name);
428 if (res->res_dev.changer_name) {
429 free(res->res_dev.changer_name);
431 if (res->res_dev.changer_command) {
432 free(res->res_dev.changer_command);
434 if (res->res_dev.alert_command) {
435 free(res->res_dev.alert_command);
437 if (res->res_dev.spool_directory) {
438 free(res->res_dev.spool_directory);
440 if (res->res_dev.mount_point) {
441 free(res->res_dev.mount_point);
443 if (res->res_dev.mount_command) {
444 free(res->res_dev.mount_command);
446 if (res->res_dev.unmount_command) {
447 free(res->res_dev.unmount_command);
449 if (res->res_dev.write_part_command) {
450 free(res->res_dev.write_part_command);
452 if (res->res_dev.free_space_command) {
453 free(res->res_dev.free_space_command);
457 if (res->res_msgs.mail_cmd) {
458 free(res->res_msgs.mail_cmd);
460 if (res->res_msgs.operator_cmd) {
461 free(res->res_msgs.operator_cmd);
463 free_msgs_res((MSGS *)res); /* free message resource */
467 Dmsg1(0, "Unknown resource type %d\n", type);
470 /* Common stuff again -- free the resource, recurse to next one */
475 free_resource(nres, type);
479 /* Save the new resource by chaining it into the head list for
480 * the resource. If this is pass 2, we update any resource
483 void save_resource(int type, RES_ITEM *items, int pass)
486 int rindex = type - r_first;
491 * Ensure that all required items are present
493 for (i=0; items[i].name; i++) {
494 if (items[i].flags & ITEM_REQUIRED) {
495 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
496 Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
497 items[i].name, resources[rindex]);
500 /* If this triggers, take a look at lib/parse_conf.h */
501 if (i >= MAX_RES_ITEMS) {
502 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"), resources[rindex]);
506 /* During pass 2, we looked up pointers to all the resources
507 * referrenced in the current resource, , now we
508 * must copy their address from the static record to the allocated
515 /* Resources not containing a resource */
520 /* Resources containing a resource or an alist */
522 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
523 Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource \"%s\"\n", res_all.res_dir.hdr.name);
525 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
528 if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
529 Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
531 res->res_store.messages = res_all.res_store.messages;
532 res->res_store.tls_allowed_cns = res_all.res_store.tls_allowed_cns;
535 if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
536 Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n",
537 res_all.res_changer.hdr.name);
539 /* we must explicitly copy the device alist pointer */
540 res->res_changer.device = res_all.res_changer.device;
542 * Now update each device in this resource to point back
543 * to the changer resource.
545 foreach_alist(dev, res->res_changer.device) {
546 dev->changer_res = (AUTOCHANGER *)&res->res_changer;
548 if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
550 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"),
551 be.strerror(errstat));
555 printf("Unknown resource type %d\n", type);
561 if (res_all.res_dir.hdr.name) {
562 free(res_all.res_dir.hdr.name);
563 res_all.res_dir.hdr.name = NULL;
565 if (res_all.res_dir.hdr.desc) {
566 free(res_all.res_dir.hdr.desc);
567 res_all.res_dir.hdr.desc = NULL;
572 /* The following code is only executed on pass 1 */
575 size = sizeof(DIRRES);
578 size = sizeof(STORES);
581 size = sizeof(DEVRES);
587 size = sizeof(AUTOCHANGER);
590 printf("Unknown resource type %d\n", type);
597 res = (URES *)malloc(size);
598 memcpy(res, &res_all, size);
599 if (!res_head[rindex]) {
600 res_head[rindex] = (RES *)res; /* store first entry */
603 /* Add new res to end of chain */
604 for (next=res_head[rindex]; next->next; next=next->next) {
605 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
606 Emsg2(M_ERROR_TERM, 0,
607 _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
608 resources[rindex].name, res->res_dir.hdr.name);
611 next->next = (RES *)res;
612 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
613 res->res_dir.hdr.name);