1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2019 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 #include "lib/parse_conf.h"
25 #include "lib/resource_item.h"
26 #include "lib/edit.h"
27 #include "lib/util.h"
28 #include "lib/address_conf.h"
29 #include "lib/alist.h"
30 
MakePathName(PoolMem & pathname,const char * str)31 static void MakePathName(PoolMem& pathname, const char* str)
32 {
33   PmStrcpy(pathname, str);
34   if (pathname.c_str()[0] != '|') {
35     pathname.check_size(pathname.size() + 1024);
36     DoShellExpansion(pathname.c_str(), pathname.size());
37   }
38 }
39 
CheckIfItemDefaultBitIsSet(ResourceItem * item)40 static void CheckIfItemDefaultBitIsSet(ResourceItem* item)
41 {
42   /*
43    * Items with a default value but without the CFG_ITEM_DEFAULT flag
44    * set are most of the time an indication of a programmers error.
45    */
46   if (item->default_value != nullptr && !(item->flags & CFG_ITEM_DEFAULT)) {
47     Pmsg1(000,
48           _("Found config item %s which has default value but no "
49             "CFG_ITEM_DEFAULT flag set\n"),
50           item->name);
51     item->flags |= CFG_ITEM_DEFAULT;
52   }
53 }
54 
SetResourceDefaultsParserPass1(ResourceItem * item)55 void ConfigurationParser::SetResourceDefaultsParserPass1(ResourceItem* item)
56 {
57   Dmsg3(900, "Item=%s def=%s defval=%s\n", item->name,
58         (item->flags & CFG_ITEM_DEFAULT) ? "yes" : "no",
59         (item->default_value) ? item->default_value : "None");
60 
61 
62   CheckIfItemDefaultBitIsSet(item);
63 
64   if (item->flags & CFG_ITEM_DEFAULT && item->default_value) {
65     switch (item->type) {
66       case CFG_TYPE_BIT:
67         if (Bstrcasecmp(item->default_value, "on")) {
68           char* bitfield = GetItemVariablePointer<char*>(*item);
69           SetBit(item->code, bitfield);
70         } else if (Bstrcasecmp(item->default_value, "off")) {
71           char* bitfield = GetItemVariablePointer<char*>(*item);
72           ClearBit(item->code, bitfield);
73         }
74         break;
75       case CFG_TYPE_BOOL:
76         if (Bstrcasecmp(item->default_value, "yes")
77             || Bstrcasecmp(item->default_value, "true")) {
78           SetItemVariable<bool>(*item, true);
79         } else if (Bstrcasecmp(item->default_value, "no")
80                    || Bstrcasecmp(item->default_value, "false")) {
81           SetItemVariable<bool>(*item, false);
82         }
83         break;
84       case CFG_TYPE_PINT32:
85       case CFG_TYPE_INT32:
86       case CFG_TYPE_SIZE32:
87         SetItemVariable<uint32_t>(*item, str_to_uint64(item->default_value));
88         break;
89       case CFG_TYPE_INT64:
90         SetItemVariable<uint64_t>(*item, str_to_int64(item->default_value));
91         break;
92       case CFG_TYPE_SIZE64:
93         SetItemVariable<uint64_t>(*item, str_to_uint64(item->default_value));
94         break;
95       case CFG_TYPE_SPEED:
96         SetItemVariable<uint64_t>(*item, str_to_uint64(item->default_value));
97         break;
98       case CFG_TYPE_TIME: {
99         SetItemVariable<utime_t>(*item, str_to_int64(item->default_value));
100         break;
101       }
102       case CFG_TYPE_STRNAME:
103       case CFG_TYPE_STR:
104         SetItemVariable<char*>(*item, strdup(item->default_value));
105         break;
106       case CFG_TYPE_STDSTR:
107         SetItemVariable<std::string>(*item, item->default_value);
108         break;
109       case CFG_TYPE_DIR: {
110         PoolMem pathname(PM_FNAME);
111         MakePathName(pathname, item->default_value);
112         SetItemVariable<char*>(*item, strdup(pathname.c_str()));
113         break;
114       }
115       case CFG_TYPE_STDSTRDIR: {
116         PoolMem pathname(PM_FNAME);
117         MakePathName(pathname, item->default_value);
118         SetItemVariable<std::string>(*item, std::string(pathname.c_str()));
119         break;
120       }
121       case CFG_TYPE_ADDRESSES: {
122         dlist** dlistvalue = GetItemVariablePointer<dlist**>(*item);
123         InitDefaultAddresses(dlistvalue, item->default_value);
124         break;
125       }
126       default:
127         if (init_res_) { init_res_(item, 1); }
128         break;
129     }
130   }
131 }
132 
SetResourceDefaultsParserPass2(ResourceItem * item)133 void ConfigurationParser::SetResourceDefaultsParserPass2(ResourceItem* item)
134 {
135   Dmsg3(900, "Item=%s def=%s defval=%s\n", item->name,
136         (item->flags & CFG_ITEM_DEFAULT) ? "yes" : "no",
137         (item->default_value) ? item->default_value : "None");
138 
139   if (item->flags & CFG_ITEM_DEFAULT && item->default_value) {
140     switch (item->type) {
141       case CFG_TYPE_ALIST_STR: {
142         alist** alistvalue = GetItemVariablePointer<alist**>(*item);
143         if (!alistvalue) { *(alistvalue) = new alist(10, owned_by_alist); }
144         (*alistvalue)->append(strdup(item->default_value));
145         break;
146       }
147       case CFG_TYPE_ALIST_DIR: {
148         PoolMem pathname(PM_FNAME);
149         alist** alistvalue = GetItemVariablePointer<alist**>(*item);
150 
151         if (!*alistvalue) { *alistvalue = new alist(10, owned_by_alist); }
152 
153         PmStrcpy(pathname, item->default_value);
154         if (*item->default_value != '|') {
155           int size;
156 
157           /*
158            * Make sure we have enough room
159            */
160           size = pathname.size() + 1024;
161           pathname.check_size(size);
162           DoShellExpansion(pathname.c_str(), pathname.size());
163         }
164         (*alistvalue)->append(strdup(pathname.c_str()));
165         break;
166       }
167       case CFG_TYPE_STR_VECTOR_OF_DIRS: {
168         std::vector<std::string>* list
169             = GetItemVariablePointer<std::vector<std::string>*>(*item);
170 
171         PoolMem pathname(PM_FNAME);
172         PmStrcpy(pathname, item->default_value);
173         if (*item->default_value != '|') {
174           int size = pathname.size() + 1024;
175           pathname.check_size(size);
176           DoShellExpansion(pathname.c_str(), pathname.size());
177         }
178         list->emplace_back(pathname.c_str());
179         break;
180       }
181       default:
182         if (init_res_) { init_res_(item, 2); }
183         break;
184     }
185   }
186 }
187 
SetAllResourceDefaultsIterateOverItems(int rcode,ResourceItem items[],std::function<void (ConfigurationParser &,ResourceItem *)> SetDefaults)188 void ConfigurationParser::SetAllResourceDefaultsIterateOverItems(
189     int rcode,
190     ResourceItem items[],
191     std::function<void(ConfigurationParser&, ResourceItem*)> SetDefaults)
192 {
193   int res_item_index = 0;
194 
195   while (items[res_item_index].name) {
196     SetDefaults(*this, &items[res_item_index]);
197 
198     if (!omit_defaults_) {
199       SetBit(res_item_index,
200              (*items[res_item_index].allocated_resource)->inherit_content_);
201     }
202 
203     res_item_index++;
204 
205     if (res_item_index >= MAX_RES_ITEMS) {
206       Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"),
207             resources_[rcode - r_first_].name);
208     }
209   }
210 }
211 
SetAllResourceDefaultsByParserPass(int rcode,ResourceItem items[],int pass)212 void ConfigurationParser::SetAllResourceDefaultsByParserPass(
213     int rcode,
214     ResourceItem items[],
215     int pass)
216 {
217   std::function<void(ConfigurationParser&, ResourceItem*)> SetDefaults;
218 
219   switch (pass) {
220     case 1:
221       SetDefaults = [rcode](ConfigurationParser& c, ResourceItem* item) {
222         (*item->allocated_resource)->rcode_ = rcode;
223         (*item->allocated_resource)->refcnt_ = 1;
224         c.SetResourceDefaultsParserPass1(item);
225       };
226       break;
227     case 2:
228       SetDefaults = &ConfigurationParser::SetResourceDefaultsParserPass2;
229       break;
230     default:
231       ASSERT(false);
232       break;
233   }
234 
235   SetAllResourceDefaultsIterateOverItems(rcode, items, SetDefaults);
236 }
237 
InitResource(int rcode,ResourceItem items[],int pass,std::function<void ()> ResourceSpecificInitializer)238 void ConfigurationParser::InitResource(
239     int rcode,
240     ResourceItem items[],
241     int pass,
242     std::function<void()> ResourceSpecificInitializer)
243 {
244   if (ResourceSpecificInitializer) { ResourceSpecificInitializer(); }
245 
246   SetAllResourceDefaultsByParserPass(rcode, items, pass);
247 }
248