Coverage Report

Created: 2025-12-31 06:20

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