s3:make "net conf addshare" atomic by wrapping all writes in one transaction
[ira/wip.git] / source3 / utils / net_conf.c
1 /*
2  *  Samba Unix/Linux SMB client library
3  *  Distributed SMB/CIFS Server Management Utility
4  *  Local configuration interface
5  *  Copyright (C) Michael Adam 2007-2008
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 /*
22  * This is an interface to Samba's configuration as made available
23  * by the libsmbconf interface (source/lib/smbconf/smbconf.c).
24  *
25  * This currently supports local interaction with the configuration
26  * stored in the registry. But other backends and remote access via
27  * rpc might get implemented in the future.
28  */
29
30 #include "includes.h"
31 #include "utils/net.h"
32
33 /**********************************************************************
34  *
35  * usage functions
36  *
37  **********************************************************************/
38
39 static int net_conf_list_usage(struct net_context *c, int argc,
40                                const char **argv)
41 {
42         d_printf("%s net conf list\n", _("Usage:"));
43         return -1;
44 }
45
46 static int net_conf_import_usage(struct net_context *c, int argc,
47                                  const char**argv)
48 {
49         d_printf("%s\n%s",
50                  _("Usage:"),
51                  _(" net conf import [--test|-T] <filename> "
52                    "[<servicename>]\n"
53                    "\t[--test|-T]    testmode - do not act, just print "
54                         "what would be done\n"
55                    "\t<servicename>  only import service <servicename>, "
56                         "ignore the rest\n"));
57         return -1;
58 }
59
60 static int net_conf_listshares_usage(struct net_context *c, int argc,
61                                      const char **argv)
62 {
63         d_printf("%s\nnet conf listshares\n", _("Usage:"));
64         return -1;
65 }
66
67 static int net_conf_drop_usage(struct net_context *c, int argc,
68                                const char **argv)
69 {
70         d_printf("%s\nnet conf drop\n", _("Usage:"));
71         return -1;
72 }
73
74 static int net_conf_showshare_usage(struct net_context *c, int argc,
75                                     const char **argv)
76 {
77         d_printf("%s\n%s",
78                  _("Usage:"),
79                  _("net conf showshare <sharename>\n"));
80         return -1;
81 }
82
83 static int net_conf_addshare_usage(struct net_context *c, int argc,
84                                    const char **argv)
85 {
86         d_printf("%s\n%s",
87                  _("Usage:"),
88                  _(" net conf addshare <sharename> <path> "
89                    "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
90                    "\t<sharename>      the new share name.\n"
91                    "\t<path>           the path on the filesystem to export.\n"
92                    "\twriteable={y|N}  set \"writeable to \"yes\" or "
93                    "\"no\" (default) on this share.\n"
94                    "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
95                    "\"no\" (default)   on this share.\n"
96                    "\t<comment>        optional comment for the new share.\n"));
97         return -1;
98 }
99
100 static int net_conf_delshare_usage(struct net_context *c, int argc,
101                                    const char **argv)
102 {
103         d_printf("%s\n%s",
104                  _("Usage:"),
105                  _("net conf delshare <sharename>\n"));
106         return -1;
107 }
108
109 static int net_conf_setparm_usage(struct net_context *c, int argc,
110                                   const char **argv)
111 {
112         d_printf("%s\n%s",
113                  _("Usage:"),
114                  _(" net conf setparm <section> <param> <value>\n"));
115         return -1;
116 }
117
118 static int net_conf_getparm_usage(struct net_context *c, int argc,
119                                   const char **argv)
120 {
121         d_printf("%s\n%s",
122                  _("Usage:"),
123                  _(" net conf getparm <section> <param>\n"));
124         return -1;
125 }
126
127 static int net_conf_delparm_usage(struct net_context *c, int argc,
128                                   const char **argv)
129 {
130         d_printf("%s\n%s",
131                  _("Usage:"),
132                  _(" net conf delparm <section> <param>\n"));
133         return -1;
134 }
135
136 static int net_conf_getincludes_usage(struct net_context *c, int argc,
137                                       const char **argv)
138 {
139         d_printf("%s\n%s",
140                  _("Usage:"),
141                  _(" net conf getincludes <section>\n"));
142         return -1;
143 }
144
145 static int net_conf_setincludes_usage(struct net_context *c, int argc,
146                                       const char **argv)
147 {
148         d_printf("%s\n%s",
149                  _("Usage:"),
150                  _(" net conf setincludes <section> [<filename>]*\n"));
151         return -1;
152 }
153
154 static int net_conf_delincludes_usage(struct net_context *c, int argc,
155                                       const char **argv)
156 {
157         d_printf("%s\n%s",
158                 _("Usage:"),
159                 _(" net conf delincludes <section>\n"));
160         return -1;
161 }
162
163
164 /**********************************************************************
165  *
166  * Helper functions
167  *
168  **********************************************************************/
169
170 /**
171  * This functions process a service previously loaded with libsmbconf.
172  */
173 static WERROR import_process_service(struct net_context *c,
174                                      struct smbconf_ctx *conf_ctx,
175                                      struct smbconf_service *service)
176 {
177         uint32_t idx;
178         WERROR werr = WERR_OK;
179         uint32_t num_includes = 0;
180         char **includes = NULL;
181         TALLOC_CTX *mem_ctx = talloc_stackframe();
182
183         if (c->opt_testmode) {
184                 const char *indent = "";
185                 if (service->name != NULL) {
186                         d_printf("[%s]\n", service->name);
187                         indent = "\t";
188                 }
189                 for (idx = 0; idx < service->num_params; idx++) {
190                         d_printf("%s%s = %s\n", indent,
191                                  service->param_names[idx],
192                                  service->param_values[idx]);
193                 }
194                 d_printf("\n");
195                 goto done;
196         }
197
198         if (smbconf_share_exists(conf_ctx, service->name)) {
199                 werr = smbconf_delete_share(conf_ctx, service->name);
200                 if (!W_ERROR_IS_OK(werr)) {
201                         goto done;
202                 }
203         }
204         werr = smbconf_create_share(conf_ctx, service->name);
205         if (!W_ERROR_IS_OK(werr)) {
206                 goto done;
207         }
208
209         for (idx = 0; idx < service->num_params; idx ++) {
210                 if (strequal(service->param_names[idx], "include")) {
211                         includes = TALLOC_REALLOC_ARRAY(mem_ctx,
212                                                         includes,
213                                                         char *,
214                                                         num_includes+1);
215                         if (includes == NULL) {
216                                 werr = WERR_NOMEM;
217                                 goto done;
218                         }
219                         includes[num_includes] = talloc_strdup(includes,
220                                                 service->param_values[idx]);
221                         if (includes[num_includes] == NULL) {
222                                 werr = WERR_NOMEM;
223                                 goto done;
224                         }
225                         num_includes++;
226                 } else {
227                         werr = smbconf_set_parameter(conf_ctx,
228                                                      service->name,
229                                                      service->param_names[idx],
230                                                      service->param_values[idx]);
231                         if (!W_ERROR_IS_OK(werr)) {
232                                 goto done;
233                         }
234                 }
235         }
236
237         werr = smbconf_set_includes(conf_ctx, service->name, num_includes,
238                                     (const char **)includes);
239
240 done:
241         TALLOC_FREE(mem_ctx);
242         return werr;
243 }
244
245
246 /**********************************************************************
247  *
248  * the main conf functions
249  *
250  **********************************************************************/
251
252 static int net_conf_list(struct net_context *c, struct smbconf_ctx *conf_ctx,
253                          int argc, const char **argv)
254 {
255         WERROR werr = WERR_OK;
256         int ret = -1;
257         TALLOC_CTX *mem_ctx;
258         uint32_t num_shares;
259         uint32_t share_count, param_count;
260         struct smbconf_service **shares = NULL;
261
262         mem_ctx = talloc_stackframe();
263
264         if (argc != 0 || c->display_usage) {
265                 net_conf_list_usage(c, argc, argv);
266                 goto done;
267         }
268
269         werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &shares);
270         if (!W_ERROR_IS_OK(werr)) {
271                 d_fprintf(stderr, _("Error getting config: %s\n"),
272                           win_errstr(werr));
273                 goto done;
274         }
275
276         for (share_count = 0; share_count < num_shares; share_count++) {
277                 const char *indent = "";
278                 if (shares[share_count]->name != NULL) {
279                         d_printf("[%s]\n", shares[share_count]->name);
280                         indent = "\t";
281                 }
282                 for (param_count = 0;
283                      param_count < shares[share_count]->num_params;
284                      param_count++)
285                 {
286                         d_printf("%s%s = %s\n",
287                                  indent,
288                                  shares[share_count]->param_names[param_count],
289                                  shares[share_count]->param_values[param_count]);
290                 }
291                 d_printf("\n");
292         }
293
294         ret = 0;
295
296 done:
297         TALLOC_FREE(mem_ctx);
298         return ret;
299 }
300
301 static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
302                            int argc, const char **argv)
303 {
304         int ret = -1;
305         const char *filename = NULL;
306         const char *servicename = NULL;
307         char *conf_source = NULL;
308         TALLOC_CTX *mem_ctx;
309         struct smbconf_ctx *txt_ctx;
310         WERROR werr;
311
312         if (c->display_usage)
313                 return net_conf_import_usage(c, argc, argv);
314
315         mem_ctx = talloc_stackframe();
316
317         switch (argc) {
318                 case 0:
319                 default:
320                         net_conf_import_usage(c, argc, argv);
321                         goto done;
322                 case 2:
323                         servicename = talloc_strdup(mem_ctx, argv[1]);
324                         if (servicename == NULL) {
325                                 d_printf(_("error: out of memory!\n"));
326                                 goto done;
327                         }
328                 case 1:
329                         filename = argv[0];
330                         break;
331         }
332
333         DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
334                 filename));
335
336         conf_source = talloc_asprintf(mem_ctx, "file:%s", filename);
337         if (conf_source == NULL) {
338                 d_printf(_("error: out of memory!\n"));
339                 goto done;
340         }
341
342         werr = smbconf_init(mem_ctx, &txt_ctx, conf_source);
343         if (!W_ERROR_IS_OK(werr)) {
344                 d_printf(_("error loading file '%s': %s\n"), filename,
345                          win_errstr(werr));
346                 goto done;
347         }
348
349         if (c->opt_testmode) {
350                 d_printf(_("\nTEST MODE - "
351                          "would import the following configuration:\n\n"));
352         }
353
354         if (servicename != NULL) {
355                 struct smbconf_service *service = NULL;
356
357                 werr = smbconf_get_share(txt_ctx, mem_ctx,
358                                          servicename,
359                                          &service);
360                 if (!W_ERROR_IS_OK(werr)) {
361                         goto cancel;
362                 }
363
364                 werr = smbconf_transaction_start(conf_ctx);
365                 if (!W_ERROR_IS_OK(werr)) {
366                         d_printf(_("error starting transaction: %s\n"),
367                                  win_errstr(werr));
368                         goto done;
369                 }
370
371                 werr = import_process_service(c, conf_ctx, service);
372                 if (!W_ERROR_IS_OK(werr)) {
373                         goto cancel;
374                 }
375         } else {
376                 struct smbconf_service **services = NULL;
377                 uint32_t num_shares, sidx;
378
379                 werr = smbconf_get_config(txt_ctx, mem_ctx,
380                                           &num_shares,
381                                           &services);
382                 if (!W_ERROR_IS_OK(werr)) {
383                         goto cancel;
384                 }
385                 if (!c->opt_testmode) {
386                         werr = smbconf_drop(conf_ctx);
387                         if (!W_ERROR_IS_OK(werr)) {
388                                 goto cancel;
389                         }
390                 }
391
392                 /*
393                  * Wrap the importing of shares into a transaction,
394                  * but only 100 at a time, in order to serve memory.
395                  * The allocated memory accumulates across the actions
396                  * within the transaction, and for me, some 1500
397                  * imported shares, the MAX_TALLOC_SIZE of 256 MB
398                  * was exceeded.
399                  */
400                 werr = smbconf_transaction_start(conf_ctx);
401                 if (!W_ERROR_IS_OK(werr)) {
402                         d_printf(_("error starting transaction: %s\n"),
403                                  win_errstr(werr));
404                         goto done;
405                 }
406
407                 for (sidx = 0; sidx < num_shares; sidx++) {
408                         werr = import_process_service(c, conf_ctx,
409                                                       services[sidx]);
410                         if (!W_ERROR_IS_OK(werr)) {
411                                 goto cancel;
412                         }
413
414                         if (sidx % 100) {
415                                 continue;
416                         }
417
418                         werr = smbconf_transaction_commit(conf_ctx);
419                         if (!W_ERROR_IS_OK(werr)) {
420                                 d_printf(_("error committing transaction: "
421                                            "%s\n"),
422                                          win_errstr(werr));
423                                 goto done;
424                         }
425                         werr = smbconf_transaction_start(conf_ctx);
426                         if (!W_ERROR_IS_OK(werr)) {
427                                 d_printf(_("error starting transaction: %s\n"),
428                                          win_errstr(werr));
429                                 goto done;
430                         }
431                 }
432         }
433
434         werr = smbconf_transaction_commit(conf_ctx);
435         if (!W_ERROR_IS_OK(werr)) {
436                 d_printf(_("error committing transaction: %s\n"),
437                          win_errstr(werr));
438         } else {
439                 ret = 0;
440         }
441
442         goto done;
443
444 cancel:
445         werr = smbconf_transaction_cancel(conf_ctx);
446         if (!W_ERROR_IS_OK(werr)) {
447                 d_printf(_("error cancelling transaction: %s\n"),
448                          win_errstr(werr));
449         }
450
451 done:
452         TALLOC_FREE(mem_ctx);
453         return ret;
454 }
455
456 static int net_conf_listshares(struct net_context *c,
457                                struct smbconf_ctx *conf_ctx, int argc,
458                                const char **argv)
459 {
460         WERROR werr = WERR_OK;
461         int ret = -1;
462         uint32_t count, num_shares = 0;
463         char **share_names = NULL;
464         TALLOC_CTX *mem_ctx;
465
466         mem_ctx = talloc_stackframe();
467
468         if (argc != 0 || c->display_usage) {
469                 net_conf_listshares_usage(c, argc, argv);
470                 goto done;
471         }
472
473         werr = smbconf_get_share_names(conf_ctx, mem_ctx, &num_shares,
474                                        &share_names);
475         if (!W_ERROR_IS_OK(werr)) {
476                 goto done;
477         }
478
479         for (count = 0; count < num_shares; count++)
480         {
481                 d_printf("%s\n", share_names[count]);
482         }
483
484         ret = 0;
485
486 done:
487         TALLOC_FREE(mem_ctx);
488         return ret;
489 }
490
491 static int net_conf_drop(struct net_context *c, struct smbconf_ctx *conf_ctx,
492                          int argc, const char **argv)
493 {
494         int ret = -1;
495         WERROR werr;
496
497         if (argc != 0 || c->display_usage) {
498                 net_conf_drop_usage(c, argc, argv);
499                 goto done;
500         }
501
502         werr = smbconf_drop(conf_ctx);
503         if (!W_ERROR_IS_OK(werr)) {
504                 d_fprintf(stderr, _("Error deleting configuration: %s\n"),
505                           win_errstr(werr));
506                 goto done;
507         }
508
509         ret = 0;
510
511 done:
512         return ret;
513 }
514
515 static int net_conf_showshare(struct net_context *c,
516                               struct smbconf_ctx *conf_ctx, int argc,
517                               const char **argv)
518 {
519         int ret = -1;
520         WERROR werr = WERR_OK;
521         const char *sharename = NULL;
522         TALLOC_CTX *mem_ctx;
523         uint32_t count;
524         struct smbconf_service *service = NULL;
525
526         mem_ctx = talloc_stackframe();
527
528         if (argc != 1 || c->display_usage) {
529                 net_conf_showshare_usage(c, argc, argv);
530                 goto done;
531         }
532
533         sharename = talloc_strdup(mem_ctx, argv[0]);
534         if (sharename == NULL) {
535                 d_printf("error: out of memory!\n");
536                 goto done;
537         }
538
539         werr = smbconf_get_share(conf_ctx, mem_ctx, sharename, &service);
540         if (!W_ERROR_IS_OK(werr)) {
541                 d_printf(_("error getting share parameters: %s\n"),
542                          win_errstr(werr));
543                 goto done;
544         }
545
546         d_printf("[%s]\n", service->name);
547
548         for (count = 0; count < service->num_params; count++) {
549                 d_printf("\t%s = %s\n", service->param_names[count],
550                          service->param_values[count]);
551         }
552
553         ret = 0;
554
555 done:
556         TALLOC_FREE(mem_ctx);
557         return ret;
558 }
559
560 /**
561  * Add a share, with a couple of standard parameters, partly optional.
562  *
563  * This is a high level utility function of the net conf utility,
564  * not a direct frontend to the smbconf API.
565  */
566 static int net_conf_addshare(struct net_context *c,
567                              struct smbconf_ctx *conf_ctx, int argc,
568                              const char **argv)
569 {
570         int ret = -1;
571         WERROR werr = WERR_OK;
572         char *sharename = NULL;
573         const char *path = NULL;
574         const char *comment = NULL;
575         const char *guest_ok = "no";
576         const char *writeable = "no";
577         SMB_STRUCT_STAT sbuf;
578         TALLOC_CTX *mem_ctx = talloc_stackframe();
579
580         if (c->display_usage) {
581                 net_conf_addshare_usage(c, argc, argv);
582                 ret = 0;
583                 goto done;
584         }
585
586         switch (argc) {
587                 case 0:
588                 case 1:
589                 default:
590                         net_conf_addshare_usage(c, argc, argv);
591                         goto done;
592                 case 5:
593                         comment = argv[4];
594                 case 4:
595                         if (!strnequal(argv[3], "guest_ok=", 9)) {
596                                 net_conf_addshare_usage(c, argc, argv);
597                                 goto done;
598                         }
599                         switch (argv[3][9]) {
600                                 case 'y':
601                                 case 'Y':
602                                         guest_ok = "yes";
603                                         break;
604                                 case 'n':
605                                 case 'N':
606                                         guest_ok = "no";
607                                         break;
608                                 default:
609                                         net_conf_addshare_usage(c, argc, argv);
610                                         goto done;
611                         }
612                 case 3:
613                         if (!strnequal(argv[2], "writeable=", 10)) {
614                                 net_conf_addshare_usage(c, argc, argv);
615                                 goto done;
616                         }
617                         switch (argv[2][10]) {
618                                 case 'y':
619                                 case 'Y':
620                                         writeable = "yes";
621                                         break;
622                                 case 'n':
623                                 case 'N':
624                                         writeable = "no";
625                                         break;
626                                 default:
627                                         net_conf_addshare_usage(c, argc, argv);
628                                         goto done;
629                         }
630                 case 2:
631                         path = argv[1];
632                         sharename = talloc_strdup(mem_ctx, argv[0]);
633                         if (sharename == NULL) {
634                                 d_printf(_("error: out of memory!\n"));
635                                 goto done;
636                         }
637
638                         break;
639         }
640
641         /*
642          * validate arguments
643          */
644
645         /* validate share name */
646
647         if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS,
648                                strlen(sharename)))
649         {
650                 d_fprintf(stderr, _("ERROR: share name %s contains "
651                         "invalid characters (any of %s)\n"),
652                         sharename, INVALID_SHARENAME_CHARS);
653                 goto done;
654         }
655
656         if (strequal(sharename, GLOBAL_NAME)) {
657                 d_fprintf(stderr,
658                           _("ERROR: 'global' is not a valid share name.\n"));
659                 goto done;
660         }
661
662         if (smbconf_share_exists(conf_ctx, sharename)) {
663                 d_fprintf(stderr, _("ERROR: share %s already exists.\n"),
664                           sharename);
665                 goto done;
666         }
667
668         /* validate path */
669
670         if (path[0] != '/') {
671                 d_fprintf(stderr,
672                           _("Error: path '%s' is not an absolute path.\n"),
673                           path);
674                 goto done;
675         }
676
677         if (sys_stat(path, &sbuf, false) != 0) {
678                 d_fprintf(stderr,
679                           _("ERROR: cannot stat path '%s' to ensure "
680                             "this is a directory.\n"
681                             "Error was '%s'.\n"),
682                           path, strerror(errno));
683                 goto done;
684         }
685
686         if (!S_ISDIR(sbuf.st_ex_mode)) {
687                 d_fprintf(stderr,
688                           _("ERROR: path '%s' is not a directory.\n"),
689                           path);
690                 goto done;
691         }
692
693         /*
694          * start a transaction
695          */
696
697         werr = smbconf_transaction_start(conf_ctx);
698         if (!W_ERROR_IS_OK(werr)) {
699                 d_printf("error starting transaction: %s\n",
700                          win_errstr(werr));
701                 goto done;
702         }
703
704         /*
705          * create the share
706          */
707
708         werr = smbconf_create_share(conf_ctx, sharename);
709         if (!W_ERROR_IS_OK(werr)) {
710                 d_fprintf(stderr, _("Error creating share %s: %s\n"),
711                           sharename, win_errstr(werr));
712                 goto cancel;
713         }
714
715         /*
716          * fill the share with parameters
717          */
718
719         werr = smbconf_set_parameter(conf_ctx, sharename, "path", path);
720         if (!W_ERROR_IS_OK(werr)) {
721                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
722                           "path", win_errstr(werr));
723                 goto cancel;
724         }
725
726         if (comment != NULL) {
727                 werr = smbconf_set_parameter(conf_ctx, sharename, "comment",
728                                              comment);
729                 if (!W_ERROR_IS_OK(werr)) {
730                         d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
731                                   "comment", win_errstr(werr));
732                         goto cancel;
733                 }
734         }
735
736         werr = smbconf_set_parameter(conf_ctx, sharename, "guest ok", guest_ok);
737         if (!W_ERROR_IS_OK(werr)) {
738                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
739                           "'guest ok'", win_errstr(werr));
740                 goto cancel;
741         }
742
743         werr = smbconf_set_parameter(conf_ctx, sharename, "writeable",
744                                      writeable);
745         if (!W_ERROR_IS_OK(werr)) {
746                 d_fprintf(stderr, _("Error setting parameter %s: %s\n"),
747                           "writeable", win_errstr(werr));
748                 goto cancel;
749         }
750
751         /*
752          * commit the whole thing
753          */
754
755         werr = smbconf_transaction_commit(conf_ctx);
756         if (!W_ERROR_IS_OK(werr)) {
757                 d_printf("error committing transaction: %s\n",
758                          win_errstr(werr));
759         } else {
760                 ret = 0;
761         }
762
763         goto done;
764
765 cancel:
766         werr = smbconf_transaction_cancel(conf_ctx);
767         if (!W_ERROR_IS_OK(werr)) {
768                 d_printf("error cancelling transaction: %s\n",
769                          win_errstr(werr));
770         }
771
772 done:
773         TALLOC_FREE(mem_ctx);
774         return ret;
775 }
776
777 static int net_conf_delshare(struct net_context *c,
778                              struct smbconf_ctx *conf_ctx, int argc,
779                              const char **argv)
780 {
781         int ret = -1;
782         const char *sharename = NULL;
783         WERROR werr = WERR_OK;
784         TALLOC_CTX *mem_ctx = talloc_stackframe();
785
786         if (argc != 1 || c->display_usage) {
787                 net_conf_delshare_usage(c, argc, argv);
788                 goto done;
789         }
790         sharename = talloc_strdup(mem_ctx, argv[0]);
791         if (sharename == NULL) {
792                 d_printf(_("error: out of memory!\n"));
793                 goto done;
794         }
795
796         werr = smbconf_delete_share(conf_ctx, sharename);
797         if (!W_ERROR_IS_OK(werr)) {
798                 d_fprintf(stderr, _("Error deleting share %s: %s\n"),
799                           sharename, win_errstr(werr));
800                 goto done;
801         }
802
803         ret = 0;
804 done:
805         TALLOC_FREE(mem_ctx);
806         return ret;
807 }
808
809 static int net_conf_setparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
810                             int argc, const char **argv)
811 {
812         int ret = -1;
813         WERROR werr = WERR_OK;
814         char *service = NULL;
815         char *param = NULL;
816         const char *value_str = NULL;
817         TALLOC_CTX *mem_ctx = talloc_stackframe();
818
819         if (argc != 3 || c->display_usage) {
820                 net_conf_setparm_usage(c, argc, argv);
821                 goto done;
822         }
823         /*
824          * NULL service name means "dangling parameters" to libsmbconf.
825          * We use the empty string from the command line for this purpose.
826          */
827         if (strlen(argv[0]) != 0) {
828                 service = talloc_strdup(mem_ctx, argv[0]);
829                 if (service == NULL) {
830                         d_printf(_("error: out of memory!\n"));
831                         goto done;
832                 }
833         }
834         param = strlower_talloc(mem_ctx, argv[1]);
835         if (param == NULL) {
836                 d_printf(_("error: out of memory!\n"));
837                 goto done;
838         }
839         value_str = argv[2];
840
841         werr = smbconf_transaction_start(conf_ctx);
842         if (!W_ERROR_IS_OK(werr)) {
843                 d_printf(_("error starting transaction: %s\n"),
844                          win_errstr(werr));
845                 goto done;
846         }
847
848         if (!smbconf_share_exists(conf_ctx, service)) {
849                 werr = smbconf_create_share(conf_ctx, service);
850                 if (!W_ERROR_IS_OK(werr)) {
851                         d_fprintf(stderr, _("Error creating share '%s': %s\n"),
852                                   service, win_errstr(werr));
853                         goto cancel;
854                 }
855         }
856
857         werr = smbconf_set_parameter(conf_ctx, service, param, value_str);
858
859         if (!W_ERROR_IS_OK(werr)) {
860                 d_fprintf(stderr, _("Error setting value '%s': %s\n"),
861                           param, win_errstr(werr));
862                 goto cancel;
863         }
864
865         werr = smbconf_transaction_commit(conf_ctx);
866         if (!W_ERROR_IS_OK(werr)) {
867                 d_printf(_("error committing transaction: %s\n"),
868                          win_errstr(werr));
869         } else {
870                 ret = 0;
871         }
872
873         goto done;
874
875 cancel:
876         werr = smbconf_transaction_cancel(conf_ctx);
877         if (!W_ERROR_IS_OK(werr)) {
878                 d_printf(_("error cancelling transaction: %s\n"),
879                          win_errstr(werr));
880         }
881
882 done:
883         TALLOC_FREE(mem_ctx);
884         return ret;
885 }
886
887 static int net_conf_getparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
888                             int argc, const char **argv)
889 {
890         int ret = -1;
891         WERROR werr = WERR_OK;
892         char *service = NULL;
893         char *param = NULL;
894         char *valstr = NULL;
895         TALLOC_CTX *mem_ctx;
896
897         mem_ctx = talloc_stackframe();
898
899         if (argc != 2 || c->display_usage) {
900                 net_conf_getparm_usage(c, argc, argv);
901                 goto done;
902         }
903         /*
904          * NULL service name means "dangling parameters" to libsmbconf.
905          * We use the empty string from the command line for this purpose.
906          */
907         if (strlen(argv[0]) != 0) {
908                 service = talloc_strdup(mem_ctx, argv[0]);
909                 if (service == NULL) {
910                         d_printf(_("error: out of memory!\n"));
911                         goto done;
912                 }
913         }
914         param = strlower_talloc(mem_ctx, argv[1]);
915         if (param == NULL) {
916                 d_printf(_("error: out of memory!\n"));
917                 goto done;
918         }
919
920         werr = smbconf_get_parameter(conf_ctx, mem_ctx, service, param, &valstr);
921
922         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
923                 d_fprintf(stderr,
924                           _("Error: given service '%s' does not exist.\n"),
925                           service);
926                 goto done;
927         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
928                 d_fprintf(stderr,
929                           _("Error: given parameter '%s' is not set.\n"),
930                           param);
931                 goto done;
932         } else if (!W_ERROR_IS_OK(werr)) {
933                 d_fprintf(stderr, _("Error getting value '%s': %s.\n"),
934                           param, win_errstr(werr));
935                 goto done;
936         }
937
938         d_printf("%s\n", valstr);
939
940         ret = 0;
941 done:
942         TALLOC_FREE(mem_ctx);
943         return ret;
944 }
945
946 static int net_conf_delparm(struct net_context *c, struct smbconf_ctx *conf_ctx,
947                             int argc, const char **argv)
948 {
949         int ret = -1;
950         WERROR werr = WERR_OK;
951         char *service = NULL;
952         char *param = NULL;
953         TALLOC_CTX *mem_ctx = talloc_stackframe();
954
955         if (argc != 2 || c->display_usage) {
956                 net_conf_delparm_usage(c, argc, argv);
957                 goto done;
958         }
959         /*
960          * NULL service name means "dangling parameters" to libsmbconf.
961          * We use the empty string from the command line for this purpose.
962          */
963         if (strlen(argv[0]) != 0) {
964                 service = talloc_strdup(mem_ctx, argv[0]);
965                 if (service == NULL) {
966                         d_printf(_("error: out of memory!\n"));
967                         goto done;
968                 }
969         }
970         param = strlower_talloc(mem_ctx, argv[1]);
971         if (param == NULL) {
972                 d_printf("error: out of memory!\n");
973                 goto done;
974         }
975
976         werr = smbconf_delete_parameter(conf_ctx, service, param);
977
978         if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
979                 d_fprintf(stderr,
980                           _("Error: given service '%s' does not exist.\n"),
981                           service);
982                 goto done;
983         } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
984                 d_fprintf(stderr,
985                           _("Error: given parameter '%s' is not set.\n"),
986                           param);
987                 goto done;
988         } else if (!W_ERROR_IS_OK(werr)) {
989                 d_fprintf(stderr, _("Error deleting value '%s': %s.\n"),
990                           param, win_errstr(werr));
991                 goto done;
992         }
993
994         ret = 0;
995
996 done:
997         TALLOC_FREE(mem_ctx);
998         return ret;
999 }
1000
1001 static int net_conf_getincludes(struct net_context *c,
1002                                 struct smbconf_ctx *conf_ctx,
1003                                 int argc, const char **argv)
1004 {
1005         WERROR werr;
1006         uint32_t num_includes;
1007         uint32_t count;
1008         char *service;
1009         char **includes = NULL;
1010         int ret = -1;
1011         TALLOC_CTX *mem_ctx = talloc_stackframe();
1012
1013         if (argc != 1 || c->display_usage) {
1014                 net_conf_getincludes_usage(c, argc, argv);
1015                 goto done;
1016         }
1017
1018         service = talloc_strdup(mem_ctx, argv[0]);
1019         if (service == NULL) {
1020                 d_printf(_("error: out of memory!\n"));
1021                 goto done;
1022         }
1023
1024         werr = smbconf_get_includes(conf_ctx, mem_ctx, service,
1025                                     &num_includes, &includes);
1026         if (!W_ERROR_IS_OK(werr)) {
1027                 d_printf(_("error getting includes: %s\n"), win_errstr(werr));
1028                 goto done;
1029         }
1030
1031         for (count = 0; count < num_includes; count++) {
1032                 d_printf("include = %s\n", includes[count]);
1033         }
1034
1035         ret = 0;
1036
1037 done:
1038         TALLOC_FREE(mem_ctx);
1039         return ret;
1040 }
1041
1042 static int net_conf_setincludes(struct net_context *c,
1043                                 struct smbconf_ctx *conf_ctx,
1044                                 int argc, const char **argv)
1045 {
1046         WERROR werr;
1047         char *service;
1048         uint32_t num_includes;
1049         const char **includes;
1050         int ret = -1;
1051         TALLOC_CTX *mem_ctx = talloc_stackframe();
1052
1053         if (argc < 1 || c->display_usage) {
1054                 net_conf_setincludes_usage(c, argc, argv);
1055                 goto done;
1056         }
1057
1058         service = talloc_strdup(mem_ctx, argv[0]);
1059         if (service == NULL) {
1060                 d_printf(_("error: out of memory!\n"));
1061                 goto done;
1062         }
1063
1064         num_includes = argc - 1;
1065         if (num_includes == 0) {
1066                 includes = NULL;
1067         } else {
1068                 includes = argv + 1;
1069         }
1070
1071         werr = smbconf_set_includes(conf_ctx, service, num_includes, includes);
1072         if (!W_ERROR_IS_OK(werr)) {
1073                 d_printf(_("error setting includes: %s\n"), win_errstr(werr));
1074                 goto done;
1075         }
1076
1077         ret = 0;
1078
1079 done:
1080         TALLOC_FREE(mem_ctx);
1081         return ret;
1082 }
1083
1084 static int net_conf_delincludes(struct net_context *c,
1085                                 struct smbconf_ctx *conf_ctx,
1086                                 int argc, const char **argv)
1087 {
1088         WERROR werr;
1089         char *service;
1090         int ret = -1;
1091         TALLOC_CTX *mem_ctx = talloc_stackframe();
1092
1093         if (argc != 1 || c->display_usage) {
1094                 net_conf_delincludes_usage(c, argc, argv);
1095                 goto done;
1096         }
1097
1098         service = talloc_strdup(mem_ctx, argv[0]);
1099         if (service == NULL) {
1100                 d_printf(_("error: out of memory!\n"));
1101                 goto done;
1102         }
1103
1104         werr = smbconf_delete_includes(conf_ctx, service);
1105         if (!W_ERROR_IS_OK(werr)) {
1106                 d_printf(_("error deleting includes: %s\n"), win_errstr(werr));
1107                 goto done;
1108         }
1109
1110         ret = 0;
1111
1112 done:
1113         TALLOC_FREE(mem_ctx);
1114         return ret;
1115 }
1116
1117
1118 /**********************************************************************
1119  *
1120  * Wrapper and net_conf_run_function mechanism.
1121  *
1122  **********************************************************************/
1123
1124 /**
1125  * Wrapper function to call the main conf functions.
1126  * The wrapper calls handles opening and closing of the
1127  * configuration.
1128  */
1129 static int net_conf_wrap_function(struct net_context *c,
1130                                   int (*fn)(struct net_context *,
1131                                             struct smbconf_ctx *,
1132                                             int, const char **),
1133                                   int argc, const char **argv)
1134 {
1135         WERROR werr;
1136         TALLOC_CTX *mem_ctx = talloc_stackframe();
1137         struct smbconf_ctx *conf_ctx;
1138         int ret = -1;
1139
1140         werr = smbconf_init(mem_ctx, &conf_ctx, "registry:");
1141
1142         if (!W_ERROR_IS_OK(werr)) {
1143                 return -1;
1144         }
1145
1146         ret = fn(c, conf_ctx, argc, argv);
1147
1148         smbconf_shutdown(conf_ctx);
1149
1150         return ret;
1151 }
1152
1153 /*
1154  * We need a functable struct of our own, because the
1155  * functions are called through a wrapper that handles
1156  * the opening and closing of the configuration, and so on.
1157  */
1158 struct conf_functable {
1159         const char *funcname;
1160         int (*fn)(struct net_context *c, struct smbconf_ctx *ctx, int argc,
1161                   const char **argv);
1162         int valid_transports;
1163         const char *description;
1164         const char *usage;
1165 };
1166
1167 /**
1168  * This imitates net_run_function but calls the main functions
1169  * through the wrapper net_conf_wrap_function().
1170  */
1171 static int net_conf_run_function(struct net_context *c, int argc,
1172                                  const char **argv, const char *whoami,
1173                                  struct conf_functable *table)
1174 {
1175         int i;
1176
1177         if (argc != 0) {
1178                 for (i=0; table[i].funcname; i++) {
1179                         if (StrCaseCmp(argv[0], table[i].funcname) == 0)
1180                                 return net_conf_wrap_function(c, table[i].fn,
1181                                                               argc-1,
1182                                                               argv+1);
1183                 }
1184         }
1185
1186         d_printf(_("Usage:\n"));
1187         for (i=0; table[i].funcname; i++) {
1188                 if (c->display_usage == false)
1189                         d_printf("%s %-15s %s\n", whoami, table[i].funcname,
1190                                  table[i].description);
1191                 else
1192                         d_printf("%s\n", table[i].usage);
1193         }
1194
1195         return c->display_usage?0:-1;
1196 }
1197
1198 /*
1199  * Entry-point for all the CONF functions.
1200  */
1201
1202 int net_conf(struct net_context *c, int argc, const char **argv)
1203 {
1204         int ret = -1;
1205         struct conf_functable func_table[] = {
1206                 {
1207                         "list",
1208                         net_conf_list,
1209                         NET_TRANSPORT_LOCAL,
1210                         N_("Dump the complete configuration in smb.conf like "
1211                            "format."),
1212                         N_("net conf list\n"
1213                            "    Dump the complete configuration in smb.conf "
1214                            "like format.")
1215
1216                 },
1217                 {
1218                         "import",
1219                         net_conf_import,
1220                         NET_TRANSPORT_LOCAL,
1221                         N_("Import configuration from file in smb.conf "
1222                            "format."),
1223                         N_("net conf import\n"
1224                            "    Import configuration from file in smb.conf "
1225                            "format.")
1226                 },
1227                 {
1228                         "listshares",
1229                         net_conf_listshares,
1230                         NET_TRANSPORT_LOCAL,
1231                         N_("List the share names."),
1232                         N_("net conf listshares\n"
1233                            "    List the share names.")
1234                 },
1235                 {
1236                         "drop",
1237                         net_conf_drop,
1238                         NET_TRANSPORT_LOCAL,
1239                         N_("Delete the complete configuration."),
1240                         N_("net conf drop\n"
1241                            "    Delete the complete configuration.")
1242                 },
1243                 {
1244                         "showshare",
1245                         net_conf_showshare,
1246                         NET_TRANSPORT_LOCAL,
1247                         N_("Show the definition of a share."),
1248                         N_("net conf showshare\n"
1249                            "    Show the definition of a share.")
1250                 },
1251                 {
1252                         "addshare",
1253                         net_conf_addshare,
1254                         NET_TRANSPORT_LOCAL,
1255                         N_("Create a new share."),
1256                         N_("net conf addshare\n"
1257                            "    Create a new share.")
1258                 },
1259                 {
1260                         "delshare",
1261                         net_conf_delshare,
1262                         NET_TRANSPORT_LOCAL,
1263                         N_("Delete a share."),
1264                         N_("net conf delshare\n"
1265                            "    Delete a share.")
1266                 },
1267                 {
1268                         "setparm",
1269                         net_conf_setparm,
1270                         NET_TRANSPORT_LOCAL,
1271                         N_("Store a parameter."),
1272                         N_("net conf setparm\n"
1273                            "    Store a parameter.")
1274                 },
1275                 {
1276                         "getparm",
1277                         net_conf_getparm,
1278                         NET_TRANSPORT_LOCAL,
1279                         N_("Retrieve the value of a parameter."),
1280                         N_("net conf getparm\n"
1281                            "    Retrieve the value of a parameter.")
1282                 },
1283                 {
1284                         "delparm",
1285                         net_conf_delparm,
1286                         NET_TRANSPORT_LOCAL,
1287                         N_("Delete a parameter."),
1288                         N_("net conf delparm\n"
1289                            "    Delete a parameter.")
1290                 },
1291                 {
1292                         "getincludes",
1293                         net_conf_getincludes,
1294                         NET_TRANSPORT_LOCAL,
1295                         N_("Show the includes of a share definition."),
1296                         N_("net conf getincludes\n"
1297                            "    Show the includes of a share definition.")
1298                 },
1299                 {
1300                         "setincludes",
1301                         net_conf_setincludes,
1302                         NET_TRANSPORT_LOCAL,
1303                         N_("Set includes for a share."),
1304                         N_("net conf setincludes\n"
1305                            "    Set includes for a share.")
1306                 },
1307                 {
1308                         "delincludes",
1309                         net_conf_delincludes,
1310                         NET_TRANSPORT_LOCAL,
1311                         N_("Delete includes from a share definition."),
1312                         N_("net conf setincludes\n"
1313                            "    Delete includes from a share definition.")
1314                 },
1315                 {NULL, NULL, 0, NULL, NULL}
1316         };
1317
1318         ret = net_conf_run_function(c, argc, argv, "net conf", func_table);
1319
1320         return ret;
1321 }
1322