Line data Source code
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 29 : static sbcErr smbconf_global_check(struct smbconf_ctx *ctx)
31 : {
32 29 : if (!smbconf_share_exists(ctx, GLOBAL_NAME)) {
33 5 : return smbconf_create_share(ctx, GLOBAL_NAME);
34 : }
35 :
36 14 : return SBC_ERR_OK;
37 : }
38 :
39 :
40 : /**********************************************************************
41 : *
42 : * The actual libsmbconf API functions that are exported.
43 : *
44 : **********************************************************************/
45 :
46 12 : const char *sbcErrorString(sbcErr error)
47 : {
48 12 : switch (error) {
49 0 : case SBC_ERR_OK:
50 0 : return "SBC_ERR_OK";
51 0 : case SBC_ERR_NOT_IMPLEMENTED:
52 0 : return "SBC_ERR_NOT_IMPLEMENTED";
53 1 : case SBC_ERR_NOT_SUPPORTED:
54 1 : return "SBC_ERR_NOT_SUPPORTED";
55 2 : case SBC_ERR_UNKNOWN_FAILURE:
56 2 : return "SBC_ERR_UNKNOWN_FAILURE";
57 0 : case SBC_ERR_NOMEM:
58 0 : return "SBC_ERR_NOMEM";
59 0 : case SBC_ERR_INVALID_PARAM:
60 0 : return "SBC_ERR_INVALID_PARAM";
61 1 : case SBC_ERR_BADFILE:
62 1 : return "SBC_ERR_BADFILE";
63 5 : case SBC_ERR_NO_SUCH_SERVICE:
64 5 : return "SBC_ERR_NO_SUCH_SERVICE";
65 0 : case SBC_ERR_IO_FAILURE:
66 0 : return "SBC_ERR_IO_FAILURE";
67 0 : case SBC_ERR_CAN_NOT_COMPLETE:
68 0 : return "SBC_ERR_CAN_NOT_COMPLETE";
69 0 : case SBC_ERR_NO_MORE_ITEMS:
70 0 : return "SBC_ERR_NO_MORE_ITEMS";
71 3 : case SBC_ERR_FILE_EXISTS:
72 3 : return "SBC_ERR_FILE_EXISTS";
73 0 : case SBC_ERR_ACCESS_DENIED:
74 0 : return "SBC_ERR_ACCESS_DENIED";
75 : }
76 :
77 0 : return "unknown sbcErr value";
78 : }
79 :
80 :
81 : /**
82 : * Tell whether the backend requires messaging to be set up
83 : * for the backend to work correctly.
84 : */
85 1 : bool smbconf_backend_requires_messaging(struct smbconf_ctx *ctx)
86 : {
87 1 : return ctx->ops->requires_messaging(ctx);
88 : }
89 :
90 : /**
91 : * Tell whether the source is writeable.
92 : */
93 4 : bool smbconf_is_writeable(struct smbconf_ctx *ctx)
94 : {
95 4 : return ctx->ops->is_writeable(ctx);
96 : }
97 :
98 : /**
99 : * Close the configuration.
100 : */
101 593 : void smbconf_shutdown(struct smbconf_ctx *ctx)
102 : {
103 593 : talloc_free(ctx);
104 593 : }
105 :
106 : /**
107 : * Detect changes in the configuration.
108 : * The given csn struct is filled with the current csn.
109 : * smbconf_changed() can also be used for initial retrieval
110 : * of the csn.
111 : */
112 1054 : bool smbconf_changed(struct smbconf_ctx *ctx, struct smbconf_csn *csn,
113 : const char *service, const char *param)
114 : {
115 0 : struct smbconf_csn old_csn;
116 :
117 1054 : if (csn == NULL) {
118 0 : return false;
119 : }
120 :
121 1054 : old_csn = *csn;
122 :
123 1054 : ctx->ops->get_csn(ctx, csn, service, param);
124 1054 : return (csn->csn != old_csn.csn);
125 : }
126 :
127 : /**
128 : * Drop the whole configuration (restarting empty).
129 : */
130 41 : sbcErr smbconf_drop(struct smbconf_ctx *ctx)
131 : {
132 41 : return ctx->ops->drop(ctx);
133 : }
134 :
135 : /**
136 : * Get the whole configuration as lists of strings with counts:
137 : *
138 : * num_shares : number of shares
139 : * share_names : list of length num_shares of share names
140 : * num_params : list of length num_shares of parameter counts for each share
141 : * param_names : list of lists of parameter names for each share
142 : * param_values : list of lists of parameter values for each share
143 : */
144 261 : sbcErr smbconf_get_config(struct smbconf_ctx *ctx,
145 : TALLOC_CTX *mem_ctx,
146 : uint32_t *num_shares,
147 : struct smbconf_service ***services)
148 : {
149 1 : sbcErr err;
150 261 : TALLOC_CTX *tmp_ctx = NULL;
151 1 : uint32_t tmp_num_shares;
152 1 : char **tmp_share_names;
153 1 : struct smbconf_service **tmp_services;
154 1 : uint32_t count;
155 :
156 261 : if ((num_shares == NULL) || (services == NULL)) {
157 0 : err = SBC_ERR_INVALID_PARAM;
158 0 : goto done;
159 : }
160 :
161 261 : tmp_ctx = talloc_stackframe();
162 :
163 261 : err = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,
164 : &tmp_share_names);
165 261 : if (!SBC_ERROR_IS_OK(err)) {
166 0 : goto done;
167 : }
168 :
169 261 : tmp_services = talloc_array(tmp_ctx, struct smbconf_service *,
170 : tmp_num_shares);
171 261 : if (tmp_services == NULL) {
172 0 : err = SBC_ERR_NOMEM;
173 0 : goto done;
174 : }
175 :
176 4146 : for (count = 0; count < tmp_num_shares; count++) {
177 3890 : err = smbconf_get_share(ctx, tmp_services,
178 3885 : tmp_share_names[count],
179 3885 : &tmp_services[count]);
180 3885 : if (!SBC_ERROR_IS_OK(err)) {
181 0 : goto done;
182 : }
183 : }
184 :
185 261 : err = SBC_ERR_OK;
186 :
187 261 : *num_shares = tmp_num_shares;
188 261 : if (tmp_num_shares > 0) {
189 65 : *services = talloc_move(mem_ctx, &tmp_services);
190 : } else {
191 196 : *services = NULL;
192 : }
193 :
194 261 : done:
195 261 : talloc_free(tmp_ctx);
196 261 : return err;
197 : }
198 :
199 : /**
200 : * get the list of share names defined in the configuration.
201 : */
202 271 : sbcErr smbconf_get_share_names(struct smbconf_ctx *ctx,
203 : TALLOC_CTX *mem_ctx,
204 : uint32_t *num_shares,
205 : char ***share_names)
206 : {
207 271 : return ctx->ops->get_share_names(ctx, mem_ctx, num_shares,
208 : share_names);
209 : }
210 :
211 : /**
212 : * check if a share/service of a given name exists
213 : */
214 2915987 : bool smbconf_share_exists(struct smbconf_ctx *ctx,
215 : const char *servicename)
216 : {
217 2915987 : return ctx->ops->share_exists(ctx, servicename);
218 : }
219 :
220 : /**
221 : * Add a service if it does not already exist.
222 : */
223 668 : sbcErr smbconf_create_share(struct smbconf_ctx *ctx,
224 : const char *servicename)
225 : {
226 668 : if ((servicename != NULL) && smbconf_share_exists(ctx, servicename)) {
227 0 : return SBC_ERR_FILE_EXISTS;
228 : }
229 :
230 667 : return ctx->ops->create_share(ctx, servicename);
231 : }
232 :
233 : /**
234 : * create and set the definition for a new share (service).
235 : */
236 439 : sbcErr smbconf_create_set_share(struct smbconf_ctx *ctx,
237 : struct smbconf_service *service)
238 : {
239 7 : sbcErr err, err2;
240 7 : int i;
241 439 : uint32_t num_includes = 0;
242 439 : char **includes = NULL;
243 439 : TALLOC_CTX *tmp_ctx = NULL;
244 :
245 439 : if ((service->name != NULL) && smbconf_share_exists(ctx, service->name))
246 : {
247 0 : return SBC_ERR_FILE_EXISTS;
248 : }
249 :
250 437 : err = smbconf_transaction_start(ctx);
251 437 : if (!SBC_ERROR_IS_OK(err)) {
252 0 : return err;
253 : }
254 :
255 437 : tmp_ctx = talloc_stackframe();
256 :
257 437 : err = smbconf_create_share(ctx, service->name);
258 437 : if (!SBC_ERROR_IS_OK(err)) {
259 0 : goto cancel;
260 : }
261 :
262 2432 : for (i = 0; i < service->num_params; i++) {
263 1995 : if (strequal(service->param_names[i], "include")) {
264 0 : includes = talloc_realloc(tmp_ctx, includes, char *,
265 : num_includes+1);
266 0 : if (includes == NULL) {
267 0 : err = SBC_ERR_NOMEM;
268 0 : goto cancel;
269 : }
270 0 : includes[num_includes] = talloc_strdup(includes,
271 0 : service->param_values[i]);
272 0 : if (includes[num_includes] == NULL) {
273 0 : err = SBC_ERR_NOMEM;
274 0 : goto cancel;
275 : }
276 0 : num_includes++;
277 : } else {
278 2004 : err = smbconf_set_parameter(ctx,
279 1995 : service->name,
280 1995 : service->param_names[i],
281 1995 : service->param_values[i]);
282 1995 : if (!SBC_ERROR_IS_OK(err)) {
283 0 : goto cancel;
284 : }
285 : }
286 : }
287 :
288 437 : err = smbconf_set_includes(ctx, service->name, num_includes,
289 : discard_const_p(const char *, includes));
290 437 : if (!SBC_ERROR_IS_OK(err)) {
291 0 : goto cancel;
292 : }
293 :
294 437 : err = smbconf_transaction_commit(ctx);
295 :
296 437 : goto done;
297 :
298 0 : cancel:
299 0 : err2 = smbconf_transaction_cancel(ctx);
300 0 : if (!SBC_ERROR_IS_OK(err2)) {
301 0 : DEBUG(5, (__location__ ": Error cancelling transaction: %s\n",
302 : sbcErrorString(err2)));
303 : }
304 :
305 0 : done:
306 437 : talloc_free(tmp_ctx);
307 437 : return err;
308 : }
309 :
310 : /**
311 : * get a definition of a share (service) from configuration.
312 : */
313 4945 : sbcErr smbconf_get_share(struct smbconf_ctx *ctx,
314 : TALLOC_CTX *mem_ctx,
315 : const char *servicename,
316 : struct smbconf_service **service)
317 : {
318 4945 : return ctx->ops->get_share(ctx, mem_ctx, servicename, service);
319 : }
320 :
321 : /**
322 : * delete a service from configuration
323 : */
324 20 : sbcErr smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
325 : {
326 20 : if (!smbconf_share_exists(ctx, servicename)) {
327 2 : return SBC_ERR_NO_SUCH_SERVICE;
328 : }
329 :
330 18 : return ctx->ops->delete_share(ctx, servicename);
331 : }
332 :
333 : /**
334 : * set a configuration parameter to the value provided.
335 : */
336 2919 : sbcErr smbconf_set_parameter(struct smbconf_ctx *ctx,
337 : const char *service,
338 : const char *param,
339 : const char *valstr)
340 : {
341 2919 : return ctx->ops->set_parameter(ctx, service, param, valstr);
342 : }
343 :
344 : /**
345 : * Set a global parameter
346 : * (i.e. a parameter in the [global] service).
347 : *
348 : * This also creates [global] when it does not exist.
349 : */
350 11 : sbcErr smbconf_set_global_parameter(struct smbconf_ctx *ctx,
351 : const char *param, const char *val)
352 : {
353 11 : sbcErr err;
354 :
355 11 : err = smbconf_global_check(ctx);
356 11 : if (!SBC_ERROR_IS_OK(err)) {
357 0 : return err;
358 : }
359 11 : err = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val);
360 :
361 11 : return err;
362 : }
363 :
364 : /**
365 : * get the value of a configuration parameter as a string
366 : */
367 6 : sbcErr smbconf_get_parameter(struct smbconf_ctx *ctx,
368 : TALLOC_CTX *mem_ctx,
369 : const char *service,
370 : const char *param,
371 : char **valstr)
372 : {
373 6 : if (valstr == NULL) {
374 0 : return SBC_ERR_INVALID_PARAM;
375 : }
376 :
377 6 : return ctx->ops->get_parameter(ctx, mem_ctx, service, param, valstr);
378 : }
379 :
380 : /**
381 : * Get the value of a global parameter.
382 : *
383 : * Create [global] if it does not exist.
384 : */
385 0 : sbcErr smbconf_get_global_parameter(struct smbconf_ctx *ctx,
386 : TALLOC_CTX *mem_ctx,
387 : const char *param,
388 : char **valstr)
389 : {
390 0 : sbcErr err;
391 :
392 0 : err = smbconf_global_check(ctx);
393 0 : if (!SBC_ERROR_IS_OK(err)) {
394 0 : return err;
395 : }
396 :
397 0 : err = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param,
398 : valstr);
399 :
400 0 : return err;
401 : }
402 :
403 : /**
404 : * delete a parameter from configuration
405 : */
406 7 : sbcErr smbconf_delete_parameter(struct smbconf_ctx *ctx,
407 : const char *service, const char *param)
408 : {
409 7 : return ctx->ops->delete_parameter(ctx, service, param);
410 : }
411 :
412 : /**
413 : * Delete a global parameter.
414 : *
415 : * Create [global] if it does not exist.
416 : */
417 2 : sbcErr smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
418 : const char *param)
419 : {
420 2 : sbcErr err;
421 :
422 2 : err = smbconf_global_check(ctx);
423 2 : if (!SBC_ERROR_IS_OK(err)) {
424 0 : return err;
425 : }
426 2 : err = smbconf_delete_parameter(ctx, GLOBAL_NAME, param);
427 :
428 2 : return err;
429 : }
430 :
431 10 : sbcErr smbconf_get_includes(struct smbconf_ctx *ctx,
432 : TALLOC_CTX *mem_ctx,
433 : const char *service,
434 : uint32_t *num_includes, char ***includes)
435 : {
436 10 : return ctx->ops->get_includes(ctx, mem_ctx, service, num_includes,
437 : includes);
438 : }
439 :
440 8 : sbcErr smbconf_get_global_includes(struct smbconf_ctx *ctx,
441 : TALLOC_CTX *mem_ctx,
442 : uint32_t *num_includes, char ***includes)
443 : {
444 0 : sbcErr err;
445 :
446 8 : err = smbconf_global_check(ctx);
447 8 : if (!SBC_ERROR_IS_OK(err)) {
448 0 : return err;
449 : }
450 8 : err = smbconf_get_includes(ctx, mem_ctx, GLOBAL_NAME,
451 : num_includes, includes);
452 :
453 8 : return err;
454 : }
455 :
456 443 : sbcErr smbconf_set_includes(struct smbconf_ctx *ctx,
457 : const char *service,
458 : uint32_t num_includes, const char **includes)
459 : {
460 443 : return ctx->ops->set_includes(ctx, service, num_includes, includes);
461 : }
462 :
463 4 : sbcErr smbconf_set_global_includes(struct smbconf_ctx *ctx,
464 : uint32_t num_includes,
465 : const char **includes)
466 : {
467 0 : sbcErr err;
468 :
469 4 : err = smbconf_global_check(ctx);
470 4 : if (!SBC_ERROR_IS_OK(err)) {
471 0 : return err;
472 : }
473 4 : err = smbconf_set_includes(ctx, GLOBAL_NAME,
474 : num_includes, includes);
475 :
476 4 : return err;
477 : }
478 :
479 :
480 10 : sbcErr smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service)
481 : {
482 10 : return ctx->ops->delete_includes(ctx, service);
483 : }
484 :
485 4 : sbcErr smbconf_delete_global_includes(struct smbconf_ctx *ctx)
486 : {
487 0 : sbcErr err;
488 :
489 4 : err = smbconf_global_check(ctx);
490 4 : if (!SBC_ERROR_IS_OK(err)) {
491 0 : return err;
492 : }
493 4 : err = smbconf_delete_includes(ctx, GLOBAL_NAME);
494 :
495 4 : return err;
496 : }
497 :
498 717 : sbcErr smbconf_transaction_start(struct smbconf_ctx *ctx)
499 : {
500 717 : return ctx->ops->transaction_start(ctx);
501 : }
502 :
503 715 : sbcErr smbconf_transaction_commit(struct smbconf_ctx *ctx)
504 : {
505 715 : return ctx->ops->transaction_commit(ctx);
506 : }
507 :
508 2 : sbcErr smbconf_transaction_cancel(struct smbconf_ctx *ctx)
509 : {
510 2 : return ctx->ops->transaction_cancel(ctx);
511 : }
|