summaryrefslogtreecommitdiff
path: root/btrfs.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2016-11-21 13:40:43 +0100
committerDavid Sterba <dsterba@suse.com>2017-03-31 19:40:57 +0200
commit010ceab56e067b87ea282fde6ff792c1ceefd7dc (patch)
treee77e9648f35f066ef5d18da1efebadfd60968a39 /btrfs.c
parent4a1d07e8c3ae610c863e57ee31e1484d652367ea (diff)
btrfs-progs: rework option parser to use getopt for global options
Preparatory work to support more global options. The current parser abuses the subcommand table to understand help and version when specified as options (--). These are now special case when processing the global options. Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'btrfs.c')
-rw-r--r--btrfs.c94
1 files changed, 75 insertions, 19 deletions
diff --git a/btrfs.c b/btrfs.c
index 9214ae6e..2d39f2ce 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -17,6 +17,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
#include "volumes.h"
#include "crc32c.h"
@@ -164,24 +165,77 @@ static int cmd_version(int argc, char **argv)
return 0;
}
-static void check_options(int argc, char **argv)
+/*
+ * Parse global options, between binary name and first non-option argument
+ * after processing all valid options (including those with arguments).
+ *
+ * Returns index to argv where parsting stopped, optind is reset to 1
+ */
+static int handle_global_options(int argc, char **argv)
{
- const char *arg;
+ enum { OPT_HELP = 256, OPT_VERSION, OPT_FULL };
+ static const struct option long_options[] = {
+ { "help", no_argument, NULL, OPT_HELP },
+ { "version", no_argument, NULL, OPT_VERSION },
+ { "full", no_argument, NULL, OPT_FULL },
+ { NULL, 0, NULL, 0}
+ };
+ int shift;
if (argc == 0)
- return;
+ return 0;
- arg = argv[0];
+ opterr = 0;
+ while (1) {
+ int c;
+
+ c = getopt_long(argc, argv, "+", long_options, NULL);
+ if (c < 0)
+ break;
+
+ switch (c) {
+ case OPT_HELP: break;
+ case OPT_VERSION: break;
+ case OPT_FULL: break;
+ default:
+ fprintf(stderr, "Unknown global option: %s\n",
+ argv[optind - 1]);
+ exit(129);
+ }
+ }
- if (arg[0] != '-' ||
- !strcmp(arg, "--help") ||
- !strcmp(arg, "--version"))
- return;
+ shift = optind;
+ optind = 1;
+
+ return shift;
+}
+
+void handle_special_globals(int shift, int argc, char **argv)
+{
+ int has_help = 0;
+ int has_full = 0;
+ int i;
+
+ for (i = 0; i < shift; i++) {
+ if (strcmp(argv[i], "--help") == 0)
+ has_help = 1;
+ else if (strcmp(argv[i], "--full") == 0)
+ has_full = 1;
+ }
+
+ if (has_help) {
+ if (has_full)
+ usage_command_group(&btrfs_cmd_group, 1, 0);
+ else
+ cmd_help(argc, argv);
+ exit(0);
+ }
- fprintf(stderr, "Unknown option: %s\n", arg);
- fprintf(stderr, "usage: %s\n",
- btrfs_cmd_group.usagestr[0]);
- exit(129);
+ for (i = 0; i < shift; i++)
+ if (strcmp(argv[i], "--version") == 0) {
+ cmd_version(argc, argv);
+ exit(0);
+ }
}
static const struct cmd_group btrfs_cmd_group = {
@@ -223,13 +277,15 @@ int main(int argc, char **argv)
if (!strcmp(bname, "btrfsck")) {
argv[0] = "check";
} else {
- argc--;
- argv++;
- check_options(argc, argv);
- if (argc > 0) {
- if (!prefixcmp(argv[0], "--"))
- argv[0] += 2;
- } else {
+ int shift;
+
+ shift = handle_global_options(argc, argv);
+ handle_special_globals(shift, argc, argv);
+ while (shift-- > 0) {
+ argc--;
+ argv++;
+ }
+ if (argc == 0) {
usage_command_group_short(&btrfs_cmd_group);
exit(1);
}