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
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 * This is an interface to Samba's configuration as made available
23 * by the libsmbconf interface (source/lib/smbconf/smbconf.c).
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.
31 #include "utils/net.h"
33 /**********************************************************************
37 **********************************************************************/
39 static int net_conf_list_usage(int argc
, const char **argv
)
41 d_printf("USAGE: net conf list\n");
45 static int net_conf_import_usage(int argc
, const char**argv
)
47 d_printf("USAGE: net conf import [--test|-T] <filename> "
49 "\t[--test|-T] testmode - do not act, just print "
50 "what would be done\n"
51 "\t<servicename> only import service <servicename>, "
56 static int net_conf_listshares_usage(int argc
, const char **argv
)
58 d_printf("USAGE: net conf listshares\n");
62 static int net_conf_drop_usage(int argc
, const char **argv
)
64 d_printf("USAGE: net conf drop\n");
68 static int net_conf_showshare_usage(int argc
, const char **argv
)
70 d_printf("USAGE: net conf showshare <sharename>\n");
74 static int net_conf_addshare_usage(int argc
, const char **argv
)
76 d_printf("USAGE: net conf addshare <sharename> <path> "
77 "[writeable={y|N} [guest_ok={y|N} [<comment>]]\n"
78 "\t<sharename> the new share name.\n"
79 "\t<path> the path on the filesystem to export.\n"
80 "\twriteable={y|N} set \"writeable to \"yes\" or "
81 "\"no\" (default) on this share.\n"
82 "\tguest_ok={y|N} set \"guest ok\" to \"yes\" or "
83 "\"no\" (default) on this share.\n"
84 "\t<comment> optional comment for the new share.\n");
88 static int net_conf_delshare_usage(int argc
, const char **argv
)
90 d_printf("USAGE: net conf delshare <sharename>\n");
94 static int net_conf_setparm_usage(int argc
, const char **argv
)
96 d_printf("USAGE: net conf setparm <section> <param> <value>\n");
100 static int net_conf_getparm_usage(int argc
, const char **argv
)
102 d_printf("USAGE: net conf getparm <section> <param>\n");
106 static int net_conf_delparm_usage(int argc
, const char **argv
)
108 d_printf("USAGE: net conf delparm <section> <param>\n");
113 /**********************************************************************
117 **********************************************************************/
120 * This formats an in-memory smbconf parameter to a string.
121 * The result string is allocated with talloc.
123 static char *parm_valstr(TALLOC_CTX
*ctx
, struct parm_struct
*parm
,
124 struct share_params
*share
)
128 void *ptr
= parm
->ptr
;
130 if (parm
->p_class
== P_LOCAL
&& share
->service
>= 0) {
131 ptr
= lp_local_ptr(share
->service
, ptr
);
134 switch (parm
->type
) {
136 valstr
= talloc_asprintf(ctx
, "%c", *(char *)ptr
);
140 valstr
= talloc_asprintf(ctx
, "%s", *(char **)ptr
);
143 valstr
= talloc_asprintf(ctx
, "%s", BOOLSTR(*(bool *)ptr
));
146 valstr
= talloc_asprintf(ctx
, "%s", BOOLSTR(!*(bool *)ptr
));
149 for (i
= 0; parm
->enum_list
[i
].name
; i
++) {
150 if (*(int *)ptr
== parm
->enum_list
[i
].value
)
152 valstr
= talloc_asprintf(ctx
, "%s",
153 parm
->enum_list
[i
].name
);
159 char *o
= octal_string(*(int *)ptr
);
160 valstr
= talloc_move(ctx
, &o
);
164 valstr
= talloc_strdup(ctx
, "");
165 if ((char ***)ptr
&& *(char ***)ptr
) {
166 char **list
= *(char ***)ptr
;
167 for (; *list
; list
++) {
168 /* surround strings with whitespace
169 * in double quotes */
170 if (strchr_m(*list
, ' '))
172 valstr
= talloc_asprintf_append(
175 ((*(list
+1))?", ":""));
177 valstr
= talloc_asprintf_append(
178 valstr
, "%s%s", *list
,
179 ((*(list
+1))?", ":""));
185 valstr
= talloc_asprintf(ctx
, "%d", *(int *)ptr
);
190 valstr
= talloc_asprintf(ctx
, "<type unimplemented>\n");
198 * This functions imports a configuration that has previously
199 * been loaded with lp_load() to registry.
201 static int import_process_service(TALLOC_CTX
*ctx
,
202 struct smbconf_ctx
*conf_ctx
,
203 struct share_params
*share
)
206 struct parm_struct
*parm
;
208 const char *servicename
;
211 TALLOC_CTX
*tmp_ctx
= NULL
;
213 tmp_ctx
= talloc_new(ctx
);
214 if (tmp_ctx
== NULL
) {
219 servicename
= (share
->service
== GLOBAL_SECTION_SNUM
)?
220 GLOBAL_NAME
: lp_servicename(share
->service
);
223 d_printf("[%s]\n", servicename
);
225 if (smbconf_share_exists(conf_ctx
, servicename
)) {
226 werr
= smbconf_delete_share(conf_ctx
, servicename
);
227 if (!W_ERROR_IS_OK(werr
)) {
231 werr
= smbconf_create_share(conf_ctx
, servicename
);
232 if (!W_ERROR_IS_OK(werr
)) {
237 while ((parm
= lp_next_parameter(share
->service
, &pnum
, 0)))
239 if ((share
->service
< 0) && (parm
->p_class
== P_LOCAL
)
240 && !(parm
->flags
& FLAG_GLOBAL
))
245 valstr
= parm_valstr(tmp_ctx
, parm
, share
);
247 if (parm
->type
!= P_SEP
) {
249 d_printf("\t%s = %s\n", parm
->label
, valstr
);
251 werr
= smbconf_set_parameter(conf_ctx
,
255 if (!W_ERROR_IS_OK(werr
)) {
257 "Error setting parameter '%s'"
258 ": %s\n", parm
->label
,
273 TALLOC_FREE(tmp_ctx
);
278 * Return true iff there are nondefault globals in the
279 * currently loaded configuration.
281 static bool globals_exist(void)
284 struct parm_struct
*parm
;
286 while ((parm
= lp_next_parameter(GLOBAL_SECTION_SNUM
, &i
, 0)) != NULL
) {
287 if (parm
->type
!= P_SEP
) {
295 /**********************************************************************
297 * the main conf functions
299 **********************************************************************/
301 static int net_conf_list(struct smbconf_ctx
*conf_ctx
,
302 int argc
, const char **argv
)
304 WERROR werr
= WERR_OK
;
309 uint32_t *num_params
;
311 char ***param_values
;
312 uint32_t share_count
, param_count
;
314 ctx
= talloc_init("list");
317 net_conf_list_usage(argc
, argv
);
321 werr
= smbconf_get_config(conf_ctx
, ctx
, &num_shares
, &share_names
,
322 &num_params
, ¶m_names
, ¶m_values
);
323 if (!W_ERROR_IS_OK(werr
)) {
324 d_fprintf(stderr
, "Error getting config: %s\n",
329 for (share_count
= 0; share_count
< num_shares
; share_count
++) {
330 d_printf("[%s]\n", share_names
[share_count
]);
331 for (param_count
= 0; param_count
< num_params
[share_count
];
334 d_printf("\t%s = %s\n",
335 param_names
[share_count
][param_count
],
336 param_values
[share_count
][param_count
]);
348 static int net_conf_import(struct smbconf_ctx
*conf_ctx
,
349 int argc
, const char **argv
)
352 const char *filename
= NULL
;
353 const char *servicename
= NULL
;
354 bool service_found
= false;
356 struct share_iterator
*shares
;
357 struct share_params
*share
;
358 struct share_params global_share
= { GLOBAL_SECTION_SNUM
};
360 ctx
= talloc_init("net_conf_import");
365 net_conf_import_usage(argc
, argv
);
368 servicename
= argv
[1];
374 DEBUG(3,("net_conf_import: reading configuration from file %s.\n",
377 if (!lp_load(filename
,
378 false, /* global_only */
379 true, /* save_defaults */
381 true)) /* initialize_globals */
383 d_fprintf(stderr
, "Error parsing configuration file.\n");
388 d_printf("\nTEST MODE - "
389 "would import the following configuration:\n\n");
392 if (((servicename
== NULL
) && globals_exist()) ||
393 strequal(servicename
, GLOBAL_NAME
))
395 service_found
= true;
396 if (import_process_service(ctx
, conf_ctx
, &global_share
) != 0) {
401 if (service_found
&& (servicename
!= NULL
)) {
406 if (!(shares
= share_list_all(ctx
))) {
407 d_fprintf(stderr
, "Could not list shares...\n");
410 while ((share
= next_share(shares
)) != NULL
) {
411 if ((servicename
== NULL
)
412 || strequal(servicename
, lp_servicename(share
->service
)))
414 service_found
= true;
415 if (import_process_service(ctx
, conf_ctx
, share
)!= 0) {
421 if ((servicename
!= NULL
) && !service_found
) {
422 d_printf("Share %s not found in file %s\n",
423 servicename
, filename
);
435 static int net_conf_listshares(struct smbconf_ctx
*conf_ctx
,
436 int argc
, const char **argv
)
438 WERROR werr
= WERR_OK
;
440 uint32_t count
, num_shares
= 0;
441 char **share_names
= NULL
;
444 ctx
= talloc_init("listshares");
447 net_conf_listshares_usage(argc
, argv
);
451 werr
= smbconf_get_share_names(conf_ctx
, ctx
, &num_shares
,
453 if (!W_ERROR_IS_OK(werr
)) {
457 for (count
= 0; count
< num_shares
; count
++)
459 d_printf("%s\n", share_names
[count
]);
469 static int net_conf_drop(struct smbconf_ctx
*conf_ctx
,
470 int argc
, const char **argv
)
476 net_conf_drop_usage(argc
, argv
);
480 werr
= smbconf_drop(conf_ctx
);
481 if (!W_ERROR_IS_OK(werr
)) {
482 d_fprintf(stderr
, "Error deleting configuration: %s\n",
493 static int net_conf_showshare(struct smbconf_ctx
*conf_ctx
,
494 int argc
, const char **argv
)
497 WERROR werr
= WERR_OK
;
498 const char *sharename
= NULL
;
505 ctx
= talloc_init("showshare");
508 net_conf_showshare_usage(argc
, argv
);
514 werr
= smbconf_get_share(conf_ctx
, ctx
, sharename
, &num_params
,
515 ¶m_names
, ¶m_values
);
516 if (!W_ERROR_IS_OK(werr
)) {
517 d_printf("error getting share parameters: %s\n",
522 d_printf("[%s]\n", sharename
);
524 for (count
= 0; count
< num_params
; count
++) {
525 d_printf("\t%s = %s\n", param_names
[count
],
526 param_values
[count
]);
537 * Add a share, with a couple of standard parameters, partly optional.
539 * This is a high level utility function of the net conf utility,
540 * not a direct frontend to the smbconf API.
542 static int net_conf_addshare(struct smbconf_ctx
*conf_ctx
,
543 int argc
, const char **argv
)
546 WERROR werr
= WERR_OK
;
547 char *sharename
= NULL
;
548 const char *path
= NULL
;
549 const char *comment
= NULL
;
550 const char *guest_ok
= "no";
551 const char *writeable
= "no";
552 SMB_STRUCT_STAT sbuf
;
558 net_conf_addshare_usage(argc
, argv
);
563 if (!strnequal(argv
[3], "guest_ok=", 9)) {
564 net_conf_addshare_usage(argc
, argv
);
567 switch (argv
[3][9]) {
577 net_conf_addshare_usage(argc
, argv
);
581 if (!strnequal(argv
[2], "writeable=", 10)) {
582 net_conf_addshare_usage(argc
, argv
);
585 switch (argv
[2][10]) {
595 net_conf_addshare_usage(argc
, argv
);
600 sharename
= strdup_lower(argv
[0]);
608 /* validate share name */
610 if (!validate_net_name(sharename
, INVALID_SHARENAME_CHARS
,
613 d_fprintf(stderr
, "ERROR: share name %s contains "
614 "invalid characters (any of %s)\n",
615 sharename
, INVALID_SHARENAME_CHARS
);
619 if (getpwnam(sharename
)) {
620 d_fprintf(stderr
, "ERROR: share name %s is already a valid "
621 "system user name.\n", sharename
);
625 if (strequal(sharename
, GLOBAL_NAME
)) {
627 "ERROR: 'global' is not a valid share name.\n");
631 if (smbconf_share_exists(conf_ctx
, sharename
)) {
632 d_fprintf(stderr
, "ERROR: share %s already exists.\n",
639 if (path
[0] != '/') {
641 "Error: path '%s' is not an absolute path.\n",
646 if (sys_stat(path
, &sbuf
) != 0) {
648 "ERROR: cannot stat path '%s' to ensure "
649 "this is a directory.\n"
651 path
, strerror(errno
));
655 if (!S_ISDIR(sbuf
.st_mode
)) {
657 "ERROR: path '%s' is not a directory.\n",
666 werr
= smbconf_create_share(conf_ctx
, sharename
);
667 if (!W_ERROR_IS_OK(werr
)) {
668 d_fprintf(stderr
, "Error creating share %s: %s\n",
669 sharename
, dos_errstr(werr
));
674 * fill the share with parameters
677 werr
= smbconf_set_parameter(conf_ctx
, sharename
, "path", path
);
678 if (!W_ERROR_IS_OK(werr
)) {
679 d_fprintf(stderr
, "Error setting parameter %s: %s\n",
680 "path", dos_errstr(werr
));
684 if (comment
!= NULL
) {
685 werr
= smbconf_set_parameter(conf_ctx
, sharename
, "comment",
687 if (!W_ERROR_IS_OK(werr
)) {
688 d_fprintf(stderr
, "Error setting parameter %s: %s\n",
689 "comment", dos_errstr(werr
));
694 werr
= smbconf_set_parameter(conf_ctx
, sharename
, "guest ok", guest_ok
);
695 if (!W_ERROR_IS_OK(werr
)) {
696 d_fprintf(stderr
, "Error setting parameter %s: %s\n",
697 "'guest ok'", dos_errstr(werr
));
701 werr
= smbconf_set_parameter(conf_ctx
, sharename
, "writeable",
703 if (!W_ERROR_IS_OK(werr
)) {
704 d_fprintf(stderr
, "Error setting parameter %s: %s\n",
705 "writeable", dos_errstr(werr
));
712 SAFE_FREE(sharename
);
716 static int net_conf_delshare(struct smbconf_ctx
*conf_ctx
,
717 int argc
, const char **argv
)
720 const char *sharename
= NULL
;
721 WERROR werr
= WERR_OK
;
724 net_conf_delshare_usage(argc
, argv
);
729 werr
= smbconf_delete_share(conf_ctx
, sharename
);
730 if (!W_ERROR_IS_OK(werr
)) {
731 d_fprintf(stderr
, "Error deleting share %s: %s\n",
732 sharename
, dos_errstr(werr
));
741 static int net_conf_setparm(struct smbconf_ctx
*conf_ctx
,
742 int argc
, const char **argv
)
745 WERROR werr
= WERR_OK
;
746 char *service
= NULL
;
748 const char *value_str
= NULL
;
751 net_conf_setparm_usage(argc
, argv
);
754 service
= strdup_lower(argv
[0]);
755 param
= strdup_lower(argv
[1]);
758 if (!smbconf_share_exists(conf_ctx
, service
)) {
759 werr
= smbconf_create_share(conf_ctx
, service
);
760 if (!W_ERROR_IS_OK(werr
)) {
761 d_fprintf(stderr
, "Error creating share '%s': %s\n",
762 service
, dos_errstr(werr
));
767 werr
= smbconf_set_parameter(conf_ctx
, service
, param
, value_str
);
769 if (!W_ERROR_IS_OK(werr
)) {
770 d_fprintf(stderr
, "Error setting value '%s': %s\n",
771 param
, dos_errstr(werr
));
783 static int net_conf_getparm(struct smbconf_ctx
*conf_ctx
,
784 int argc
, const char **argv
)
787 WERROR werr
= WERR_OK
;
788 char *service
= NULL
;
793 ctx
= talloc_init("getparm");
796 net_conf_getparm_usage(argc
, argv
);
799 service
= strdup_lower(argv
[0]);
800 param
= strdup_lower(argv
[1]);
802 werr
= smbconf_get_parameter(conf_ctx
, ctx
, service
, param
, &valstr
);
804 if (W_ERROR_EQUAL(werr
, WERR_NO_SUCH_SERVICE
)) {
806 "Error: given service '%s' does not exist.\n",
809 } else if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
811 "Error: given parameter '%s' is not set.\n",
814 } else if (!W_ERROR_IS_OK(werr
)) {
815 d_fprintf(stderr
, "Error getting value '%s': %s.\n",
816 param
, dos_errstr(werr
));
820 d_printf("%s\n", valstr
);
830 static int net_conf_delparm(struct smbconf_ctx
*conf_ctx
,
831 int argc
, const char **argv
)
834 WERROR werr
= WERR_OK
;
835 char *service
= NULL
;
839 net_conf_delparm_usage(argc
, argv
);
842 service
= strdup_lower(argv
[0]);
843 param
= strdup_lower(argv
[1]);
845 werr
= smbconf_delete_parameter(conf_ctx
, service
, param
);
847 if (W_ERROR_EQUAL(werr
, WERR_NO_SUCH_SERVICE
)) {
849 "Error: given service '%s' does not exist.\n",
852 } else if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
854 "Error: given parameter '%s' is not set.\n",
857 } else if (!W_ERROR_IS_OK(werr
)) {
858 d_fprintf(stderr
, "Error deleting value '%s': %s.\n",
859 param
, dos_errstr(werr
));
872 /**********************************************************************
874 * Wrapper and net_conf_run_function mechanism.
876 **********************************************************************/
879 * Wrapper function to call the main conf functions.
880 * The wrapper calls handles opening and closing of the
883 static int net_conf_wrap_function(int (*fn
)(struct smbconf_ctx
*,
885 int argc
, const char **argv
)
888 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
889 struct smbconf_ctx
*conf_ctx
;
892 werr
= smbconf_init_reg(mem_ctx
, &conf_ctx
, NULL
);
894 if (!W_ERROR_IS_OK(werr
)) {
898 ret
= fn(conf_ctx
, argc
, argv
);
900 smbconf_shutdown(conf_ctx
);
906 * We need a functable struct of our own, because the
907 * functions are called through a wrapper that handles
908 * the opening and closing of the configuration, and so on.
910 struct conf_functable
{
911 const char *funcname
;
912 int (*fn
)(struct smbconf_ctx
*ctx
, int argc
, const char **argv
);
913 const char *helptext
;
917 * This imitates net_run_function2 but calls the main functions
918 * through the wrapper net_conf_wrap_function().
920 static int net_conf_run_function(int argc
, const char **argv
,
922 struct conf_functable
*table
)
927 for (i
=0; table
[i
].funcname
; i
++) {
928 if (StrCaseCmp(argv
[0], table
[i
].funcname
) == 0)
929 return net_conf_wrap_function(table
[i
].fn
,
935 for (i
=0; table
[i
].funcname
; i
++) {
936 d_printf("%s %-15s %s\n", whoami
, table
[i
].funcname
,
944 * Entry-point for all the CONF functions.
947 int net_conf(int argc
, const char **argv
)
950 struct conf_functable func_table
[] = {
951 {"list", net_conf_list
,
952 "Dump the complete configuration in smb.conf like format."},
953 {"import", net_conf_import
,
954 "Import configuration from file in smb.conf format."},
955 {"listshares", net_conf_listshares
,
956 "List the share names."},
957 {"drop", net_conf_drop
,
958 "Delete the complete configuration."},
959 {"showshare", net_conf_showshare
,
960 "Show the definition of a share."},
961 {"addshare", net_conf_addshare
,
962 "Create a new share."},
963 {"delshare", net_conf_delshare
,
965 {"setparm", net_conf_setparm
,
966 "Store a parameter."},
967 {"getparm", net_conf_getparm
,
968 "Retrieve the value of a parameter."},
969 {"delparm", net_conf_delparm
,
970 "Delete a parameter."},
974 ret
= net_conf_run_function(argc
, argv
, "net conf", func_table
);