From 7fb70440cff73c57a2b3a53f22a6ff023718ea39 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Wed, 20 Jun 2018 08:38:38 +0800 Subject: [PATCH] btrfs-progs: Fix wrong optind re-initialization to allow mixed option and non-option In function handle_global_options(), we reset @optind to 1. However according to man page of getopt(3) NOTES section, if we need to rescan options later, @optind should be reset to 0 to initialize the internal variables correctly. This explains the reason why in cmd_check(), getopt_long() doesn't handle the following command correctly: "btrfs check /dev/data/btrfs --check-data-csum" While mkfs.btrfs handles mixed non-option and option correctly: "mkfs.btrfs -f /dev/data/disk1 --data raid1 /dev/data/disk2" Cc: Paul Jones Cc: Hugo Mills Fixes: 010ceab56e06 ("btrfs-progs: rework option parser to use getopt for global options") Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- cmds-balance.c | 2 ++ cmds-device.c | 3 +++ cmds-fi-du.c | 1 + cmds-fi-usage.c | 1 + cmds-filesystem.c | 2 ++ cmds-inspect-dump-tree.c | 1 + cmds-inspect-tree-stats.c | 1 + cmds-inspect.c | 3 +++ cmds-qgroup.c | 3 +++ cmds-quota.c | 1 + cmds-receive.c | 1 + cmds-replace.c | 3 +++ cmds-rescue.c | 2 ++ cmds-restore.c | 1 + cmds-send.c | 1 + cmds-subvolume.c | 6 ++++++ 16 files changed, 32 insertions(+) diff --git a/cmds-balance.c b/cmds-balance.c index 0c91bdf1..6cc26c35 100644 --- a/cmds-balance.c +++ b/cmds-balance.c @@ -528,6 +528,7 @@ static int cmd_balance_start(int argc, char **argv) memset(&args, 0, sizeof(args)); + optind = 0; while (1) { enum { GETOPT_VAL_FULL_BALANCE = 256, GETOPT_VAL_BACKGROUND = 257 }; @@ -831,6 +832,7 @@ static int cmd_balance_status(int argc, char **argv) int verbose = 0; int ret; + optind = 0; while (1) { int opt; static const struct option longopts[] = { diff --git a/cmds-device.c b/cmds-device.c index a49c9d9d..2a05f70a 100644 --- a/cmds-device.c +++ b/cmds-device.c @@ -57,6 +57,7 @@ static int cmd_device_add(int argc, char **argv) int force = 0; int last_dev; + optind = 0; while (1) { int c; static const struct option long_options[] = { @@ -267,6 +268,7 @@ static int cmd_device_scan(int argc, char **argv) int all = 0; int ret = 0; + optind = 0; while (1) { int c; static const struct option long_options[] = { @@ -403,6 +405,7 @@ static int cmd_device_stats(int argc, char **argv) __u64 flags = 0; DIR *dirstream = NULL; + optind = 0; while (1) { int c; static const struct option long_options[] = { diff --git a/cmds-fi-du.c b/cmds-fi-du.c index 7e6bb7f6..4e639f6d 100644 --- a/cmds-fi-du.c +++ b/cmds-fi-du.c @@ -565,6 +565,7 @@ int cmd_filesystem_du(int argc, char **argv) unit_mode = get_unit_mode_from_arg(&argc, argv, 1); + optind = 0; while (1) { static const struct option long_options[] = { { "summarize", no_argument, NULL, 's'}, diff --git a/cmds-fi-usage.c b/cmds-fi-usage.c index eacca7b9..dca2e8d0 100644 --- a/cmds-fi-usage.c +++ b/cmds-fi-usage.c @@ -974,6 +974,7 @@ int cmd_filesystem_usage(int argc, char **argv) unit_mode = get_unit_mode_from_arg(&argc, argv, 1); + optind = 0; while (1) { int c; diff --git a/cmds-filesystem.c b/cmds-filesystem.c index 30a50bf5..06c8311b 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -685,6 +685,7 @@ static int cmd_filesystem_show(int argc, char **argv) unit_mode = get_unit_mode_from_arg(&argc, argv, 0); + optind = 0; while (1) { int c; static const struct option long_options[] = { @@ -924,6 +925,7 @@ static int cmd_filesystem_defrag(int argc, char **argv) defrag_global_errors = 0; defrag_global_verbose = 0; defrag_global_errors = 0; + optind = 0; while(1) { int c = getopt(argc, argv, "vrc::fs:l:t:"); if (c < 0) diff --git a/cmds-inspect-dump-tree.c b/cmds-inspect-dump-tree.c index 92a2a45b..c8acd55a 100644 --- a/cmds-inspect-dump-tree.c +++ b/cmds-inspect-dump-tree.c @@ -235,6 +235,7 @@ int cmd_inspect_dump_tree(int argc, char **argv) * tree blocks as possible. */ open_ctree_flags = OPEN_CTREE_PARTIAL | OPEN_CTREE_NO_BLOCK_GROUPS; + optind = 0; while (1) { int c; enum { GETOPT_VAL_FOLLOW = 256 }; diff --git a/cmds-inspect-tree-stats.c b/cmds-inspect-tree-stats.c index eced0db9..dfa34c52 100644 --- a/cmds-inspect-tree-stats.c +++ b/cmds-inspect-tree-stats.c @@ -434,6 +434,7 @@ int cmd_inspect_tree_stats(int argc, char **argv) int opt; int ret = 0; + optind = 0; while ((opt = getopt(argc, argv, "vb")) != -1) { switch (opt) { case 'v': diff --git a/cmds-inspect.c b/cmds-inspect.c index afd7fe48..2fc50c1a 100644 --- a/cmds-inspect.c +++ b/cmds-inspect.c @@ -94,6 +94,7 @@ static int cmd_inspect_inode_resolve(int argc, char **argv) int ret; DIR *dirstream = NULL; + optind = 0; while (1) { int c = getopt(argc, argv, "v"); if (c < 0) @@ -148,6 +149,7 @@ static int cmd_inspect_logical_resolve(int argc, char **argv) char *path_ptr; DIR *dirstream = NULL; + optind = 0; while (1) { int c = getopt(argc, argv, "Pvs:"); if (c < 0) @@ -591,6 +593,7 @@ static int cmd_inspect_min_dev_size(int argc, char **argv) DIR *dirstream = NULL; u64 devid = 1; + optind = 0; while (1) { int c; enum { GETOPT_VAL_DEVID = 256 }; diff --git a/cmds-qgroup.c b/cmds-qgroup.c index 93206900..b928edc7 100644 --- a/cmds-qgroup.c +++ b/cmds-qgroup.c @@ -46,6 +46,7 @@ static int _cmd_qgroup_assign(int assign, int argc, char **argv, DIR *dirstream = NULL; if (assign) { + optind = 0; while (1) { enum { GETOPT_VAL_RESCAN = 256, GETOPT_VAL_NO_RESCAN }; static const struct option long_options[] = { @@ -310,6 +311,7 @@ static int cmd_qgroup_show(int argc, char **argv) unit_mode = get_unit_mode_from_arg(&argc, argv, 0); + optind = 0; while (1) { int c; enum { @@ -429,6 +431,7 @@ static int cmd_qgroup_limit(int argc, char **argv) DIR *dirstream = NULL; enum btrfs_util_error err; + optind = 0; while (1) { int c = getopt(argc, argv, "ce"); if (c < 0) diff --git a/cmds-quota.c b/cmds-quota.c index 745889d1..c9ea9c0f 100644 --- a/cmds-quota.c +++ b/cmds-quota.c @@ -119,6 +119,7 @@ static int cmd_quota_rescan(int argc, char **argv) DIR *dirstream = NULL; int wait_for_completion = 0; + optind = 0; while (1) { int c = getopt(argc, argv, "sw"); if (c < 0) diff --git a/cmds-receive.c b/cmds-receive.c index 68123a31..34d51ef3 100644 --- a/cmds-receive.c +++ b/cmds-receive.c @@ -1267,6 +1267,7 @@ int cmd_receive(int argc, char **argv) realmnt[0] = 0; fromfile[0] = 0; + optind = 0; while (1) { int c; enum { GETOPT_VAL_DUMP = 257 }; diff --git a/cmds-replace.c b/cmds-replace.c index 032a44fc..1fa80284 100644 --- a/cmds-replace.c +++ b/cmds-replace.c @@ -134,6 +134,7 @@ static int cmd_replace_start(int argc, char **argv) u64 srcdev_size; u64 dstdev_size; + optind = 0; while ((c = getopt(argc, argv, "Brf")) != -1) { switch (c) { case 'B': @@ -333,6 +334,7 @@ static int cmd_replace_status(int argc, char **argv) int ret; DIR *dirstream = NULL; + optind = 0; while ((c = getopt(argc, argv, "1")) != -1) { switch (c) { case '1': @@ -501,6 +503,7 @@ static int cmd_replace_cancel(int argc, char **argv) char *path; DIR *dirstream = NULL; + optind = 0; while ((c = getopt(argc, argv, "")) != -1) { switch (c) { case '?': diff --git a/cmds-rescue.c b/cmds-rescue.c index c61145bc..38c4ab9b 100644 --- a/cmds-rescue.c +++ b/cmds-rescue.c @@ -52,6 +52,7 @@ static int cmd_rescue_chunk_recover(int argc, char *argv[]) int yes = 0; int verbose = 0; + optind = 0; while (1) { int c = getopt(argc, argv, "yvh"); if (c < 0) @@ -119,6 +120,7 @@ static int cmd_rescue_super_recover(int argc, char **argv) int yes = 0; char *dname; + optind = 0; while (1) { int c = getopt(argc, argv, "vy"); if (c < 0) diff --git a/cmds-restore.c b/cmds-restore.c index 342f5cc7..2933b7f5 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -1440,6 +1440,7 @@ int cmd_restore(int argc, char **argv) regex_t match_reg, *mreg = NULL; char reg_err[256]; + optind = 0; while (1) { int opt; enum { GETOPT_VAL_PATH_REGEX = 256 }; diff --git a/cmds-send.c b/cmds-send.c index c5ecdaa1..16b9f8d2 100644 --- a/cmds-send.c +++ b/cmds-send.c @@ -508,6 +508,7 @@ int cmd_send(int argc, char **argv) send.dump_fd = fileno(stdout); outname[0] = 0; + optind = 0; while (1) { enum { GETOPT_VAL_SEND_NO_DATA = 256 }; static const struct option long_options[] = { diff --git a/cmds-subvolume.c b/cmds-subvolume.c index 45363a5a..e7a884af 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -102,6 +102,7 @@ static int cmd_subvol_create(int argc, char **argv) struct btrfs_qgroup_inherit *inherit = NULL; DIR *dirstream = NULL; + optind = 0; while (1) { int c = getopt(argc, argv, "c:i:"); if (c < 0) @@ -248,6 +249,7 @@ static int cmd_subvol_delete(int argc, char **argv) enum { COMMIT_AFTER = 1, COMMIT_EACH = 2 }; enum btrfs_util_error err; + optind = 0; while (1) { int c; static const struct option long_options[] = { @@ -466,6 +468,7 @@ static int cmd_subvol_list(int argc, char **argv) filter_set = btrfs_list_alloc_filter_set(); comparer_set = btrfs_list_alloc_comparer_set(); + optind = 0; while(1) { int c; static const struct option long_options[] = { @@ -636,6 +639,7 @@ static int cmd_subvol_snapshot(int argc, char **argv) DIR *dirstream1 = NULL, *dirstream2 = NULL; memset(&args, 0, sizeof(args)); + optind = 0; while (1) { int c = getopt(argc, argv, "c:i:r"); if (c < 0) @@ -933,6 +937,7 @@ static int cmd_subvol_show(int argc, char **argv) char *subvol_path = NULL; enum btrfs_util_error err; + optind = 0; while (1) { int c; static const struct option long_options[] = { @@ -1132,6 +1137,7 @@ static int cmd_subvol_sync(int argc, char **argv) int sleep_interval = 1; enum btrfs_util_error err; + optind = 0; while (1) { int c = getopt(argc, argv, "s:");