libsmbconf: add open and close operations to the smbconf_ops.
[Samba.git] / source / lib / smbconf / smbconf.c
blob4a5cbbd48996b5306fbb1529aa3ac2c960178a92
1 /*
2 * Unix SMB/CIFS implementation.
3 * libnet smbconf registry Support
4 * Copyright (C) Michael Adam 2007-2008
5 * Copyright (C) Guenther Deschner 2007
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.
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.
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/>.
21 #include "includes.h"
22 #include "smbconf_private.h"
24 /**********************************************************************
26 * Helper functions (mostly registry related)
28 **********************************************************************/
30 /**
31 * add a string to a talloced array of strings.
33 static WERROR smbconf_add_string_to_array(TALLOC_CTX *mem_ctx,
34 char ***array,
35 uint32_t count,
36 const char *string)
38 char **new_array = NULL;
40 if ((array == NULL) || (string == NULL)) {
41 return WERR_INVALID_PARAM;
44 new_array = TALLOC_REALLOC_ARRAY(mem_ctx, *array, char *, count + 1);
45 if (new_array == NULL) {
46 return WERR_NOMEM;
49 new_array[count] = talloc_strdup(new_array, string);
50 if (new_array[count] == NULL) {
51 TALLOC_FREE(new_array);
52 return WERR_NOMEM;
55 *array = new_array;
57 return WERR_OK;
60 /**
61 * Open a registry key specified by "path"
63 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
64 struct smbconf_ctx *ctx,
65 const char *path,
66 uint32 desired_access,
67 struct registry_key **key)
69 WERROR werr = WERR_OK;
71 if (ctx == NULL) {
72 DEBUG(1, ("Error: configuration is not open!\n"));
73 werr = WERR_INVALID_PARAM;
74 goto done;
77 if (ctx->token == NULL) {
78 DEBUG(1, ("Error: token missing from smbconf_ctx. "
79 "was smbconf_open() called?\n"));
80 werr = WERR_INVALID_PARAM;
81 goto done;
84 if (path == NULL) {
85 DEBUG(1, ("Error: NULL path string given\n"));
86 werr = WERR_INVALID_PARAM;
87 goto done;
90 werr = reg_open_path(mem_ctx, path, desired_access, ctx->token, key);
92 if (!W_ERROR_IS_OK(werr)) {
93 DEBUG(1, ("Error opening registry path '%s': %s\n",
94 path, dos_errstr(werr)));
97 done:
98 return werr;
102 * Open a subkey of KEY_SMBCONF (i.e a service)
104 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
105 struct smbconf_ctx *ctx,
106 const char *servicename,
107 uint32 desired_access,
108 struct registry_key **key)
110 WERROR werr = WERR_OK;
111 char *path = NULL;
113 if (servicename == NULL) {
114 DEBUG(3, ("Error: NULL servicename given.\n"));
115 werr = WERR_INVALID_PARAM;
116 goto done;
119 path = talloc_asprintf(mem_ctx, "%s\\%s", KEY_SMBCONF, servicename);
120 if (path == NULL) {
121 werr = WERR_NOMEM;
122 goto done;
125 werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
127 done:
128 TALLOC_FREE(path);
129 return werr;
133 * open the base key KEY_SMBCONF
135 static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
136 struct smbconf_ctx *ctx,
137 uint32 desired_access,
138 struct registry_key **key)
140 return smbconf_reg_open_path(mem_ctx, ctx, KEY_SMBCONF, desired_access,
141 key);
145 * check if a value exists in a given registry key
147 static bool smbconf_value_exists(struct registry_key *key, const char *param)
149 bool ret = false;
150 WERROR werr = WERR_OK;
151 TALLOC_CTX *ctx = talloc_stackframe();
152 struct registry_value *value = NULL;
154 werr = reg_queryvalue(ctx, key, param, &value);
155 if (W_ERROR_IS_OK(werr)) {
156 ret = true;
159 TALLOC_FREE(ctx);
160 return ret;
164 * create a subkey of KEY_SMBCONF
166 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
167 struct smbconf_ctx *ctx,
168 const char * subkeyname,
169 struct registry_key **newkey)
171 WERROR werr = WERR_OK;
172 struct registry_key *create_parent = NULL;
173 TALLOC_CTX *create_ctx;
174 enum winreg_CreateAction action = REG_ACTION_NONE;
176 /* create a new talloc ctx for creation. it will hold
177 * the intermediate parent key (SMBCONF) for creation
178 * and will be destroyed when leaving this function... */
179 if (!(create_ctx = talloc_stackframe())) {
180 werr = WERR_NOMEM;
181 goto done;
184 werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
185 &create_parent);
186 if (!W_ERROR_IS_OK(werr)) {
187 goto done;
190 werr = reg_createkey(mem_ctx, create_parent, subkeyname,
191 REG_KEY_WRITE, newkey, &action);
192 if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
193 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
194 werr = WERR_ALREADY_EXISTS;
196 if (!W_ERROR_IS_OK(werr)) {
197 DEBUG(5, ("Error creating key %s: %s\n",
198 subkeyname, dos_errstr(werr)));
201 done:
202 TALLOC_FREE(create_ctx);
203 return werr;
207 * add a value to a key.
209 static WERROR smbconf_reg_set_value(struct registry_key *key,
210 const char *valname,
211 const char *valstr)
213 struct registry_value val;
214 WERROR werr = WERR_OK;
215 char *subkeyname;
216 const char *canon_valname;
217 const char *canon_valstr;
219 if (!lp_canonicalize_parameter_with_value(valname, valstr,
220 &canon_valname,
221 &canon_valstr))
223 if (canon_valname == NULL) {
224 DEBUG(5, ("invalid parameter '%s' given\n",
225 valname));
226 } else {
227 DEBUG(5, ("invalid value '%s' given for "
228 "parameter '%s'\n", valstr, valname));
230 werr = WERR_INVALID_PARAM;
231 goto done;
234 ZERO_STRUCT(val);
236 val.type = REG_SZ;
237 val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
238 val.v.sz.len = strlen(canon_valstr) + 1;
240 if (registry_smbconf_valname_forbidden(canon_valname)) {
241 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
242 canon_valname));
243 werr = WERR_INVALID_PARAM;
244 goto done;
247 subkeyname = strrchr_m(key->key->name, '\\');
248 if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
249 DEBUG(5, ("Invalid registry key '%s' given as "
250 "smbconf section.\n", key->key->name));
251 werr = WERR_INVALID_PARAM;
252 goto done;
254 subkeyname++;
255 if (!strequal(subkeyname, GLOBAL_NAME) &&
256 lp_parameter_is_global(valname))
258 DEBUG(5, ("Global paramter '%s' not allowed in "
259 "service definition ('%s').\n", canon_valname,
260 subkeyname));
261 werr = WERR_INVALID_PARAM;
262 goto done;
265 werr = reg_setvalue(key, canon_valname, &val);
266 if (!W_ERROR_IS_OK(werr)) {
267 DEBUG(5, ("Error adding value '%s' to "
268 "key '%s': %s\n",
269 canon_valname, key->key->name, dos_errstr(werr)));
272 done:
273 return werr;
277 * format a registry_value into a string.
279 * This is intended to be used for smbconf registry values,
280 * which are ar stored as REG_SZ values, so the incomplete
281 * handling should be ok.
283 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
284 struct registry_value *value)
286 char *result = NULL;
288 /* alternatively, create a new talloc context? */
289 if (mem_ctx == NULL) {
290 return result;
293 switch (value->type) {
294 case REG_DWORD:
295 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
296 break;
297 case REG_SZ:
298 case REG_EXPAND_SZ:
299 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
300 break;
301 case REG_MULTI_SZ: {
302 uint32 j;
303 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
304 result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
305 result,
306 value->v.multi_sz.strings[j]);
307 if (result == NULL) {
308 break;
311 break;
313 case REG_BINARY:
314 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
315 (int)value->v.binary.length);
316 break;
317 default:
318 result = talloc_asprintf(mem_ctx, "<unprintable>");
319 break;
321 return result;
325 * Get the values of a key as a list of value names
326 * and a list of value strings (ordered)
328 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
329 struct registry_key *key,
330 uint32_t *num_values,
331 char ***value_names,
332 char ***value_strings)
334 TALLOC_CTX *tmp_ctx = NULL;
335 WERROR werr = WERR_OK;
336 uint32_t count;
337 struct registry_value *valvalue = NULL;
338 char *valname = NULL;
339 char **tmp_valnames = NULL;
340 char **tmp_valstrings = NULL;
342 if ((num_values == NULL) || (value_names == NULL) ||
343 (value_strings == NULL))
345 werr = WERR_INVALID_PARAM;
346 goto done;
349 tmp_ctx = talloc_stackframe();
350 if (tmp_ctx == NULL) {
351 werr = WERR_NOMEM;
352 goto done;
355 for (count = 0;
356 W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
357 &valvalue));
358 count++)
360 char *valstring;
362 werr = smbconf_add_string_to_array(tmp_ctx,
363 &tmp_valnames,
364 count, valname);
365 if (!W_ERROR_IS_OK(werr)) {
366 goto done;
369 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
370 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
371 count, valstring);
372 if (!W_ERROR_IS_OK(werr)) {
373 goto done;
376 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
377 goto done;
380 werr = WERR_OK;
382 *num_values = count;
383 if (count > 0) {
384 *value_names = talloc_move(mem_ctx, &tmp_valnames);
385 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
386 } else {
387 *value_names = NULL;
388 *value_strings = NULL;
391 done:
392 TALLOC_FREE(tmp_ctx);
393 return werr;
396 static int smbconf_destroy_ctx(struct smbconf_ctx *ctx)
398 return ctx->ops->close_conf(ctx);
401 static WERROR smbconf_global_check(struct smbconf_ctx *ctx)
403 if (!smbconf_share_exists(ctx, GLOBAL_NAME)) {
404 return smbconf_create_share(ctx, GLOBAL_NAME);
406 return WERR_OK;
410 /**********************************************************************
412 * smbconf operations: registry implementations
414 **********************************************************************/
417 * initialize the registry smbconf backend
419 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx)
421 WERROR werr = WERR_OK;
423 if (!registry_init_smbconf()) {
424 werr = WERR_REG_IO_FAILURE;
425 goto done;
428 werr = ntstatus_to_werror(registry_create_admin_token(ctx,
429 &(ctx->token)));
430 if (!W_ERROR_IS_OK(werr)) {
431 DEBUG(1, ("Error creating admin token\n"));
432 goto done;
435 done:
436 return werr;
439 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
441 return regdb_open();
444 static int smbconf_reg_close(struct smbconf_ctx *ctx)
446 return regdb_close();
450 * Get the change sequence number of the given service/parameter.
451 * service and parameter strings may be NULL.
453 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
454 struct smbconf_csn *csn,
455 const char *service, const char *param)
457 if (csn == NULL) {
458 return;
460 csn->csn = (uint64_t)regdb_get_seqnum();
464 * Drop the whole configuration (restarting empty) - registry version
466 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
468 char *path, *p;
469 WERROR werr = WERR_OK;
470 struct registry_key *parent_key = NULL;
471 struct registry_key *new_key = NULL;
472 TALLOC_CTX* mem_ctx = talloc_stackframe();
473 enum winreg_CreateAction action;
475 path = talloc_strdup(mem_ctx, KEY_SMBCONF);
476 if (path == NULL) {
477 werr = WERR_NOMEM;
478 goto done;
480 p = strrchr(path, '\\');
481 *p = '\0';
482 werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
483 &parent_key);
485 if (!W_ERROR_IS_OK(werr)) {
486 goto done;
489 werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
491 if (!W_ERROR_IS_OK(werr)) {
492 goto done;
495 werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
496 &new_key, &action);
498 done:
499 TALLOC_FREE(mem_ctx);
500 return werr;
504 * get the list of share names defined in the configuration.
505 * registry version.
507 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
508 TALLOC_CTX *mem_ctx,
509 uint32_t *num_shares,
510 char ***share_names)
512 uint32_t count;
513 uint32_t added_count = 0;
514 TALLOC_CTX *tmp_ctx = NULL;
515 WERROR werr = WERR_OK;
516 struct registry_key *key = NULL;
517 char *subkey_name = NULL;
518 char **tmp_share_names = NULL;
520 if ((num_shares == NULL) || (share_names == NULL)) {
521 werr = WERR_INVALID_PARAM;
522 goto done;
525 tmp_ctx = talloc_stackframe();
526 if (tmp_ctx == NULL) {
527 werr = WERR_NOMEM;
528 goto done;
531 /* make sure "global" is always listed first */
532 if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
533 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
534 0, GLOBAL_NAME);
535 if (!W_ERROR_IS_OK(werr)) {
536 goto done;
538 added_count++;
541 werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
542 SEC_RIGHTS_ENUM_SUBKEYS, &key);
543 if (!W_ERROR_IS_OK(werr)) {
544 goto done;
547 for (count = 0;
548 W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
549 &subkey_name, NULL));
550 count++)
552 if (strequal(subkey_name, GLOBAL_NAME)) {
553 continue;
556 werr = smbconf_add_string_to_array(tmp_ctx,
557 &tmp_share_names,
558 added_count,
559 subkey_name);
560 if (!W_ERROR_IS_OK(werr)) {
561 goto done;
563 added_count++;
565 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
566 goto done;
568 werr = WERR_OK;
570 *num_shares = added_count;
571 if (added_count > 0) {
572 *share_names = talloc_move(mem_ctx, &tmp_share_names);
573 } else {
574 *share_names = NULL;
577 done:
578 TALLOC_FREE(tmp_ctx);
579 return werr;
583 * check if a share/service of a given name exists - registry version
585 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
586 const char *servicename)
588 bool ret = false;
589 WERROR werr = WERR_OK;
590 TALLOC_CTX *mem_ctx = talloc_stackframe();
591 struct registry_key *key = NULL;
593 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
594 REG_KEY_READ, &key);
595 if (W_ERROR_IS_OK(werr)) {
596 ret = true;
599 TALLOC_FREE(mem_ctx);
600 return ret;
604 * Add a service if it does not already exist - registry version
606 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
607 const char *servicename)
609 WERROR werr;
610 TALLOC_CTX *mem_ctx = talloc_stackframe();
611 struct registry_key *key = NULL;
613 werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
615 TALLOC_FREE(mem_ctx);
616 return werr;
620 * get a definition of a share (service) from configuration.
622 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
623 TALLOC_CTX *mem_ctx,
624 const char *servicename,
625 uint32_t *num_params,
626 char ***param_names, char ***param_values)
628 WERROR werr = WERR_OK;
629 struct registry_key *key = NULL;
631 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
632 REG_KEY_READ, &key);
633 if (!W_ERROR_IS_OK(werr)) {
634 goto done;
637 werr = smbconf_reg_get_values(mem_ctx, key, num_params,
638 param_names, param_values);
640 done:
641 TALLOC_FREE(key);
642 return werr;
646 * delete a service from configuration
648 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
649 const char *servicename)
651 WERROR werr = WERR_OK;
652 struct registry_key *key = NULL;
653 TALLOC_CTX *mem_ctx = talloc_stackframe();
655 werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
656 if (!W_ERROR_IS_OK(werr)) {
657 goto done;
660 werr = reg_deletekey_recursive(key, key, servicename);
662 done:
663 TALLOC_FREE(mem_ctx);
664 return werr;
668 * set a configuration parameter to the value provided.
670 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
671 const char *service,
672 const char *param,
673 const char *valstr)
675 WERROR werr;
676 struct registry_key *key = NULL;
677 TALLOC_CTX *mem_ctx = talloc_stackframe();
679 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
680 REG_KEY_WRITE, &key);
681 if (!W_ERROR_IS_OK(werr)) {
682 goto done;
685 werr = smbconf_reg_set_value(key, param, valstr);
687 done:
688 TALLOC_FREE(mem_ctx);
689 return werr;
693 * get the value of a configuration parameter as a string
695 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
696 TALLOC_CTX *mem_ctx,
697 const char *service,
698 const char *param,
699 char **valstr)
701 WERROR werr = WERR_OK;
702 struct registry_key *key = NULL;
703 struct registry_value *value = NULL;
705 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
706 REG_KEY_READ, &key);
707 if (!W_ERROR_IS_OK(werr)) {
708 goto done;
711 if (!smbconf_value_exists(key, param)) {
712 werr = WERR_INVALID_PARAM;
713 goto done;
716 werr = reg_queryvalue(mem_ctx, key, param, &value);
717 if (!W_ERROR_IS_OK(werr)) {
718 goto done;
721 *valstr = smbconf_format_registry_value(mem_ctx, value);
723 if (*valstr == NULL) {
724 werr = WERR_NOMEM;
727 done:
728 TALLOC_FREE(key);
729 TALLOC_FREE(value);
730 return werr;
734 * delete a parameter from configuration
736 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
737 const char *service,
738 const char *param)
740 struct registry_key *key = NULL;
741 WERROR werr = WERR_OK;
742 TALLOC_CTX *mem_ctx = talloc_stackframe();
744 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
745 REG_KEY_ALL, &key);
746 if (!W_ERROR_IS_OK(werr)) {
747 goto done;
750 if (!smbconf_value_exists(key, param)) {
751 werr = WERR_INVALID_PARAM;
752 goto done;
755 werr = reg_deletevalue(key, param);
757 done:
758 TALLOC_FREE(mem_ctx);
759 return werr;
762 struct smbconf_ops smbconf_ops_reg = {
763 .init = smbconf_reg_init,
764 .open_conf = smbconf_reg_open,
765 .close_conf = smbconf_reg_close,
766 .get_csn = smbconf_reg_get_csn,
767 .drop = smbconf_reg_drop,
768 .get_share_names = smbconf_reg_get_share_names,
769 .share_exists = smbconf_reg_share_exists,
770 .create_share = smbconf_reg_create_share,
771 .get_share = smbconf_reg_get_share,
772 .delete_share = smbconf_reg_delete_share,
773 .set_parameter = smbconf_reg_set_parameter,
774 .get_parameter = smbconf_reg_get_parameter,
775 .delete_parameter = smbconf_reg_delete_parameter
779 /**********************************************************************
781 * The actual libsmbconf API functions that are exported.
783 **********************************************************************/
786 * Open the configuration.
788 * This should be the first function in a sequence of calls to smbconf
789 * functions:
791 * Upon success, this creates and returns the conf context
792 * that should be passed around in subsequent calls to the other
793 * smbconf functions.
795 * After the work with the configuration is completed, smbconf_close()
796 * should be called.
798 WERROR smbconf_open(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx)
800 WERROR werr = WERR_OK;
801 struct smbconf_ctx *ctx;
803 if (conf_ctx == NULL) {
804 return WERR_INVALID_PARAM;
807 ctx = TALLOC_ZERO_P(mem_ctx, struct smbconf_ctx);
808 if (ctx == NULL) {
809 return WERR_NOMEM;
812 ctx->ops = &smbconf_ops_reg;
814 werr = ctx->ops->init(ctx);
815 if (!W_ERROR_IS_OK(werr)) {
816 goto fail;
819 talloc_set_destructor(ctx, smbconf_destroy_ctx);
821 *conf_ctx = ctx;
822 return werr;
824 fail:
825 TALLOC_FREE(ctx);
826 return werr;
830 * Close the configuration.
832 void smbconf_close(struct smbconf_ctx *ctx)
834 /* this also closes the registry (by destructor): */
835 TALLOC_FREE(ctx);
839 * Detect changes in the configuration.
840 * The given csn struct is filled with the current csn.
841 * smbconf_changed() can also be used for initial retrieval
842 * of the csn.
844 bool smbconf_changed(struct smbconf_ctx *ctx, struct smbconf_csn *csn,
845 const char *service, const char *param)
847 struct smbconf_csn old_csn;
849 if (csn == NULL) {
850 return false;
853 old_csn = *csn;
855 ctx->ops->get_csn(ctx, csn, service, param);
856 return (csn->csn != old_csn.csn);
860 * Drop the whole configuration (restarting empty).
862 WERROR smbconf_drop(struct smbconf_ctx *ctx)
864 return ctx->ops->drop(ctx);
868 * Get the whole configuration as lists of strings with counts:
870 * num_shares : number of shares
871 * share_names : list of length num_shares of share names
872 * num_params : list of length num_shares of parameter counts for each share
873 * param_names : list of lists of parameter names for each share
874 * param_values : list of lists of parameter values for each share
876 WERROR smbconf_get_config(struct smbconf_ctx *ctx,
877 TALLOC_CTX *mem_ctx,
878 uint32_t *num_shares,
879 char ***share_names, uint32_t **num_params,
880 char ****param_names, char ****param_values)
882 WERROR werr = WERR_OK;
883 TALLOC_CTX *tmp_ctx = NULL;
884 uint32_t tmp_num_shares;
885 char **tmp_share_names;
886 uint32_t *tmp_num_params;
887 char ***tmp_param_names;
888 char ***tmp_param_values;
889 uint32_t count;
891 if ((num_shares == NULL) || (share_names == NULL) ||
892 (num_params == NULL) || (param_names == NULL) ||
893 (param_values == NULL))
895 werr = WERR_INVALID_PARAM;
896 goto done;
899 tmp_ctx = talloc_stackframe();
900 if (tmp_ctx == NULL) {
901 werr = WERR_NOMEM;
902 goto done;
905 werr = smbconf_get_share_names(ctx, tmp_ctx, &tmp_num_shares,
906 &tmp_share_names);
907 if (!W_ERROR_IS_OK(werr)) {
908 goto done;
911 tmp_num_params = TALLOC_ARRAY(tmp_ctx, uint32_t, tmp_num_shares);
912 tmp_param_names = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
913 tmp_param_values = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
915 if ((tmp_num_params == NULL) || (tmp_param_names == NULL) ||
916 (tmp_param_values == NULL))
918 werr = WERR_NOMEM;
919 goto done;
922 for (count = 0; count < tmp_num_shares; count++) {
923 werr = smbconf_get_share(ctx, mem_ctx,
924 tmp_share_names[count],
925 &tmp_num_params[count],
926 &tmp_param_names[count],
927 &tmp_param_values[count]);
928 if (!W_ERROR_IS_OK(werr)) {
929 goto done;
933 werr = WERR_OK;
935 *num_shares = tmp_num_shares;
936 if (tmp_num_shares > 0) {
937 *share_names = talloc_move(mem_ctx, &tmp_share_names);
938 *num_params = talloc_move(mem_ctx, &tmp_num_params);
939 *param_names = talloc_move(mem_ctx, &tmp_param_names);
940 *param_values = talloc_move(mem_ctx, &tmp_param_values);
941 } else {
942 *share_names = NULL;
943 *num_params = NULL;
944 *param_names = NULL;
945 *param_values = NULL;
948 done:
949 TALLOC_FREE(tmp_ctx);
950 return werr;
954 * get the list of share names defined in the configuration.
956 WERROR smbconf_get_share_names(struct smbconf_ctx *ctx,
957 TALLOC_CTX *mem_ctx,
958 uint32_t *num_shares,
959 char ***share_names)
961 return ctx->ops->get_share_names(ctx, mem_ctx, num_shares,
962 share_names);
966 * check if a share/service of a given name exists
968 bool smbconf_share_exists(struct smbconf_ctx *ctx,
969 const char *servicename)
971 if (servicename == NULL) {
972 return false;
974 return ctx->ops->share_exists(ctx, servicename);
978 * Add a service if it does not already exist.
980 WERROR smbconf_create_share(struct smbconf_ctx *ctx,
981 const char *servicename)
983 if (smbconf_share_exists(ctx, servicename)) {
984 return WERR_ALREADY_EXISTS;
987 return ctx->ops->create_share(ctx, servicename);
991 * get a definition of a share (service) from configuration.
993 WERROR smbconf_get_share(struct smbconf_ctx *ctx,
994 TALLOC_CTX *mem_ctx,
995 const char *servicename, uint32_t *num_params,
996 char ***param_names, char ***param_values)
998 if (!smbconf_share_exists(ctx, servicename)) {
999 return WERR_NO_SUCH_SERVICE;
1002 return ctx->ops->get_share(ctx, mem_ctx, servicename, num_params,
1003 param_names, param_values);
1007 * delete a service from configuration
1009 WERROR smbconf_delete_share(struct smbconf_ctx *ctx, const char *servicename)
1011 if (!smbconf_share_exists(ctx, servicename)) {
1012 return WERR_NO_SUCH_SERVICE;
1015 return ctx->ops->delete_share(ctx, servicename);
1019 * set a configuration parameter to the value provided.
1021 WERROR smbconf_set_parameter(struct smbconf_ctx *ctx,
1022 const char *service,
1023 const char *param,
1024 const char *valstr)
1026 if (!smbconf_share_exists(ctx, service)) {
1027 return WERR_NO_SUCH_SERVICE;
1030 return ctx->ops->set_parameter(ctx, service, param, valstr);
1034 * Set a global parameter
1035 * (i.e. a parameter in the [global] service).
1037 * This also creates [global] when it does not exist.
1039 WERROR smbconf_set_global_parameter(struct smbconf_ctx *ctx,
1040 const char *param, const char *val)
1042 WERROR werr;
1044 werr = smbconf_global_check(ctx);
1045 if (W_ERROR_IS_OK(werr)) {
1046 werr = smbconf_set_parameter(ctx, GLOBAL_NAME, param, val);
1049 return werr;
1053 * get the value of a configuration parameter as a string
1055 WERROR smbconf_get_parameter(struct smbconf_ctx *ctx,
1056 TALLOC_CTX *mem_ctx,
1057 const char *service,
1058 const char *param,
1059 char **valstr)
1061 if (valstr == NULL) {
1062 return WERR_INVALID_PARAM;
1065 if (!smbconf_share_exists(ctx, service)) {
1066 return WERR_NO_SUCH_SERVICE;
1069 return ctx->ops->get_parameter(ctx, mem_ctx, service, param, valstr);
1073 * Get the value of a global parameter.
1075 * Create [global] if it does not exist.
1077 WERROR smbconf_get_global_parameter(struct smbconf_ctx *ctx,
1078 TALLOC_CTX *mem_ctx,
1079 const char *param,
1080 char **valstr)
1082 WERROR werr;
1084 werr = smbconf_global_check(ctx);
1085 if (W_ERROR_IS_OK(werr)) {
1086 werr = smbconf_get_parameter(ctx, mem_ctx, GLOBAL_NAME, param,
1087 valstr);
1090 return werr;
1094 * delete a parameter from configuration
1096 WERROR smbconf_delete_parameter(struct smbconf_ctx *ctx,
1097 const char *service, const char *param)
1099 if (!smbconf_share_exists(ctx, service)) {
1100 return WERR_NO_SUCH_SERVICE;
1103 return ctx->ops->delete_parameter(ctx, service, param);
1107 * Delete a global parameter.
1109 * Create [global] if it does not exist.
1111 WERROR smbconf_delete_global_parameter(struct smbconf_ctx *ctx,
1112 const char *param)
1114 WERROR werr;
1116 werr = smbconf_global_check(ctx);
1117 if (W_ERROR_IS_OK(werr)) {
1118 werr = smbconf_delete_parameter(ctx, GLOBAL_NAME, param);
1121 return werr;