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>
This commit is contained in:
parent
4a1d07e8c3
commit
010ceab56e
94
btrfs.c
94
btrfs.c
|
@ -17,6 +17,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "volumes.h"
|
#include "volumes.h"
|
||||||
#include "crc32c.h"
|
#include "crc32c.h"
|
||||||
|
@ -164,24 +165,77 @@ static int cmd_version(int argc, char **argv)
|
||||||
return 0;
|
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)
|
if (argc == 0)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
arg = argv[0];
|
opterr = 0;
|
||||||
|
while (1) {
|
||||||
|
int c;
|
||||||
|
|
||||||
if (arg[0] != '-' ||
|
c = getopt_long(argc, argv, "+", long_options, NULL);
|
||||||
!strcmp(arg, "--help") ||
|
if (c < 0)
|
||||||
!strcmp(arg, "--version"))
|
break;
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, "Unknown option: %s\n", arg);
|
switch (c) {
|
||||||
fprintf(stderr, "usage: %s\n",
|
case OPT_HELP: break;
|
||||||
btrfs_cmd_group.usagestr[0]);
|
case OPT_VERSION: break;
|
||||||
exit(129);
|
case OPT_FULL: break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown global option: %s\n",
|
||||||
|
argv[optind - 1]);
|
||||||
|
exit(129);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
static const struct cmd_group btrfs_cmd_group = {
|
||||||
|
@ -223,13 +277,15 @@ int main(int argc, char **argv)
|
||||||
if (!strcmp(bname, "btrfsck")) {
|
if (!strcmp(bname, "btrfsck")) {
|
||||||
argv[0] = "check";
|
argv[0] = "check";
|
||||||
} else {
|
} else {
|
||||||
argc--;
|
int shift;
|
||||||
argv++;
|
|
||||||
check_options(argc, argv);
|
shift = handle_global_options(argc, argv);
|
||||||
if (argc > 0) {
|
handle_special_globals(shift, argc, argv);
|
||||||
if (!prefixcmp(argv[0], "--"))
|
while (shift-- > 0) {
|
||||||
argv[0] += 2;
|
argc--;
|
||||||
} else {
|
argv++;
|
||||||
|
}
|
||||||
|
if (argc == 0) {
|
||||||
usage_command_group_short(&btrfs_cmd_group);
|
usage_command_group_short(&btrfs_cmd_group);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue