diff mbox series

[4/9] share: introduce share_cmd

Message ID 20220307013344.29064-5-ematsumiya@suse.de
State New
Headers show
Series Unify all programs into a single binary "ksmbdctl" | expand

Commit Message

Enzo Matsumiya March 7, 2022, 1:33 a.m. UTC
Create share command in preparation for binary unification.

Introduce a command to list available shares.

Makes open_smbconf() optionally truncate the file (for list command).

Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
---
 include/ksmbdtools.h |  16 ++-
 share/Makefile.am    |   2 +-
 share/addshare.c     | 172 --------------------------------
 share/share.c        | 227 +++++++++++++++++++++++++++++++++++++++++++
 share/share_admin.c  |  85 ++++++++++++----
 share/share_admin.h  |  35 ++++++-
 6 files changed, 335 insertions(+), 202 deletions(-)
 delete mode 100644 share/addshare.c
 create mode 100644 share/share.c

Comments

Namjae Jeon March 10, 2022, 2:19 a.m. UTC | #1
2022-03-07 10:33 GMT+09:00, Enzo Matsumiya <ematsumiya@suse.de>:
> Create share command in preparation for binary unification.
>
> Introduce a command to list available shares.
>
> Makes open_smbconf() optionally truncate the file (for list command).
>
> Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
> ---
>  include/ksmbdtools.h |  16 ++-
>  share/Makefile.am    |   2 +-
>  share/addshare.c     | 172 --------------------------------
>  share/share.c        | 227 +++++++++++++++++++++++++++++++++++++++++++
>  share/share_admin.c  |  85 ++++++++++++----
>  share/share_admin.h  |  35 ++++++-
>  6 files changed, 335 insertions(+), 202 deletions(-)
>  delete mode 100644 share/addshare.c
>  create mode 100644 share/share.c
>
> diff --git a/include/ksmbdtools.h b/include/ksmbdtools.h
> index 170ce23ead2c..fccb88d8898a 100644
> --- a/include/ksmbdtools.h
> +++ b/include/ksmbdtools.h
> @@ -101,12 +101,14 @@ extern int ksmbd_health_status;
>  //---------------------------------------------------------------//
>  #define LOGAPP		"[%s/%d]:"
>  #define PRERR		LOGAPP" ERROR: "
> +#define PRWARN		LOGAPP" WARN: "
>  #define PRINF		LOGAPP" INFO: "
>  #define PRDEBUG		LOGAPP" DEBUG: "
>
>  #define PR_ERROR	0
> -#define PR_INFO		1
> -#define PR_DEBUG	2
> +#define PR_WARN		1
> +#define PR_INFO		2
> +#define PR_DEBUG	3
>
>  static int log_level = PR_INFO;
>
> @@ -134,12 +136,16 @@ extern void pr_logger_init(int flags);
>  					##__VA_ARGS__);			\
>  	} while (0)
>
> -#define pr_debug(f, ...)	\
> +#define pr_debug(f, ...) \
>  	pr_log(PR_DEBUG, PRDEBUG f, ##__VA_ARGS__)
> -#define pr_info(f, ...)	\
> +#define pr_info(f, ...) \
>  	pr_log(PR_INFO, PRINF f, ##__VA_ARGS__)
> -#define pr_err(f, ...)	\
> +#define pr_warn(f, ...) \
> +	pr_log(PR_WARN, PRWARN f, ##__VA_ARGS__)
> +#define pr_err(f, ...) \
>  	pr_log(PR_ERROR, PRERR f, ##__VA_ARGS__)
> +#define pr_out(f, ...) \
> +	fprintf(stderr, f, ##__VA_ARGS__)
>
>  //---------------------------------------------------------------//
>
> diff --git a/share/Makefile.am b/share/Makefile.am
> index dafc985add5d..bea487edfeeb 100644
> --- a/share/Makefile.am
> +++ b/share/Makefile.am
> @@ -4,4 +4,4 @@ ksmbd_addshare_LDADD = $(top_builddir)/lib/libksmbdtools.a
>
>  sbin_PROGRAMS = ksmbd.addshare
>
> -ksmbd_addshare_SOURCES = share_admin.c addshare.c share_admin.h
> +ksmbd_addshare_SOURCES = share_admin.c share.c share_admin.h
> diff --git a/share/addshare.c b/share/addshare.c
> deleted file mode 100644
> index 4ff94b18a641..000000000000
> --- a/share/addshare.c
> +++ /dev/null
> @@ -1,172 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-or-later
> -/*
> - *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
> - *
> - *   linux-cifsd-devel@lists.sourceforge.net
> - */
> -
> -#include <glib.h>
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <unistd.h>
> -#include <getopt.h>
> -#include <sys/stat.h>
> -#include <fcntl.h>
> -#include <sys/types.h>
> -#include <signal.h>
> -#include <errno.h>
> -#include <ctype.h>
> -
> -#include "config_parser.h"
> -#include "ksmbdtools.h"
> -#include "management/share.h"
> -#include "linux/ksmbd_server.h"
> -#include "share_admin.h"
> -#include "version.h"
> -
> -static char *arg_name;
> -static char *arg_opts;
> -
> -enum {
> -	COMMAND_ADD_SHARE = 1,
> -	COMMAND_DEL_SHARE,
> -	COMMAND_UPDATE_SHARE,
> -};
> -
> -static void usage(void)
> -{
> -	int i;
> -
> -	fprintf(stderr, "Usage: smbshareadd\n");
> -
> -	fprintf(stderr, "\t-a | --add-share=share\n");
> -	fprintf(stderr, "\t-d | --del-share=share\n");
> -	fprintf(stderr, "\t-u | --update-share=share\n");
> -	fprintf(stderr, "\t-o | --options=\"op1=val1 op2=val2...\"\n");
> -
> -	fprintf(stderr, "\t-c smb.conf\n");
> -	fprintf(stderr, "\t-V | --version\n");
> -	fprintf(stderr, "\t-v | --verbose\n");
> -
> -	fprintf(stderr, "Supported share options:\n");
> -	for (i = 0; i < KSMBD_SHARE_CONF_MAX; i++)
> -		fprintf(stderr, "\t%s\n", KSMBD_SHARE_CONF[i]);
> -	exit(EXIT_FAILURE);
> -}
> -
> -static void show_version(void)
> -{
> -	printf("ksmbd-tools version : %s\n", KSMBD_TOOLS_VERSION);
> -	exit(EXIT_FAILURE);
> -}
> -
> -static int parse_configs(char *smbconf)
> -{
> -	int ret;
> -
> -	ret = test_file_access(smbconf);
> -	if (ret)
> -		return ret;
> -
> -	ret = cp_smbconfig_hash_create(smbconf);
> -	if (ret)
> -		return ret;
> -	return 0;
> -}
> -
> -static int sanity_check_share_name_simple(char *name)
> -{
> -	int sz, i;
> -
> -	if (!name)
> -		return -EINVAL;
> -
> -	sz = strlen(name);
> -	if (sz < 1)
> -		return -EINVAL;
> -	if (sz >= KSMBD_REQ_MAX_SHARE_NAME)
> -		return -EINVAL;
> -
> -	if (!cp_key_cmp(name, "global"))
> -		return -EINVAL;
> -
> -	return -EINVAL;
> -}
> -
> -int main(int argc, char *argv[])
> -{
> -	int ret = EXIT_FAILURE;
> -	char *smbconf = PATH_SMBCONF;
> -	int c, cmd = 0;
> -
> -	set_logger_app_name("ksmbd.addshare");
> -
> -	opterr = 0;
> -	while ((c = getopt(argc, argv, "c:a:d:u:p:o:Vvh")) != EOF)
> -		switch (c) {
> -		case 'a':
> -			arg_name = g_ascii_strdown(optarg, strlen(optarg));
> -			cmd = COMMAND_ADD_SHARE;
> -			break;
> -		case 'd':
> -			arg_name = g_ascii_strdown(optarg, strlen(optarg));
> -			cmd = COMMAND_DEL_SHARE;
> -			break;
> -		case 'u':
> -			arg_name = g_ascii_strdown(optarg, strlen(optarg));
> -			cmd = COMMAND_UPDATE_SHARE;
> -			break;
> -		case 'c':
> -			smbconf = strdup(optarg);
> -			break;
> -		case 'o':
> -			arg_opts = strdup(optarg);
> -			break;
> -		case 'V':
> -			show_version();
> -			break;
> -		case 'v':
> -			break;
> -		case '?':
> -		case 'h':
> -		default:
> -			usage();
> -	}
> -
> -	if (cmd != COMMAND_DEL_SHARE && !arg_opts) {
> -		usage();
> -		return -1;
> -	}
> -
> -	if (sanity_check_share_name_simple(arg_name)) {
> -		pr_err("share name sanity check failure\n");
> -		goto out;
> -	}
> -
> -	if (!smbconf) {
> -		pr_err("Out of memory\n");
> -		goto out;
> -	}
> -
> -	ret = parse_configs(smbconf);
> -	if (ret) {
> -		pr_err("Unable to parse configuration files\n");
> -		goto out;
> -	}
> -
> -	if (cmd == COMMAND_ADD_SHARE)
> -		ret = command_add_share(smbconf, arg_name, arg_opts);
> -	if (cmd == COMMAND_DEL_SHARE)
> -		ret = command_del_share(smbconf, arg_name);
> -	if (cmd == COMMAND_UPDATE_SHARE)
> -		ret = command_update_share(smbconf, arg_name, arg_opts);
> -
> -	/*
> -	 * We support only ADD_SHARE command for the time being
> -	 */
> -	if (ret == 0 && cmd == COMMAND_ADD_SHARE)
> -		notify_ksmbd_daemon();
> -out:
> -	cp_smbconfig_destroy();
> -	return ret;
> -}
> diff --git a/share/share.c b/share/share.c
> new file mode 100644
> index 000000000000..91d23d28c426
> --- /dev/null
> +++ b/share/share.c
> @@ -0,0 +1,227 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
> + *   Copyright (C) 2021 SUSE LLC
> + *
> + *   linux-cifsd-devel@lists.sourceforge.net
> + */
> +
> +#include <glib.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <getopt.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <sys/types.h>
> +#include <signal.h>
> +#include <errno.h>
> +#include <ctype.h>
> +
> +#include "config_parser.h"
> +#include "ksmbdtools.h"
> +#include "management/share.h"
> +#include "linux/ksmbd_server.h"
> +#include "share_admin.h"
> +
> +static ksmbd_share_cmd ksmbd_share_get_cmd(char *cmd)
> +{
> +	int i;
> +
> +	if (!cmd)
> +		return KSMBD_CMD_SHARE_NONE;
> +
> +	for (i = 1; i < KSMBD_CMD_SHARE_MAX; i++)
> +		if (!strcmp(cmd, ksmbd_share_cmds_str[i]))
> +			return (ksmbd_share_cmd)i;
> +
> +	return KSMBD_CMD_SHARE_NONE;
> +}
> +
> +static const char *ksmbd_share_get_cmd_str(ksmbd_share_cmd cmd)
> +{
> +	if (cmd > KSMBD_CMD_SHARE_MAX)
> +		return ksmbd_share_cmds_str[KSMBD_CMD_SHARE_NONE];
> +
> +	return ksmbd_share_cmds_str[(int)cmd];
> +}
> +
> +static int parse_configs(char *smbconf)
> +{
> +	int ret;
> +
> +	ret = test_file_access(smbconf);
> +	if (ret)
> +		return ret;
> +
> +	ret = cp_smbconfig_hash_create(smbconf);
> +	if (ret)
> +		return ret;
> +	return 0;
> +}
> +
> +static int sanity_check_share_name_simple(char *name)
> +{
> +	int sz, i;
> +
> +	if (!name)
> +		return -EINVAL;
> +
> +	sz = strlen(name);
> +	if (sz < 1)
> +		return -EINVAL;
> +	if (sz >= KSMBD_REQ_MAX_SHARE_NAME)
> +		return -EINVAL;
> +
> +	if (!cp_key_cmp(name, "global"))
> +		return -EINVAL;
> +
> +	for (i = 0; i < sz; i++) {
> +		if (isalnum(name[i]))
This check was removed before. Please remove this.

Thanks.
> +			return 0;
> +	}
> +	return -EINVAL;
> +}
> +
> +void share_usage(ksmbd_share_cmd cmd)
> +{
> +	int i;
> +	const char *cmd_str = ksmbd_share_get_cmd_str(cmd);
> +
> +	switch (cmd) {
> +	case KSMBD_CMD_SHARE_ADD:
> +	case KSMBD_CMD_SHARE_UPDATE:
> +		pr_out("Usage: ksmbdctl share %s <share_name> [-c <file>] -o
> \"op1=val1,op2=val2,...\"\n", cmd_str);
> +		pr_out("Adds or updates a share to smb.conf file.\n\n");
> +		pr_out("%-30s%s", "  -c, --conf=<file>", "Use <file> as smb.conf\n");
> +		pr_out("%-30s%s", "  -o, --options=<options>", "Specify options for
> share\n\n");
> +		pr_out("Supported share options:\n");
> +		for (i = 0; i < KSMBD_SHARE_CONF_MAX; i++)
> +			pr_out("%s\n", KSMBD_SHARE_CONF[i]);
> +		break;
> +	case KSMBD_CMD_SHARE_DELETE:
> +		pr_out("Usage: ksmbdctl share delete <share_name>\n");
> +		pr_out("Deletes a share.\n\n");
> +		break;
> +	default:
> +		pr_out("Usage: ksmbdctl share <subcommand> <args> [options]\n");
> +		pr_out("Share management.\n\n");
> +		pr_out("List of available subcommands:\n");
> +		pr_out("%-20s%s", "  add", "Add a share\n");
> +		pr_out("%-20s%s", "  delete", "Delete a share\n");
> +		pr_out("%-20s%s", "  update", "Update a share\n");
> +		pr_out("%-20s%s", "  list", "List the names of all shares
> available\n\n");
> +		break;
> +	}
> +
> +	exit(EXIT_FAILURE);
> +}
> +
> +int share_cmd(int argc, char *argv[])
> +{
> +	int ret = EXIT_FAILURE;
> +	char *smbconf = PATH_SMBCONF;
> +	char *share_name = NULL;
> +	char *options = NULL;
> +	ksmbd_share_cmd cmd = KSMBD_CMD_SHARE_NONE;
> +	int c;
> +
> +	if (argc < 2)
> +		goto usage;
> +
> +	set_logger_app_name("ksmbd-share");
> +
> +	cmd = ksmbd_share_get_cmd(argv[1]);
> +
> +	if (cmd == KSMBD_CMD_SHARE_NONE)
> +		goto usage;
> +
> +	if(argc == 2 && cmd != KSMBD_CMD_SHARE_LIST)
> +		goto missing_arg;
> +
> +	if (argv[2] && argv[2][0] != '-')
> +		share_name = g_ascii_strdown(argv[2], strlen(argv[2]));
> +	else if (cmd != KSMBD_CMD_SHARE_LIST)
> +		goto usage;
> +
> +	optind = 1;
> +	while ((c = getopt_long(argc, argv, "-:c:o:", share_opts, NULL)) != EOF)
> +		switch (c) {
> +		case 1:
> +			break;
> +		case 'c':
> +			if (cmd == KSMBD_CMD_SHARE_DELETE)
> +				continue;
> +			smbconf = strdup(optarg);
> +			break;
> +		case 'o':
> +			if (cmd == KSMBD_CMD_SHARE_DELETE || cmd == KSMBD_CMD_SHARE_LIST)
> +				continue;
> +			options = strdup(optarg);
> +			break;
> +		case ':':
> +		case '?':
> +		default:
> +			goto usage;
> +		}
> +
> +	if (cmd == KSMBD_CMD_SHARE_LIST)
> +		goto share_list;
> +
> +	if (!share_name)
> +		goto missing_arg;
> +
> +	if (cmd != KSMBD_CMD_SHARE_DELETE && !options) {
> +		pr_out("Subcommand \"%s\" requires '-o' option set.\n\n",
> ksmbd_share_get_cmd_str(cmd));
> +		goto usage;
> +	}
> +
> +	if (sanity_check_share_name_simple(share_name)) {
> +		pr_err("Share name (%s) sanity check failure\n", share_name);
> +		goto out;
> +	}
> +
> +share_list:
> +	if (!smbconf) {
> +		pr_err("Out of memory\n");
> +		goto out;
> +	}
> +
> +	ret = parse_configs(smbconf);
> +	if (ret) {
> +		pr_err("Unable to parse configuration file %s\n", smbconf);
> +		goto out;
> +	}
> +
> +	switch (cmd) {
> +	case KSMBD_CMD_SHARE_ADD:
> +		ret = share_add_cmd(smbconf, share_name, options);
> +		break;
> +	case KSMBD_CMD_SHARE_DELETE:
> +		ret = share_delete_cmd(smbconf, share_name);
> +		break;
> +	case KSMBD_CMD_SHARE_UPDATE:
> +		ret = share_update_cmd(smbconf, share_name, options);
> +		break;
> +	case KSMBD_CMD_SHARE_LIST:
> +		ret = share_list_cmd(smbconf);
> +		break;
> +	}
> +
> +	/*
> +	 * FIXME: We support only ADD_SHARE command for the time being
> +	 */
> +	if (ret == 0 && cmd == KSMBD_CMD_SHARE_ADD)
> +		notify_ksmbd_daemon();
> +
> +out:
> +	cp_smbconfig_destroy();
> +	return ret;
> +missing_arg:
> +	if (cmd > KSMBD_CMD_SHARE_NONE && cmd < KSMBD_CMD_SHARE_MAX)
> +		pr_out("Subcommand \"%s\" requires an argument.\n\n",
> ksmbd_share_get_cmd_str(cmd));
> +usage:
> +	share_usage(cmd);
> +
> +	return ret;
> +}
> diff --git a/share/share_admin.c b/share/share_admin.c
> index 0ff13d8017dd..61780fb00b5a 100644
> --- a/share/share_admin.c
> +++ b/share/share_admin.c
> @@ -1,12 +1,14 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
> + *   Copyright (C) 2021 SUSE LLC
>   *
>   *   linux-cifsd-devel@lists.sourceforge.net
>   */
>
>  #include <glib.h>
>  #include <stdlib.h>
> +#include <stdbool.h>
>  #include <stdio.h>
>  #include <unistd.h>
>  #include <getopt.h>
> @@ -48,24 +50,26 @@ static char *aux_group_name(char *name)
>  	return gn;
>  }
>
> -static int __open_smbconf(char *smbconf)
> +static int open_smbconf(char *smbconf, bool truncate)
>  {
> -	conf_fd = open(smbconf, O_WRONLY);
> +	conf_fd = open(smbconf, O_RDWR);
>  	if (conf_fd == -1) {
>  		pr_err("%s %s\n", strerr(errno), smbconf);
>  		return -EINVAL;
>  	}
>
> -	if (ftruncate(conf_fd, 0)) {
> -		pr_err("%s %s\n", strerr(errno), smbconf);
> -		close(conf_fd);
> -		return -EINVAL;
> +	if (truncate) {
> +		if (ftruncate(conf_fd, 0)) {
> +			pr_err("%s %s\n", strerr(errno), smbconf);
> +			close(conf_fd);
> +			return -EINVAL;
> +		}
>  	}
>
>  	return 0;
>  }
>
> -static void __write(void)
> +static void do_write(void)
>  {
>  	int nr = 0;
>  	int ret;
> @@ -83,7 +87,7 @@ static void __write(void)
>  	}
>  }
>
> -static void __write_share(gpointer key, gpointer value, gpointer buf)
> +static void write_share(gpointer key, gpointer value, gpointer buf)
>  {
>  	char *k = (char *)key;
>  	char *v = (char *)value;
> @@ -95,14 +99,14 @@ static void __write_share(gpointer key, gpointer value,
> gpointer buf)
>  			sizeof(wbuf));
>  		exit(EXIT_FAILURE);
>  	}
> -	__write();
> +	do_write();
>  }
>
> -static void write_share(struct smbconf_group *g)
> +static void write_share_all(struct smbconf_group *g)
>  {
>  	wsz = snprintf(wbuf, sizeof(wbuf), "[%s]\n", g->name);
> -	__write();
> -	g_hash_table_foreach(g->kv, __write_share, NULL);
> +	do_write();
> +	g_hash_table_foreach(g->kv, write_share, NULL);
>  }
>
>  static void write_share_cb(gpointer key, gpointer value, gpointer
> share_data)
> @@ -113,7 +117,7 @@ static void write_share_cb(gpointer key, gpointer value,
> gpointer share_data)
>  	 * Do not write AUX group
>  	 */
>  	if (!strstr(g->name, AUX_GROUP_PREFIX))
> -		write_share(g);
> +		write_share_all(g);
>  }
>
>  static void write_remove_share_cb(gpointer key,
> @@ -127,7 +131,7 @@ static void write_remove_share_cb(gpointer key,
>  		return;
>  	}
>
> -	write_share(g);
> +	write_share_all(g);
>  }
>
>  static void update_share_cb(gpointer key,
> @@ -145,12 +149,32 @@ static void update_share_cb(gpointer key,
>  	g_hash_table_insert(g, nk, nv);
>  }
>
> -int command_add_share(char *smbconf, char *name, char *opts)
> +static void list_shares_cb(gpointer key, gpointer value, gpointer data)
> +{
> +	char *nk, *nv;
> +
> +	nk = g_strdup(key);
> +	nv = g_strdup(value);
> +
> +	if (!nk || !nv)
> +		exit(EXIT_FAILURE);
> +
> +	if (!strcmp(nk, "global"))
> +		goto out;
> +
> +	pr_out("%s\n", nk);
> +
> +out:
> +	g_free(nk);
> +	g_free(nv);
> +}
> +
> +int share_add_cmd(char *smbconf, char *name, char *opts)
>  {
>  	char *new_name = NULL;
>
>  	if (g_hash_table_lookup(parser.groups, name)) {
> -		pr_err("Share already exists: %s\n", name);
> +		pr_warn("Share already exists: %s\n", name);
>  		return -EEXIST;
>  	}
>
> @@ -158,7 +182,7 @@ int command_add_share(char *smbconf, char *name, char
> *opts)
>  	if (cp_parse_external_smbconf_group(new_name, opts))
>  		goto error;
>
> -	if (__open_smbconf(smbconf))
> +	if (open_smbconf(smbconf, true))
>  		goto error;
>  	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
>  	close(conf_fd);
> @@ -170,7 +194,7 @@ error:
>  	return -EINVAL;
>  }
>
> -int command_update_share(char *smbconf, char *name, char *opts)
> +int share_update_cmd(char *smbconf, char *name, char *opts)
>  {
>  	struct smbconf_group *existing_group;
>  	struct smbconf_group *update_group;
> @@ -198,7 +222,7 @@ int command_update_share(char *smbconf, char *name, char
> *opts)
>  			     update_share_cb,
>  			     existing_group->kv);
>
> -	if (__open_smbconf(smbconf))
> +	if (open_smbconf(smbconf, true))
>  		goto error;
>
>  	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
> @@ -211,9 +235,9 @@ error:
>  	return -EINVAL;
>  }
>
> -int command_del_share(char *smbconf, char *name)
> +int share_delete_cmd(char *smbconf, char *name)
>  {
> -	if (__open_smbconf(smbconf))
> +	if (open_smbconf(smbconf, true))
>  		return -EINVAL;
>
>  	g_hash_table_foreach(parser.groups,
> @@ -222,3 +246,22 @@ int command_del_share(char *smbconf, char *name)
>  	close(conf_fd);
>  	return 0;
>  }
> +
> +int share_list_cmd(char *smbconf)
> +{
> +	if (open_smbconf(smbconf, false))
> +		return -EINVAL;
> +
> +	if (g_hash_table_size(parser.groups) <= 1) {
> +		pr_out("No shares available in %s.\n", smbconf);
> +		goto out;
> +	}
> +
> +	pr_out("Shares available in %s:\n", smbconf);
> +	g_hash_table_foreach(parser.groups,
> +			     list_shares_cb,
> +			     NULL);
> +out:
> +	close(conf_fd);
> +	return 0;
> +}
> diff --git a/share/share_admin.h b/share/share_admin.h
> index 7df3871bfe81..00cf1147af18 100644
> --- a/share/share_admin.h
> +++ b/share/share_admin.h
> @@ -1,6 +1,7 @@
>  /* SPDX-License-Identifier: GPL-2.0-or-later */
>  /*
>   *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
> + *   Copyright (C) 2021 SUSE LLC
>   *
>   *   linux-cifsd-devel@lists.sourceforge.net
>   */
> @@ -8,8 +9,36 @@
>  #ifndef __KSMBD_SHARE_ADMIN_H__
>  #define __KSMBD_SHARE_ADMIN_H__
>
> -int command_add_share(char *smbconf, char *name, char *opts);
> -int command_update_share(char *smbconf, char *name, char *opts);
> -int command_del_share(char *smbconf, char *name);
> +int share_add_cmd(char *smbconf, char *name, char *opts);
> +int share_delete_cmd(char *smbconf, char *name);
> +int share_update_cmd(char *smbconf, char *name, char *opts);
> +int share_list_cmd(char *smbconf);
> +
> +typedef enum {
> +	KSMBD_CMD_SHARE_NONE = 0,
> +	KSMBD_CMD_SHARE_ADD,
> +	KSMBD_CMD_SHARE_DELETE,
> +	KSMBD_CMD_SHARE_UPDATE,
> +	KSMBD_CMD_SHARE_LIST,
> +	KSMBD_CMD_SHARE_MAX
> +} ksmbd_share_cmd;
> +
> +/* List of supported subcommands */
> +static const char *ksmbd_share_cmds_str[] = {
> +	"none",
> +	"add",
> +	"delete",
> +	"update",
> +	"list"
> +};
> +
> +static struct option share_opts[] = {
> +        { "conf", required_argument, NULL, 'c' },
> +        { "options", required_argument, NULL, 'o' },
> +	{ 0, 0, 0, 0 },
> +};
> +
> +void share_usage(ksmbd_share_cmd cmd);
> +int share_cmd(int argc, char *argv[]);
>
>  #endif /* __KSMBD_SHARE_ADMIN_H__ */
> --
> 2.34.1
>
>
diff mbox series

Patch

diff --git a/include/ksmbdtools.h b/include/ksmbdtools.h
index 170ce23ead2c..fccb88d8898a 100644
--- a/include/ksmbdtools.h
+++ b/include/ksmbdtools.h
@@ -101,12 +101,14 @@  extern int ksmbd_health_status;
 //---------------------------------------------------------------//
 #define LOGAPP		"[%s/%d]:"
 #define PRERR		LOGAPP" ERROR: "
+#define PRWARN		LOGAPP" WARN: "
 #define PRINF		LOGAPP" INFO: "
 #define PRDEBUG		LOGAPP" DEBUG: "
 
 #define PR_ERROR	0
-#define PR_INFO		1
-#define PR_DEBUG	2
+#define PR_WARN		1
+#define PR_INFO		2
+#define PR_DEBUG	3
 
 static int log_level = PR_INFO;
 
@@ -134,12 +136,16 @@  extern void pr_logger_init(int flags);
 					##__VA_ARGS__);			\
 	} while (0)
 
-#define pr_debug(f, ...)	\
+#define pr_debug(f, ...) \
 	pr_log(PR_DEBUG, PRDEBUG f, ##__VA_ARGS__)
-#define pr_info(f, ...)	\
+#define pr_info(f, ...) \
 	pr_log(PR_INFO, PRINF f, ##__VA_ARGS__)
-#define pr_err(f, ...)	\
+#define pr_warn(f, ...) \
+	pr_log(PR_WARN, PRWARN f, ##__VA_ARGS__)
+#define pr_err(f, ...) \
 	pr_log(PR_ERROR, PRERR f, ##__VA_ARGS__)
+#define pr_out(f, ...) \
+	fprintf(stderr, f, ##__VA_ARGS__)
 
 //---------------------------------------------------------------//
 
diff --git a/share/Makefile.am b/share/Makefile.am
index dafc985add5d..bea487edfeeb 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -4,4 +4,4 @@  ksmbd_addshare_LDADD = $(top_builddir)/lib/libksmbdtools.a
 
 sbin_PROGRAMS = ksmbd.addshare
 
-ksmbd_addshare_SOURCES = share_admin.c addshare.c share_admin.h
+ksmbd_addshare_SOURCES = share_admin.c share.c share_admin.h
diff --git a/share/addshare.c b/share/addshare.c
deleted file mode 100644
index 4ff94b18a641..000000000000
--- a/share/addshare.c
+++ /dev/null
@@ -1,172 +0,0 @@ 
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
- *
- *   linux-cifsd-devel@lists.sourceforge.net
- */
-
-#include <glib.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "config_parser.h"
-#include "ksmbdtools.h"
-#include "management/share.h"
-#include "linux/ksmbd_server.h"
-#include "share_admin.h"
-#include "version.h"
-
-static char *arg_name;
-static char *arg_opts;
-
-enum {
-	COMMAND_ADD_SHARE = 1,
-	COMMAND_DEL_SHARE,
-	COMMAND_UPDATE_SHARE,
-};
-
-static void usage(void)
-{
-	int i;
-
-	fprintf(stderr, "Usage: smbshareadd\n");
-
-	fprintf(stderr, "\t-a | --add-share=share\n");
-	fprintf(stderr, "\t-d | --del-share=share\n");
-	fprintf(stderr, "\t-u | --update-share=share\n");
-	fprintf(stderr, "\t-o | --options=\"op1=val1 op2=val2...\"\n");
-
-	fprintf(stderr, "\t-c smb.conf\n");
-	fprintf(stderr, "\t-V | --version\n");
-	fprintf(stderr, "\t-v | --verbose\n");
-
-	fprintf(stderr, "Supported share options:\n");
-	for (i = 0; i < KSMBD_SHARE_CONF_MAX; i++)
-		fprintf(stderr, "\t%s\n", KSMBD_SHARE_CONF[i]);
-	exit(EXIT_FAILURE);
-}
-
-static void show_version(void)
-{
-	printf("ksmbd-tools version : %s\n", KSMBD_TOOLS_VERSION);
-	exit(EXIT_FAILURE);
-}
-
-static int parse_configs(char *smbconf)
-{
-	int ret;
-
-	ret = test_file_access(smbconf);
-	if (ret)
-		return ret;
-
-	ret = cp_smbconfig_hash_create(smbconf);
-	if (ret)
-		return ret;
-	return 0;
-}
-
-static int sanity_check_share_name_simple(char *name)
-{
-	int sz, i;
-
-	if (!name)
-		return -EINVAL;
-
-	sz = strlen(name);
-	if (sz < 1)
-		return -EINVAL;
-	if (sz >= KSMBD_REQ_MAX_SHARE_NAME)
-		return -EINVAL;
-
-	if (!cp_key_cmp(name, "global"))
-		return -EINVAL;
-
-	return -EINVAL;
-}
-
-int main(int argc, char *argv[])
-{
-	int ret = EXIT_FAILURE;
-	char *smbconf = PATH_SMBCONF;
-	int c, cmd = 0;
-
-	set_logger_app_name("ksmbd.addshare");
-
-	opterr = 0;
-	while ((c = getopt(argc, argv, "c:a:d:u:p:o:Vvh")) != EOF)
-		switch (c) {
-		case 'a':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
-			cmd = COMMAND_ADD_SHARE;
-			break;
-		case 'd':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
-			cmd = COMMAND_DEL_SHARE;
-			break;
-		case 'u':
-			arg_name = g_ascii_strdown(optarg, strlen(optarg));
-			cmd = COMMAND_UPDATE_SHARE;
-			break;
-		case 'c':
-			smbconf = strdup(optarg);
-			break;
-		case 'o':
-			arg_opts = strdup(optarg);
-			break;
-		case 'V':
-			show_version();
-			break;
-		case 'v':
-			break;
-		case '?':
-		case 'h':
-		default:
-			usage();
-	}
-
-	if (cmd != COMMAND_DEL_SHARE && !arg_opts) {
-		usage();
-		return -1;
-	}
-
-	if (sanity_check_share_name_simple(arg_name)) {
-		pr_err("share name sanity check failure\n");
-		goto out;
-	}
-
-	if (!smbconf) {
-		pr_err("Out of memory\n");
-		goto out;
-	}
-
-	ret = parse_configs(smbconf);
-	if (ret) {
-		pr_err("Unable to parse configuration files\n");
-		goto out;
-	}
-
-	if (cmd == COMMAND_ADD_SHARE)
-		ret = command_add_share(smbconf, arg_name, arg_opts);
-	if (cmd == COMMAND_DEL_SHARE)
-		ret = command_del_share(smbconf, arg_name);
-	if (cmd == COMMAND_UPDATE_SHARE)
-		ret = command_update_share(smbconf, arg_name, arg_opts);
-
-	/*
-	 * We support only ADD_SHARE command for the time being
-	 */
-	if (ret == 0 && cmd == COMMAND_ADD_SHARE)
-		notify_ksmbd_daemon();
-out:
-	cp_smbconfig_destroy();
-	return ret;
-}
diff --git a/share/share.c b/share/share.c
new file mode 100644
index 000000000000..91d23d28c426
--- /dev/null
+++ b/share/share.c
@@ -0,0 +1,227 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ *   Copyright (C) 2021 SUSE LLC
+ *
+ *   linux-cifsd-devel@lists.sourceforge.net
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "config_parser.h"
+#include "ksmbdtools.h"
+#include "management/share.h"
+#include "linux/ksmbd_server.h"
+#include "share_admin.h"
+
+static ksmbd_share_cmd ksmbd_share_get_cmd(char *cmd)
+{
+	int i;
+
+	if (!cmd)
+		return KSMBD_CMD_SHARE_NONE;
+
+	for (i = 1; i < KSMBD_CMD_SHARE_MAX; i++)
+		if (!strcmp(cmd, ksmbd_share_cmds_str[i]))
+			return (ksmbd_share_cmd)i;
+
+	return KSMBD_CMD_SHARE_NONE;
+}
+
+static const char *ksmbd_share_get_cmd_str(ksmbd_share_cmd cmd)
+{
+	if (cmd > KSMBD_CMD_SHARE_MAX)
+		return ksmbd_share_cmds_str[KSMBD_CMD_SHARE_NONE];
+
+	return ksmbd_share_cmds_str[(int)cmd];
+}
+
+static int parse_configs(char *smbconf)
+{
+	int ret;
+
+	ret = test_file_access(smbconf);
+	if (ret)
+		return ret;
+
+	ret = cp_smbconfig_hash_create(smbconf);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+static int sanity_check_share_name_simple(char *name)
+{
+	int sz, i;
+
+	if (!name)
+		return -EINVAL;
+
+	sz = strlen(name);
+	if (sz < 1)
+		return -EINVAL;
+	if (sz >= KSMBD_REQ_MAX_SHARE_NAME)
+		return -EINVAL;
+
+	if (!cp_key_cmp(name, "global"))
+		return -EINVAL;
+
+	for (i = 0; i < sz; i++) {
+		if (isalnum(name[i]))
+			return 0;
+	}
+	return -EINVAL;
+}
+
+void share_usage(ksmbd_share_cmd cmd)
+{
+	int i;
+	const char *cmd_str = ksmbd_share_get_cmd_str(cmd);
+
+	switch (cmd) {
+	case KSMBD_CMD_SHARE_ADD:
+	case KSMBD_CMD_SHARE_UPDATE:
+		pr_out("Usage: ksmbdctl share %s <share_name> [-c <file>] -o \"op1=val1,op2=val2,...\"\n", cmd_str);
+		pr_out("Adds or updates a share to smb.conf file.\n\n");
+		pr_out("%-30s%s", "  -c, --conf=<file>", "Use <file> as smb.conf\n");
+		pr_out("%-30s%s", "  -o, --options=<options>", "Specify options for share\n\n");
+		pr_out("Supported share options:\n");
+		for (i = 0; i < KSMBD_SHARE_CONF_MAX; i++)
+			pr_out("%s\n", KSMBD_SHARE_CONF[i]);
+		break;
+	case KSMBD_CMD_SHARE_DELETE:
+		pr_out("Usage: ksmbdctl share delete <share_name>\n");
+		pr_out("Deletes a share.\n\n");
+		break;
+	default:
+		pr_out("Usage: ksmbdctl share <subcommand> <args> [options]\n");
+		pr_out("Share management.\n\n");
+		pr_out("List of available subcommands:\n");
+		pr_out("%-20s%s", "  add", "Add a share\n");
+		pr_out("%-20s%s", "  delete", "Delete a share\n");
+		pr_out("%-20s%s", "  update", "Update a share\n");
+		pr_out("%-20s%s", "  list", "List the names of all shares available\n\n");
+		break;
+	}
+
+	exit(EXIT_FAILURE);
+}
+
+int share_cmd(int argc, char *argv[])
+{
+	int ret = EXIT_FAILURE;
+	char *smbconf = PATH_SMBCONF;
+	char *share_name = NULL;
+	char *options = NULL;
+	ksmbd_share_cmd cmd = KSMBD_CMD_SHARE_NONE;
+	int c;
+
+	if (argc < 2)
+		goto usage;
+
+	set_logger_app_name("ksmbd-share");
+
+	cmd = ksmbd_share_get_cmd(argv[1]);
+
+	if (cmd == KSMBD_CMD_SHARE_NONE)
+		goto usage;
+
+	if(argc == 2 && cmd != KSMBD_CMD_SHARE_LIST)
+		goto missing_arg;
+
+	if (argv[2] && argv[2][0] != '-')
+		share_name = g_ascii_strdown(argv[2], strlen(argv[2]));
+	else if (cmd != KSMBD_CMD_SHARE_LIST)
+		goto usage;
+
+	optind = 1;
+	while ((c = getopt_long(argc, argv, "-:c:o:", share_opts, NULL)) != EOF)
+		switch (c) {
+		case 1:
+			break;
+		case 'c':
+			if (cmd == KSMBD_CMD_SHARE_DELETE)
+				continue;
+			smbconf = strdup(optarg);
+			break;
+		case 'o':
+			if (cmd == KSMBD_CMD_SHARE_DELETE || cmd == KSMBD_CMD_SHARE_LIST)
+				continue;
+			options = strdup(optarg);
+			break;
+		case ':':
+		case '?':
+		default:
+			goto usage;
+		}
+
+	if (cmd == KSMBD_CMD_SHARE_LIST)
+		goto share_list;
+
+	if (!share_name)
+		goto missing_arg;
+
+	if (cmd != KSMBD_CMD_SHARE_DELETE && !options) {
+		pr_out("Subcommand \"%s\" requires '-o' option set.\n\n", ksmbd_share_get_cmd_str(cmd));
+		goto usage;
+	}
+
+	if (sanity_check_share_name_simple(share_name)) {
+		pr_err("Share name (%s) sanity check failure\n", share_name);
+		goto out;
+	}
+
+share_list:
+	if (!smbconf) {
+		pr_err("Out of memory\n");
+		goto out;
+	}
+
+	ret = parse_configs(smbconf);
+	if (ret) {
+		pr_err("Unable to parse configuration file %s\n", smbconf);
+		goto out;
+	}
+
+	switch (cmd) {
+	case KSMBD_CMD_SHARE_ADD:
+		ret = share_add_cmd(smbconf, share_name, options);
+		break;
+	case KSMBD_CMD_SHARE_DELETE:
+		ret = share_delete_cmd(smbconf, share_name);
+		break;
+	case KSMBD_CMD_SHARE_UPDATE:
+		ret = share_update_cmd(smbconf, share_name, options);
+		break;
+	case KSMBD_CMD_SHARE_LIST:
+		ret = share_list_cmd(smbconf);
+		break;
+	}
+
+	/*
+	 * FIXME: We support only ADD_SHARE command for the time being
+	 */
+	if (ret == 0 && cmd == KSMBD_CMD_SHARE_ADD)
+		notify_ksmbd_daemon();
+
+out:
+	cp_smbconfig_destroy();
+	return ret;
+missing_arg:
+	if (cmd > KSMBD_CMD_SHARE_NONE && cmd < KSMBD_CMD_SHARE_MAX)
+		pr_out("Subcommand \"%s\" requires an argument.\n\n", ksmbd_share_get_cmd_str(cmd));
+usage:
+	share_usage(cmd);
+
+	return ret;
+}
diff --git a/share/share_admin.c b/share/share_admin.c
index 0ff13d8017dd..61780fb00b5a 100644
--- a/share/share_admin.c
+++ b/share/share_admin.c
@@ -1,12 +1,14 @@ 
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ *   Copyright (C) 2021 SUSE LLC
  *
  *   linux-cifsd-devel@lists.sourceforge.net
  */
 
 #include <glib.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <getopt.h>
@@ -48,24 +50,26 @@  static char *aux_group_name(char *name)
 	return gn;
 }
 
-static int __open_smbconf(char *smbconf)
+static int open_smbconf(char *smbconf, bool truncate)
 {
-	conf_fd = open(smbconf, O_WRONLY);
+	conf_fd = open(smbconf, O_RDWR);
 	if (conf_fd == -1) {
 		pr_err("%s %s\n", strerr(errno), smbconf);
 		return -EINVAL;
 	}
 
-	if (ftruncate(conf_fd, 0)) {
-		pr_err("%s %s\n", strerr(errno), smbconf);
-		close(conf_fd);
-		return -EINVAL;
+	if (truncate) {
+		if (ftruncate(conf_fd, 0)) {
+			pr_err("%s %s\n", strerr(errno), smbconf);
+			close(conf_fd);
+			return -EINVAL;
+		}
 	}
 
 	return 0;
 }
 
-static void __write(void)
+static void do_write(void)
 {
 	int nr = 0;
 	int ret;
@@ -83,7 +87,7 @@  static void __write(void)
 	}
 }
 
-static void __write_share(gpointer key, gpointer value, gpointer buf)
+static void write_share(gpointer key, gpointer value, gpointer buf)
 {
 	char *k = (char *)key;
 	char *v = (char *)value;
@@ -95,14 +99,14 @@  static void __write_share(gpointer key, gpointer value, gpointer buf)
 			sizeof(wbuf));
 		exit(EXIT_FAILURE);
 	}
-	__write();
+	do_write();
 }
 
-static void write_share(struct smbconf_group *g)
+static void write_share_all(struct smbconf_group *g)
 {
 	wsz = snprintf(wbuf, sizeof(wbuf), "[%s]\n", g->name);
-	__write();
-	g_hash_table_foreach(g->kv, __write_share, NULL);
+	do_write();
+	g_hash_table_foreach(g->kv, write_share, NULL);
 }
 
 static void write_share_cb(gpointer key, gpointer value, gpointer share_data)
@@ -113,7 +117,7 @@  static void write_share_cb(gpointer key, gpointer value, gpointer share_data)
 	 * Do not write AUX group
 	 */
 	if (!strstr(g->name, AUX_GROUP_PREFIX))
-		write_share(g);
+		write_share_all(g);
 }
 
 static void write_remove_share_cb(gpointer key,
@@ -127,7 +131,7 @@  static void write_remove_share_cb(gpointer key,
 		return;
 	}
 
-	write_share(g);
+	write_share_all(g);
 }
 
 static void update_share_cb(gpointer key,
@@ -145,12 +149,32 @@  static void update_share_cb(gpointer key,
 	g_hash_table_insert(g, nk, nv);
 }
 
-int command_add_share(char *smbconf, char *name, char *opts)
+static void list_shares_cb(gpointer key, gpointer value, gpointer data)
+{
+	char *nk, *nv;
+
+	nk = g_strdup(key);
+	nv = g_strdup(value);
+
+	if (!nk || !nv)
+		exit(EXIT_FAILURE);
+
+	if (!strcmp(nk, "global"))
+		goto out;
+
+	pr_out("%s\n", nk);
+
+out:
+	g_free(nk);
+	g_free(nv);
+}
+
+int share_add_cmd(char *smbconf, char *name, char *opts)
 {
 	char *new_name = NULL;
 
 	if (g_hash_table_lookup(parser.groups, name)) {
-		pr_err("Share already exists: %s\n", name);
+		pr_warn("Share already exists: %s\n", name);
 		return -EEXIST;
 	}
 
@@ -158,7 +182,7 @@  int command_add_share(char *smbconf, char *name, char *opts)
 	if (cp_parse_external_smbconf_group(new_name, opts))
 		goto error;
 
-	if (__open_smbconf(smbconf))
+	if (open_smbconf(smbconf, true))
 		goto error;
 	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
 	close(conf_fd);
@@ -170,7 +194,7 @@  error:
 	return -EINVAL;
 }
 
-int command_update_share(char *smbconf, char *name, char *opts)
+int share_update_cmd(char *smbconf, char *name, char *opts)
 {
 	struct smbconf_group *existing_group;
 	struct smbconf_group *update_group;
@@ -198,7 +222,7 @@  int command_update_share(char *smbconf, char *name, char *opts)
 			     update_share_cb,
 			     existing_group->kv);
 
-	if (__open_smbconf(smbconf))
+	if (open_smbconf(smbconf, true))
 		goto error;
 
 	g_hash_table_foreach(parser.groups, write_share_cb, NULL);
@@ -211,9 +235,9 @@  error:
 	return -EINVAL;
 }
 
-int command_del_share(char *smbconf, char *name)
+int share_delete_cmd(char *smbconf, char *name)
 {
-	if (__open_smbconf(smbconf))
+	if (open_smbconf(smbconf, true))
 		return -EINVAL;
 
 	g_hash_table_foreach(parser.groups,
@@ -222,3 +246,22 @@  int command_del_share(char *smbconf, char *name)
 	close(conf_fd);
 	return 0;
 }
+
+int share_list_cmd(char *smbconf)
+{
+	if (open_smbconf(smbconf, false))
+		return -EINVAL;
+
+	if (g_hash_table_size(parser.groups) <= 1) {
+		pr_out("No shares available in %s.\n", smbconf);
+		goto out;
+	}
+
+	pr_out("Shares available in %s:\n", smbconf);
+	g_hash_table_foreach(parser.groups,
+			     list_shares_cb,
+			     NULL);
+out:
+	close(conf_fd);
+	return 0;
+}
diff --git a/share/share_admin.h b/share/share_admin.h
index 7df3871bfe81..00cf1147af18 100644
--- a/share/share_admin.h
+++ b/share/share_admin.h
@@ -1,6 +1,7 @@ 
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ *   Copyright (C) 2021 SUSE LLC
  *
  *   linux-cifsd-devel@lists.sourceforge.net
  */
@@ -8,8 +9,36 @@ 
 #ifndef __KSMBD_SHARE_ADMIN_H__
 #define __KSMBD_SHARE_ADMIN_H__
 
-int command_add_share(char *smbconf, char *name, char *opts);
-int command_update_share(char *smbconf, char *name, char *opts);
-int command_del_share(char *smbconf, char *name);
+int share_add_cmd(char *smbconf, char *name, char *opts);
+int share_delete_cmd(char *smbconf, char *name);
+int share_update_cmd(char *smbconf, char *name, char *opts);
+int share_list_cmd(char *smbconf);
+
+typedef enum {
+	KSMBD_CMD_SHARE_NONE = 0,
+	KSMBD_CMD_SHARE_ADD,
+	KSMBD_CMD_SHARE_DELETE,
+	KSMBD_CMD_SHARE_UPDATE,
+	KSMBD_CMD_SHARE_LIST,
+	KSMBD_CMD_SHARE_MAX
+} ksmbd_share_cmd;
+
+/* List of supported subcommands */
+static const char *ksmbd_share_cmds_str[] = {
+	"none",
+	"add",
+	"delete",
+	"update",
+	"list"
+};
+
+static struct option share_opts[] = {
+        { "conf", required_argument, NULL, 'c' },
+        { "options", required_argument, NULL, 'o' },
+	{ 0, 0, 0, 0 },
+};
+
+void share_usage(ksmbd_share_cmd cmd);
+int share_cmd(int argc, char *argv[]);
 
 #endif /* __KSMBD_SHARE_ADMIN_H__ */