1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2020 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, March MM
25 */
26 /**
27 * @file
28 * Configuration file parser for Bareos Storage daemon
29 */
30
31 #include "include/bareos.h"
32 #include "stored/stored_conf.h"
33 #include "stored/autochanger_resource.h"
34 #include "stored/device_resource.h"
35 #include "stored/stored.h"
36 #include "stored/stored_globals.h"
37 #include "stored/sd_backends.h"
38 #include "lib/address_conf.h"
39 #include "lib/bareos_resource.h"
40 #include "lib/berrno.h"
41 #include "lib/messages_resource.h"
42 #include "lib/resource_item.h"
43 #include "lib/parse_conf.h"
44 #include "lib/tls_resource_items.h"
45 #define NEED_JANSSON_NAMESPACE 1
46 #include "lib/output_formatter.h"
47 #include "lib/json.h"
48 #include "include/auth_types.h"
49 #include "include/jcr.h"
50
51 namespace storagedaemon {
52
53 static BareosResource* sres_head[R_LAST - R_FIRST + 1];
54 static BareosResource** res_head = sres_head;
55
56 static void FreeResource(BareosResource* sres, int type);
57 static bool SaveResource(int type, ResourceItem* items, int pass);
58 static void DumpResource(int type,
59 BareosResource* reshdr,
60 void sendit(void* sock, const char* fmt, ...),
61 void* sock,
62 bool hide_sensitive_data,
63 bool verbose);
64
65 /* the first configuration pass uses this static memory */
66 static DirectorResource* res_dir;
67 static NdmpResource* res_ndmp;
68 static StorageResource* res_store;
69 static DeviceResource* res_dev;
70 static AutochangerResource* res_changer;
71
72 static MessagesResource* res_msgs;
73 #include "lib/messages_resource_items.h"
74
75 /* clang-format off */
76
77 static ResourceItem store_items[] = {
78 {"Name", CFG_TYPE_NAME, ITEM(res_store, resource_name_), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
79 {"Description", CFG_TYPE_STR, ITEM(res_store, description_), 0, 0, NULL, NULL, NULL},
80 {"SdPort", CFG_TYPE_ADDRESSES_PORT, ITEM(res_store, SDaddrs), 0, CFG_ITEM_DEFAULT, SD_DEFAULT_PORT, NULL, NULL},
81 {"SdAddress", CFG_TYPE_ADDRESSES_ADDRESS, ITEM(res_store, SDaddrs), 0, CFG_ITEM_DEFAULT, SD_DEFAULT_PORT, NULL, NULL},
82 {"SdAddresses", CFG_TYPE_ADDRESSES, ITEM(res_store, SDaddrs), 0, CFG_ITEM_DEFAULT, SD_DEFAULT_PORT, NULL, NULL},
83 {"SdSourceAddress", CFG_TYPE_ADDRESSES_ADDRESS, ITEM(res_store, SDsrc_addr), 0, CFG_ITEM_DEFAULT, "0", NULL, NULL},
84 {"WorkingDirectory", CFG_TYPE_DIR, ITEM(res_store, working_directory), 0,
85 CFG_ITEM_DEFAULT | CFG_ITEM_PLATFORM_SPECIFIC, _PATH_BAREOS_WORKINGDIR, NULL, NULL},
86 {"PidDirectory", CFG_TYPE_DIR, ITEM(res_store, pid_directory), 0,
87 CFG_ITEM_DEFAULT | CFG_ITEM_PLATFORM_SPECIFIC, _PATH_BAREOS_PIDDIR, NULL, NULL},
88 {"SubSysDirectory", CFG_TYPE_DIR, ITEM(res_store, subsys_directory), CFG_ITEM_DEPRECATED, 0, NULL, NULL, NULL},
89 #if defined(HAVE_DYNAMIC_SD_BACKENDS)
90 {"BackendDirectory", CFG_TYPE_STR_VECTOR_OF_DIRS, ITEM(res_store, backend_directories), 0,
91 CFG_ITEM_DEFAULT | CFG_ITEM_PLATFORM_SPECIFIC, _PATH_BAREOS_BACKENDDIR, NULL, NULL},
92 #endif
93 {"PluginDirectory", CFG_TYPE_DIR, ITEM(res_store, plugin_directory), 0, 0, NULL, NULL, NULL},
94 {"PluginNames", CFG_TYPE_PLUGIN_NAMES, ITEM(res_store, plugin_names), 0, 0, NULL, NULL, NULL},
95 {"ScriptsDirectory", CFG_TYPE_DIR, ITEM(res_store, scripts_directory), 0, 0, NULL, NULL, NULL},
96 {"MaximumConcurrentJobs", CFG_TYPE_PINT32, ITEM(res_store, MaxConcurrentJobs), 0, CFG_ITEM_DEFAULT, "20", NULL, NULL},
97 {"MaximumConnections", CFG_TYPE_PINT32, ITEM(res_store, MaxConnections), 0, CFG_ITEM_DEFAULT, "42", "15.2.3-", NULL},
98 {"Messages", CFG_TYPE_RES, ITEM(res_store, messages), R_MSGS, 0, NULL, NULL, NULL},
99 {"SdConnectTimeout", CFG_TYPE_TIME, ITEM(res_store, SDConnectTimeout), 0, CFG_ITEM_DEFAULT, "1800" /* 30 minutes */, NULL, NULL},
100 {"FdConnectTimeout", CFG_TYPE_TIME, ITEM(res_store, FDConnectTimeout), 0, CFG_ITEM_DEFAULT, "1800" /* 30 minutes */, NULL, NULL},
101 {"HeartbeatInterval", CFG_TYPE_TIME, ITEM(res_store, heartbeat_interval), 0, CFG_ITEM_DEFAULT, "0", NULL, NULL},
102 {"MaximumNetworkBufferSize", CFG_TYPE_PINT32, ITEM(res_store, max_network_buffer_size), 0, 0, NULL, NULL, NULL},
103 {"ClientConnectWait", CFG_TYPE_TIME, ITEM(res_store, client_wait), 0, CFG_ITEM_DEFAULT, "1800" /* 30 minutes */, NULL, NULL},
104 {"VerId", CFG_TYPE_STR, ITEM(res_store, verid), 0, 0, NULL, NULL, NULL},
105 {"Compatible", CFG_TYPE_BOOL, ITEM(res_store, compatible), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
106 {"MaximumBandwidthPerJob", CFG_TYPE_SPEED, ITEM(res_store, max_bandwidth_per_job), 0, 0, NULL, NULL, NULL},
107 {"AllowBandwidthBursting", CFG_TYPE_BOOL, ITEM(res_store, allow_bw_bursting), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
108 {"NdmpEnable", CFG_TYPE_BOOL, ITEM(res_store, ndmp_enable), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
109 {"NdmpSnooping", CFG_TYPE_BOOL, ITEM(res_store, ndmp_snooping), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
110 {"NdmpLogLevel", CFG_TYPE_PINT32, ITEM(res_store, ndmploglevel), 0, CFG_ITEM_DEFAULT, "4", NULL, NULL},
111 {"NdmpAddress", CFG_TYPE_ADDRESSES_ADDRESS, ITEM(res_store, NDMPaddrs), 0, CFG_ITEM_DEFAULT, "10000", NULL, NULL},
112 {"NdmpAddresses", CFG_TYPE_ADDRESSES, ITEM(res_store, NDMPaddrs), 0, CFG_ITEM_DEFAULT, "10000", NULL, NULL},
113 {"NdmpPort", CFG_TYPE_ADDRESSES_PORT, ITEM(res_store, NDMPaddrs), 0, CFG_ITEM_DEFAULT, "10000", NULL, NULL},
114 {"AutoXFlateOnReplication", CFG_TYPE_BOOL, ITEM(res_store, autoxflateonreplication), 0, CFG_ITEM_DEFAULT, "false", "13.4.0-", NULL},
115 {"AbsoluteJobTimeout", CFG_TYPE_PINT32, ITEM(res_store, jcr_watchdog_time), 0, 0, NULL, NULL, NULL},
116 {"CollectDeviceStatistics", CFG_TYPE_BOOL, ITEM(res_store, collect_dev_stats), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
117 {"CollectJobStatistics", CFG_TYPE_BOOL, ITEM(res_store, collect_job_stats), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
118 {"StatisticsCollectInterval", CFG_TYPE_PINT32, ITEM(res_store, stats_collect_interval), 0, CFG_ITEM_DEFAULT, "30", NULL, NULL},
119 {"DeviceReserveByMediaType", CFG_TYPE_BOOL, ITEM(res_store, device_reserve_by_mediatype), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
120 {"FileDeviceConcurrentRead", CFG_TYPE_BOOL, ITEM(res_store, filedevice_concurrent_read), 0, CFG_ITEM_DEFAULT, "false", NULL, NULL},
121 {"SecureEraseCommand", CFG_TYPE_STR, ITEM(res_store, secure_erase_cmdline), 0, 0, NULL, "15.2.1-",
122 "Specify command that will be called when bareos unlinks files."},
123 {"LogTimestampFormat", CFG_TYPE_STR, ITEM(res_store, log_timestamp_format), 0, 0, NULL, "15.2.3-", NULL},
124 TLS_COMMON_CONFIG(res_store),
125 TLS_CERT_CONFIG(res_store),
126 {nullptr, 0, 0, nullptr, 0, 0, nullptr, nullptr, nullptr}
127 };
128
129 static ResourceItem dir_items[] = {
130 {"Name", CFG_TYPE_NAME, ITEM(res_dir, resource_name_), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
131 {"Description", CFG_TYPE_STR, ITEM(res_dir, description_), 0, 0, NULL, NULL, NULL},
132 {"Password", CFG_TYPE_AUTOPASSWORD, ITEM(res_dir, password_), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
133 {"Monitor", CFG_TYPE_BOOL, ITEM(res_dir, monitor), 0, 0, NULL, NULL, NULL},
134 {"MaximumBandwidthPerJob", CFG_TYPE_SPEED, ITEM(res_dir, max_bandwidth_per_job), 0, 0, NULL, NULL, NULL},
135 {"KeyEncryptionKey", CFG_TYPE_AUTOPASSWORD, ITEM(res_dir, keyencrkey), 1, 0, NULL, NULL, NULL},
136 TLS_COMMON_CONFIG(res_dir),
137 TLS_CERT_CONFIG(res_dir),
138 {nullptr, 0, 0, nullptr, 0, 0, nullptr, nullptr, nullptr}
139 };
140
141 static ResourceItem ndmp_items[] = {
142 {"Name", CFG_TYPE_NAME, ITEM(res_ndmp, resource_name_), 0, CFG_ITEM_REQUIRED, 0, NULL, NULL},
143 {"Description", CFG_TYPE_STR, ITEM(res_ndmp, description_), 0, 0, 0, NULL, NULL},
144 {"Username", CFG_TYPE_STR, ITEM(res_ndmp, username), 0, CFG_ITEM_REQUIRED, 0, NULL, NULL},
145 {"Password", CFG_TYPE_AUTOPASSWORD, ITEM(res_ndmp, password), 0, CFG_ITEM_REQUIRED, 0, NULL, NULL},
146 {"AuthType", CFG_TYPE_AUTHTYPE, ITEM(res_ndmp, AuthType), 0, CFG_ITEM_DEFAULT, "None", NULL, NULL},
147 {"LogLevel", CFG_TYPE_PINT32, ITEM(res_ndmp, LogLevel), 0, CFG_ITEM_DEFAULT, "4", NULL, NULL},
148 {nullptr, 0, 0, nullptr, 0, 0, nullptr, nullptr, nullptr}
149 };
150
151 static ResourceItem dev_items[] = {
152 {"Name", CFG_TYPE_NAME, ITEM(res_dev, resource_name_), 0, CFG_ITEM_REQUIRED, NULL, NULL, "Unique identifier of the resource."},
153 {"Description", CFG_TYPE_STR, ITEM(res_dev, description_), 0, 0, NULL, NULL,
154 "The Description directive provides easier human recognition, but is not used by Bareos directly."},
155 {"MediaType", CFG_TYPE_STRNAME, ITEM(res_dev, media_type), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
156 {"DeviceType", CFG_TYPE_DEVTYPE, ITEM(res_dev, dev_type), 0, 0, NULL, NULL, NULL},
157 {"ArchiveDevice", CFG_TYPE_STRNAME, ITEM(res_dev, device_name), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
158 {"DeviceOptions", CFG_TYPE_STR, ITEM(res_dev, device_options), 0, 0, NULL, "15.2.0-", NULL},
159 {"DiagnosticDevice", CFG_TYPE_STRNAME, ITEM(res_dev, diag_device_name), 0, 0, NULL, NULL, NULL},
160 {"HardwareEndOfFile", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_EOF, CFG_ITEM_DEFAULT, "on", NULL, NULL},
161 {"HardwareEndOfMedium", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_EOM, CFG_ITEM_DEFAULT, "on", NULL, NULL},
162 {"BackwardSpaceRecord", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_BSR, CFG_ITEM_DEFAULT, "on", NULL, NULL},
163 {"BackwardSpaceFile", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_BSF, CFG_ITEM_DEFAULT, "on", NULL, NULL},
164 {"BsfAtEom", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_BSFATEOM, CFG_ITEM_DEFAULT, "off", NULL, NULL},
165 {"TwoEof", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_TWOEOF, CFG_ITEM_DEFAULT, "off", NULL, NULL},
166 {"ForwardSpaceRecord", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_FSR, CFG_ITEM_DEFAULT, "on", NULL, NULL},
167 {"ForwardSpaceFile", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_FSF, CFG_ITEM_DEFAULT, "on", NULL, NULL},
168 {"FastForwardSpaceFile", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_FASTFSF, CFG_ITEM_DEFAULT, "on", NULL, NULL},
169 {"RemovableMedia", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_REM, CFG_ITEM_DEFAULT, "on", NULL, NULL},
170 {"RandomAccess", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_RACCESS, CFG_ITEM_DEFAULT, "off", NULL, NULL},
171 {"AutomaticMount", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_AUTOMOUNT, CFG_ITEM_DEFAULT, "off", NULL, NULL},
172 {"LabelMedia", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_LABEL, CFG_ITEM_DEFAULT, "off", NULL, NULL},
173 {"AlwaysOpen", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_ALWAYSOPEN, CFG_ITEM_DEFAULT, "on", NULL, NULL},
174 {"Autochanger", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_AUTOCHANGER, CFG_ITEM_DEFAULT, "off", NULL, NULL},
175 {"CloseOnPoll", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_CLOSEONPOLL, CFG_ITEM_DEFAULT, "off", NULL, NULL},
176 {"BlockPositioning", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_POSITIONBLOCKS, CFG_ITEM_DEFAULT, "on", NULL, NULL},
177 {"UseMtiocget", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_MTIOCGET, CFG_ITEM_DEFAULT, "on", NULL, NULL},
178 {"CheckLabels", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_CHECKLABELS, CFG_ITEM_DEFAULT, "off", NULL, NULL},
179 {"RequiresMount", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_REQMOUNT, CFG_ITEM_DEFAULT, "off", NULL, NULL},
180 {"OfflineOnUnmount", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_OFFLINEUNMOUNT, CFG_ITEM_DEFAULT, "off", NULL, NULL},
181 {"BlockChecksum", CFG_TYPE_BIT, ITEM(res_dev, cap_bits), CAP_BLOCKCHECKSUM, CFG_ITEM_DEFAULT, "on", NULL, NULL},
182 {"AutoSelect", CFG_TYPE_BOOL, ITEM(res_dev, autoselect), 0, CFG_ITEM_DEFAULT, "true", NULL, NULL},
183 {"ChangerDevice", CFG_TYPE_STRNAME, ITEM(res_dev, changer_name), 0, 0, NULL, NULL, NULL},
184 {"ChangerCommand", CFG_TYPE_STRNAME, ITEM(res_dev, changer_command), 0, 0, NULL, NULL, NULL},
185 {"AlertCommand", CFG_TYPE_STRNAME, ITEM(res_dev, alert_command), 0, 0, NULL, NULL, NULL},
186 {"MaximumChangerWait", CFG_TYPE_TIME, ITEM(res_dev, max_changer_wait), 0, CFG_ITEM_DEFAULT,
187 "300" /* 5 minutes */, NULL, NULL},
188 {"MaximumOpenWait", CFG_TYPE_TIME, ITEM(res_dev, max_open_wait), 0, CFG_ITEM_DEFAULT, "300" /* 5 minutes */, NULL, NULL},
189 {"MaximumOpenVolumes", CFG_TYPE_PINT32, ITEM(res_dev, max_open_vols), 0, CFG_ITEM_DEFAULT, "1", NULL, NULL},
190 {"MaximumNetworkBufferSize", CFG_TYPE_PINT32, ITEM(res_dev, max_network_buffer_size), 0, 0, NULL, NULL, NULL},
191 {"VolumePollInterval", CFG_TYPE_TIME, ITEM(res_dev, vol_poll_interval), 0, CFG_ITEM_DEFAULT, "300" /* 5 minutes */, NULL, NULL},
192 {"MaximumRewindWait", CFG_TYPE_TIME, ITEM(res_dev, max_rewind_wait), 0, CFG_ITEM_DEFAULT,
193 "300" /* 5 minutes */, NULL, NULL},
194 {"LabelBlockSize", CFG_TYPE_PINT32, ITEM(res_dev, label_block_size), 0, CFG_ITEM_DEFAULT,
195 "64512" /* DEFAULT_BLOCK_SIZE */, NULL, NULL},
196 {"MinimumBlockSize", CFG_TYPE_PINT32, ITEM(res_dev, min_block_size), 0, 0, NULL, NULL, NULL},
197 {"MaximumBlockSize", CFG_TYPE_MAXBLOCKSIZE, ITEM(res_dev, max_block_size), 0, 0, NULL, NULL, NULL},
198 {"MaximumVolumeSize", CFG_TYPE_SIZE64, ITEM(res_dev, max_volume_size), 0, CFG_ITEM_DEPRECATED, NULL, NULL, NULL},
199 {"MaximumFileSize", CFG_TYPE_SIZE64, ITEM(res_dev, max_file_size), 0, CFG_ITEM_DEFAULT, "1000000000", NULL, NULL},
200 {"VolumeCapacity", CFG_TYPE_SIZE64, ITEM(res_dev, volume_capacity), 0, 0, NULL, NULL, NULL},
201 {"MaximumConcurrentJobs", CFG_TYPE_PINT32, ITEM(res_dev, max_concurrent_jobs), 0, 0, NULL, NULL, NULL},
202 {"SpoolDirectory", CFG_TYPE_DIR, ITEM(res_dev, spool_directory), 0, 0, NULL, NULL, NULL},
203 {"MaximumSpoolSize", CFG_TYPE_SIZE64, ITEM(res_dev, max_spool_size), 0, 0, NULL, NULL, NULL},
204 {"MaximumJobSpoolSize", CFG_TYPE_SIZE64, ITEM(res_dev, max_job_spool_size), 0, 0, NULL, NULL, NULL},
205 {"DriveIndex", CFG_TYPE_PINT16, ITEM(res_dev, drive_index), 0, 0, NULL, NULL, NULL},
206 {"MaximumPartSize", CFG_TYPE_SIZE64, ITEM(res_dev, max_part_size), 0, CFG_ITEM_DEPRECATED, NULL, NULL, NULL},
207 {"MountPoint", CFG_TYPE_STRNAME, ITEM(res_dev, mount_point), 0, 0, NULL, NULL, NULL},
208 {"MountCommand", CFG_TYPE_STRNAME, ITEM(res_dev, mount_command), 0, 0, NULL, NULL, NULL},
209 {"UnmountCommand", CFG_TYPE_STRNAME, ITEM(res_dev, unmount_command), 0, 0, NULL, NULL, NULL},
210 {"WritePartCommand", CFG_TYPE_STRNAME, ITEM(res_dev, write_part_command), 0, CFG_ITEM_DEPRECATED, NULL, NULL, NULL},
211 {"FreeSpaceCommand", CFG_TYPE_STRNAME, ITEM(res_dev, free_space_command), 0, CFG_ITEM_DEPRECATED, NULL, NULL, NULL},
212 {"LabelType", CFG_TYPE_LABEL, ITEM(res_dev, label_type), 0, 0, NULL, NULL, NULL},
213 {"NoRewindOnClose", CFG_TYPE_BOOL, ITEM(res_dev, norewindonclose), 0, CFG_ITEM_DEFAULT, "true", NULL, NULL},
214 {"DriveTapeAlertEnabled", CFG_TYPE_BOOL, ITEM(res_dev, drive_tapealert_enabled), 0, 0, NULL, NULL, NULL},
215 {"DriveCryptoEnabled", CFG_TYPE_BOOL, ITEM(res_dev, drive_crypto_enabled), 0, 0, NULL, NULL, NULL},
216 {"QueryCryptoStatus", CFG_TYPE_BOOL, ITEM(res_dev, query_crypto_status), 0, 0, NULL, NULL, NULL},
217 {"AutoDeflate", CFG_TYPE_IODIRECTION, ITEM(res_dev, autodeflate), 0, 0, NULL, "13.4.0-", NULL},
218 {"AutoDeflateAlgorithm", CFG_TYPE_CMPRSALGO, ITEM(res_dev, autodeflate_algorithm), 0, 0, NULL, "13.4.0-", NULL},
219 {"AutoDeflateLevel", CFG_TYPE_PINT16, ITEM(res_dev, autodeflate_level), 0, CFG_ITEM_DEFAULT, "6", "13.4.0-",NULL},
220 {"AutoInflate", CFG_TYPE_IODIRECTION, ITEM(res_dev, autoinflate), 0, 0, NULL, "13.4.0-", NULL},
221 {"CollectStatistics", CFG_TYPE_BOOL, ITEM(res_dev, collectstats), 0, CFG_ITEM_DEFAULT, "true", NULL, NULL},
222 {"EofOnErrorIsEot", CFG_TYPE_BOOL, ITEM(res_dev, eof_on_error_is_eot), 0, CFG_ITEM_DEFAULT, NULL, "18.2.4-",
223 "If Yes, Bareos will treat any read error at an end-of-file mark as end-of-tape. You should only set "
224 "this option if your tape-drive fails to detect end-of-tape while reading."},
225 {"Count", CFG_TYPE_PINT32, ITEM(res_dev, count), 0, CFG_ITEM_DEFAULT, "1", NULL, "If Count is set to (1 < Count < 10000), "
226 "this resource will be multiplied Count times. The names of multiplied resources will have a serial number (0001, 0002, ...) attached. "
227 "If set to 1 only this single resource will be used and its name will not be altered."},
228 {nullptr, 0, 0, nullptr, 0, 0, nullptr, nullptr, nullptr}
229 };
230
231 static ResourceItem autochanger_items[] = {
232 {"Name", CFG_TYPE_NAME, ITEM(res_changer, resource_name_), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
233 {"Description", CFG_TYPE_STR, ITEM(res_changer, description_), 0, 0, NULL, NULL, NULL},
234 {"Device", CFG_TYPE_ALIST_RES, ITEM(res_changer, device), R_DEVICE, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
235 {"ChangerDevice", CFG_TYPE_STRNAME, ITEM(res_changer, changer_name), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
236 {"ChangerCommand", CFG_TYPE_STRNAME, ITEM(res_changer, changer_command), 0, CFG_ITEM_REQUIRED, NULL, NULL, NULL},
237 {nullptr, 0, 0, nullptr, 0, 0, nullptr, nullptr, nullptr}
238 };
239
240 static ResourceTable resources[] = {
241 {"Director", dir_items, R_DIRECTOR, sizeof(DirectorResource),
__anon7447261b0102() 242 []() { res_dir = new DirectorResource(); }, reinterpret_cast<BareosResource**>(&res_dir)},
243 {"Ndmp", ndmp_items, R_NDMP, sizeof(NdmpResource),
__anon7447261b0202() 244 []() { res_ndmp = new NdmpResource(); }, reinterpret_cast<BareosResource**>(&res_ndmp)},
245 {"Storage", store_items, R_STORAGE, sizeof(StorageResource),
__anon7447261b0302() 246 []() { res_store = new StorageResource(); }, reinterpret_cast<BareosResource**>(&res_store)},
247 {"Device", dev_items, R_DEVICE, sizeof(DeviceResource),
__anon7447261b0402() 248 []() { res_dev = new DeviceResource(); }, reinterpret_cast<BareosResource**>(&res_dev)},
249 {"Messages", msgs_items, R_MSGS, sizeof(MessagesResource),
__anon7447261b0502() 250 []() { res_msgs = new MessagesResource(); }, reinterpret_cast<BareosResource**>(&res_msgs)},
251 {"Autochanger", autochanger_items, R_AUTOCHANGER, sizeof(AutochangerResource),
__anon7447261b0602() 252 []() { res_changer = new AutochangerResource(); }, reinterpret_cast<BareosResource**>(&res_changer)},
253 {nullptr, nullptr, 0, 0, nullptr, nullptr}};
254
255 /* clang-format on */
256
257 static struct s_kw authentication_methods[] = {{"None", AT_NONE},
258 {"Clear", AT_CLEAR},
259 {"MD5", AT_MD5},
260 {NULL, 0}};
261
262 static s_kw device_types[] = {
263 {"file", B_FILE_DEV},
264 {"tape", B_TAPE_DEV},
265 {"fifo", B_FIFO_DEV},
266 {"vtl", B_VTL_DEV},
267 {"gfapi", B_GFAPI_DEV},
268 /* compatibility: object have been renamed to droplet */
269 {"object", B_DROPLET_DEV},
270 {"droplet", B_DROPLET_DEV},
271 {"rados", B_RADOS_DEV},
272 {"cephfs", B_CEPHFS_DEV},
273 {"elasto", B_ELASTO_DEV},
274 {NULL, 0}};
275
276 static s_kw io_directions[] = {{"in", IO_DIRECTION_IN},
277 {"out", IO_DIRECTION_OUT},
278 {"both", IO_DIRECTION_INOUT},
279 {NULL, 0}};
280
281 static s_kw compression_algorithms[] = {
282 {"gzip", COMPRESS_GZIP}, {"lzo", COMPRESS_LZO1X},
283 {"lzfast", COMPRESS_FZFZ}, {"lz4", COMPRESS_FZ4L},
284 {"lz4hc", COMPRESS_FZ4H}, {NULL, 0}};
285
StoreAuthenticationType(LEX * lc,ResourceItem * item,int index,int pass)286 static void StoreAuthenticationType(LEX* lc,
287 ResourceItem* item,
288 int index,
289 int pass)
290 {
291 int i;
292
293 LexGetToken(lc, BCT_NAME);
294 /*
295 * Store the type both pass 1 and pass 2
296 */
297 for (i = 0; authentication_methods[i].name; i++) {
298 if (Bstrcasecmp(lc->str, authentication_methods[i].name)) {
299 SetItemVariable<uint32_t>(*item, authentication_methods[i].token);
300 i = 0;
301 break;
302 }
303 }
304 if (i != 0) {
305 scan_err1(lc, _("Expected a Authentication Type keyword, got: %s"),
306 lc->str);
307 }
308 ScanToEol(lc);
309 SetBit(index, (*item->allocated_resource)->item_present_);
310 ClearBit(index, (*item->allocated_resource)->inherit_content_);
311 }
312
313 /**
314 * Store password either clear if for NDMP or MD5 hashed for native.
315 */
StoreAutopassword(LEX * lc,ResourceItem * item,int index,int pass)316 static void StoreAutopassword(LEX* lc, ResourceItem* item, int index, int pass)
317 {
318 switch ((*item->allocated_resource)->rcode_) {
319 case R_DIRECTOR:
320 /*
321 * As we need to store both clear and MD5 hashed within the same
322 * resource class we use the item->code as a hint default is 0
323 * and for clear we need a code of 1.
324 */
325 switch (item->code) {
326 case 1:
327 my_config->StoreResource(CFG_TYPE_CLEARPASSWORD, lc, item, index,
328 pass);
329 break;
330 default:
331 my_config->StoreResource(CFG_TYPE_MD5PASSWORD, lc, item, index, pass);
332 break;
333 }
334 break;
335 case R_NDMP:
336 my_config->StoreResource(CFG_TYPE_CLEARPASSWORD, lc, item, index, pass);
337 break;
338 default:
339 my_config->StoreResource(CFG_TYPE_MD5PASSWORD, lc, item, index, pass);
340 break;
341 }
342 }
343
StoreDeviceType(LEX * lc,ResourceItem * item,int index,int pass)344 static void StoreDeviceType(LEX* lc, ResourceItem* item, int index, int pass)
345 {
346 int i;
347
348 LexGetToken(lc, BCT_NAME);
349 /*
350 * Store the label pass 2 so that type is defined
351 */
352 for (i = 0; device_types[i].name; i++) {
353 if (Bstrcasecmp(lc->str, device_types[i].name)) {
354 SetItemVariable<uint32_t>(*item, device_types[i].token);
355 i = 0;
356 break;
357 }
358 }
359 if (i != 0) {
360 scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
361 }
362 ScanToEol(lc);
363 SetBit(index, (*item->allocated_resource)->item_present_);
364 ClearBit(index, (*item->allocated_resource)->inherit_content_);
365 }
366
367 /**
368 * Store Maximum Block Size, and check it is not greater than MAX_BLOCK_LENGTH
369 */
StoreMaxblocksize(LEX * lc,ResourceItem * item,int index,int pass)370 static void StoreMaxblocksize(LEX* lc, ResourceItem* item, int index, int pass)
371 {
372 my_config->StoreResource(CFG_TYPE_SIZE32, lc, item, index, pass);
373 if (GetItemVariable<uint32_t>(*item) > MAX_BLOCK_LENGTH) {
374 scan_err2(lc,
375 _("Maximum Block Size configured value %u is greater than "
376 "allowed maximum: %u"),
377 GetItemVariable<uint32_t>(*item), MAX_BLOCK_LENGTH);
378 }
379 }
380
381 /**
382 * Store the IO direction on a certain device.
383 */
StoreIoDirection(LEX * lc,ResourceItem * item,int index,int pass)384 static void StoreIoDirection(LEX* lc, ResourceItem* item, int index, int pass)
385 {
386 int i;
387
388 LexGetToken(lc, BCT_NAME);
389 for (i = 0; io_directions[i].name; i++) {
390 if (Bstrcasecmp(lc->str, io_directions[i].name)) {
391 SetItemVariable<uint16_t>(*item, io_directions[i].token & 0xffff);
392 i = 0;
393 break;
394 }
395 }
396 if (i != 0) {
397 scan_err1(lc, _("Expected a IO direction keyword, got: %s"), lc->str);
398 }
399 ScanToEol(lc);
400 SetBit(index, (*item->allocated_resource)->item_present_);
401 ClearBit(index, (*item->allocated_resource)->inherit_content_);
402 }
403
404 /**
405 * Store the compression algorithm to use on a certain device.
406 */
StoreCompressionalgorithm(LEX * lc,ResourceItem * item,int index,int pass)407 static void StoreCompressionalgorithm(LEX* lc,
408 ResourceItem* item,
409 int index,
410 int pass)
411 {
412 int i;
413
414 LexGetToken(lc, BCT_NAME);
415 for (i = 0; compression_algorithms[i].name; i++) {
416 if (Bstrcasecmp(lc->str, compression_algorithms[i].name)) {
417 SetItemVariable<uint32_t>(*item,
418 compression_algorithms[i].token & 0xffffffff);
419 i = 0;
420 break;
421 }
422 }
423 if (i != 0) {
424 scan_err1(lc, _("Expected a Compression algorithm keyword, got: %s"),
425 lc->str);
426 }
427 ScanToEol(lc);
428 SetBit(index, (*item->allocated_resource)->item_present_);
429 ClearBit(index, (*item->allocated_resource)->inherit_content_);
430 }
431
432 /**
433 * callback function for init_resource
434 * See ../lib/parse_conf.c, function InitResource, for more generic handling.
435 */
InitResourceCb(ResourceItem * item,int pass)436 static void InitResourceCb(ResourceItem* item, int pass)
437 {
438 switch (pass) {
439 case 1:
440 switch (item->type) {
441 case CFG_TYPE_AUTHTYPE:
442 for (int i = 0; authentication_methods[i].name; i++) {
443 if (Bstrcasecmp(item->default_value,
444 authentication_methods[i].name)) {
445 SetItemVariable<uint32_t>(*item, authentication_methods[i].token);
446 }
447 }
448 break;
449 default:
450 break;
451 }
452 break;
453 default:
454 break;
455 }
456 }
457
ParseConfigCb(LEX * lc,ResourceItem * item,int index,int pass)458 static void ParseConfigCb(LEX* lc, ResourceItem* item, int index, int pass)
459 {
460 switch (item->type) {
461 case CFG_TYPE_AUTOPASSWORD:
462 StoreAutopassword(lc, item, index, pass);
463 break;
464 case CFG_TYPE_AUTHTYPE:
465 StoreAuthenticationType(lc, item, index, pass);
466 break;
467 case CFG_TYPE_DEVTYPE:
468 StoreDeviceType(lc, item, index, pass);
469 break;
470 case CFG_TYPE_MAXBLOCKSIZE:
471 StoreMaxblocksize(lc, item, index, pass);
472 break;
473 case CFG_TYPE_IODIRECTION:
474 StoreIoDirection(lc, item, index, pass);
475 break;
476 case CFG_TYPE_CMPRSALGO:
477 StoreCompressionalgorithm(lc, item, index, pass);
478 break;
479 default:
480 break;
481 }
482 }
483
MultiplyDevice(DeviceResource & multiplied_device_resource)484 static void MultiplyDevice(DeviceResource& multiplied_device_resource)
485 {
486 /* append 0001 to the name of the existing resource */
487 multiplied_device_resource.CreateAndAssignSerialNumber(1);
488
489 multiplied_device_resource.multiplied_device_resource =
490 std::addressof(multiplied_device_resource);
491
492 uint32_t count = multiplied_device_resource.count - 1;
493
494 /* create the copied devices */
495 for (uint32_t i = 0; i < count; i++) {
496 DeviceResource* copied_device_resource =
497 new DeviceResource(multiplied_device_resource);
498
499 /* append 0002, 0003, ... */
500 copied_device_resource->CreateAndAssignSerialNumber(i + 2);
501
502 copied_device_resource->multiplied_device_resource =
503 std::addressof(multiplied_device_resource);
504 copied_device_resource->count = 0;
505
506 my_config->AppendToResourcesChain(copied_device_resource,
507 copied_device_resource->rcode_);
508
509 if (copied_device_resource->changer_res) {
510 if (copied_device_resource->changer_res->device) {
511 copied_device_resource->changer_res->device->append(
512 copied_device_resource);
513 }
514 }
515 }
516 }
517
MultiplyConfiguredDevices(ConfigurationParser & my_config)518 static void MultiplyConfiguredDevices(ConfigurationParser& my_config)
519 {
520 BareosResource* p = nullptr;
521 while ((p = my_config.GetNextRes(R_DEVICE, p))) {
522 DeviceResource& d = dynamic_cast<DeviceResource&>(*p);
523 if (d.count > 1) { MultiplyDevice(d); }
524 }
525 }
526
ConfigBeforeCallback(ConfigurationParser & my_config)527 static void ConfigBeforeCallback(ConfigurationParser& my_config)
528 {
529 std::map<int, std::string> map{
530 {R_DIRECTOR, "R_DIRECTOR"},
531 {R_JOB, "R_JOB"}, /* needed for client name conversion */
532 {R_NDMP, "R_NDMP"},
533 {R_STORAGE, "R_STORAGE"},
534 {R_MSGS, "R_MSGS"},
535 {R_DEVICE, "R_DEVICE"},
536 {R_AUTOCHANGER, "R_AUTOCHANGER"},
537 {R_CLIENT, "R_CLIENT"}}; /* needed for network dump */
538 my_config.InitializeQualifiedResourceNameTypeConverter(map);
539 }
540
CheckDropletDevices(ConfigurationParser & my_config)541 static void CheckDropletDevices(ConfigurationParser& my_config)
542 {
543 BareosResource* p = nullptr;
544
545 while ((p = my_config.GetNextRes(R_DEVICE, p)) != nullptr) {
546 DeviceResource* device = dynamic_cast<DeviceResource*>(p);
547 if (device && device->dev_type == B_DROPLET_DEV) {
548 if (device->max_concurrent_jobs == 0) {
549 /*
550 * 0 is the general default. However, for this dev_type, only 1 works.
551 * So we set it to this value.
552 */
553 Jmsg1(nullptr, M_WARNING, 0,
554 _("device %s is set to the default 'Maximum Concurrent Jobs' = "
555 "1.\n"),
556 device->device_name);
557 device->max_concurrent_jobs = 1;
558 } else if (device->max_concurrent_jobs > 1) {
559 Jmsg2(nullptr, M_ERROR_TERM, 0,
560 _("device %s is configured with 'Maximum Concurrent Jobs' = %d, "
561 "however only 1 is supported.\n"),
562 device->device_name, device->max_concurrent_jobs);
563 }
564 }
565 }
566 }
567
ConfigReadyCallback(ConfigurationParser & my_config)568 static void ConfigReadyCallback(ConfigurationParser& my_config)
569 {
570 MultiplyConfiguredDevices(my_config);
571 CheckDropletDevices(my_config);
572 }
573
InitSdConfig(const char * configfile,int exit_code)574 ConfigurationParser* InitSdConfig(const char* configfile, int exit_code)
575 {
576 ConfigurationParser* config = new ConfigurationParser(
577 configfile, nullptr, nullptr, InitResourceCb, ParseConfigCb, nullptr,
578 exit_code, R_FIRST, R_LAST, resources, res_head,
579 default_config_filename.c_str(), "bareos-sd.d", ConfigBeforeCallback,
580 ConfigReadyCallback, SaveResource, DumpResource, FreeResource);
581 if (config) { config->r_own_ = R_STORAGE; }
582 return config;
583 }
584
ParseSdConfig(const char * configfile,int exit_code)585 bool ParseSdConfig(const char* configfile, int exit_code)
586 {
587 bool retval;
588
589 retval = my_config->ParseConfig();
590
591 if (retval) {
592 me = (StorageResource*)my_config->GetNextRes(R_STORAGE, NULL);
593 my_config->own_resource_ = me;
594 if (!me) {
595 Emsg1(exit_code, 0,
596 _("No Storage resource defined in %s. Cannot continue.\n"),
597 configfile);
598 return retval;
599 }
600
601 #if defined(HAVE_DYNAMIC_SD_BACKENDS)
602 SdSetBackendDirs(std::move(me->backend_directories));
603 #endif
604 }
605
606 return retval;
607 }
608
609 /**
610 * Print configuration file schema in json format
611 */
612 #ifdef HAVE_JANSSON
PrintConfigSchemaJson(PoolMem & buffer)613 bool PrintConfigSchemaJson(PoolMem& buffer)
614 {
615 ResourceTable* resources = my_config->resources_;
616
617 InitializeJson();
618
619 json_t* json = json_object();
620 json_object_set_new(json, "format-version", json_integer(2));
621 json_object_set_new(json, "component", json_string("bareos-sd"));
622 json_object_set_new(json, "version", json_string(kBareosVersionStrings.Full));
623
624 /*
625 * Resources
626 */
627 json_t* resource = json_object();
628 json_object_set(json, "resource", resource);
629 json_t* bareos_sd = json_object();
630 json_object_set(resource, "bareos-sd", bareos_sd);
631
632 for (int r = 0; resources[r].name; r++) {
633 ResourceTable resource = my_config->resources_[r];
634 json_object_set(bareos_sd, resource.name, json_items(resource.items));
635 }
636
637 PmStrcat(buffer, json_dumps(json, JSON_INDENT(2)));
638 json_decref(json);
639
640 return true;
641 }
642 #else
PrintConfigSchemaJson(PoolMem & buffer)643 bool PrintConfigSchemaJson(PoolMem& buffer)
644 {
645 PmStrcat(buffer, "{ \"success\": false, \"message\": \"not available\" }");
646 return false;
647 }
648 #endif
649
650 #include <cassert>
651
DumpResource_(int type,BareosResource * res,void sendit (void * sock,const char * fmt,...),void * sock,bool hide_sensitive_data,bool verbose)652 static bool DumpResource_(int type,
653 BareosResource* res,
654 void sendit(void* sock, const char* fmt, ...),
655 void* sock,
656 bool hide_sensitive_data,
657 bool verbose)
658 {
659 PoolMem buf;
660 bool recurse = true;
661
662 if (!res) {
663 sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"),
664 my_config->ResToStr(type), type);
665 return false;
666 }
667
668 if (type < 0) { /* no recursion */
669 type = -type;
670 recurse = false;
671 }
672
673 bool buffer_is_valid = true;
674
675 switch (type) {
676 case R_MSGS: {
677 MessagesResource* resclass = dynamic_cast<MessagesResource*>(res);
678 assert(resclass);
679 resclass->PrintConfig(buf, *my_config);
680 break;
681 }
682 case R_DEVICE: {
683 DeviceResource* dev = dynamic_cast<DeviceResource*>(res);
684 assert(dev);
685 buffer_is_valid = dev->PrintConfig(buf, *my_config);
686 break;
687 }
688 case R_AUTOCHANGER: {
689 AutochangerResource* autochanger =
690 dynamic_cast<AutochangerResource*>(res);
691 assert(autochanger);
692 autochanger->PrintConfigToBuffer(buf);
693 break;
694 }
695 default:
696 BareosResource* p = dynamic_cast<BareosResource*>(res);
697 assert(p);
698 p->PrintConfig(buf, *my_config);
699 break;
700 }
701
702 if (buffer_is_valid) { sendit(sock, "%s", buf.c_str()); }
703
704 return recurse;
705 }
706
DumpResource(int type,BareosResource * res,void sendit (void * sock,const char * fmt,...),void * sock,bool hide_sensitive_data,bool verbose)707 static void DumpResource(int type,
708 BareosResource* res,
709 void sendit(void* sock, const char* fmt, ...),
710 void* sock,
711 bool hide_sensitive_data,
712 bool verbose)
713 {
714 bool recurse = true;
715 BareosResource* p = res;
716
717 while (recurse && p) {
718 recurse =
719 DumpResource_(type, p, sendit, sock, hide_sensitive_data, verbose);
720 p = p->next_;
721 }
722 }
723
SaveResource(int type,ResourceItem * items,int pass)724 static bool SaveResource(int type, ResourceItem* items, int pass)
725 {
726 int rindex = type - R_FIRST;
727 int i;
728 int error = 0;
729
730 // Ensure that all required items are present
731 for (i = 0; items[i].name; i++) {
732 if (items[i].flags & CFG_ITEM_REQUIRED) {
733 if (!BitIsSet(i, (*items[i].allocated_resource)->item_present_)) {
734 Emsg2(M_ERROR_TERM, 0,
735 _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
736 items[i].name, resources[rindex].name);
737 }
738 }
739
740 if (i >= MAX_RES_ITEMS) {
741 Emsg1(M_ERROR_TERM, 0, _("Too many items in \"%s\" resource\n"),
742 resources[rindex].name);
743 }
744 }
745
746 // save previously discovered pointers into dynamic memory
747 if (pass == 2) {
748 switch (type) {
749 case R_DEVICE:
750 case R_MSGS:
751 case R_NDMP:
752 // Resources not containing a resource
753 break;
754 case R_DIRECTOR: {
755 DirectorResource* p = dynamic_cast<DirectorResource*>(
756 my_config->GetResWithName(R_DIRECTOR, res_dir->resource_name_));
757 if (!p) {
758 Emsg1(M_ERROR_TERM, 0, _("Cannot find Director resource %s\n"),
759 res_dir->resource_name_);
760 } else {
761 p->tls_cert_.allowed_certificate_common_names_ =
762 std::move(res_dir->tls_cert_.allowed_certificate_common_names_);
763 }
764 break;
765 }
766 case R_STORAGE: {
767 StorageResource* p = dynamic_cast<StorageResource*>(
768 my_config->GetResWithName(R_STORAGE, res_store->resource_name_));
769 if (!p) {
770 Emsg1(M_ERROR_TERM, 0, _("Cannot find Storage resource %s\n"),
771 res_store->resource_name_);
772 } else {
773 p->plugin_names = res_store->plugin_names;
774 p->messages = res_store->messages;
775 p->backend_directories = res_store->backend_directories;
776 p->tls_cert_.allowed_certificate_common_names_ =
777 std::move(res_store->tls_cert_.allowed_certificate_common_names_);
778 }
779 break;
780 }
781 case R_AUTOCHANGER: {
782 AutochangerResource* p =
783 dynamic_cast<AutochangerResource*>(my_config->GetResWithName(
784 R_AUTOCHANGER, res_changer->resource_name_));
785
786 if (!p) {
787 Emsg1(M_ERROR_TERM, 0, _("Cannot find AutoChanger resource %s\n"),
788 res_changer->resource_name_);
789 } else {
790 p->device = res_changer->device;
791
792 DeviceResource* q = nullptr;
793 foreach_alist (q, p->device) {
794 q->changer_res = p;
795 }
796
797 int errstat;
798 if ((errstat = RwlInit(&p->changer_lock, PRIO_SD_ACH_ACCESS)) != 0) {
799 BErrNo be;
800 Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init lock: ERR=%s\n"),
801 be.bstrerror(errstat));
802 }
803 }
804 break;
805 }
806 default:
807 printf(_("Unknown resource type %d\n"), type);
808 error = 1;
809 break;
810 }
811
812 /* resource_name_ was already deep copied during 1. pass
813 * as matter of fact the remaining allocated memory is
814 * redundant and would not be freed in the dynamic resources;
815 *
816 * currently, this is the best place to free that */
817
818 BareosResource* res = *items[0].allocated_resource;
819
820 if (res) {
821 if (res->resource_name_) {
822 free(res->resource_name_);
823 res->resource_name_ = nullptr;
824 }
825 if (res->description_) {
826 free(res->description_);
827 res->description_ = nullptr;
828 }
829 }
830 return (error == 0);
831 }
832
833 if (!error) {
834 BareosResource* new_resource = nullptr;
835 switch (resources[rindex].rcode) {
836 case R_DIRECTOR:
837 new_resource = res_dir;
838 res_dir = nullptr;
839 break;
840 case R_NDMP:
841 new_resource = res_ndmp;
842 res_ndmp = nullptr;
843 break;
844 case R_STORAGE:
845 new_resource = res_store;
846 res_store = nullptr;
847 break;
848 case R_DEVICE:
849 new_resource = res_dev;
850 res_dev = nullptr;
851 break;
852 case R_MSGS:
853 new_resource = res_msgs;
854 res_msgs = nullptr;
855 break;
856 case R_AUTOCHANGER:
857 new_resource = res_changer;
858 res_changer = nullptr;
859 break;
860 default:
861 ASSERT(false);
862 break;
863 }
864 error = my_config->AppendToResourcesChain(new_resource, type) ? 0 : 1;
865 }
866 return (error == 0);
867 } // namespace storagedaemon
868
FreeResource(BareosResource * res,int type)869 static void FreeResource(BareosResource* res, int type)
870 {
871 if (!res) return;
872
873 if (res->resource_name_) {
874 free(res->resource_name_);
875 res->resource_name_ = nullptr;
876 }
877 if (res->description_) {
878 free(res->description_);
879 res->description_ = nullptr;
880 }
881
882 BareosResource* next_ressource = (BareosResource*)res->next_;
883
884 switch (type) {
885 case R_DIRECTOR: {
886 DirectorResource* p = dynamic_cast<DirectorResource*>(res);
887 assert(p);
888 if (p->password_.value) { free(p->password_.value); }
889 if (p->address) { free(p->address); }
890 if (p->keyencrkey.value) { free(p->keyencrkey.value); }
891 delete p;
892 break;
893 }
894 case R_NDMP: {
895 NdmpResource* p = dynamic_cast<NdmpResource*>(res);
896 assert(p);
897 if (p->username) { free(p->username); }
898 if (p->password.value) { free(p->password.value); }
899 delete p;
900 break;
901 }
902 case R_AUTOCHANGER: {
903 AutochangerResource* p = dynamic_cast<AutochangerResource*>(res);
904 assert(p);
905 if (p->changer_name) { free(p->changer_name); }
906 if (p->changer_command) { free(p->changer_command); }
907 if (p->device) { delete p->device; }
908 RwlDestroy(&p->changer_lock);
909 delete p;
910 break;
911 }
912 case R_STORAGE: {
913 StorageResource* p = dynamic_cast<StorageResource*>(res);
914 assert(p);
915 if (p->SDaddrs) { FreeAddresses(p->SDaddrs); }
916 if (p->SDsrc_addr) { FreeAddresses(p->SDsrc_addr); }
917 if (p->NDMPaddrs) { FreeAddresses(p->NDMPaddrs); }
918 if (p->working_directory) { free(p->working_directory); }
919 if (p->pid_directory) { free(p->pid_directory); }
920 if (p->subsys_directory) { free(p->subsys_directory); }
921 if (p->plugin_directory) { free(p->plugin_directory); }
922 if (p->plugin_names) { delete p->plugin_names; }
923 if (p->scripts_directory) { free(p->scripts_directory); }
924 if (p->verid) { free(p->verid); }
925 if (p->secure_erase_cmdline) { free(p->secure_erase_cmdline); }
926 if (p->log_timestamp_format) { free(p->log_timestamp_format); }
927 delete p;
928 break;
929 }
930 case R_DEVICE: {
931 DeviceResource* p = dynamic_cast<DeviceResource*>(res);
932 assert(p);
933 if (p->media_type) { free(p->media_type); }
934 if (p->device_name) { free(p->device_name); }
935 if (p->device_options) { free(p->device_options); }
936 if (p->diag_device_name) { free(p->diag_device_name); }
937 if (p->changer_name) { free(p->changer_name); }
938 if (p->changer_command) { free(p->changer_command); }
939 if (p->alert_command) { free(p->alert_command); }
940 if (p->spool_directory) { free(p->spool_directory); }
941 if (p->mount_point) { free(p->mount_point); }
942 if (p->mount_command) { free(p->mount_command); }
943 if (p->unmount_command) { free(p->unmount_command); }
944 if (p->write_part_command) { free(p->write_part_command); }
945 if (p->free_space_command) { free(p->free_space_command); }
946 delete p;
947 break;
948 }
949 case R_MSGS: {
950 MessagesResource* p = dynamic_cast<MessagesResource*>(res);
951 assert(p);
952 delete p;
953 break;
954 }
955 default:
956 Dmsg1(0, _("Unknown resource type %d\n"), type);
957 break;
958 }
959 if (next_ressource) { my_config->FreeResourceCb_(next_ressource, type); }
960 }
961
962 } /* namespace storagedaemon */
963