2
* Unix SMB/CIFS implementation.
3
* libsmbconf - Samba configuration library, text backend
4
* Copyright (C) Michael Adam 2008
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, see <http://www.gnu.org/licenses/>.
21
* This is a sample implementation of a libsmbconf text backend
22
* using the params.c parser.
25
* Don't expect brilliant performance, since it is not hashing the lists.
29
#include "smbconf_private.h"
32
uint32_t current_share;
40
struct txt_private_data {
41
struct txt_cache *cache;
46
/**********************************************************************
50
**********************************************************************/
53
* a convenience helper to cast the private data structure
55
static struct txt_private_data *pd(struct smbconf_ctx *ctx)
57
return (struct txt_private_data *)(ctx->data);
60
static bool smbconf_txt_do_section(const char *section, void *private_data)
64
struct txt_private_data *tpd = (struct txt_private_data *)private_data;
65
struct txt_cache *cache = tpd->cache;
67
if (smbconf_find_in_array(section, cache->share_names,
68
cache->num_shares, &idx))
70
cache->current_share = idx;
74
werr = smbconf_add_string_to_array(cache, &(cache->share_names),
75
cache->num_shares, section);
76
if (!W_ERROR_IS_OK(werr)) {
79
cache->current_share = cache->num_shares;
82
cache->param_names = talloc_realloc(cache,
86
if (cache->param_names == NULL) {
89
cache->param_names[cache->current_share] = NULL;
91
cache->param_values = talloc_realloc(cache,
95
if (cache->param_values == NULL) {
98
cache->param_values[cache->current_share] = NULL;
100
cache->num_params = talloc_realloc(cache,
104
if (cache->num_params == NULL) {
107
cache->num_params[cache->current_share] = 0;
112
static bool smbconf_txt_do_parameter(const char *param_name,
113
const char *param_value,
117
char **param_names, **param_values;
120
struct txt_private_data *tpd = (struct txt_private_data *)private_data;
121
struct txt_cache *cache = tpd->cache;
123
if (cache->num_shares == 0) {
125
* not in any share yet,
126
* initialize the "empty" section (NULL):
127
* parameters without a previous [section] are stored here.
129
if (!smbconf_txt_do_section(NULL, private_data)) {
134
param_names = cache->param_names[cache->current_share];
135
param_values = cache->param_values[cache->current_share];
136
num_params = cache->num_params[cache->current_share];
138
if (!(tpd->verbatim) &&
139
smbconf_find_in_array(param_name, param_names, num_params, &idx))
141
talloc_free(param_values[idx]);
142
param_values[idx] = talloc_strdup(cache, param_value);
143
if (param_values[idx] == NULL) {
148
werr = smbconf_add_string_to_array(cache,
149
&(cache->param_names[cache->current_share]),
150
num_params, param_name);
151
if (!W_ERROR_IS_OK(werr)) {
154
werr = smbconf_add_string_to_array(cache,
155
&(cache->param_values[cache->current_share]),
156
num_params, param_value);
157
cache->num_params[cache->current_share]++;
158
return W_ERROR_IS_OK(werr);
161
static void smbconf_txt_flush_cache(struct smbconf_ctx *ctx)
163
talloc_free(pd(ctx)->cache);
164
pd(ctx)->cache = NULL;
167
static WERROR smbconf_txt_init_cache(struct smbconf_ctx *ctx)
169
if (pd(ctx)->cache != NULL) {
170
smbconf_txt_flush_cache(ctx);
173
pd(ctx)->cache = talloc_zero(pd(ctx), struct txt_cache);
175
if (pd(ctx)->cache == NULL) {
182
static WERROR smbconf_txt_load_file(struct smbconf_ctx *ctx)
187
if (!file_exist(ctx->path)) {
191
new_csn = (uint64_t)file_modtime(ctx->path);
192
if (new_csn == pd(ctx)->csn) {
196
werr = smbconf_txt_init_cache(ctx);
197
if (!W_ERROR_IS_OK(werr)) {
201
if (!pm_process(ctx->path, smbconf_txt_do_section,
202
smbconf_txt_do_parameter, pd(ctx)))
204
return WERR_CAN_NOT_COMPLETE;
207
pd(ctx)->csn = new_csn;
213
/**********************************************************************
215
* smbconf operations: text backend implementations
217
**********************************************************************/
220
* initialize the text based smbconf backend
222
static WERROR smbconf_txt_init(struct smbconf_ctx *ctx, const char *path)
227
ctx->path = talloc_strdup(ctx, path);
228
if (ctx->path == NULL) {
232
ctx->data = talloc_zero(ctx, struct txt_private_data);
233
if (ctx->data == NULL) {
237
pd(ctx)->verbatim = true;
242
static int smbconf_txt_shutdown(struct smbconf_ctx *ctx)
244
return ctx->ops->close_conf(ctx);
247
static bool smbconf_txt_requires_messaging(struct smbconf_ctx *ctx)
252
static bool smbconf_txt_is_writeable(struct smbconf_ctx *ctx)
254
/* no write support in this backend yet... */
258
static WERROR smbconf_txt_open(struct smbconf_ctx *ctx)
260
return smbconf_txt_load_file(ctx);
263
static int smbconf_txt_close(struct smbconf_ctx *ctx)
265
smbconf_txt_flush_cache(ctx);
270
* Get the change sequence number of the given service/parameter.
271
* service and parameter strings may be NULL.
273
static void smbconf_txt_get_csn(struct smbconf_ctx *ctx,
274
struct smbconf_csn *csn,
275
const char *service, const char *param)
281
csn->csn = (uint64_t)file_modtime(ctx->path);
285
* Drop the whole configuration (restarting empty)
287
static WERROR smbconf_txt_drop(struct smbconf_ctx *ctx)
289
return WERR_NOT_SUPPORTED;
293
* get the list of share names defined in the configuration.
295
static WERROR smbconf_txt_get_share_names(struct smbconf_ctx *ctx,
297
uint32_t *num_shares,
301
uint32_t added_count = 0;
302
TALLOC_CTX *tmp_ctx = NULL;
303
WERROR werr = WERR_OK;
304
char **tmp_share_names = NULL;
306
if ((num_shares == NULL) || (share_names == NULL)) {
307
werr = WERR_INVALID_PARAM;
311
werr = smbconf_txt_load_file(ctx);
312
if (!W_ERROR_IS_OK(werr)) {
316
tmp_ctx = talloc_stackframe();
318
/* make sure "global" is always listed first,
319
* possibly after NULL section */
321
if (smbconf_share_exists(ctx, NULL)) {
322
werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
324
if (!W_ERROR_IS_OK(werr)) {
330
if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
331
werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
332
added_count, GLOBAL_NAME);
333
if (!W_ERROR_IS_OK(werr)) {
339
for (count = 0; count < pd(ctx)->cache->num_shares; count++) {
340
if (strequal(pd(ctx)->cache->share_names[count], GLOBAL_NAME) ||
341
(pd(ctx)->cache->share_names[count] == NULL))
346
werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
348
pd(ctx)->cache->share_names[count]);
349
if (!W_ERROR_IS_OK(werr)) {
355
*num_shares = added_count;
356
if (added_count > 0) {
357
*share_names = talloc_move(mem_ctx, &tmp_share_names);
363
talloc_free(tmp_ctx);
368
* check if a share/service of a given name exists
370
static bool smbconf_txt_share_exists(struct smbconf_ctx *ctx,
371
const char *servicename)
375
werr = smbconf_txt_load_file(ctx);
376
if (!W_ERROR_IS_OK(werr)) {
380
return smbconf_find_in_array(servicename,
381
pd(ctx)->cache->share_names,
382
pd(ctx)->cache->num_shares, NULL);
386
* Add a service if it does not already exist
388
static WERROR smbconf_txt_create_share(struct smbconf_ctx *ctx,
389
const char *servicename)
391
return WERR_NOT_SUPPORTED;
395
* get a definition of a share (service) from configuration.
397
static WERROR smbconf_txt_get_share(struct smbconf_ctx *ctx,
399
const char *servicename,
400
struct smbconf_service **service)
403
uint32_t sidx, count;
405
TALLOC_CTX *tmp_ctx = NULL;
406
struct smbconf_service *tmp_service = NULL;
408
werr = smbconf_txt_load_file(ctx);
409
if (!W_ERROR_IS_OK(werr)) {
413
found = smbconf_find_in_array(servicename,
414
pd(ctx)->cache->share_names,
415
pd(ctx)->cache->num_shares,
418
return WERR_NO_SUCH_SERVICE;
421
tmp_ctx = talloc_stackframe();
423
tmp_service = talloc_zero(tmp_ctx, struct smbconf_service);
424
if (tmp_service == NULL) {
429
if (servicename != NULL) {
430
tmp_service->name = talloc_strdup(tmp_service, servicename);
431
if (tmp_service->name == NULL) {
437
for (count = 0; count < pd(ctx)->cache->num_params[sidx]; count++) {
438
werr = smbconf_add_string_to_array(tmp_service,
439
&(tmp_service->param_names),
441
pd(ctx)->cache->param_names[sidx][count]);
442
if (!W_ERROR_IS_OK(werr)) {
445
werr = smbconf_add_string_to_array(tmp_service,
446
&(tmp_service->param_values),
448
pd(ctx)->cache->param_values[sidx][count]);
449
if (!W_ERROR_IS_OK(werr)) {
454
tmp_service->num_params = count;
456
*service = talloc_move(mem_ctx, &tmp_service);
462
talloc_free(tmp_ctx);
467
* delete a service from configuration
469
static WERROR smbconf_txt_delete_share(struct smbconf_ctx *ctx,
470
const char *servicename)
472
return WERR_NOT_SUPPORTED;
476
* set a configuration parameter to the value provided.
478
static WERROR smbconf_txt_set_parameter(struct smbconf_ctx *ctx,
483
return WERR_NOT_SUPPORTED;
487
* get the value of a configuration parameter as a string
489
static WERROR smbconf_txt_get_parameter(struct smbconf_ctx *ctx,
497
uint32_t share_index, param_index;
499
werr = smbconf_txt_load_file(ctx);
500
if (!W_ERROR_IS_OK(werr)) {
504
found = smbconf_find_in_array(service,
505
pd(ctx)->cache->share_names,
506
pd(ctx)->cache->num_shares,
509
return WERR_NO_SUCH_SERVICE;
512
found = smbconf_reverse_find_in_array(param,
513
pd(ctx)->cache->param_names[share_index],
514
pd(ctx)->cache->num_params[share_index],
517
return WERR_INVALID_PARAM;
520
*valstr = talloc_strdup(mem_ctx,
521
pd(ctx)->cache->param_values[share_index][param_index]);
523
if (*valstr == NULL) {
531
* delete a parameter from configuration
533
static WERROR smbconf_txt_delete_parameter(struct smbconf_ctx *ctx,
537
return WERR_NOT_SUPPORTED;
540
static WERROR smbconf_txt_get_includes(struct smbconf_ctx *ctx,
543
uint32_t *num_includes,
548
uint32_t sidx, count;
549
TALLOC_CTX *tmp_ctx = NULL;
550
uint32_t tmp_num_includes = 0;
551
char **tmp_includes = NULL;
553
werr = smbconf_txt_load_file(ctx);
554
if (!W_ERROR_IS_OK(werr)) {
558
found = smbconf_find_in_array(service,
559
pd(ctx)->cache->share_names,
560
pd(ctx)->cache->num_shares,
563
return WERR_NO_SUCH_SERVICE;
566
tmp_ctx = talloc_stackframe();
568
for (count = 0; count < pd(ctx)->cache->num_params[sidx]; count++) {
569
if (strequal(pd(ctx)->cache->param_names[sidx][count],
572
werr = smbconf_add_string_to_array(tmp_ctx,
575
pd(ctx)->cache->param_values[sidx][count]);
576
if (!W_ERROR_IS_OK(werr)) {
583
*num_includes = tmp_num_includes;
584
if (*num_includes > 0) {
585
*includes = talloc_move(mem_ctx, &tmp_includes);
586
if (*includes == NULL) {
597
talloc_free(tmp_ctx);
601
static WERROR smbconf_txt_set_includes(struct smbconf_ctx *ctx,
603
uint32_t num_includes,
604
const char **includes)
606
return WERR_NOT_SUPPORTED;
609
static WERROR smbconf_txt_delete_includes(struct smbconf_ctx *ctx,
612
return WERR_NOT_SUPPORTED;
615
static WERROR smbconf_txt_transaction_start(struct smbconf_ctx *ctx)
620
static WERROR smbconf_txt_transaction_commit(struct smbconf_ctx *ctx)
625
static WERROR smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)
630
static struct smbconf_ops smbconf_ops_txt = {
631
.init = smbconf_txt_init,
632
.shutdown = smbconf_txt_shutdown,
633
.requires_messaging = smbconf_txt_requires_messaging,
634
.is_writeable = smbconf_txt_is_writeable,
635
.open_conf = smbconf_txt_open,
636
.close_conf = smbconf_txt_close,
637
.get_csn = smbconf_txt_get_csn,
638
.drop = smbconf_txt_drop,
639
.get_share_names = smbconf_txt_get_share_names,
640
.share_exists = smbconf_txt_share_exists,
641
.create_share = smbconf_txt_create_share,
642
.get_share = smbconf_txt_get_share,
643
.delete_share = smbconf_txt_delete_share,
644
.set_parameter = smbconf_txt_set_parameter,
645
.get_parameter = smbconf_txt_get_parameter,
646
.delete_parameter = smbconf_txt_delete_parameter,
647
.get_includes = smbconf_txt_get_includes,
648
.set_includes = smbconf_txt_set_includes,
649
.delete_includes = smbconf_txt_delete_includes,
650
.transaction_start = smbconf_txt_transaction_start,
651
.transaction_commit = smbconf_txt_transaction_commit,
652
.transaction_cancel = smbconf_txt_transaction_cancel,
657
* initialize the smbconf text backend
658
* the only function that is exported from this module
660
WERROR smbconf_init_txt(TALLOC_CTX *mem_ctx,
661
struct smbconf_ctx **conf_ctx,
666
werr = smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_txt);
667
if (!W_ERROR_IS_OK(werr)) {
671
return smbconf_txt_load_file(*conf_ctx);