From patchwork Thu Nov 2 17:28:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133790 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1D8AD43270; Thu, 2 Nov 2023 18:33:23 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1A21742D9F; Thu, 2 Nov 2023 18:33:00 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 69BDB42D78 for ; Thu, 2 Nov 2023 18:32:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698946377; x=1730482377; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NAqxBTEfIPl/1gaXusCLrD/tJQGFRafdBw6uehpsejE=; b=cBEbVUwTJWWhCtxRXqx3ju6vptWjrmBw8wcCGrYJahELpqoakGm6IiOe ewPodhfa8nrw09VA8+xNSjC4kKjoodHagCBOByr21eMn6uLN4kss4QhZc SJpJIvKw8CfCvStDsGHp2qGyXfMfYiZ1+nL9CykBH06nN4ycc9Qj5Fn+b egF8i7afqJeppsempm94fqthxDgSs4VaYQuP8PkzDPAI1JiGmb9mN+8GF 25twicIdankJ35xCWKiCgJyvc4tLfh6Y/K132eX8wA8GBvL4ometqaEgQ 5gfeYnWYxVDvS0lE8/6TVqCMx7LRA9NrvIoaUdTukNrK3XjKTJyY3n2BY g==; X-IronPort-AV: E=McAfee;i="6600,9927,10882"; a="1645215" X-IronPort-AV: E=Sophos;i="6.03,272,1694761200"; d="scan'208";a="1645215" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2023 10:29:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10882"; a="878330517" X-IronPort-AV: E=Sophos;i="6.03,272,1694761200"; d="scan'208";a="878330517" Received: from silpixa00401385.ir.intel.com ([10.237.214.164]) by fmsmga002.fm.intel.com with ESMTP; 02 Nov 2023 10:29:07 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: Bruce Richardson Subject: [24.03 RFC 3/3] args: add functions to check parameter validity Date: Thu, 2 Nov 2023 17:28:49 +0000 Message-Id: <20231102172849.7400-4-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231102172849.7400-1-bruce.richardson@intel.com> References: <20231102172849.7400-1-bruce.richardson@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add in functions which can be used to check for valid arguments for EAL or for the application. This can be used to separate out mixed arguments. Signed-off-by: Bruce Richardson --- lib/args/args.c | 122 +++++++++++++++++++++++++++++++++++++++++++ lib/args/rte_args.h | 56 ++++++++++++++++++++ lib/args/version.map | 3 ++ 3 files changed, 181 insertions(+) diff --git a/lib/args/args.c b/lib/args/args.c index 80eb6670da..c04faa6323 100644 --- a/lib/args/args.c +++ b/lib/args/args.c @@ -22,6 +22,15 @@ struct rte_args { #define DEFAULT_SIZE_HINT 8 +#define INVALID_ARG '?' +#define VALID_ARG 'x' +#define PARAM_ARG ':' + +static char *app_shortopts; +static struct option *app_longopts; +static char *eal_shortopts; +static struct option *eal_longopts; + struct rte_args * rte_args_alloc(uint32_t size_hint) { @@ -177,3 +186,116 @@ rte_args_eal_init(struct rte_args *a) return rte_eal_init(argc, argv); } + +static int +args_register_opts(const char *shortopts, const struct option *longopts, + char **sopt_var, struct option **lopt_var) +{ + static struct option emptyopt = {0}; + struct option *lopts = &emptyopt; + char *sopts; + + if (shortopts == NULL) { + rte_errno = EINVAL; + return -1; + } + + /* for short options, we need to pre-pend ':' for extra argument reporting */ + if (shortopts[0] != '\0' && shortopts[0] != ':') { + size_t len = strlen(shortopts); + + sopts = malloc(len + 2); + if (sopts == NULL) { + rte_errno = ENOMEM; + return -1; + } + snprintf(sopts, len + 2, ":%s", shortopts); + } else + sopts = strdup(shortopts); + + /* for long options, we need to ensure we always return a value, not setting a flag */ + if (longopts != NULL) { + int i, n = 0; + while (memcmp(&longopts[n], &emptyopt, sizeof(emptyopt)) != 0) + n++; + lopts = calloc(n + 1, sizeof(emptyopt)); + if (lopts == NULL) { + free(sopts); + rte_errno = ENOMEM; + return -1; + } + for (i = 0; i < n; i++) { + lopts[i].name = longopts[i].name; + lopts[i].has_arg = longopts[i].has_arg; + lopts[i].flag = NULL; + lopts[i].val = VALID_ARG; + } + memset(&lopts[i], 0, sizeof(lopts[i])); + } + + if (*sopt_var != NULL) + free(*sopt_var); + if (*lopt_var != NULL) + free(*lopt_var); + + *sopt_var = sopts; + *lopt_var = lopts; + return 0; +} + +int +rte_args_register_app_opts(const char *shortopts, const struct option *longopts) +{ + return args_register_opts(shortopts, longopts, &app_shortopts, &app_longopts); +} + +static int +args_is_valid_arg(const char *arg, const char *sopts, const struct option *lopts) +{ + const int save_optind = optind, + save_opterr = opterr, + save_optopt = optopt; + + int ret = getopt_long(1, (void *)&arg, sopts, lopts, NULL); + switch (ret) { + case INVALID_ARG: + ret = 0; break; + case VALID_ARG: + ret = 1; break; + case PARAM_ARG: + ret = 2; break; + default: + ret = -1; break; + } + + /* restore saved values */ + optind = save_optind; + opterr = save_opterr; + optopt = save_optopt; + return ret; +} + +int +rte_args_is_app_arg(const char *arg) +{ + if (app_shortopts == NULL || app_longopts == NULL) { + rte_errno = EINVAL; + return -1; + } + + return args_is_valid_arg(arg, app_shortopts, app_longopts); +} + +int +rte_args_is_eal_arg(const char *arg) +{ + if (eal_shortopts == NULL || eal_longopts == NULL) { + const struct option *l; + const char *s; + + rte_eal_getopt_params(&s, &l); + if (args_register_opts(s, l, &eal_shortopts, &eal_longopts) < 0) + return -1; + } + return args_is_valid_arg(arg, eal_shortopts, eal_longopts);; +} diff --git a/lib/args/rte_args.h b/lib/args/rte_args.h index 3b80b9a39c..7e2ba5348d 100644 --- a/lib/args/rte_args.h +++ b/lib/args/rte_args.h @@ -191,6 +191,62 @@ __rte_experimental int rte_args_eal_init(struct rte_args *a); +/** + * Register the application arguments to allow testing args for validity + * + * This function should only be called once per application, and each call + * will replace any previouly registered values. This function is not + * multi-thread safe and should only be called from one thread at a time. + * + * @param shortopts + * The array of short options, as passed to getopt/getopt_long + * @param longopts + * The array of longer options, as passed to getopt_long + * @return + * -1 on error, with rte_errno set appropriately; + * 0 otherwise + */ +__rte_experimental +int +rte_args_register_app_opts(const char *shortopts, const struct option *longopts); + +/** + * Determine if a given argument is valid or not for the app + * + * Determine if the passed argument is valid or not, based on previously registered + * application arguments. This function uses getopt, and so is not multi-thread safe. + * + * @param arg + * The argument to test + * @return + * 0 - the argument is not a valid one + * 1 - the argument is valid + * 2 - the argument is valid, but it takes the next argument as parameter + * or -1 on error, with rte_errno set appropriately + */ +__rte_experimental +int +rte_args_is_app_arg(const char *arg); + + +/** + * Determine if a given argument is an EAL argument or not + * + * Determine if the passed argument is valid or not for EAL initialization. + * This function uses getopt, and so is not multi-thread safe. + + * @param arg + * The argument to test + * @return + * 0 - the argument is not a valid one for EAL + * 1 - the argument is valid for EAL + * 2 - the argument is valid for EAL, but it takes the next argument as parameter + * or -1 on error, with rte_errno set appropriately + */ +__rte_experimental +int +rte_args_is_eal_arg(const char *arg); + #ifdef __cplusplus } #endif diff --git a/lib/args/version.map b/lib/args/version.map index 776bd22b82..ef80f0d762 100644 --- a/lib/args/version.map +++ b/lib/args/version.map @@ -16,4 +16,7 @@ EXPERIMENTAL { rte_args_get_argc; rte_args_get_argv; rte_args_has_arg; + rte_args_is_app_arg; + rte_args_is_eal_arg; + rte_args_register_app_opts; };