root/source4/param/share_ldb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sldb_init
  2. sldb_string_option
  3. sldb_int_option
  4. sldb_bool_option
  5. sldb_string_list_option
  6. sldb_list_all
  7. sldb_get_config
  8. sldb_create
  9. sldb_set
  10. sldb_remove
  11. share_ldb_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    
   4    LDB based shares configuration
   5    
   6    Copyright (C) Simo Sorce     2006
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "ldb/include/ldb.h"
  24 #include "ldb/include/ldb_errors.h"
  25 #include "auth/auth.h"
  26 #include "ldb_wrap.h"
  27 #include "param/share.h"
  28 #include "param/param.h"
  29 
  30 static NTSTATUS sldb_init(TALLOC_CTX *mem_ctx, const struct share_ops *ops, 
     /* [<][>][^][v][top][bottom][index][help] */
  31                           struct tevent_context *ev_ctx,
  32                           struct loadparm_context *lp_ctx,
  33                           struct share_context **ctx)
  34 {
  35         struct ldb_context *sdb;
  36 
  37         *ctx = talloc(mem_ctx, struct share_context);
  38         if (!*ctx) {
  39                 DEBUG(0, ("ERROR: Out of memory!\n"));
  40                 return NT_STATUS_NO_MEMORY;
  41         }
  42         
  43         sdb = ldb_wrap_connect(*ctx, ev_ctx, lp_ctx, 
  44                                private_path(*ctx, lp_ctx, "share.ldb"),
  45                                system_session(*ctx, lp_ctx),
  46                                NULL, 0, NULL);
  47 
  48         if (!sdb) {
  49                 talloc_free(*ctx);
  50                 return NT_STATUS_UNSUCCESSFUL;
  51         }
  52 
  53         (*ctx)->ops = ops;
  54         (*ctx)->priv_data = (void *)sdb;
  55 
  56         return NT_STATUS_OK;
  57 }
  58 
  59 static const char *sldb_string_option(struct share_config *scfg, const char *opt_name, const char *defval)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         struct ldb_message *msg;
  62         struct ldb_message_element *el;
  63 
  64         if (scfg == NULL) return defval;
  65 
  66         msg = talloc_get_type(scfg->opaque, struct ldb_message);
  67 
  68         if (strchr(opt_name, ':')) {
  69                 char *name, *p;
  70 
  71                 name = talloc_strdup(scfg, opt_name);
  72                 if (!name) {
  73                         return NULL;
  74                 }
  75                 p = strchr(name, ':');
  76                 *p = '-';
  77 
  78                 el = ldb_msg_find_element(msg, name);
  79         } else {
  80                 el = ldb_msg_find_element(msg, opt_name);
  81         }
  82 
  83         if (el == NULL) {
  84                 return defval;
  85         }
  86 
  87         return (const char *)(el->values[0].data);
  88 }
  89 
  90 static int sldb_int_option(struct share_config *scfg, const char *opt_name, int defval)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92         const char *val;
  93         int ret;
  94 
  95         val = sldb_string_option(scfg, opt_name, NULL);
  96         if (val == NULL) return defval;
  97 
  98         errno = 0;
  99         ret = (int)strtol(val, NULL, 10);
 100         if (errno) return -1;
 101 
 102         return ret;
 103 }
 104 
 105 static bool sldb_bool_option(struct share_config *scfg, const char *opt_name, bool defval)
     /* [<][>][^][v][top][bottom][index][help] */
 106 {
 107         const char *val;
 108 
 109         val = sldb_string_option(scfg, opt_name, NULL);
 110         if (val == NULL) return defval;
 111 
 112         if (strcasecmp(val, "true") == 0) return true;
 113 
 114         return false;
 115 }
 116 
 117 static const char **sldb_string_list_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name)
     /* [<][>][^][v][top][bottom][index][help] */
 118 {
 119         struct ldb_message *msg;
 120         struct ldb_message_element *el;
 121         const char **list;
 122         int i;
 123 
 124         if (scfg == NULL) return NULL;
 125 
 126         msg = talloc_get_type(scfg->opaque, struct ldb_message);
 127 
 128         if (strchr(opt_name, ':')) {
 129                 char *name, *p;
 130 
 131                 name = talloc_strdup(scfg, opt_name);
 132                 if (!name) {
 133                         return NULL;
 134                 }
 135                 p = strchr(name, ':');
 136                 *p = '-';
 137 
 138                 el = ldb_msg_find_element(msg, name);
 139         } else {
 140                 el = ldb_msg_find_element(msg, opt_name);
 141         }
 142 
 143         if (el == NULL) {
 144                 return NULL;
 145         }
 146 
 147         list = talloc_array(mem_ctx, const char *, el->num_values + 1);
 148         if (!list) return NULL;
 149 
 150         for (i = 0; i < el->num_values; i++) {
 151                 list[i] = (const char *)(el->values[i].data);
 152         }
 153         list[i] = NULL;
 154 
 155         return list;
 156 }
 157 
 158 static NTSTATUS sldb_list_all(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 159                                  struct share_context *ctx,
 160                                  int *count,
 161                                  const char ***names)
 162 {
 163         int ret, i, j;
 164         const char **n;
 165         struct ldb_context *ldb;
 166         struct ldb_result *res;
 167         TALLOC_CTX *tmp_ctx;
 168 
 169         tmp_ctx = talloc_new(mem_ctx);
 170         if (!tmp_ctx) {
 171                 DEBUG(0,("ERROR: Out of memory!\n"));
 172                 return NT_STATUS_NO_MEMORY;
 173         }
 174 
 175         ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
 176 
 177         ret = ldb_search(ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, ldb, "CN=SHARES"),
 178                          LDB_SCOPE_SUBTREE, NULL, "(name=*)");
 179         if (ret != LDB_SUCCESS) {
 180                 talloc_free(tmp_ctx);
 181                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
 182         }
 183 
 184         n = talloc_array(mem_ctx, const char *, res->count);
 185         if (!n) {
 186                 DEBUG(0,("ERROR: Out of memory!\n"));
 187                 talloc_free(tmp_ctx);
 188                 return NT_STATUS_NO_MEMORY;
 189         }
 190 
 191         for (i = 0, j = 0; i < res->count; i++) {
 192                 n[j] = talloc_strdup(n, ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL));
 193                 if (!n[j]) {
 194                         DEBUG(0,("WARNING: Malformed share object in share database\n!"));
 195                         continue;
 196                 }
 197                 j++;
 198         }
 199 
 200         *names = n;
 201         *count = j;
 202         talloc_free(tmp_ctx);
 203 
 204         return NT_STATUS_OK;
 205 }
 206 
 207 static NTSTATUS sldb_get_config(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 208                          struct share_context *ctx,
 209                          const char *name,
 210                          struct share_config **scfg)
 211 {
 212         int ret;
 213         struct share_config *s;
 214         struct ldb_context *ldb;
 215         struct ldb_result *res;
 216         TALLOC_CTX *tmp_ctx;
 217 
 218         tmp_ctx = talloc_new(mem_ctx);
 219         if (!tmp_ctx) {
 220                 DEBUG(0,("ERROR: Out of memory!\n"));
 221                 return NT_STATUS_NO_MEMORY;
 222         }
 223 
 224         ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
 225 
 226         ret = ldb_search(ldb, tmp_ctx, &res,
 227                                  ldb_dn_new(tmp_ctx, ldb, "CN=SHARES"), LDB_SCOPE_SUBTREE, NULL,
 228                                  "(name=%s)", name);
 229         if (ret != LDB_SUCCESS || res->count > 1) {
 230                 talloc_free(tmp_ctx);
 231                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
 232         } else if (res->count != 1) {
 233                 talloc_free(tmp_ctx);
 234                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 235         }
 236 
 237         s = talloc(tmp_ctx, struct share_config);
 238         if (!s) {
 239                 DEBUG(0,("ERROR: Out of memory!\n"));
 240                 talloc_free(tmp_ctx);
 241                 return NT_STATUS_NO_MEMORY;
 242         }
 243 
 244         s->name = talloc_strdup(s, ldb_msg_find_attr_as_string(res->msgs[0], "name", NULL));
 245         if (!s->name) {
 246                 DEBUG(0,("ERROR: Invalid share object!\n"));
 247                 talloc_free(tmp_ctx);
 248                 return NT_STATUS_UNSUCCESSFUL;
 249         }
 250 
 251         s->opaque = talloc_steal(s, res->msgs[0]);
 252         if (!s->opaque) {
 253                 DEBUG(0,("ERROR: Invalid share object!\n"));
 254                 talloc_free(tmp_ctx);
 255                 return NT_STATUS_UNSUCCESSFUL;
 256         }
 257 
 258         s->ctx = ctx;
 259 
 260         *scfg = talloc_steal(mem_ctx, s);
 261 
 262         talloc_free(tmp_ctx);
 263         return NT_STATUS_OK;
 264 }
 265 
 266 #define SHARE_ADD_STRING(name, value) do { \
 267         err = ldb_msg_add_string(msg, name, value); \
 268         if (err != LDB_SUCCESS) { \
 269                 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
 270                 ret = NT_STATUS_UNSUCCESSFUL; \
 271                 goto done; \
 272         } } while(0)
 273 
 274 #define SHARE_ADD_INT(name, value) do { \
 275         err = ldb_msg_add_fmt(msg, name, "%d", value); \
 276         if (err != LDB_SUCCESS) { \
 277                 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
 278                 ret = NT_STATUS_UNSUCCESSFUL; \
 279                 goto done; \
 280         } } while(0)
 281 
 282 #define SHARE_ADD_BLOB(name, value) do { \
 283         err = ldb_msg_add_value(msg, name, value, NULL); \
 284         if (err != LDB_SUCCESS) { \
 285                 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
 286                 ret = NT_STATUS_UNSUCCESSFUL; \
 287                 goto done; \
 288         } } while(0)
 289 
 290 static NTSTATUS sldb_create(struct share_context *ctx, const char *name, struct share_info *info, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 291 {
 292         struct ldb_context *ldb;
 293         struct ldb_message *msg;
 294         TALLOC_CTX *tmp_ctx;
 295         NTSTATUS ret;
 296         int err, i, j;
 297 
 298         for (i = 0, j = 0; i < count && j != 0x03; i++) {
 299                 if (strcasecmp(info[i].name, SHARE_TYPE) == 0) j |= 0x02;
 300                 if (strcasecmp(info[i].name, SHARE_PATH) == 0) j |= 0x01;
 301                 if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
 302                         if (strcasecmp(name, (char *)info[i].value) != 0) {
 303                                 return NT_STATUS_INVALID_PARAMETER;
 304                         }
 305                 }
 306         }
 307         if (!name || j != 0x03) {
 308                 return NT_STATUS_INVALID_PARAMETER;
 309         }
 310         
 311         tmp_ctx = talloc_new(NULL);
 312         if (!tmp_ctx) {
 313                 DEBUG(0,("ERROR: Out of memory!\n"));
 314                 return NT_STATUS_NO_MEMORY;
 315         }
 316 
 317         ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
 318 
 319         msg = ldb_msg_new(tmp_ctx);
 320         if (!msg) {
 321                 DEBUG(0,("ERROR: Out of memory!\n"));
 322                 ret = NT_STATUS_NO_MEMORY;
 323                 goto done;
 324         }
 325 
 326         /* TODO: escape info->name */
 327         msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
 328         if (!msg->dn) {
 329                 DEBUG(0,("ERROR: Out of memory!\n"));
 330                 ret = NT_STATUS_NO_MEMORY;
 331                 goto done;
 332         }
 333 
 334         SHARE_ADD_STRING("objectClass", "top");
 335         SHARE_ADD_STRING("objectClass", "share");
 336         SHARE_ADD_STRING("cn", name);
 337         SHARE_ADD_STRING(SHARE_NAME, name);
 338 
 339         for (i = 0; i < count; i++) {
 340                 if (strcasecmp(info[i].name, SHARE_NAME) == 0) continue;
 341 
 342                 switch (info[i].type) {
 343                 case SHARE_INFO_STRING:
 344                         SHARE_ADD_STRING(info[i].name, (char *)info[i].value);
 345                         break;
 346                 case SHARE_INFO_INT:
 347                         SHARE_ADD_INT(info[i].name, *((int *)info[i].value));
 348                         break;
 349                 case SHARE_INFO_BLOB:
 350                         SHARE_ADD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
 351                         break;
 352                 default:
 353                         DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
 354                         ret = NT_STATUS_INVALID_PARAMETER;
 355                         goto done;
 356                 }
 357         }
 358 
 359         /* TODO: Security Descriptor */
 360 
 361         SHARE_ADD_STRING(SHARE_AVAILABLE, "true");
 362         SHARE_ADD_STRING(SHARE_BROWSEABLE, "true");
 363         SHARE_ADD_STRING(SHARE_READONLY, "false");
 364         SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "unixuid");
 365         SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "posix");
 366 
 367         err = ldb_add(ldb, msg);
 368         if (err != LDB_SUCCESS) {
 369                 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
 370                          "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
 371                 if (err == LDB_ERR_NO_SUCH_OBJECT) {
 372                         ret = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 373                 } else if (err == LDB_ERR_ENTRY_ALREADY_EXISTS) {
 374                         ret = NT_STATUS_OBJECT_NAME_COLLISION;
 375                 } else {
 376                         ret = NT_STATUS_UNSUCCESSFUL;
 377                 }
 378                 goto done;
 379         }
 380 
 381         ret = NT_STATUS_OK;
 382 done:
 383         talloc_free(tmp_ctx);
 384         return ret;
 385 }
 386 
 387 #define SHARE_MOD_STRING(name, value) do { \
 388         err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
 389         if (err != LDB_SUCCESS) { \
 390                 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
 391                 ret = NT_STATUS_UNSUCCESSFUL; \
 392                 goto done; \
 393         } \
 394         err = ldb_msg_add_string(msg, name, value); \
 395         if (err != LDB_SUCCESS) { \
 396                 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
 397                 ret = NT_STATUS_UNSUCCESSFUL; \
 398                 goto done; \
 399         } } while(0)
 400 
 401 #define SHARE_MOD_INT(name, value) do { \
 402         err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
 403         if (err != LDB_SUCCESS) { \
 404                 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
 405                 ret = NT_STATUS_UNSUCCESSFUL; \
 406                 goto done; \
 407         } \
 408         err = ldb_msg_add_fmt(msg, name, "%d", value); \
 409         if (err != LDB_SUCCESS) { \
 410                 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
 411                 ret = NT_STATUS_UNSUCCESSFUL; \
 412                 goto done; \
 413         } } while(0)
 414 
 415 #define SHARE_MOD_BLOB(name, value) do { \
 416         err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
 417         if (err != LDB_SUCCESS) { \
 418                 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
 419                 ret = NT_STATUS_UNSUCCESSFUL; \
 420                 goto done; \
 421         } \
 422         err = ldb_msg_add_value(msg, name, value, NULL); \
 423         if (err != LDB_SUCCESS) { \
 424                 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
 425                 ret = NT_STATUS_UNSUCCESSFUL; \
 426                 goto done; \
 427         } } while(0)
 428 
 429 static NTSTATUS sldb_set(struct share_context *ctx, const char *name, struct share_info *info, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 430 {
 431         struct ldb_context *ldb;
 432         struct ldb_message *msg;
 433         TALLOC_CTX *tmp_ctx;
 434         NTSTATUS ret;
 435         bool do_rename = false;
 436         char *newname;
 437         int err, i;
 438 
 439         if (!name) {
 440                 return NT_STATUS_INVALID_PARAMETER;
 441         }
 442         
 443         tmp_ctx = talloc_new(NULL);
 444         if (!tmp_ctx) {
 445                 DEBUG(0,("ERROR: Out of memory!\n"));
 446                 return NT_STATUS_NO_MEMORY;
 447         }
 448 
 449         ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
 450 
 451         msg = ldb_msg_new(tmp_ctx);
 452         if (!msg) {
 453                 DEBUG(0,("ERROR: Out of memory!\n"));
 454                 ret = NT_STATUS_NO_MEMORY;
 455                 goto done;
 456         }
 457 
 458         /* TODO: escape name */
 459         msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
 460         if (!msg->dn) {
 461                 DEBUG(0,("ERROR: Out of memory!\n"));
 462                 ret = NT_STATUS_NO_MEMORY;
 463                 goto done;
 464         }
 465 
 466         for (i = 0; i < count; i++) {
 467                 if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
 468                         if (strcasecmp(name, (char *)info[i].value) != 0) {
 469                                 do_rename = true;
 470                                 newname = (char *)info[i].value;
 471                                 SHARE_MOD_STRING("cn", (char *)info[i].value);
 472                         }
 473                 }
 474 
 475                 switch (info[i].type) {
 476                 case SHARE_INFO_STRING:
 477                         SHARE_MOD_STRING(info[i].name, (char *)info[i].value);
 478                         break;
 479                 case SHARE_INFO_INT:
 480                         SHARE_MOD_INT(info[i].name, *((int *)info[i].value));
 481                         break;
 482                 case SHARE_INFO_BLOB:
 483                         SHARE_MOD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
 484                         break;
 485                 default:
 486                         DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
 487                         ret = NT_STATUS_INVALID_PARAMETER;
 488                         goto done;
 489                 }
 490         }
 491 
 492         if (do_rename) {
 493                 struct ldb_dn *olddn, *newdn;
 494 
 495                 olddn = msg->dn;
 496 
 497                 /* TODO: escape newname */
 498                 newdn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", newname);
 499                 if (!newdn) {
 500                         DEBUG(0,("ERROR: Out of memory!\n"));
 501                         ret = NT_STATUS_NO_MEMORY;
 502                         goto done;
 503                 }
 504 
 505                 err = ldb_rename(ldb, olddn, newdn);
 506                 if (err != LDB_SUCCESS) {
 507                         DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
 508                                  "       err=%d [%s]\n", name, newname, err, ldb_errstring(ldb)));
 509                         if (err == LDB_ERR_NO_SUCH_OBJECT) {
 510                                 ret = NT_STATUS_OBJECT_NAME_COLLISION;
 511                         } else {
 512                                 ret = NT_STATUS_UNSUCCESSFUL;
 513                         }
 514                         goto done;
 515                 }
 516 
 517                 msg->dn = newdn;
 518         }
 519 
 520         err = ldb_modify(ldb, msg);
 521         if (err != LDB_SUCCESS) {
 522                 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
 523                          "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
 524                 if (err == LDB_ERR_NO_SUCH_OBJECT) {
 525                         ret = NT_STATUS_OBJECT_NAME_COLLISION;
 526                 } else {
 527                         ret = NT_STATUS_UNSUCCESSFUL;
 528                 }
 529                 goto done;
 530         }
 531 
 532         ret = NT_STATUS_OK;
 533 done:
 534         talloc_free(tmp_ctx);
 535         return ret;
 536 }
 537 
 538 static NTSTATUS sldb_remove(struct share_context *ctx, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 539 {
 540         struct ldb_context *ldb;
 541         struct ldb_dn *dn;
 542         TALLOC_CTX *tmp_ctx;
 543         NTSTATUS ret;
 544         int err;
 545 
 546         tmp_ctx = talloc_new(NULL);
 547         if (!tmp_ctx) {
 548                 DEBUG(0,("ERROR: Out of memory!\n"));
 549                 return NT_STATUS_NO_MEMORY;
 550         }
 551 
 552         ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
 553 
 554         dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
 555         if (!dn) {
 556                 DEBUG(0,("ERROR: Out of memory!\n"));
 557                 ret = NT_STATUS_NO_MEMORY;
 558                 goto done;
 559         }
 560 
 561         err = ldb_delete(ldb, dn);
 562         if (err != LDB_SUCCESS) {
 563                 DEBUG(2,("ERROR: unable to remove share %s from share.ldb\n"
 564                          "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
 565                 ret = NT_STATUS_UNSUCCESSFUL;
 566                 goto done;
 567         }
 568 
 569         ret = NT_STATUS_OK;
 570 done:
 571         talloc_free(tmp_ctx);
 572         return ret;
 573 }
 574 
 575 static const struct share_ops ops = {
 576         .name = "ldb",
 577         .init = sldb_init,
 578         .string_option = sldb_string_option,
 579         .int_option = sldb_int_option,
 580         .bool_option = sldb_bool_option,
 581         .string_list_option = sldb_string_list_option,
 582         .list_all = sldb_list_all,
 583         .get_config = sldb_get_config,
 584         .create = sldb_create,
 585         .set = sldb_set,
 586         .remove = sldb_remove
 587 };
 588 
 589 NTSTATUS share_ldb_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 590 {
 591         return share_register(&ops);
 592 }

/* [<][>][^][v][top][bottom][index][help] */