Use WERR_FILE_EXISTS which is the equivalent of WERR_ALREADY_EXISTS
[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                           struct smbconf_service ***services)
95 {
96         WERROR werr = WERR_OK;
97         TALLOC_CTX *tmp_ctx = NULL;
98         uint32_t tmp_num_shares;
99         char **tmp_share_names;
100         struct smbconf_service **tmp_services;
101         uint32_t count;
102
103         if ((num_shares == NULL) || (services == NULL)) {
104                 werr = WERR_INVALID_PARAM;
105                 goto done;
106         }
107
108         tmp_ctx = talloc_stackframe();
109
110         werr = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,
111                                        &tmp_share_names);
112         if (!W_ERROR_IS_OK(werr)) {
113                 goto done;
114         }
115
116         tmp_services = TALLOC_ARRAY(tmp_ctx, struct smbconf_service *,
117                                     tmp_num_shares);
118
119         if (tmp_services == NULL) {
120                 werr = WERR_NOMEM;
121                 goto done;
122         }
123
124         for (count = 0; count < tmp_num_shares; count++) {
125                 werr = smbconf_get_share(ctx, tmp_services,
126                                          tmp_share_names[count],
127                                          &tmp_services[count]);
128                 if (!W_ERROR_IS_OK(werr)) {
129                         goto done;
130                 }
131         }
132
133         werr = WERR_OK;
134
135         *num_shares = tmp_num_shares;
136         if (tmp_num_shares > 0) {
137                 *services = talloc_move(mem_ctx, &tmp_services);
138         } else {
139                 *services = NULL;
140         }
141
142 done:
143         TALLOC_FREE(tmp_ctx);
144         return werr;
145 }
146
147 /**
148  * get the list of share names defined in the configuration.
149  */
150 WERROR smbconf_get_share_names(struct smbconf_ctx *ctx,
151                                TALLOC_CTX *mem_ctx,
152                                uint32_t *num_shares,
153                                char ***share_names)
154 {
155         return ctx->ops->get_share_names(ctx, mem_ctx, num_shares,
156                                          share_names);
157 }
158
159 /**
160  * check if a share/service of a given name exists
161  */
162 bool smbconf_share_exists(struct smbconf_ctx *ctx,
163                           const char *servicename)
164 {
165         return ctx->ops->share_exists(ctx, servicename);
166 }
167
168 /**
169  * Add a service if it does not already exist.
170  */
171 WERROR smbconf_create_share(struct smbconf_ctx *ctx,
172                             const char *servicename)
173 {
174         if ((servicename != NULL) && smbconf_share_exists(ctx, servicename)) {
175                 return WERR_FILE_EXISTS;
176         }
177
178         return ctx->ops->create_share(ctx, servicename);
179 }
180
181 /**
182  * get a definition of a share (service) from configuration.
183  */
184 WERROR smbconf_get_share(struct smbconf_ctx *ctx,
185                          TALLOC_CTX *mem_ctx,
186                          const char *servicename,
187                          struct smbconf_service **service)
188 {
189         if (!smbconf_share_exists(ctx, servicename)) {
190                 return WERR_NO_SUCH_SERVICE;
191         }
192
193         return ctx->ops->get_share(ctx, mem_ctx, servicename, service);
194 }
195
196 /**
197  * delete a service from configuration
198  */
199 WERROR smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
200 {
201         if (!smbconf_share_exists(ctx, servicename)) {
202                 return WERR_NO_SUCH_SERVICE;
203         }
204
205         return ctx->ops->delete_share(ctx, servicename);
206 }
207
208 /**
209  * set a configuration parameter to the value provided.
210  */
211 WERROR smbconf_set_parameter(struct smbconf_ctx *ctx,
212                              const char *service,
213                              const char *param,
214                              const char *valstr)
215 {
216         if (!smbconf_share_exists(ctx, service)) {
217                 return WERR_NO_SUCH_SERVICE;
218         }
219
220         return ctx->ops->set_parameter(ctx, service, param, valstr);
221 }
222
223 /**
224  * Set a global parameter
225  * (i.e. a parameter in the [global] service).
226  *
227  * This also creates [global] when it does not exist.
228  */
229 WERROR smbconf_set_global_parameter(struct smbconf_ctx *ctx,
230                                     const char *param, const char *val)
231 {
232         WERROR werr;
233
234         werr = smbconf_global_check(ctx);
235         if (W_ERROR_IS_OK(werr)) {
236                 werr = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val);
237         }
238
239         return werr;
240 }
241
242 /**
243  * get the value of a configuration parameter as a string
244  */
245 WERROR smbconf_get_parameter(struct smbconf_ctx *ctx,
246                              TALLOC_CTX *mem_ctx,
247                              const char *service,
248                              const char *param,
249                              char **valstr)
250 {
251         if (valstr == NULL) {
252                 return WERR_INVALID_PARAM;
253         }
254
255         if (!smbconf_share_exists(ctx, service)) {
256                 return WERR_NO_SUCH_SERVICE;
257         }
258
259         return ctx->ops->get_parameter(ctx, mem_ctx, service, param, valstr);
260 }
261
262 /**
263  * Get the value of a global parameter.
264  *
265  * Create [global] if it does not exist.
266  */
267 WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx,
268                                     TALLOC_CTX *mem_ctx,
269                                     const char *param,
270                                     char **valstr)
271 {
272         WERROR werr;
273
274         werr = smbconf_global_check(ctx);
275         if (W_ERROR_IS_OK(werr)) {
276                 werr = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param,
277                                              valstr);
278         }
279
280         return werr;
281 }
282
283 /**
284  * delete a parameter from configuration
285  */
286 WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx,
287                                 const char *service, const char *param)
288 {
289         if (!smbconf_share_exists(ctx, service)) {
290                 return WERR_NO_SUCH_SERVICE;
291         }
292
293         return ctx->ops->delete_parameter(ctx, service, param);
294 }
295
296 /**
297  * Delete a global parameter.
298  *
299  * Create [global] if it does not exist.
300  */
301 WERROR smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
302                                        const char *param)
303 {
304         WERROR werr;
305
306         werr = smbconf_global_check(ctx);
307         if (W_ERROR_IS_OK(werr)) {
308                 werr = smbconf_delete_parameter(ctx, GLOBAL_NAME, param);
309         }
310
311         return werr;
312 }
313
314 WERROR smbconf_get_includes(struct smbconf_ctx *ctx,
315                             TALLOC_CTX *mem_ctx,
316                             const char *service,
317                             uint32_t *num_includes, char ***includes)
318 {
319         if (!smbconf_share_exists(ctx, service)) {
320                 return WERR_NO_SUCH_SERVICE;
321         }
322
323         return ctx->ops->get_includes(ctx, mem_ctx, service, num_includes,
324                                       includes);
325 }
326
327 WERROR smbconf_get_global_includes(struct smbconf_ctx *ctx,
328                                    TALLOC_CTX *mem_ctx,
329                                    uint32_t *num_includes, char ***includes)
330 {
331         WERROR werr;
332
333         werr = smbconf_global_check(ctx);
334         if (W_ERROR_IS_OK(werr)) {
335                 werr = smbconf_get_includes(ctx, mem_ctx, GLOBAL_NAME,
336                                             num_includes, includes);
337         }
338
339         return werr;
340 }
341
342 WERROR smbconf_set_includes(struct smbconf_ctx *ctx,
343                             const char *service,
344                             uint32_t num_includes, const char **includes)
345 {
346         if (!smbconf_share_exists(ctx, service)) {
347                 return WERR_NO_SUCH_SERVICE;
348         }
349
350         return ctx->ops->set_includes(ctx, service, num_includes, includes);
351 }
352
353 WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx,
354                                    uint32_t num_includes,
355                                    const char **includes)
356 {
357         WERROR werr;
358
359         werr = smbconf_global_check(ctx);
360         if (W_ERROR_IS_OK(werr)) {
361                 werr = smbconf_set_includes(ctx, GLOBAL_NAME,
362                                             num_includes, includes);
363         }
364
365         return werr;
366 }
367
368
369 WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service)
370 {
371         if (!smbconf_share_exists(ctx, service)) {
372                 return WERR_NO_SUCH_SERVICE;
373         }
374
375         return ctx->ops->delete_includes(ctx, service);
376 }
377
378 WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx)
379 {
380         WERROR werr;
381
382         werr = smbconf_global_check(ctx);
383         if (W_ERROR_IS_OK(werr)) {
384                 werr = smbconf_delete_includes(ctx, GLOBAL_NAME);
385         }
386
387         return werr;
388 }