libsmbconf: don't complain with WERR_ALREADY_EXISTS for NULL share in smbconf_create_...
[ira/wip.git] / source3 / lib / smbconf / smbconf.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libsmbconf - Samba configuration library
4  *  Copyright (C) Michael Adam 2007-2008
5  *  Copyright (C) Guenther Deschner 2007
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "smbconf_private.h"
23
24 /**********************************************************************
25  *
26  * internal helper functions
27  *
28  **********************************************************************/
29
30 static WERROR smbconf_global_check(struct smbconf_ctx *ctx)
31 {
32         if (!smbconf_share_exists(ctx, GLOBAL_NAME)) {
33                 return smbconf_create_share(ctx, GLOBAL_NAME);
34         }
35         return WERR_OK;
36 }
37
38
39 /**********************************************************************
40  *
41  * The actual libsmbconf API functions that are exported.
42  *
43  **********************************************************************/
44
45 /**
46  * Close the configuration.
47  */
48 void smbconf_shutdown(struct smbconf_ctx *ctx)
49 {
50         TALLOC_FREE(ctx);
51 }
52
53 /**
54  * Detect changes in the configuration.
55  * The given csn struct is filled with the current csn.
56  * smbconf_changed() can also be used for initial retrieval
57  * of the csn.
58  */
59 bool smbconf_changed(struct smbconf_ctx *ctx, struct smbconf_csn *csn,
60                      const char *service, const char *param)
61 {
62         struct smbconf_csn old_csn;
63
64         if (csn == NULL) {
65                 return false;
66         }
67
68         old_csn = *csn;
69
70         ctx->ops->get_csn(ctx, csn, service, param);
71         return (csn->csn != old_csn.csn);
72 }
73
74 /**
75  * Drop the whole configuration (restarting empty).
76  */
77 WERROR smbconf_drop(struct smbconf_ctx *ctx)
78 {
79         return ctx->ops->drop(ctx);
80 }
81
82 /**
83  * Get the whole configuration as lists of strings with counts:
84  *
85  *  num_shares   : number of shares
86  *  share_names  : list of length num_shares of share names
87  *  num_params   : list of length num_shares of parameter counts for each share
88  *  param_names  : list of lists of parameter names for each share
89  *  param_values : list of lists of parameter values for each share
90  */
91 WERROR smbconf_get_config(struct smbconf_ctx *ctx,
92                           TALLOC_CTX *mem_ctx,
93                           uint32_t *num_shares,
94                           char ***share_names, uint32_t **num_params,
95                           char ****param_names, char ****param_values)
96 {
97         WERROR werr = WERR_OK;
98         TALLOC_CTX *tmp_ctx = NULL;
99         uint32_t tmp_num_shares;
100         char **tmp_share_names;
101         uint32_t *tmp_num_params;
102         char ***tmp_param_names;
103         char ***tmp_param_values;
104         uint32_t count;
105
106         if ((num_shares == NULL) || (share_names == NULL) ||
107             (num_params == NULL) || (param_names == NULL) ||
108             (param_values == NULL))
109         {
110                 werr = WERR_INVALID_PARAM;
111                 goto done;
112         }
113
114         tmp_ctx = talloc_stackframe();
115         if (tmp_ctx == NULL) {
116                 werr = WERR_NOMEM;
117                 goto done;
118         }
119
120         werr = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,
121                                        &tmp_share_names);
122         if (!W_ERROR_IS_OK(werr)) {
123                 goto done;
124         }
125
126         tmp_num_params   = TALLOC_ARRAY(tmp_ctx, uint32_t, tmp_num_shares);
127         tmp_param_names  = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
128         tmp_param_values = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
129
130         if ((tmp_num_params == NULL) || (tmp_param_names == NULL) ||
131             (tmp_param_values == NULL))
132         {
133                 werr = WERR_NOMEM;
134                 goto done;
135         }
136
137         for (count = 0; count < tmp_num_shares; count++) {
138                 werr = smbconf_get_share(ctx, mem_ctx,
139                                          tmp_share_names[count],
140                                          &tmp_num_params[count],
141                                          &tmp_param_names[count],
142                                          &tmp_param_values[count]);
143                 if (!W_ERROR_IS_OK(werr)) {
144                         goto done;
145                 }
146         }
147
148         werr = WERR_OK;
149
150         *num_shares = tmp_num_shares;
151         if (tmp_num_shares > 0) {
152                 *share_names = talloc_move(mem_ctx, &tmp_share_names);
153                 *num_params = talloc_move(mem_ctx, &tmp_num_params);
154                 *param_names = talloc_move(mem_ctx, &tmp_param_names);
155                 *param_values = talloc_move(mem_ctx, &tmp_param_values);
156         } else {
157                 *share_names = NULL;
158                 *num_params = NULL;
159                 *param_names = NULL;
160                 *param_values = NULL;
161         }
162
163 done:
164         TALLOC_FREE(tmp_ctx);
165         return werr;
166 }
167
168 /**
169  * get the list of share names defined in the configuration.
170  */
171 WERROR smbconf_get_share_names(struct smbconf_ctx *ctx,
172                                TALLOC_CTX *mem_ctx,
173                                uint32_t *num_shares,
174                                char ***share_names)
175 {
176         return ctx->ops->get_share_names(ctx, mem_ctx, num_shares,
177                                          share_names);
178 }
179
180 /**
181  * check if a share/service of a given name exists
182  */
183 bool smbconf_share_exists(struct smbconf_ctx *ctx,
184                           const char *servicename)
185 {
186         return ctx->ops->share_exists(ctx, servicename);
187 }
188
189 /**
190  * Add a service if it does not already exist.
191  */
192 WERROR smbconf_create_share(struct smbconf_ctx *ctx,
193                             const char *servicename)
194 {
195         if ((servicename != NULL) && smbconf_share_exists(ctx, servicename)) {
196                 return WERR_ALREADY_EXISTS;
197         }
198
199         return ctx->ops->create_share(ctx, servicename);
200 }
201
202 /**
203  * get a definition of a share (service) from configuration.
204  */
205 WERROR smbconf_get_share(struct smbconf_ctx *ctx,
206                          TALLOC_CTX *mem_ctx,
207                          const char *servicename, uint32_t *num_params,
208                          char ***param_names, char ***param_values)
209 {
210         if (!smbconf_share_exists(ctx, servicename)) {
211                 return WERR_NO_SUCH_SERVICE;
212         }
213
214         return ctx->ops->get_share(ctx, mem_ctx, servicename, num_params,
215                                    param_names, param_values);
216 }
217
218 /**
219  * delete a service from configuration
220  */
221 WERROR smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
222 {
223         if (!smbconf_share_exists(ctx, servicename)) {
224                 return WERR_NO_SUCH_SERVICE;
225         }
226
227         return ctx->ops->delete_share(ctx, servicename);
228 }
229
230 /**
231  * set a configuration parameter to the value provided.
232  */
233 WERROR smbconf_set_parameter(struct smbconf_ctx *ctx,
234                              const char *service,
235                              const char *param,
236                              const char *valstr)
237 {
238         if (!smbconf_share_exists(ctx, service)) {
239                 return WERR_NO_SUCH_SERVICE;
240         }
241
242         return ctx->ops->set_parameter(ctx, service, param, valstr);
243 }
244
245 /**
246  * Set a global parameter
247  * (i.e. a parameter in the [global] service).
248  *
249  * This also creates [global] when it does not exist.
250  */
251 WERROR smbconf_set_global_parameter(struct smbconf_ctx *ctx,
252                                     const char *param, const char *val)
253 {
254         WERROR werr;
255
256         werr = smbconf_global_check(ctx);
257         if (W_ERROR_IS_OK(werr)) {
258                 werr = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val);
259         }
260
261         return werr;
262 }
263
264 /**
265  * get the value of a configuration parameter as a string
266  */
267 WERROR smbconf_get_parameter(struct smbconf_ctx *ctx,
268                              TALLOC_CTX *mem_ctx,
269                              const char *service,
270                              const char *param,
271                              char **valstr)
272 {
273         if (valstr == NULL) {
274                 return WERR_INVALID_PARAM;
275         }
276
277         if (!smbconf_share_exists(ctx, service)) {
278                 return WERR_NO_SUCH_SERVICE;
279         }
280
281         return ctx->ops->get_parameter(ctx, mem_ctx, service, param, valstr);
282 }
283
284 /**
285  * Get the value of a global parameter.
286  *
287  * Create [global] if it does not exist.
288  */
289 WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx,
290                                     TALLOC_CTX *mem_ctx,
291                                     const char *param,
292                                     char **valstr)
293 {
294         WERROR werr;
295
296         werr = smbconf_global_check(ctx);
297         if (W_ERROR_IS_OK(werr)) {
298                 werr = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param,
299                                              valstr);
300         }
301
302         return werr;
303 }
304
305 /**
306  * delete a parameter from configuration
307  */
308 WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx,
309                                 const char *service, const char *param)
310 {
311         if (!smbconf_share_exists(ctx, service)) {
312                 return WERR_NO_SUCH_SERVICE;
313         }
314
315         return ctx->ops->delete_parameter(ctx, service, param);
316 }
317
318 /**
319  * Delete a global parameter.
320  *
321  * Create [global] if it does not exist.
322  */
323 WERROR smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
324                                        const char *param)
325 {
326         WERROR werr;
327
328         werr = smbconf_global_check(ctx);
329         if (W_ERROR_IS_OK(werr)) {
330                 werr = smbconf_delete_parameter(ctx, GLOBAL_NAME, param);
331         }
332
333         return werr;
334 }
335
336 WERROR smbconf_get_includes(struct smbconf_ctx *ctx,
337                             TALLOC_CTX *mem_ctx,
338                             const char *service,
339                             uint32_t *num_includes, char ***includes)
340 {
341         if (!smbconf_share_exists(ctx, service)) {
342                 return WERR_NO_SUCH_SERVICE;
343         }
344
345         return ctx->ops->get_includes(ctx, mem_ctx, service, num_includes,
346                                       includes);
347 }
348
349 WERROR smbconf_get_global_includes(struct smbconf_ctx *ctx,
350                                    TALLOC_CTX *mem_ctx,
351                                    uint32_t *num_includes, char ***includes)
352 {
353         WERROR werr;
354
355         werr = smbconf_global_check(ctx);
356         if (W_ERROR_IS_OK(werr)) {
357                 werr = smbconf_get_includes(ctx, mem_ctx, GLOBAL_NAME,
358                                             num_includes, includes);
359         }
360
361         return werr;
362 }
363
364 WERROR smbconf_set_includes(struct smbconf_ctx *ctx,
365                             const char *service,
366                             uint32_t num_includes, const char **includes)
367 {
368         if (!smbconf_share_exists(ctx, service)) {
369                 return WERR_NO_SUCH_SERVICE;
370         }
371
372         return ctx->ops->set_includes(ctx, service, num_includes, includes);
373 }
374
375 WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx,
376                                    uint32_t num_includes,
377                                    const char **includes)
378 {
379         WERROR werr;
380
381         werr = smbconf_global_check(ctx);
382         if (W_ERROR_IS_OK(werr)) {
383                 werr = smbconf_set_includes(ctx, GLOBAL_NAME,
384                                             num_includes, includes);
385         }
386
387         return werr;
388 }
389
390
391 WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service)
392 {
393         if (!smbconf_share_exists(ctx, service)) {
394                 return WERR_NO_SUCH_SERVICE;
395         }
396
397         return ctx->ops->delete_includes(ctx, service);
398 }
399
400 WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx)
401 {
402         WERROR werr;
403
404         werr = smbconf_global_check(ctx);
405         if (W_ERROR_IS_OK(werr)) {
406                 werr = smbconf_delete_includes(ctx, GLOBAL_NAME);
407         }
408
409         return werr;
410 }