From 9d326f4ffb1d5ca3045932a226876cdf78778000 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 12 Aug 2016 15:52:18 -0500 Subject: commands: new method for defining commands --- scripts/command-lines.in | 800 +++++++++++++++++++++++ scripts/create-commands.c | 1534 +++++++++++++++++++++++++++++++++++++++++++++ tools/args.h | 2 +- tools/command.h | 200 ++++++ tools/commands.h | 1428 ++--------------------------------------- tools/lvmcmdlib.c | 2 +- tools/lvmcmdline.c | 346 ++++++---- tools/toollib.c | 2 +- tools/tools.h | 17 +- 9 files changed, 2837 insertions(+), 1494 deletions(-) create mode 100644 scripts/command-lines.in create mode 100644 scripts/create-commands.c create mode 100644 tools/command.h diff --git a/scripts/command-lines.in b/scripts/command-lines.in new file mode 100644 index 000000000..e1944fefc --- /dev/null +++ b/scripts/command-lines.in @@ -0,0 +1,800 @@ +# +# A new command has a unique combination of: +# command name, required option args and required +# positional args. +# +# To define a new command, begin a single line with a +# command name, followed by required options/args, +# (e.g. --foo, or --foo val), followed by required +# positional args, (e.g. VG) +# +# After the single line of required elements are lines +# of optional elements: +# . optional options/args are on new line that begins OO: +# . optional positional args are on a new line that begins OP: +# +# command_name required_opt_arg ... required_pos_arg ... +# OO: optional_opt_arg, ... +# OP: optional_pos_arg ... +# +# required_opt_arg/optional_opt_arg must begin with the +# long form option name, e.g. --foo. If the option name +# takes a value, then the type of value is specified, +# e.g. --foo String. +# +# Possible option names are listed in args.h +# +# Use --foo_long to specify that only the long form of +# --foo is accepted by the command. (This is uncommon.) +# +# Possible option arg types that can follow --opt are: +# Bool, Number, String, PV, VG, LV, Tag, Select. +# +# Option args outside the list of types are treated as literal +# (non-variable) strings or numbers. +# +# required_pos_arg/optional_pos_arg can be one of the following: +# PV, VG, LV, Tag, Select. +# +# required_pos_arg/optional_pos_arg can be multiple types +# separated by |, e.g. VG|LV|Tag +# +# If the required_pos_arg/optional_pos_arg is repeatable, +# it is followed by ..., e.g. VG|LV|Tag ... +# +# LV can have a suffix indicating the LV type, e.g. LV_linear, LV_thinpool. +# LV_raid represents any raidN. +# +# VG, LV can have the suffix _new, indicating the named VG or LV +# does not yet exist. +# +# If Select is included in pos_arg, it means that the pos_arg +# may be empty if the --select option is used. +# +# To define a common set of options: +# OO_NAME: --foo, --bar String +# +# To use this set of options, include it on the OO: line, e.g. +# OO: --example, OO_NAME +# +# which is expaneded to +# OO: --example, --foo, --bar String +# +# Including OO_NAME after a command name on the required line +# means that any one of the options is required and the rest +# are optional. The usage syntax for this case is printed as: +# command (--foo A, --bar B) +# + +# +# OO_ALL is included in every command automatically. +# FIXME: add --force and --test to OO_ALL so that all commands will +# accept them even if they are not used? +# +OO_ALL: --commandprofile String, --config String, --debug, +--driverloaded Bool, --help, --profile String, --quiet, +--verbose, --version, --yes + +# +# pvs, lvs, vgs, fullreport +# +OO_REPORT: --aligned, --all, --binary, --configreport String, --foreign, +--ignorelockingfailure, --ignoreskippedcluster, --logonly, +--nameprefixes, --noheadings, --nolocking, --nosuffix, +--options String, --partial, --readonly, --reportformat String, --rows, +--select String, --separator String, --shared, --sort String, +--trustcache, --unbuffered, --units String, --unquoted + +# +# config, dumpconfig, lvmconfig +# +OO_CONFIG: --atversion String, --configtype String, --file String, --ignoreadvanced, +--ignoreunsupported, --ignorelocal, --list, --mergedconfig, --metadataprofile String, +--sinceversion String, --showdeprecated, --showunsupported, --validate, --withsummary, +--withcomments, --withspaces, --unconfigured, --withversions + + +config +OO: OO_CONFIG +OP: String ... + +devtypes +OO: --aligned, --binary, --nameprefixes, --noheadings, +--nosuffix, --options String, --reportformat String, --rows, +--select String, --separator String, --sort String, --unbuffered, --unquoted + +dumpconfig +OO: OO_CONFIG +OP: String ... + +formats + +help + +fullreport +OO: OO_REPORT +OP: VG ... + +lastlog +OO: --reportformat String, --select String + + +# +# None of these can function as a required option for lvchange. +# +OO_LVCHANGE: --autobackup Bool, --force, --ignorelockingfailure, +--ignoremonitoring, --ignoreskippedcluster, --noudevsync, +--reportformat String, --sysinit, --test, --select String + +# +# Any of these can function as a required option for lvchange. +# profile is also part of OO_ALL, but is repeated in OO_LVCHANGE_META +# because it can function as a required opt. +# +OO_LVCHANGE_META: --addtag Tag, --deltag Tag, +--alloc String, --contiguous Bool, +--detachprofile, --metadataprofile String, --profile String, +--permission, --readahead Number|String, --setactivationskip Bool, +--errorwhenfull Bool, --discards String, --zero Bool, +--cachemode String, --cachepolicy String, --cachesettings String, +--minrecoveryrate Number, --maxrecoveryrate Number, +--writebehind Number, --writemostly PV + +lvchange OO_LVCHANGE_META VG|LV|Tag|Select ... +OO: OO_LVCHANGE + +lvchange --resync VG|LV|Tag|Select ... +OO: OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --syncaction String VG|LV|Tag|Select ... +OO: OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --rebuild PV VG|LV|Tag|Select ... +OO: OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --activate String VG|LV|Tag|Select ... +OO: --activationmode String, --partial, --ignoreactivationskip, OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --refresh VG|LV|Tag|Select ... +OO: OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --monitor Bool VG|LV|Tag|Select ... +OO: --poll Bool, OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --poll Bool VG|LV|Tag|Select ... +OO: --monitor Bool, OO_LVCHANGE_META, OO_LVCHANGE + +lvchange --persistent Bool VG|LV|Tag|Select ... +OO: --minor Number, --major Number, OO_LVCHANGE_META, OO_LVCHANGE + + +OO_LVCONVERT_RAID: --mirrors Number, --stripes_long Number, +--stripesize Number, --regionsize Number + +OO_LVCONVERT_POOL: --poolmetadata LV, --poolmetadatasize Number, +--poolmetadataspare Bool, --readahead Number|String, --chunksize Number + +OO_LVCONVERT: --alloc String, --background, --force, --noudevsync, +--test, --usepolicies + +# FIXME: use different option names for different operations +lvconvert --merge LV_linear|LV_striped|LV_raid|LV_thin|LV_snapshot|VG|Tag ... +OO: --background, --interval Number +DESC: Merge LV that was previously split from a mirror. +DESC: Merge thin LV into its origin LV. +DESC: Merge COW snapshot LV into its origin. + +lvconvert --type snapshot LV_linear|LV_striped|LV_raid LV_snapshot +OO: --chunksize Number, --zero Bool, OO_LVCONVERT +DESC: Combine LV with a previously split snapshot LV. + +lvconvert --type thin --thinpool LV LV_linear|LV_striped|LV_raid +OO: --originname LV_new, OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type thin with an external origin. + +# alternate form of lvconvert --type thin +lvconvert --thin --thinpool LV LV_linear|LV_striped|LV_raid +OO: --type thin, --originname LV_new, OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type thin with an external origin (infers --type thin). + +lvconvert --type cache --cachepool LV LV_linear|LV_striped|LV_raid|LV_thinpool +OO: --cachepolicy String, --cachesettings String, OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type cache. + +# alternate form of lvconvert --type cache +lvconvert --cache --cachepool LV LV_linear|LV_striped|LV_raid|LV_thinpool +OO: --type cache, --cachepolicy String, --cachesettings String, OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type cache (infers --type cache). + +lvconvert --type thin-pool LV_linear|LV_striped|LV_raid|LV_cache +OO: --discards String, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type thin-pool. + +lvconvert --type cache-pool LV_linear|LV_striped|LV_raid +OO: OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Convert LV to type cache-pool. + +lvconvert --type mirror LV_linear|LV_striped|LV_raid +OO: OO_LVCONVERT_RAID, OO_LVCONVERT +OP: PV ... +DESC: Convert LV to type mirror. + +lvconvert --type raid LV_linear|LV_striped|LV_mirror|LV_raid +OO: OO_LVCONVERT_RAID, OO_LVCONVERT +OP: PV ... +DESC: Convert LV to type raid. +DESC: Change LV raid type. + +lvconvert --mirrors Number LV_raid|LV_mirror +OO: OO_LVCONVERT +OP: PV ... +DESC: Change the number of mirror images in the LV. + +lvconvert --mirrors Number LV_linear|LV_striped +OO: OO_LVCONVERT_RAID, OO_LVCONVERT +OP: PV ... +DESC: Alternate form to convert LV to type raid1 or mirror (use --type raid1|mirror). + +lvconvert --splitmirrors Number --name LV_new LV_raid|LV_mirror|LV_cache +OO: OO_LVCONVERT +DESC: Split images from a raid1 or mirror LV and use them to create a new LV. + +lvconvert --splitmirrors Number --trackchanges LV_raid|LV_cache +OO: OO_LVCONVERT +DESC: Split images from a raid1 LV and use them to create a new LV. + +lvconvert --repair LV_raid|LV_mirror|LV_thinpool +OO: OO_LVCONVERT +DESC: Replace failed PVs in a mirror or raid LV. +DESC: Repair a thin pool. + +lvconvert --replace PV LV_raid +OO: OO_LVCONVERT +OP: PV ... +DESC: Replace specific PV(s) in a raid* LV with another PV. + +lvconvert --type striped LV_raid +OO: OO_LVCONVERT_RAID, OO_LVCONVERT +OP: PV ... +DESC: Convert LV to type striped. + +lvconvert --type linear LV_raid|LV_mirror +OO: OO_LVCONVERT +DESC: Convert LV to type linear. + +lvconvert --mirrorlog String LV_mirror +OO: OO_LVCONVERT +DESC: Change the type of log used by LV. + +lvconvert --splitcache LV_cachepool|LV_cache|LV_thinpool +OO: OO_LVCONVERT +DESC: Separate and preserve a cache pool from a cache LV. + +lvconvert --uncache LV_cache|LV_thinpool +OO: OO_LVCONVERT +DESC: Separate and remove a cache pool from a cache LV. + +lvconvert --splitsnapshot LV_snapshot +OO: OO_LVCONVERT +DESC: Separate a COW snapshot from its origin LV. + +# deprecated because of non-standard syntax +lvconvert --thinpool LV +OO: OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Alternate form to convert LV to type thin-pool (use --type thin-pool). + +# deprecated because of non-standard syntax +lvconvert --cachepool LV +OO: OO_LVCONVERT_POOL, OO_LVCONVERT +DESC: Alternate form to convert LV to type cache-pool (use --type cache-pool). + +# FIXME: add a new option defining this operation, e.g. --poll-mirror +# The function of this command is not entirely clear. +lvconvert LV_mirror +DESC: Poll LV to collapse resync layers. + +# FIXME: add a new option defining this operation, e.g. --swapmetadata +lvconvert --poolmetadata LV LV_thinpool|LV_cachepool +DESC: Swap metadata LV in a thin pool or cache pool (temporary command). + + +# --extents or --size are interchangable + +OO_LVCREATE: --addtag Tag, --alloc String, --autobackup Bool, --activate String, +--contiguous Bool, --ignoreactivationskip, --ignoremonitoring, --major Number, +--metadataprofile String, --minor Number, --monitor Bool, --name String, --nosync, +--noudevsync, --permission, --persistent Bool, --readahead Number|String, +--reportformat String, --setactivationskip Bool, --test, --wipesignatures Bool, +--zero Bool + +OO_LVCREATE_CACHE: --cachemode String, --cachepolicy String, --cachesettings String + +OO_LVCREATE_POOL: --poolmetadatasize Number, --poolmetadataspare Bool, --chunksize Number + +OO_LVCREATE_THIN: --discards String, --errorwhenfull Bool + +OO_LVCREATE_RAID: --mirrors Number, --stripes Number, --stripesize Number, +--regionsize Number, --minrecoveryrate Number, --maxrecoveryrate Number + +lvcreate --type error --size Number VG +OO: OO_LVCREATE +DESC: Create an LV that returns errors when used. + +lvcreate --type zero --size Number VG +OO: OO_LVCREATE +DESC: Create an LV that returns zeros when read. + +lvcreate --type linear --size Number VG +OO: OO_LVCREATE +OP: PV ... +DESC: Create a linear LV. + +lvcreate --type striped --size Number VG +OO: --stripes Number, --stripesize Number, OO_LVCREATE +OP: PV ... +DESC: Create a striped LV. + +lvcreate --type mirror --size Number VG +OO: --mirrors Number, --mirrorlog String, --corelog, --regionsize Number, OO_LVCREATE +OP: PV ... +DESC: Create a mirror LV. + +lvcreate --type raid --size Number VG +OO: OO_LVCREATE_RAID, OO_LVCREATE +OP: PV ... +DESC: Create a raid LV (a specific raid level must be used, e.g. raid1). + +lvcreate --type snapshot --size Number LV +OO: OO_LVCREATE +OP: PV ... +DESC: Create a COW snapshot from an origin LV. + +lvcreate --type snapshot --size Number --virtualsize Number VG +OO: --virtualoriginsize Number, OO_LVCREATE +OP: PV ... +DESC: Create a sparse COW snapshot LV of a virtual origin LV. + +lvcreate --type thin-pool --size Number VG +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin pool. + +lvcreate --type cache-pool --size Number VG +OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE +OP: PV ... +DESC: Create a cache pool. + +lvcreate --type thin --virtualsize Number --thinpool LV_thinpool +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV in a thin pool. + +lvcreate --type thin --snapshot LV_thin +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV that is a snapshot of an existing thin LV. + +lvcreate --type thin --snapshot --thinpool LV_thinpool LV +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV that is a snapshot of an external origin LV named in arg pos 1. + +lvcreate --type thin --virtualsize Number --size Number --thinpool LV_new +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named by the --thinpool arg. + +lvcreate --type thin --virtualsize Number --size Number LV_new +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named in arg pos 1. + +lvcreate --type thin --virtualsize Number --size Number VG +OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it. + +# FIXME: this should be done by lvconvert, and this command deprecated +lvcreate --type cache --size Number LV +OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE +OP: PV ... +DESC: Convert the specified LV to type cache after creating a new cache pool LV to use. + +lvcreate --type cache --size Number --cachepool LV_cachepool +OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE +OP: PV ... +DESC: Create a cache LV, first creating a new origin LV, then combining it with the existing cache pool in arg pos 1. + +lvcreate --size Number VG +OO: --type linear, OO_LVCREATE +OP: PV ... +DESC: Create a linear LV. (default --type linear) + +lvcreate --stripes Number --size Number VG +OO: --type striped, --stripesize Number, OO_LVCREATE +OP: PV ... +DESC: Create a striped LV. (infers --type striped) + +lvcreate --mirrors Number --size Number VG +OO: --type raid1|mirror, --mirrorlog String, --corelog, OO_LVCREATE_RAID, OO_LVCREATE +OP: PV ... +DESC: Create a raid1 or mirror LV. (infers --type raid1|mirror) + +lvcreate --snapshot --size Number LV +OO: --type snapshot, OO_LVCREATE +OP: PV ... +DESC: Create a COW snapshot LV of the origin LV in arg pos 1. (infers --type snapshot) + +lvcreate --thin --size Number VG +OO: --type thin-pool, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin pool. (infers --type thin-pool) + +lvcreate --cache --size Number VG +OO: --type cache-pool, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE +OP: PV ... +DESC: Create a cache pool. (infers --type cache-pool) + +lvcreate --snapshot LV_thin +OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV that is a snapshot of an existing thin LV. (infers --type thin) + +lvcreate --snapshot --thinpool LV_thinpool LV +OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV that is a snapshot of an external origin LV. (infers --type thin) + +lvcreate --virtualsize Number --thinpool LV_thinpool +OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE +DESC: Create a thin LV in a thin pool. (infers --type thin) + +lvcreate --size Number --cachepool LV_cachepool +OO: --type cache, OO_LVCREATE_CACHE, OO_LVCREATE +OP: PV ... +DESC: Create a new origin LV, combining it with an existing cache pool to create a new cache LV. (infers --type cache) + +lvcreate --thin --virtualsize Number --size Number --thinpool LV_new +OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named by the --thinpool arg. (infers --type thin) + +lvcreate --thin --virtualsize Number --size Number LV_new +OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named in arg pos 1. (infers --type thin) + +lvcreate --size Number --virtualsize Number VG +OO: --type thin, --type snapshot, --thin, --snapshot, +--virtualoriginsize Number, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE +OP: PV ... +DESC: Create a thin LV, first creating a thin pool for it. (infers --type thin) +DESC: Create a sparse snapshot of a virtual origin LV. (infers --type snapshot) +DESC: (infers --type thin or --type snapshot according to sparse_segtype_default) + +lvdisplay +OO: --aligned, --all, --binary, --colon, --columns, +--configreport String, --foreign, --history, --ignorelockingfailure, +--ignoreskippedcluster, --logonly, --maps, --noheadings, +--nosuffix, --options String, --sort String, --partial, --readonly, +--reportformat String, --segments, --select String, --separator String, +--shared, --unbuffered, --units String +OP: VG|LV|Tag ... + +# --extents or --size are interchangable +lvextend --size Number LV +OO: --alloc String, --autobackup Bool, --force, --mirrors Number, +--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs, +--stripes Number, --stripesize Number, --test, --poolmetadatasize Number +OP: PV ... + +lvextend LV PV ... +OO: --alloc String, --autobackup Bool, --force, --mirrors Number, +--nofsck, --nosync, --noudevsync, +--reportformat String, --resizefs, --stripes Number, --stripesize Number, +--test + +lvextend --poolmetadatasize Number LV_thinpool +OO: --alloc String, --autobackup Bool, --force, --mirrors Number, +--nofsck, --nosync, --noudevsync, +--reportformat String, --stripes Number, --stripesize Number, +--test +OP: PV ... + +lvextend --usepolicies LV_thinpool|LV_snapshot +OO: --alloc String, --autobackup Bool, --force, --mirrors Number, +--nofsck, --nosync, --noudevsync, +--reportformat String, --resizefs, +--test + +lvmchange + +lvmconfig +OO: OO_CONFIG + +lvmdiskscan +OO: --lvmpartition, --readonly + +lvmsadc + +lvmsar +OO: --full, --stdin + +# --extents or --size are interchangable +lvreduce --size Number LV +OO: --autobackup Bool, --force, --nofsck, --noudevsync, +--reportformat String, --resizefs, --test + +lvremove VG|LV|Tag|Select ... +OO: --autobackup Bool, --force, --nohistory, --noudevsync, +--reportformat String, --select String, --test + +lvrename VG LV LV_new +OO: --autobackup Bool, --noudevsync, --reportformat String, --test + +lvrename LV LV_new +OO: --autobackup Bool, --noudevsync, --reportformat String, --test + +# --extents or --size are interchangable +lvresize --size Number LV +OO: --alloc String, --autobackup Bool, --force, +--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs, +--stripes Number, --stripesize Number, --test, --poolmetadatasize Number +OP: PV ... + +lvresize LV PV ... +OO: --alloc String, --autobackup Bool, --force, +--nofsck, --nosync, --noudevsync, +--reportformat String, --resizefs, --stripes Number, --stripesize Number, +--test + +lvresize --poolmetadatasize Number LV_thinpool +OO: --alloc String, --autobackup Bool, --force, +--nofsck, --nosync, --noudevsync, +--reportformat String, --stripes Number, --stripesize Number, +--test +OP: PV ... + +lvs +OO: --history, --segments, OO_REPORT +OP: VG|LV|Tag ... + +lvscan +OO: --all, --blockdevice, --ignorelockingfailure, --partial, +--readonly, --reportformat String, --cache_long + + +# +# None of these can function as a required option for pvchange. +# +OO_PVCHANGE: --autobackup Bool, --force, --ignoreskippedcluster, +--reportformat String, --test, --uuid + +# +# Any of these can function as a required option for pvchange. +# +OO_PVCHANGE_META: --allocatable Bool, --addtag Tag, --deltag Tag, +--uuid, --metadataignore Bool + +pvchange OO_PVCHANGE_META --all +OO: OO_PVCHANGE + +pvchange OO_PVCHANGE_META PV|Select ... +OO: --select String, OO_PVCHANGE + +pvresize PV ... +OO: --setphysicalvolumesize Number, --reportformat String, --test + +pvck PV ... +OO: --labelsector Number + +# +# Use --uuidstr here which will be converted to uuidstr_ARG +# which is actually --uuid string on the command line. +# +pvcreate PV ... +OO: --dataalignment Number, --dataalignmentoffset Number, --bootloaderareasize Number, +--force, --test, --labelsector Number, --metadatatype String, +--pvmetadatacopies Number, --metadatasize Number, --metadataignore Bool, +--norestorefile, --setphysicalvolumesize Number, +--reportformat String, --restorefile String, --uuidstr String, --zero Bool + +pvdata + +pvdisplay +OO: --aligned, --all, --binary, --colon, --columns, --configreport String, +--foreign, --ignorelockingfailure, --ignoreskippedcluster, +--logonly, --maps, --noheadings, --nosuffix, --options String, +--readonly, --reportformat String, --select String, --separator String, --shared, +--short, --sort String, --unbuffered, --units String +OP: PV|Tag ... + +pvmove PV +OO: --abort, --alloc String, --atomic, --autobackup Bool, --background, +--interval Number, --name LV, --noudevsync, --reportformat String, --test +OP: PV ... + +pvmove +OO: --abort, --background, --test + +lvpoll --polloperation String LV ... +OO: --abort, --autobackup Bool, --handlemissingpvs, --interval Number, --test + +pvremove PV ... +OO: --force, --reportformat String, --test + +pvs +OO: --segments, OO_REPORT +OP: PV|Tag ... + +pvscan +OO: --ignorelockingfailure, --reportformat String, --exported, --novolumegroup, +--short, --uuid + +pvscan --cache +OO: --ignorelockingfailure, --reportformat String, --background, +--activate String, --major Number, --minor Number, +OP: PV|String ... + +segtypes + +systemid + +tags + +vgcfgbackup +OO: --file String, --foreign, --ignorelockingfailure, --partial, --readonly, +--reportformat String + +vgcfgrestore VG +OO: --file String, --force_long, --list, --metadatatype String, --test + +vgcfgrestore --list --file String + +# +# None of these can function as a required option for vgchange. +# +OO_VGCHANGE: --autobackup Bool, --ignoremonitoring, --ignoreskippedcluster, +--noudevsync, --reportformat String, --select String, --test, --force + +# +# Any of these can function as a required option for vgchange. +# profile is also part of OO_ALL, but is repeated in OO_VGCHANGE_META +# because it can function as a required opt. +# +OO_VGCHANGE_META: --addtag Tag, --deltag Tag, +--logicalvolume Number, --maxphysicalvolumes Number, --alloc String, --uuid, +--clustered Bool, --metadatacopies Number, --vgmetadatacopies Number|String, +--physicalextentsize Number, --resizeable Bool, --systemid String, --locktype String, +--profile String, --detachprofile, --metadataprofile String, + +vgchange OO_VGCHANGE_META +OO: OO_VGCHANGE +OP: VG|Tag ... + +vgchange --monitor Bool +OO: --sysinit, --ignorelockingfailure, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgchange --poll Bool +OO: --ignorelockingfailure, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgchange --activate String +OO: --activationmode String, --ignoreactivationskip, --partial, --sysinit, +--ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgchange --refresh +OO: --sysinit, --ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgchange --lockstart +OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgchange --lockstop +OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE +OP: VG|Tag ... + +vgck +OO: --reportformat String +OP: VG|Tag ... + +vgconvert VG ... +OO: --force, --test, --labelsector Number, --bootloaderareasize Number, +--metadatatype String, --pvmetadatacopies Number, +--metadatasize Number, --reportformat String + +vgcreate VG_new PV ... +OO: --addtag Tag, --alloc String, --autobackup Bool, --clustered Bool, --maxlogicalvolumes Number, +--maxphysicalvolumes Number, --metadataprofile String, --metadatatype String, +--physicalextentsize Number, --test, --force, --zero Bool, --labelsector Number, +--metadatasize Number, --pvmetadatacopies Number, --reportformat String, --metadatacopies Number, +--vgmetadatacopies Number|String, --dataalignment Number, --dataalignmentoffset Number, +--shared, --systemid String, --locktype String, --lockopt String + +vgdisplay +OO: --activevolumegroups, --aligned, --binary, --colon, --columns, +--configreport String, --foreign, --ignorelockingfailure, +--ignoreskippedcluster, --logonly, --noheadings, --nosuffix, +--options String, --partial, --readonly, --reportformat String, --select String, +--shared, --short, --separator String, --sort String, --unbuffered, --units String +OP: VG|Tag ... + +OO_VGEXPORT: --reportformat String, --test + +vgexport VG|Tag|Select ... +OO: --select String, OO_VGEXPORT + +vgexport --all +OO: OO_VGEXPORT + +vgextend VG PV ... +OO: --autobackup Bool, --test, +--force, --zero Bool, --labelsector Number, --metadatatype String, +--metadatasize Number, --pvmetadatacopies Number, +--metadataignore Bool, --dataalignment Number, --dataalignmentoffset Number, +--reportformat String, --restoremissing + +OO_VGIMPORT: --force, --reportformat String, --test + +vgimport VG|Tag|Select ... +OO: --select String, OO_VGIMPORT + +vgimport --all +OO: OO_VGIMPORT + +vgimportclone PV ... +OO: --basevgname VG, --test, --import + +vgmerge VG VG +OO: --autobackup Bool, --list, --test + +vgmknodes +OO: --ignorelockingfailure, --refresh, --reportformat String +OP: VG|LV|Tag ... + +OO_VGREDUCE: --autobackup Bool, --force, --reportformat String, --test + +vgreduce VG PV ... +OO: OO_VGREDUCE + +vgreduce --all VG +OO: OO_VGREDUCE + +vgreduce --removemissing VG +OO: --mirrorsonly, OO_VGREDUCE + +vgremove VG|Tag|Select ... +OO: --force, --noudevsync, --reportformat String, --select String, --test + +vgrename VG VG_new +OO: --autobackup Bool, --force, --reportformat String, --test + +vgrename String VG_new +OO: --autobackup Bool, --force, --reportformat String, --test + +vgs +OO: OO_REPORT +OP: VG|Tag ... + +vgscan +OO: --cache_long, --ignorelockingfailure, --mknodes, --notifydbus, +--partial, --reportformat String + +OO_VGSPLIT: --autobackup Bool, --test + +OO_VGSPLIT_NEW: --alloc String, --clustered Bool, +--maxlogicalvolumes Number, --maxphysicalvolumes Number, +--metadatatype String, --vgmetadatacopies Number|String + +vgsplit VG VG PV ... +OO: OO_VGSPLIT + +vgsplit --name LV VG VG +OO: OO_VGSPLIT + +vgsplit VG VG_new PV ... +OO: OO_VGSPLIT, OO_VGSPLIT_NEW + +vgsplit --name LV VG VG_new +OO: OO_VGSPLIT, OO_VGSPLIT_NEW + +version + diff --git a/scripts/create-commands.c b/scripts/create-commands.c new file mode 100644 index 000000000..6238daa81 --- /dev/null +++ b/scripts/create-commands.c @@ -0,0 +1,1534 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* needed to include args.h */ +#define ARG_COUNTABLE 0x00000001 +#define ARG_GROUPABLE 0x00000002 +struct cmd_context; +struct arg_values; +int yes_no_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int activation_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int cachemode_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int discards_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int mirrorlog_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int size_kb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int size_mb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int size_mb_arg_with_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int int_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int int_arg_with_sign(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int int_arg_with_sign_and_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int major_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int minor_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int string_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int tag_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int permission_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int metadatatype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int units_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int segtype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int alloc_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int locktype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int readahead_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; } +int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; } + +struct opt_name { + const char *enum_name; + int enum_val; + const char short_opt; + char _padding[7]; + const char *long_opt; + + /* NULL if option takes no arg */ + int (*fn) (struct cmd_context *cmd, struct arg_values *av); + + uint32_t unused1; + uint32_t unused2; +}; + +/* enum for opt names */ +enum { +#define arg(a, b, c, d, e, f) a , +#include "args.h" +#undef arg +}; + +static struct opt_name opt_names[ARG_COUNT + 1] = { +#define arg(a, b, c, d, e, f) { # a, a, b, "", "--" c, d, e, f}, +#include "args.h" +#undef arg +}; + +#include "command.h" + +#define MAX_CMD_NAMES 128 +struct cmd_name { + const char *name; +}; + +static struct cmd_name cmd_names[MAX_CMD_NAMES] = { +#define xx(a, b...) { # a } , +#include "commands.h" +#undef xx +}; + +#define MAX_LINE 1024 +#define MAX_LINE_ARGC 256 + +#define REQUIRED 1 +#define OPTIONAL 0 + +struct oo_line { + char *name; + char *line; +}; + +#define MAX_CMDS 256 +int cmd_count; +struct command cmd_array[MAX_CMDS]; + +#define MAX_OO_LINES 256 +int oo_line_count; +struct oo_line oo_lines[MAX_OO_LINES]; + + +static void add_optional_opt_line(struct command *cmd, int argc, char *argv[]); + + +static int opt_str_to_num(char *str) +{ + char long_name[32]; + char *p; + int i; + + /* + * --foo_long means there are two args entries + * for --foo, one with a short option and one + * without, and we want the one without the + * short option. + */ + if (strstr(str, "_long")) { + strcpy(long_name, str); + p = strstr(long_name, "_long"); + *p = '\0'; + + for (i = 0; i < ARG_COUNT; i++) { + if (!opt_names[i].long_opt) + continue; + /* skip anything with a short opt */ + if (opt_names[i].short_opt) + continue; + if (!strcmp(opt_names[i].long_opt, long_name)) + return opt_names[i].enum_val; + } + + printf("Unknown opt str: %s %s\n", str, long_name); + exit(1); + } + + for (i = 0; i < ARG_COUNT; i++) { + if (!opt_names[i].long_opt) + continue; + /* These are only selected using --foo_long */ + if (strstr(opt_names[i].enum_name, "_long_ARG")) + continue; + if (!strcmp(opt_names[i].long_opt, str)) + return opt_names[i].enum_val; + } + + printf("Unknown opt str: \"%s\"\n", str); + exit(1); +} + +static int lv_str_to_num(char *str) +{ + char name[32] = { 0 }; + char *new; + int i; + + /* compare the lv name before the _new suffix */ + + strncpy(name, str, 31); + if ((new = strstr(name, "_new"))) + *new = '\0'; + + if (!strcmp(name, "LV")) + return 0; + + for (i = 1; i < ARG_DEF_LVS; i++) { + if (!arg_def_lvs[i].name) + break; + + if (!strcmp(name, arg_def_lvs[i].name)) + return arg_def_lvs[i].flag; + } + + printf("Unknown LV type: \"%s\" \"%s\"\n", name, str); + exit(1); +} + +static int type_str_to_num(char *str) +{ + char name[32] = { 0 }; + char *new; + int i; + + /* compare the name before the _new suffix */ + + strncpy(name, str, 31); + if ((new = strstr(name, "_new"))) + *new = '\0'; + + for (i = 0; i < ARG_DEF_TYPES; i++) { + if (!arg_def_types[i].name) + break; + if (!strncmp(name, arg_def_types[i].name, strlen(arg_def_types[i].name))) + return arg_def_types[i].flag; + } + + return 0; +} + +/* + * modifies buf, replacing the sep characters with \0 + * argv pointers point to positions in buf + */ + +static char *split_line(char *buf, int *argc, char **argv, char sep) +{ + char *p = buf, *rp = NULL; + int i; + + argv[0] = p; + + for (i = 1; i < MAX_LINE_ARGC; i++) { + p = strchr(buf, sep); + if (!p) + break; + *p = '\0'; + + argv[i] = p + 1; + buf = p + 1; + } + *argc = i; + + /* we ended by hitting \0, return the point following that */ + if (!rp) + rp = strchr(buf, '\0') + 1; + + return rp; +} + +static const char *is_command_name(char *str) +{ + int i; + + for (i = 0; i < MAX_CMD_NAMES; i++) { + if (!cmd_names[i].name) + break; + if (!strcmp(cmd_names[i].name, str)) + return cmd_names[i].name; + } + return NULL; +} + +static int is_opt_name(char *str) +{ + if (!strncmp(str, "--", 2)) + return 1; + + if ((str[0] == '-') && (str[1] != '-')) { + printf("Options must be specified in long form: %s\n", str); + exit(1); + } + + return 0; +} + +/* + * "Select" as a pos name means that the position + * can be empty if the --select option is used. + */ + +static int is_pos_name(char *str) +{ + if (!strncmp(str, "VG", 2)) + return 1; + if (!strncmp(str, "LV", 2)) + return 1; + if (!strncmp(str, "PV", 2)) + return 1; + if (!strncmp(str, "Tag", 3)) + return 1; + if (!strncmp(str, "String", 6)) + return 1; + if (!strncmp(str, "Select", 6)) + return 1; + return 0; +} + +static int is_oo_definition(char *str) +{ + if (!strncmp(str, "OO_", 3)) + return 1; + return 0; +} + +static int is_oo_line(char *str) +{ + if (!strncmp(str, "OO:", 3)) + return 1; + return 0; +} + +static int is_op_line(char *str) +{ + if (!strncmp(str, "OP:", 3)) + return 1; + return 0; +} + +static int is_desc_line(char *str) +{ + if (!strncmp(str, "DESC:", 5)) + return 1; + return 0; +} + +/* + * parse str for anything that can appear in a position, + * like VG, VG|LV, VG|LV_linear|LV_striped, etc + */ + +static void set_pos_def(struct command *cmd, char *str, struct arg_def *def) +{ + char *argv[MAX_LINE_ARGC]; + int argc; + char *name; + int type_num; + int i; + + split_line(str, &argc, argv, '|'); + + for (i = 0; i < argc; i++) { + name = argv[i]; + + type_num = type_str_to_num(name); + + if (!type_num) { + printf("Unknown pos arg: %s\n", name); + exit(1); + } + + def->types |= type_num; + + if ((type_num == ARG_DEF_TYPE_NAME_LV) && strstr(name, "_")) + def->lv_types |= lv_str_to_num(name); + + if (strstr(name, "_new")) + def->flags |= ARG_DEF_FLAG_NEW; + } +} + +/* + * parse str for anything that can follow --option + */ + +static void set_opt_def(struct command *cmd, char *str, struct arg_def *def) +{ + char *argv[MAX_LINE_ARGC]; + int argc; + char *name; + int type_num; + int i, j; + + split_line(str, &argc, argv, '|'); + + for (i = 0; i < argc; i++) { + name = argv[i]; + + type_num = type_str_to_num(name); + + if (!type_num) { + /* a literal number or string */ + + if (isdigit(name[0])) + type_num = ARG_DEF_TYPE_NUM_CONST; + + else if (isalpha(name[0])) + type_num = ARG_DEF_TYPE_STR_CONST; + + else { + printf("Unknown opt arg: %s\n", name); + exit(0); + } + } + + + switch (type_num) { + case ARG_DEF_TYPE_NONE: + break; + + case ARG_DEF_TYPE_BOOL: + case ARG_DEF_TYPE_NUM_ANY: + case ARG_DEF_TYPE_STR_ANY: + case ARG_DEF_TYPE_NAME_ANY: + case ARG_DEF_TYPE_NAME_PV: + case ARG_DEF_TYPE_NAME_VG: + case ARG_DEF_TYPE_TAG: + def->types |= type_num; + break; + + case ARG_DEF_TYPE_NUM_CONST: + def->types |= type_num; + def->num = (uint64_t)atoi(name); + break; + + case ARG_DEF_TYPE_STR_CONST: + if (def->types & ARG_DEF_TYPE_STR_CONST) { + def->types &= ~ARG_DEF_TYPE_STR_CONST; + def->types |= ARG_DEF_TYPE_STR_SET; + def->str_set[0] = def->str; + def->str = NULL; + } + + if (def->types & ARG_DEF_TYPE_STR_SET) { + for (j = 0; j < MAX_STR_SET; j++) { + if (def->str_set[j]) + continue; + def->str_set[j] = strdup(name); + break; + } + } else { + def->types |= type_num; + def->str = strdup(name); + } + break; + + case ARG_DEF_TYPE_NAME_LV: + def->types |= type_num; + if (strstr(name, "_")) + def->lv_types |= lv_str_to_num(name); + break; + } + + if ((type_num == ARG_DEF_TYPE_NAME_VG) || + (type_num == ARG_DEF_TYPE_NAME_LV) || + (type_num == ARG_DEF_TYPE_NAME_PV)) { + if (strstr(name, "_new")) + def->flags |= ARG_DEF_FLAG_NEW; + } + } +} + + +/* + * OO_FOO: --opt1 ... + * + * oo->name = "OO_FOO"; + * oo->line = "--opt1 ..."; + */ + +static void add_oo_definition_line(const char *name, const char *line) +{ + struct oo_line *oo; + char *colon; + char *start; + + oo = &oo_lines[oo_line_count++]; + oo->name = strdup(name); + + if ((colon = strstr(oo->name, ":"))) + *colon = '\0'; + else { + printf("invalid OO definition\n"); + exit(1); + } + + start = strstr(line, ":") + 2; + oo->line = strdup(start); +} + +/* when OO_FOO: continues on multiple lines */ + +static void append_oo_definition_line(const char *new_line) +{ + struct oo_line *oo; + char *old_line; + char *line; + int len; + + oo = &oo_lines[oo_line_count-1]; + + old_line = oo->line; + + /* +2 = 1 space between old and new + 1 terminating \0 */ + len = strlen(old_line) + strlen(new_line) + 2; + line = malloc(len); + memset(line, 0, len); + + strcat(line, old_line); + strcat(line, " "); + strcat(line, new_line); + + free(oo->line); + oo->line = line; +} + +char *get_oo_line(char *str) +{ + char *name; + char *end; + char str2[64]; + int i; + + strcpy(str2, str); + if ((end = strstr(str2, ":"))) + *end = '\0'; + if ((end = strstr(str2, ","))) + *end = '\0'; + + for (i = 0; i < oo_line_count; i++) { + name = oo_lines[i].name; + if (!strcmp(name, str2)) + return oo_lines[i].line; + } + return NULL; +} + +/* add optional_opt_args entries when OO_FOO appears on OO: line */ + +static void include_optional_opt_args(struct command *cmd, char *str) +{ + char *oo_line; + char *line; + char *line_argv[MAX_LINE_ARGC]; + int line_argc; + + if (!(oo_line = get_oo_line(str))) { + printf("No OO line found for %s\n", str); + exit(1); + } + + if (!(line = strdup(oo_line))) + exit(1); + + split_line(line, &line_argc, line_argv, ' '); + add_optional_opt_line(cmd, line_argc, line_argv); + free(line); +} + +static void add_opt_arg(struct command *cmd, char *str, int *takes_arg, int required) +{ + char *comma; + int opt; + + /* opt_arg.opt set here */ + /* opt_arg.def will be set in update_prev_opt_arg() if needed */ + + if ((comma = strstr(str, ","))) + *comma = '\0'; + + /* + * Work around nasty hack where --uuid is used for both uuid_ARG + * and uuidstr_ARG. The input uses --uuidstr, where an actual + * command uses --uuid string. + */ + if (!strcmp(str, "--uuidstr")) { + opt = uuidstr_ARG; + goto skip; + } + + opt = opt_str_to_num(str); +skip: + if (required) + cmd->required_opt_args[cmd->ro_count++].opt = opt; + else + cmd->optional_opt_args[cmd->oo_count++].opt = opt; + + *takes_arg = opt_names[opt].fn ? 1 : 0; +} + +static void update_prev_opt_arg(struct command *cmd, char *str, int required) +{ + struct arg_def def = { 0 }; + char *comma; + + if (str[0] == '-') { + printf("Option %s must be followed by an arg.\n", str); + exit(1); + } + + /* opt_arg.def set here */ + /* opt_arg.opt was previously set in add_opt_arg() when --foo was read */ + + if ((comma = strstr(str, ","))) + *comma = '\0'; + + set_opt_def(cmd, str, &def); + + if (required) + cmd->required_opt_args[cmd->ro_count-1].def = def; + else + cmd->optional_opt_args[cmd->oo_count-1].def = def; +} + +static void add_pos_arg(struct command *cmd, char *str, int required) +{ + struct arg_def def = { 0 }; + + /* pos_arg.pos and pos_arg.def are set here */ + + set_pos_def(cmd, str, &def); + + if (required) { + cmd->required_pos_args[cmd->rp_count].pos = cmd->pos_count++; + cmd->required_pos_args[cmd->rp_count].def = def; + cmd->rp_count++; + } else { + cmd->optional_pos_args[cmd->op_count].pos = cmd->pos_count++;; + cmd->optional_pos_args[cmd->op_count].def = def; + cmd->op_count++; + } +} + +/* process something that follows a pos arg, which is not a new pos arg */ + +static void update_prev_pos_arg(struct command *cmd, char *str, int required) +{ + struct arg_def *def; + + /* a previous pos_arg.def is modified here */ + + if (required) + def = &cmd->required_pos_args[cmd->rp_count-1].def; + else + def = &cmd->optional_pos_args[cmd->op_count-1].def; + + if (!strcmp(str, "...")) + def->flags |= ARG_DEF_FLAG_MAY_REPEAT; + else { + printf("Unknown pos arg: %s\n", str); + exit(1); + } +} + +/* process what follows OO:, which are optional opt args */ + +static void add_optional_opt_line(struct command *cmd, int argc, char *argv[]) +{ + int takes_arg; + int i; + + for (i = 0; i < argc; i++) { + if (!i && !strncmp(argv[i], "OO:", 3)) + continue; + if (is_opt_name(argv[i])) + add_opt_arg(cmd, argv[i], &takes_arg, OPTIONAL); + else if (!strncmp(argv[i], "OO_", 3)) + include_optional_opt_args(cmd, argv[i]); + else if (takes_arg) + update_prev_opt_arg(cmd, argv[i], OPTIONAL); + else + printf("Can't parse argc %d argv %s prev %s\n", + i, argv[i], argv[i-1]); + } +} + +/* process what follows OP:, which are optional pos args */ + +static void add_optional_pos_line(struct command *cmd, int argc, char *argv[]) +{ + int i; + + for (i = 0; i < argc; i++) { + if (!i && !strncmp(argv[i], "OP:", 3)) + continue; + if (is_pos_name(argv[i])) + add_pos_arg(cmd, argv[i], OPTIONAL); + else + update_prev_pos_arg(cmd, argv[i], OPTIONAL); + } +} + +/* add required opt args from OO_FOO definition */ + +static void add_required_opt_line(struct command *cmd, int argc, char *argv[]) +{ + int takes_arg; + int i; + + for (i = 0; i < argc; i++) { + if (is_opt_name(argv[i])) + add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED); + else if (takes_arg) + update_prev_opt_arg(cmd, argv[i], REQUIRED); + else + printf("Can't parse argc %d argv %s prev %s\n", + i, argv[i], argv[i-1]); + } +} + +/* add to required_opt_args when OO_FOO appears on required line */ + +static void include_required_opt_args(struct command *cmd, char *str) +{ + char *oo_line; + char *line; + char *line_argv[MAX_LINE_ARGC]; + int line_argc; + + if (!(oo_line = get_oo_line(str))) { + printf("No OO line found for %s\n", str); + exit(1); + } + + if (!(line = strdup(oo_line))) + exit(1); + + split_line(line, &line_argc, line_argv, ' '); + add_required_opt_line(cmd, line_argc, line_argv); + free(line); +} + +/* process what follows command_name, which are required opt/pos args */ + +static void add_required_line(struct command *cmd, int argc, char *argv[]) +{ + int i; + int takes_arg; + int prev_was_opt = 0, prev_was_pos = 0; + + /* argv[0] is command name */ + + for (i = 1; i < argc; i++) { + if (is_opt_name(argv[i])) { + add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED); + prev_was_opt = 1; + prev_was_pos = 0; + } else if (prev_was_opt && takes_arg) { + update_prev_opt_arg(cmd, argv[i], REQUIRED); + prev_was_opt = 0; + prev_was_pos = 0; + } else if (is_pos_name(argv[i])) { + add_pos_arg(cmd, argv[i], REQUIRED); + prev_was_opt = 0; + prev_was_pos = 1; + } else if (!strncmp(argv[i], "OO_", 3)) { + cmd->cmd_flags |= CMD_FLAG_ONE_REQUIRED_OPT; + include_required_opt_args(cmd, argv[i]); + } else if (prev_was_pos) { + update_prev_pos_arg(cmd, argv[i], REQUIRED); + } else + printf("Can't parse argc %d argv %s prev %s\n", + i, argv[i], argv[i-1]); + + } +} + +static void print_def(struct arg_def *def) +{ + int sep = 0; + int i; + + if (def->types & ARG_DEF_TYPE_BOOL) { + if (sep) printf("|"); + printf("Bool"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NUM_ANY) { + if (sep) printf("|"); + printf("Number"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_STR_ANY) { + if (sep) printf("|"); + printf("String"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NAME_ANY) { + if (sep) printf("|"); + printf("Name"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NAME_PV) { + if (sep) printf("|"); + printf("PV"); + if (def->flags & ARG_DEF_FLAG_NEW) + printf("_new"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NAME_VG) { + if (sep) printf("|"); + printf("VG"); + if (def->flags & ARG_DEF_FLAG_NEW) + printf("_new"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NAME_LV) { + if (!def->lv_types) { + if (sep) printf("|"); + printf("LV"); + sep = 1; + } else { + for (i = 0; i < ARG_DEF_LVS; i++) { + if (def->lv_types & arg_def_lvs[i].flag) { + if (sep) printf("|"); + printf("%s", arg_def_lvs[i].name); + sep = 1; + } + } + } + if (def->flags & ARG_DEF_FLAG_NEW) + printf("_new"); + } + + if (def->types & ARG_DEF_TYPE_TAG) { + if (sep) printf("|"); + printf("Tag"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_SELECT) { + if (sep) printf("|"); + printf("Select"); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_STR_CONST) { + if (sep) printf("|"); + printf("%s", def->str); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_NUM_CONST) { + if (sep) printf("|"); + printf("%llu", def->num); + sep = 1; + } + + if (def->types & ARG_DEF_TYPE_STR_SET) { + for (i = 0; i < MAX_STR_SET; i++) { + if (def->str_set[i]) { + if (sep) printf("|"); + printf("%s", def->str_set[i]); + sep = 1; + } + } + } + + if (def->flags & ARG_DEF_FLAG_MAY_REPEAT) + printf(" ..."); +} + +void print_data_expanded(void) +{ + struct command *cmd; + int i, ro, rp, oo, op; + + for (i = 0; i < cmd_count; i++) { + cmd = &cmd_array[i]; + printf("%s", cmd->name); + + if (cmd->ro_count) { + for (ro = 0; ro < cmd->ro_count; ro++) { + printf(" %s", opt_names[cmd->required_opt_args[ro].opt].long_opt); + if (cmd->required_opt_args[ro].def.types) { + printf(" "); + print_def(&cmd->required_opt_args[ro].def); + } + } + } + + if (cmd->rp_count) { + for (rp = 0; rp < cmd->rp_count; rp++) { + if (cmd->required_pos_args[rp].def.types) { + printf(" "); + print_def(&cmd->required_pos_args[rp].def); + } + } + } + + if (cmd->oo_count) { + printf("\n"); + printf("OO:"); + for (oo = 0; oo < cmd->oo_count; oo++) { + if (oo) + printf(","); + printf(" %s", opt_names[cmd->optional_opt_args[oo].opt].long_opt); + if (cmd->optional_opt_args[oo].def.types) { + printf(" "); + print_def(&cmd->optional_opt_args[oo].def); + } + } + } + + if (cmd->op_count) { + printf("\n"); + printf("OP:"); + for (op = 0; op < cmd->op_count; op++) { + if (cmd->optional_pos_args[op].def.types) { + printf(" "); + print_def(&cmd->optional_pos_args[op].def); + } + } + } + + printf("\n\n"); + } +} + +static const char *opt_to_enum_str(int opt) +{ + return opt_names[opt].enum_name; +} + +static char *type_num_to_flags(int types) +{ + static char buf[128]; + int or = 0; + + memset(buf, 0, sizeof(buf)); + + if (types & ARG_DEF_TYPE_BOOL) { + strcat(buf, "ARG_DEF_TYPE_BOOL"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NUM_ANY) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NUM_ANY"); + or = 1; + } + + if (types & ARG_DEF_TYPE_STR_ANY) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_STR_ANY"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NUM_CONST) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NUM_CONST"); + or = 1; + } + + if (types & ARG_DEF_TYPE_STR_CONST) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_STR_CONST"); + or = 1; + } + + if (types & ARG_DEF_TYPE_STR_SET) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_STR_SET"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NAME_ANY) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NAME_ANY"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NAME_PV) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NAME_PV"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NAME_VG) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NAME_VG"); + or = 1; + } + + if (types & ARG_DEF_TYPE_NAME_LV) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_NAME_LV"); + or = 1; + } + + if (types & ARG_DEF_TYPE_TAG) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_TAG"); + or = 1; + } + + if (types & ARG_DEF_TYPE_SELECT) { + if (or) strcat(buf, "|"); + strcat(buf, "ARG_DEF_TYPE_SELECT"); + or = 1; + } + + return buf; +} + +static char *lv_num_to_flags(int lv_types) +{ + static char buf_lv_types[128]; + int or = 0; + + memset(buf_lv_types, 0, sizeof(buf_lv_types)); + + if (lv_types & ARG_DEF_LV_LINEAR) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_LINEAR"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_STRIPED) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_STRIPED"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_SNAPSHOT) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_SNAPSHOT"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_MIRROR) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_MIRROR"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID0) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID0"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID1) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID1"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID4) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID4"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID5) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID5"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID6) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID6"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_RAID10) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_RAID10"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_THIN) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_THIN"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_THINPOOL) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_THINPOOL"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_CACHE) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_CACHE"); + or = 1; + } + + if (lv_types & ARG_DEF_LV_CACHEPOOL) { + if (or) strcat(buf_lv_types, "|"); + strcat(buf_lv_types, "ARG_DEF_LV_CACHEPOOL"); + or = 1; + } + + return buf_lv_types; +} + +static char *flags_to_str(int flags) +{ + static char buf_flags[32]; + + memset(buf_flags, 0, sizeof(buf_flags)); + + if (flags & ARG_DEF_FLAG_MAY_REPEAT) + strcat(buf_flags, "ARG_DEF_FLAG_MAY_REPEAT"); + if (flags & ARG_DEF_FLAG_NEW) + strcat(buf_flags, "ARG_DEF_FLAG_NEW"); + + return buf_flags; +} + +void print_define_command_count(void) +{ + printf("#define COMMAND_COUNT %d\n", cmd_count); +} + +void print_usage(struct command *cmd) +{ + int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0; + int i, ro, rp, oo, op; + + printf("\"%s", cmd->name); + + if (cmd->ro_count) { + if (onereq) + printf(" ("); + for (ro = 0; ro < cmd->ro_count; ro++) { + if (ro && onereq) + printf(","); + printf(" %s", opt_names[cmd->required_opt_args[ro].opt].long_opt); + + if (cmd->required_opt_args[ro].def.types) { + printf(" "); + print_def(&cmd->required_opt_args[ro].def); + } + } + if (onereq) + printf(" )"); + } + + if (cmd->rp_count) { + for (rp = 0; rp < cmd->rp_count; rp++) { + if (cmd->required_pos_args[rp].def.types) { + printf(" "); + print_def(&cmd->required_pos_args[rp].def); + } + } + } + + printf("\""); + + if (!cmd->oo_count) + goto op_count; + + printf("\n"); + printf("\"["); + + if (cmd->oo_count) { + for (oo = 0; oo < cmd->oo_count; oo++) { + if (oo) + printf(","); + printf(" %s", opt_names[cmd->optional_opt_args[oo].opt].long_opt); + if (cmd->optional_opt_args[oo].def.types) { + printf(" "); + print_def(&cmd->optional_opt_args[oo].def); + } + } + } + + printf(" ]\""); + + op_count: + if (!cmd->op_count) + goto done; + + printf("\n"); + printf("\"["); + + if (cmd->op_count) { + for (op = 0; op < cmd->op_count; op++) { + if (cmd->optional_pos_args[op].def.types) { + printf(" "); + print_def(&cmd->optional_pos_args[op].def); + } + } + } + + printf(" ]\""); + + done: + printf(";\n"); +} + +void print_command_count(void) +{ + printf("#define COMMAND_COUNT %d\n", cmd_count); +} + +void print_command_structs(void) +{ + struct command *cmd; + int i, j, ro, rp, oo, op; + + for (i = 0; i < cmd_count; i++) { + cmd = &cmd_array[i]; + + printf("commands[%d].name = \"%s\";\n", i, cmd->name); + printf("commands[%d].fn = %s;\n", i, cmd->name); + printf("commands[%d].desc = \"%s\";\n", i, cmd->desc ?: ""); + printf("commands[%d].usage = ", i); + print_usage(cmd); + + if (cmd->ro_count) { + for (ro = 0; ro < cmd->ro_count; ro++) { + printf("commands[%d].required_opt_args[%d].opt = %s;\n", + i, ro, opt_to_enum_str(cmd->required_opt_args[ro].opt)); + + if (!cmd->required_opt_args[ro].def.types) + continue; + + printf("commands[%d].required_opt_args[%d].def.types = %s;\n", + i, ro, type_num_to_flags(cmd->required_opt_args[ro].def.types)); + + if (cmd->required_opt_args[ro].def.lv_types) + printf("commands[%d].required_opt_args[%d].def.lv_types = %s;\n", + i, ro, lv_num_to_flags(cmd->required_opt_args[ro].def.lv_types)); + if (cmd->required_opt_args[ro].def.types & ARG_DEF_TYPE_NUM_CONST) + printf("commands[%d].required_opt_args[%d].def.num = %d;\n", + i, ro, cmd->required_opt_args[ro].def.num); + if (cmd->required_opt_args[ro].def.flags) + printf("commands[%d].required_opt_args[%d].def.flags = %s;\n", + i, ro, flags_to_str(cmd->required_opt_args[ro].def.flags)); + if (cmd->required_opt_args[ro].def.types & ARG_DEF_TYPE_STR_CONST) + printf("commands[%d].required_opt_args[%d].def.str = \"%s\";\n", + i, ro, cmd->required_opt_args[ro].def.str ?: "NULL"); + if (cmd->required_opt_args[ro].def.types & ARG_DEF_TYPE_STR_SET) { + for (j = 0; j < MAX_STR_SET; j++) { + if (cmd->required_opt_args[ro].def.str_set[j]) + printf("commands[%d].required_opt_args[%d].def.str_set[%d] = %s;\n", + i, ro, j, cmd->required_opt_args[ro].def.str_set[j] ?: "NULL"); + } + } + } + } + + if (cmd->rp_count) { + for (rp = 0; rp < cmd->rp_count; rp++) { + printf("commands[%d].required_pos_args[%d].pos = %d;\n", + i, rp, cmd->required_pos_args[rp].pos); + + if (!cmd->required_pos_args[rp].def.types) + continue; + + printf("commands[%d].required_pos_args[%d].def.types = %s;\n", + i, rp, type_num_to_flags(cmd->required_pos_args[rp].def.types)); + + if (cmd->required_pos_args[rp].def.lv_types) + printf("commands[%d].required_pos_args[%d].def.lv_types = %s;\n", + i, rp, lv_num_to_flags(cmd->required_pos_args[rp].def.lv_types)); + if (cmd->required_pos_args[rp].def.types & ARG_DEF_TYPE_NUM_CONST) + printf("commands[%d].required_pos_args[%d].def.num = %d;\n", + i, rp, cmd->required_pos_args[rp].def.num); + if (cmd->required_pos_args[rp].def.flags) + printf("commands[%d].required_pos_args[%d].def.flags = %s;\n", + i, rp, flags_to_str(cmd->required_pos_args[rp].def.flags)); + if (cmd->required_pos_args[rp].def.types & ARG_DEF_TYPE_STR_CONST) + printf("commands[%d].required_pos_args[%d].def.str = \"%s\";\n", + i, rp, cmd->required_pos_args[rp].def.str ?: "NULL"); + if (cmd->required_pos_args[rp].def.types & ARG_DEF_TYPE_STR_SET) { + for (j = 0; j < MAX_STR_SET; j++) { + if (cmd->required_pos_args[rp].def.str_set[j]) + printf("commands[%d].required_pos_args[%d].def.str_set[%d] = \"%s\";\n", + i, rp, j, cmd->required_pos_args[rp].def.str_set[j] ?: "NULL"); + } + } + } + } + + if (cmd->oo_count) { + for (oo = 0; oo < cmd->oo_count; oo++) { + printf("commands[%d].optional_opt_args[%d].opt = %s;\n", + i, oo, opt_to_enum_str(cmd->optional_opt_args[oo].opt)); + + if (!cmd->optional_opt_args[oo].def.types) + continue; + + printf("commands[%d].optional_opt_args[%d].def.types = %s;\n", + i, oo, type_num_to_flags(cmd->optional_opt_args[oo].def.types)); + + if (cmd->optional_opt_args[oo].def.lv_types) + printf("commands[%d].optional_opt_args[%d].def.lv_types = %s;\n", + i, oo, lv_num_to_flags(cmd->optional_opt_args[oo].def.lv_types)); + if (cmd->optional_opt_args[oo].def.types & ARG_DEF_TYPE_NUM_CONST) + printf("commands[%d].optional_opt_args[%d].def.num = %d;\n", + i, oo, cmd->optional_opt_args[oo].def.num); + if (cmd->optional_opt_args[oo].def.flags) + printf("commands[%d].optional_opt_args[%d].def.flags = %s;\n", + i, oo, flags_to_str(cmd->optional_opt_args[oo].def.flags)); + if (cmd->optional_opt_args[oo].def.types & ARG_DEF_TYPE_STR_CONST) + printf("commands[%d].optional_opt_args[%d].def.str = \"%s\";\n", + i, oo, cmd->optional_opt_args[oo].def.str ?: "NULL"); + if (cmd->optional_opt_args[oo].def.types & ARG_DEF_TYPE_STR_SET) { + for (j = 0; j < MAX_STR_SET; j++) { + if (cmd->optional_opt_args[oo].def.str_set[j]) + printf("commands[%d].optional_opt_args[%d].def.str_set[%d] = \"%s\";\n", + i, oo, j, cmd->optional_opt_args[oo].def.str_set[j] ?: "NULL"); + } + } + } + } + + if (cmd->op_count) { + for (op = 0; op < cmd->op_count; op++) { + printf("commands[%d].optional_pos_args[%d].pos = %d;\n", + i, op, cmd->optional_pos_args[op].pos); + + if (!cmd->optional_pos_args[op].def.types) + continue; + + printf("commands[%d].optional_pos_args[%d].def.types = %s;\n", + i, op, type_num_to_flags(cmd->optional_pos_args[op].def.types)); + + if (cmd->optional_pos_args[op].def.lv_types) + printf("commands[%d].optional_pos_args[%d].def.lv_types = %s;\n", + i, op, lv_num_to_flags(cmd->optional_pos_args[op].def.lv_types)); + if (cmd->optional_pos_args[op].def.types & ARG_DEF_TYPE_NUM_CONST) + printf("commands[%d].optional_pos_args[%d].def.num = %d;\n", + i, op, cmd->optional_pos_args[op].def.num); + if (cmd->optional_pos_args[op].def.flags) + printf("commands[%d].optional_pos_args[%d].def.flags = %s;\n", + i, op, flags_to_str(cmd->optional_pos_args[op].def.flags)); + if (cmd->optional_pos_args[op].def.types & ARG_DEF_TYPE_STR_CONST) + printf("commands[%d].optional_pos_args[%d].def.str = \"%s\";\n", + i, op, cmd->optional_pos_args[op].def.str ?: "NULL"); + if (cmd->optional_pos_args[op].def.types & ARG_DEF_TYPE_STR_SET) { + for (j = 0; j < MAX_STR_SET; j++) { + if (cmd->optional_pos_args[op].def.str_set[j]) + printf("commands[%d].optional_pos_args[%d].def.str_set[%d] = \"%s\";\n", + i, op, j, cmd->optional_pos_args[op].def.str_set[j] ?: "NULL"); + } + } + } + } + + printf("\n"); + } +} + +void print_command_list(void) +{ + int i; + + for (i = 0; i < MAX_CMD_NAMES; i++) { + if (!cmd_names[i].name) { + printf("found %d command names\n", i); + break; + } + printf("%s\n", cmd_names[i].name); + } +} + +void print_option_list(void) +{ + int i; + + for (i = 0; i < ARG_COUNT; i++) + printf("%d %s %s %c\n", + opt_names[i].enum_val, opt_names[i].enum_name, + opt_names[i].long_opt, opt_names[i].short_opt ?: ' '); +} + +static void print_help(int argc, char *argv[]) +{ + printf("%s --output struct|count|expand \n", argv[0]); + printf("\n"); + printf("struct: print C structures for command definitions.\n"); + printf("expand: print expanded input format.\n"); + printf("count: print #define COMMAND_COUNT \n"); +} + +int main(int argc, char *argv[]) +{ + char *outputformat = NULL; + char *inputfile = NULL; + FILE *file; + struct command *cmd; + char line[MAX_LINE]; + char line_orig[MAX_LINE]; + const char *name; + char *line_argv[MAX_LINE_ARGC]; + char *n; + int line_argc; + int prev_was_oo_def = 0; + int prev_was_oo = 0; + int prev_was_op = 0; + + if (argc < 2) { + print_help(argc, argv); + exit(EXIT_FAILURE); + } + + static struct option long_options[] = { + {"help", no_argument, 0, 'h' }, + {"output", required_argument, 0, 'o' }, + {0, 0, 0, 0 } + }; + + while (1) { + int c; + int option_index = 0; + + c = getopt_long(argc, argv, "ho:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case '0': + break; + case 'h': + print_help(argc, argv); + exit(EXIT_SUCCESS); + case 'o': + outputformat = strdup(optarg); + break; + } + } + + if (optind < argc) + inputfile = argv[optind]; + else { + printf("Missing filename.\n"); + return 0; + } + + if (!(file = fopen(inputfile, "r"))) { + printf("Cannot open %s\n", argv[1]); + return -1; + } + + while (fgets(line, MAX_LINE, file)) { + if (line[0] == '#') + continue; + if (line[0] == '\n') + continue; + + if ((n = strchr(line, '\n'))) + *n = '\0'; + + memcpy(line_orig, line, sizeof(line)); + split_line(line, &line_argc, line_argv, ' '); + + if (!line_argc) + continue; + + /* command ... */ + if ((name = is_command_name(line_argv[0]))) { + if (cmd_count >= MAX_CMDS) { + printf("MAX_CMDS too small\n"); + return -1; + } + cmd = &cmd_array[cmd_count++]; + cmd->name = name; + cmd->pos_count = 1; + add_required_line(cmd, line_argc, line_argv); + + /* Every cmd gets the OO_ALL options */ + include_optional_opt_args(cmd, "OO_ALL:"); + continue; + } + + if (is_desc_line(line_argv[0])) { + char *desc = strdup(strstr(line_orig, ":") + 2); + if (cmd->desc) { + cmd->desc = realloc((char *)cmd->desc, strlen(cmd->desc) + strlen(desc) + 2); + strcat((char *)cmd->desc, "\n"); + strcat((char *)cmd->desc, desc); + free(desc); + } else + cmd->desc = desc; + continue; + } + + /* OO_FOO: ... */ + if (is_oo_definition(line_argv[0])) { + add_oo_definition_line(line_argv[0], line_orig); + prev_was_oo_def = 1; + prev_was_oo = 0; + prev_was_op = 0; + continue; + } + + /* OO: ... */ + if (is_oo_line(line_argv[0])) { + add_optional_opt_line(cmd, line_argc, line_argv); + prev_was_oo_def = 0; + prev_was_oo = 1; + prev_was_op = 0; + continue; + } + + /* OP: ... */ + if (is_op_line(line_argv[0])) { + add_optional_pos_line(cmd, line_argc, line_argv); + prev_was_oo_def = 0; + prev_was_oo = 0; + prev_was_op = 1; + continue; + } + + /* handle OO_FOO:, OO:, OP: continuing on multiple lines */ + + if (prev_was_oo_def) { + append_oo_definition_line(line_orig); + continue; + } + + if (prev_was_oo) { + add_optional_opt_line(cmd, line_argc, line_argv); + continue; + } + + if (prev_was_op) { + add_optional_pos_line(cmd, line_argc, line_argv); + continue; + } + } + + fclose(file); + + if (!outputformat) + print_data_expanded(); + else if (!strcmp(outputformat, "struct")) + print_command_structs(); + else if (!strcmp(outputformat, "count")) + print_command_count(); + else if (!strcmp(outputformat, "expand")) + print_data_expanded(); + else + print_help(argc, argv); +} + diff --git a/tools/args.h b/tools/args.h index a04d81d5e..bd491885f 100644 --- a/tools/args.h +++ b/tools/args.h @@ -32,7 +32,7 @@ arg(cachepool_ARG, '\0', "cachepool", string_arg, 0, 0) arg(commandprofile_ARG, '\0', "commandprofile", string_arg, 0, 0) arg(config_ARG, '\0', "config", string_arg, 0, 0) arg(configreport_ARG, '\0', "configreport", string_arg, ARG_GROUPABLE, 1) -arg(configtype_ARG, '\0', "type", string_arg, 0, 0) +arg(configtype_ARG, '\0', "configtype", string_arg, 0, 0) arg(corelog_ARG, '\0', "corelog", NULL, 0, 0) arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0, 0) arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0, 0) diff --git a/tools/command.h b/tools/command.h new file mode 100644 index 000000000..b2abcc45e --- /dev/null +++ b/tools/command.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _LVM_COMMAND_H +#define _LVM_COMMAND_H + +struct cmd_context; + +/* command functions */ +typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv); + +/* + * Command defintion + * + * A command is defined in terms of a command name, + * required options (+args), optional options (+args), + * required positional args, optional positional args. + * + * A positional arg always has non-zero pos_arg.def.types. + * The first positional arg has pos_arg.pos of 1. + */ + +/* Number of string constants accepted after an option. */ +#define MAX_STR_SET 16 + +/* arg_def flags */ +#define ARG_DEF_FLAG_NEW 1 +#define ARG_DEF_FLAG_MAY_REPEAT 2 + +/* arg_def types, can be multiple */ +enum { + ARG_DEF_TYPE_NONE = 0, + ARG_DEF_TYPE_BOOL = 1 << 0, + ARG_DEF_TYPE_NUM_ANY = 1 << 1, + ARG_DEF_TYPE_STR_ANY = 1 << 2, + ARG_DEF_TYPE_NUM_CONST = 1 << 3, + ARG_DEF_TYPE_STR_CONST = 1 << 4, + ARG_DEF_TYPE_STR_SET = 1 << 5, /* a set of specific accepted string values */ + ARG_DEF_TYPE_NAME_ANY = 1 << 6, + ARG_DEF_TYPE_NAME_PV = 1 << 7, + ARG_DEF_TYPE_NAME_VG = 1 << 8, + ARG_DEF_TYPE_NAME_LV = 1 << 9, + ARG_DEF_TYPE_TAG = 1 << 10, + ARG_DEF_TYPE_SELECT = 1 << 11, +}; + +#define ARG_DEF_TYPES 16 +struct arg_def_type { + const char *name; + int flag; +}; + +/* The names used for arg_def types in command-lines.in */ +static struct arg_def_type arg_def_types[ARG_DEF_TYPES] = { + { "None", ARG_DEF_TYPE_NONE}, + { "Bool", ARG_DEF_TYPE_BOOL}, + { "Number", ARG_DEF_TYPE_NUM_ANY}, + { "String", ARG_DEF_TYPE_STR_ANY}, + { "Name", ARG_DEF_TYPE_NAME_ANY}, + { "PV", ARG_DEF_TYPE_NAME_PV}, + { "VG", ARG_DEF_TYPE_NAME_VG}, + { "LV", ARG_DEF_TYPE_NAME_LV}, + { "Tag", ARG_DEF_TYPE_TAG}, + { "Select", ARG_DEF_TYPE_SELECT}, +}; + +/* arg_def lv_types, can be multiple */ +enum { + ARG_DEF_LV_ANY = 0, + ARG_DEF_LV_LINEAR = 1 << 0, + ARG_DEF_LV_STRIPED = 1 << 1, + ARG_DEF_LV_SNAPSHOT = 1 << 2, + ARG_DEF_LV_MIRROR = 1 << 3, + ARG_DEF_LV_RAID = 1 << 4, + ARG_DEF_LV_RAID0 = 1 << 5, + ARG_DEF_LV_RAID1 = 1 << 6, + ARG_DEF_LV_RAID4 = 1 << 7, + ARG_DEF_LV_RAID5 = 1 << 8, + ARG_DEF_LV_RAID6 = 1 << 9, + ARG_DEF_LV_RAID10 = 1 << 10, + ARG_DEF_LV_THIN = 1 << 11, + ARG_DEF_LV_THINPOOL = 1 << 12, + ARG_DEF_LV_CACHE = 1 << 13, + ARG_DEF_LV_CACHEPOOL = 1 << 14, +}; + +#define ARG_DEF_LVS 64 +struct arg_def_lv { + const char *name; + int flag; +}; + +/* The names used for arg_def lv_types in command-lines.in */ +static struct arg_def_lv arg_def_lvs[ARG_DEF_LVS] = { + { "LV", ARG_DEF_LV_ANY}, + { "LV_linear", ARG_DEF_LV_LINEAR}, + { "LV_striped", ARG_DEF_LV_STRIPED}, + { "LV_snapshot", ARG_DEF_LV_SNAPSHOT}, + { "LV_mirror", ARG_DEF_LV_MIRROR}, + { "LV_raid", ARG_DEF_LV_RAID}, + { "LV_raid0", ARG_DEF_LV_RAID0}, + { "LV_raid1", ARG_DEF_LV_RAID1}, + { "LV_raid4", ARG_DEF_LV_RAID4}, + { "LV_raid5", ARG_DEF_LV_RAID5}, + { "LV_raid6", ARG_DEF_LV_RAID6}, + { "LV_raid10", ARG_DEF_LV_RAID10}, + { "LV_thin", ARG_DEF_LV_THIN}, + { "LV_thinpool", ARG_DEF_LV_THINPOOL}, + { "LV_cache", ARG_DEF_LV_CACHE}, + { "LV_cachepool", ARG_DEF_LV_CACHEPOOL}, +}; + +/* Description a value that follows an option or exists in a position. */ + +struct arg_def { + uint32_t types; /* ARG_DEF_TYPE_, can be multiple */ + uint32_t lv_types; /* ARG_DEF_LV_, can be multiple */ + uint64_t num; /* a literal number for ARG_DEF_TYPE_NUM_CONST */ + const char *str; /* a literal string for ARG_DEF_TYPE_STR_CONST */ + const char *str_set[MAX_STR_SET]; /* literal strings for ARG_DEF_TYPE_STR_SET */ + uint32_t flags; /* ARG_DEF_FLAG_ */ +}; + +/* Description of an option and the value that follows it. */ + +struct opt_arg { + int opt; /* option, e.g. foo_ARG */ + struct arg_def def; /* defines accepted values */ +}; + +/* Description of a position and the value that exists there. */ + +struct pos_arg { + int pos; /* position, e.g. first is 1 */ + struct arg_def def; /* defines accepted values */ +}; + +/* + * CMD_RO_ARGS needs to accomodate a list of options, + * of which one is required after which the rest are + * optional. + */ +#define CMD_RO_ARGS 32 /* required opt args */ +#define CMD_OO_ARGS ARG_COUNT /* optional opt args */ +#define CMD_RP_ARGS 8 /* required positional args */ +#define CMD_OP_ARGS 8 /* optional positional args */ + +/* + * one or more from required_opt_args is required, + * then the rest are optional. + */ +#define CMD_FLAG_ONE_REQUIRED_OPT 1 + +/* a register of the lvm commands */ +struct command { + const char *name; + const char *desc; + const char *usage; + command_fn fn; + + unsigned int flags; + + unsigned int cmd_flags; /* CMD_FLAG_ */ + + /* definitions of opt/pos args */ + + /* required args following an --opt */ + struct opt_arg required_opt_args[CMD_RO_ARGS]; + + /* optional args following an --opt */ + struct opt_arg optional_opt_args[CMD_OO_ARGS]; + + /* required positional args */ + struct pos_arg required_pos_args[CMD_RP_ARGS]; + + /* optional positional args */ + struct pos_arg optional_pos_args[CMD_OP_ARGS]; + + int ro_count; + int oo_count; + int rp_count; + int op_count; + + /* used for processing current position */ + int pos_count; +}; + +#endif diff --git a/tools/commands.h b/tools/commands.h index baf89b15f..c66320794 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -13,1546 +13,232 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/*********** Replace with script? -xx(e2fsadm, - "Resize logical volume and ext2 filesystem", - "e2fsadm " - "[-d|--debug] " "[-h|--help] " "[-n|--nofsck]\n" - "\t{[-l|--extents] [+|-]LogicalExtentsNumber |\n" - "\t [-L|--size] [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tLogicalVolumePath\n", - - extents_ARG, size_ARG, nofsck_ARG, test_ARG) -*********/ - xx(config, "Display and manipulate configuration information", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "config\n" - "\t[-f|--file filename]\n" - "\t[--type {current|default|diff|full|list|missing|new|profilable|profilable-command|profilable-metadata}]\n" - "\t[--atversion version]\n" - "\t[--ignoreadvanced]\n" - "\t[--ignoreunsupported]\n" - "\t[--ignorelocal]\n" - "\t[-l|--list]\n" - "\t[--config ConfigurationString]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--profile ProfileName]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[--mergedconfig]\n" - "\t[--sinceversion version]\n" - "\t[--showdeprecated]\n" - "\t[--showunsupported]\n" - "\t[--validate]\n" - "\t[--withsummary]\n" - "\t[--withcomments]\n" - "\t[--withspaces]\n" - "\t[--unconfigured]\n" - "\t[--withversions]\n" - "\t[ConfigurationNode...]\n", - atversion_ARG, configtype_ARG, file_ARG, ignoreadvanced_ARG, - ignoreunsupported_ARG, ignorelocal_ARG, list_ARG, mergedconfig_ARG, metadataprofile_ARG, - sinceversion_ARG, showdeprecated_ARG, showunsupported_ARG, validate_ARG, withsummary_ARG, - withcomments_ARG, withspaces_ARG, unconfigured_ARG, withversions_ARG) + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(devtypes, "Display recognised built-in block device types", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "devtypes\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--nameprefixes]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--rows]\n" - "\t[-S|--select Selection]\n" - "\t[--separator Separator]\n" - "\t[--unbuffered]\n" - "\t[--unquoted]\n" - "\t[--version]\n", - - aligned_ARG, binary_ARG, nameprefixes_ARG, noheadings_ARG, - nosuffix_ARG, options_ARG, reportformat_ARG, rows_ARG, - select_ARG, separator_ARG, sort_ARG, unbuffered_ARG, unquoted_ARG) + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(dumpconfig, "Display and manipulate configuration information", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "dumpconfig\n" - "\t[-f|--file filename]\n" - "\t[--type {current|default|diff|full|list|missing|new|profilable|profilable-command|profilable-metadata}]\n" - "\t[--atversion version]\n" - "\t[--ignoreadvanced]\n" - "\t[--ignoreunsupported]\n" - "\t[--ignorelocal]\n" - "\t[-l|--list]\n" - "\t[--config ConfigurationString]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--profile ProfileName]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[--mergedconfig]\n" - "\t[--sinceversion version]\n" - "\t[--showdeprecated]\n" - "\t[--showunsupported]\n" - "\t[--validate]\n" - "\t[--withsummary]\n" - "\t[--withcomments]\n" - "\t[--withspaces]\n" - "\t[--unconfigured]\n" - "\t[--withversions]\n" - "\t[ConfigurationNode...]\n", - atversion_ARG, configtype_ARG, file_ARG, ignoreadvanced_ARG, - ignoreunsupported_ARG, ignorelocal_ARG, list_ARG, mergedconfig_ARG, metadataprofile_ARG, - sinceversion_ARG, showdeprecated_ARG, showunsupported_ARG, validate_ARG, withsummary_ARG, - withcomments_ARG, withspaces_ARG, unconfigured_ARG, withversions_ARG) + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(formats, "List available metadata formats", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "formats\n") + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(help, "Display help for commands", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "help \n") - -/********* -xx(lvactivate, - "Activate logical volume on given partition(s)", - "lvactivate " - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-v|--verbose]\n" - "Logical Volume(s)\n") -***********/ + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(fullreport, "Display full report", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "fullreport\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[-a|--all]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--nameprefixes]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--rows]\n" - "\t[-S|--select Selection]\n" - "\t[--separator Separator]\n" - "\t[--trustcache]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--unquoted]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName [VolumeGroupName...]]\n", - - aligned_ARG, all_ARG, binary_ARG, configreport_ARG, foreign_ARG, - ignorelockingfailure_ARG, ignoreskippedcluster_ARG, logonly_ARG, - nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, - options_ARG, partial_ARG, readonly_ARG, reportformat_ARG, rows_ARG, - select_ARG, separator_ARG, shared_ARG, sort_ARG, trustcache_ARG, - unbuffered_ARG, units_ARG, unquoted_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(lastlog, "Display last command's log report", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "log\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n", - - reportformat_ARG, select_ARG) + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(lvchange, "Change the attributes of logical volume(s)", - CACHE_VGMETADATA | PERMITTED_READ_ONLY, - "lvchange\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[-a|--activate [a][e|s|l]{y|n}]\n" - "\t[--activationmode {complete|degraded|partial}" - "\t[--addtag ]\n" - "\t[--alloc ]\n" - "\t[--rebuild PhysicalVolume]\n" - "\t[-C|--contiguous {y|n}]\n" - "\t[--cachemode ]\n" - "\t[--cachepolicy ] [--cachesettings ]\n" - "\t[--commandprofile ]\n" - "\t[-d|--debug]\n" - "\t[--deltag ]\n" - "\t[--detachprofile]\n" - "\t[--errorwhenfull {y|n}]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--discards {ignore|nopassdown|passdown}]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoremonitoring]\n" - "\t[--ignoreskippedcluster]\n" - "\t[-k|--setactivationskip {y|n}]\n" - "\t[-K|--ignoreactivationskip]\n" - "\t[--monitor {y|n}]\n" - "\t[--poll {y|n}]\n" - "\t[--noudevsync]\n" - "\t[-M|--persistent {y|n}] [-j|--major ] [--minor ]\n" - "\t[--metadataprofile ]\n" - "\t[-P|--partial]\n" - "\t[-p|--permission {r|rw}]\n" - "\t[--[raid]minrecoveryrate ]\n" - "\t[--[raid]maxrecoveryrate ]\n" - "\t[--[raid]syncaction {check|repair}\n" - "\t[--[raid]writebehind ]\n" - "\t[--[raid]writemostly [:{t|n|y}]]\n" - "\t[-r|--readahead |auto|none]\n" - "\t[--refresh]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--resync]\n" - "\t[-S|--select Selection]\n" - "\t[--sysinit]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[-y|--yes]\n" - "\t[-Z|--zero {y|n}]\n" - "\t [...]\n", - - activationmode_ARG, addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, - available_ARG, cachemode_ARG, cachepolicy_ARG, cachesettings_ARG, - contiguous_ARG, deltag_ARG, - discards_ARG, detachprofile_ARG, errorwhenfull_ARG, force_ARG, - ignorelockingfailure_ARG, ignoremonitoring_ARG, ignoreactivationskip_ARG, - ignoreskippedcluster_ARG, major_ARG, metadataprofile_ARG, minor_ARG, - monitor_ARG, minrecoveryrate_ARG, maxrecoveryrate_ARG, noudevsync_ARG, - partial_ARG, permission_ARG, persistent_ARG, poll_ARG, - raidrebuild_ARG, raidminrecoveryrate_ARG, raidmaxrecoveryrate_ARG, - raidsyncaction_ARG, raidwritebehind_ARG, raidwritemostly_ARG, readahead_ARG, - reportformat_ARG, rebuild_ARG, resync_ARG, refresh_ARG, select_ARG, setactivationskip_ARG, - syncaction_ARG, sysinit_ARG, test_ARG, writebehind_ARG, writemostly_ARG, zero_ARG) - -#define COMMON_OPTS \ - "\t[--commandprofile ] [-d|--debug] [-h|-?|--help]\n" \ - "\t[--noudevsync] [-t|--test] [-v|--verbose] [--version] [-y|--yes]\n" + CACHE_VGMETADATA | PERMITTED_READ_ONLY) xx(lvconvert, "Change logical volume layout", - 0, - "lvconvert " - "[-m|--mirrors [--mirrorlog {disk|core|mirrored}|--corelog]]\n" - "\t[--type ]\n" - "\t[--rebuild PhysicalVolume]\n" - "\t[--repair [--use-policies]]\n" - "\t[--replace PhysicalVolume]\n" - "\t[-R|--regionsize ]\n" - "\t[--alloc ]\n" - "\t[-b|--background]\n" - "\t[-f|--force]\n" - "\t[-i|--interval ]\n" - "\t[--stripes [-I|--stripesize ]]\n" - COMMON_OPTS - "\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n\n" - - "lvconvert " - "[--splitmirrors --trackchanges]\n" - "\t[--splitmirrors Images --name SplitLogicalVolumeName]\n" - COMMON_OPTS - "\tLogicalVolume[Path] [SplittablePhysicalVolume[Path]...]\n\n" - - "lvconvert " - "--splitsnapshot\n" - COMMON_OPTS - "\tSnapshotLogicalVolume[Path]\n\n" - - "lvconvert " - "--splitcache\n" - COMMON_OPTS - "\tCacheLogicalVolume[Path]\n\n" - - "lvconvert " - "--split\n" - "\t[--name SplitLogicalVolumeName]\n" - COMMON_OPTS - "\tSplitableLogicalVolume[Path]\n\n" - - "lvconvert " - "--uncache\n" - COMMON_OPTS - "\tCacheLogicalVolume[Path]\n\n" - - "lvconvert " - "[--type snapshot|-s|--snapshot]\n" - "\t[-c|--chunksize ]\n" - "\t[-Z|--zero {y|n}]\n" - COMMON_OPTS - "\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n\n" - - "lvconvert " - "--merge\n" - "\t[-b|--background]\n" - "\t[-i|--interval ]\n" - COMMON_OPTS - "\tLogicalVolume[Path]\n\n" - - "lvconvert " - "[--type thin[-pool]|-T|--thin]\n" - "\t[--thinpool ThinPoolLogicalVolume[Path]]\n" - "\t[--chunksize ]\n" - "\t[--discards {ignore|nopassdown|passdown}]\n" - "\t[--poolmetadataspare {y|n}]\n" - "\t[--poolmetadata ThinMetadataLogicalVolume[Path] |\n" - "\t --poolmetadatasize ]\n" - "\t[-r|--readahead |auto|none]\n" - "\t[--stripes [-I|--stripesize ]]]\n" - "\t[--originname NewExternalOriginVolumeName]]\n" - "\t[-Z|--zero {y|n}]\n" - COMMON_OPTS - "\t[ExternalOrigin|ThinDataPool]LogicalVolume[Path] [PhysicalVolumePath...]\n\n" - - "lvconvert " - "[--type cache[-pool]|-H|--cache]\n" - "\t[--cachepool CacheDataLogicalVolume[Path]]\n" - "\t[--cachemode ]\n" - "\t[--cachepolicy ]\n" - "\t[--cachesettings =]\n" - "\t[--chunksize ]\n" - "\t[--poolmetadata CacheMetadataLogicalVolume[Path] |\n" - "\t --poolmetadatasize ]\n" - "\t[--poolmetadataspare {y|n}]]\n" - COMMON_OPTS - "\t[Cache|CacheDataPool]LogicalVolume[Path] [PhysicalVolumePath...]\n\n", - - alloc_ARG, background_ARG, cache_ARG, cachemode_ARG, - cachepool_ARG, cachepolicy_ARG, cachesettings_ARG, chunksize_ARG, - corelog_ARG, discards_ARG, force_ARG, interval_ARG, merge_ARG, mirrorlog_ARG, - mirrors_ARG, name_ARG, noudevsync_ARG, originname_ARG, poolmetadata_ARG, - poolmetadatasize_ARG, poolmetadataspare_ARG, readahead_ARG, regionsize_ARG, - repair_ARG, replace_ARG, snapshot_ARG, - split_ARG, splitcache_ARG, splitmirrors_ARG, splitsnapshot_ARG, - stripes_long_ARG, stripesize_ARG, test_ARG, thin_ARG, thinpool_ARG, - trackchanges_ARG, type_ARG, uncache_ARG, usepolicies_ARG, zero_ARG) + 0) xx(lvcreate, "Create a logical volume", - 0, - "lvcreate\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[-a|--activate [a|e|l]{y|n}]\n" - "\t[--addtag Tag]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[-H|--cache\n" - "\t [--cachemode {writeback|writethrough}]\n" - "\t [--cachepolicy policy]\n" - "\t [--cachesettings key=value]\n" - "\t[--cachepool CachePoolLogicalVolume{Name|Path}]\n" - "\t[-c|--chunksize ChunkSize]\n" - "\t[-C|--contiguous {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|-?|--help]\n" - "\t[--errorwhenfull {y|n}]\n" - "\t[--ignoremonitoring]\n" - "\t[--monitor {y|n}]\n" - "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" - "\t[-k|--setactivationskip {y|n}]\n" - "\t[-K|--ignoreactivationskip]\n" - "\t{-l|--extents LogicalExtentsNumber[%{VG|PVS|FREE}] |\n" - "\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - "\t[-M|--persistent {y|n}] [-j|--major major] [--minor minor]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[-m|--mirrors Mirrors [--nosync]\n" - "\t [{--mirrorlog {disk|core|mirrored}|--corelog}]]\n" - "\t[-n|--name LogicalVolumeName]\n" - "\t[--noudevsync]\n" - "\t[-p|--permission {r|rw}]\n" - //"\t[--pooldatasize DataSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--poolmetadatasize MetadataSize[bBsSkKmMgG]]\n" - "\t[--poolmetadataspare {y|n}]]\n" - "\t[--[raid]minrecoveryrate Rate]\n" - "\t[--[raid]maxrecoveryrate Rate]\n" - "\t[-r|--readahead {ReadAheadSectors|auto|none}]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-R|--regionsize MirrorLogRegionSize]\n" - "\t[-T|--thin\n" - "\t [--discards {ignore|nopassdown|passdown}]\n" - "\t[--thinpool ThinPoolLogicalVolume{Name|Path}]\n" - "\t[-t|--test]\n" - "\t[--type VolumeType]\n" - "\t[-v|--verbose]\n" - "\t[-W|--wipesignatures {y|n}]\n" - "\t[-Z|--zero {y|n}]\n" - "\t[--version]\n" - "\tVolumeGroupName [PhysicalVolumePath...]\n\n" - - "lvcreate\n" - "\t{ {-s|--snapshot} OriginalLogicalVolume[Path] |\n" - "\t [-s|--snapshot] VolumeGroupName[Path] -V|--virtualsize VirtualSize}\n" - "\t {-H|--cache} VolumeGroupName[Path][/OriginalLogicalVolume]\n" - "\t {-T|--thin} VolumeGroupName[Path][/PoolLogicalVolume]\n" - "\t -V|--virtualsize VirtualSize}\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--addtag Tag]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[--cachepolicy Policy] [--cachesettings Key=Value]\n" - "\t[-c|--chunksize]\n" - "\t[-C|--contiguous {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[--discards {ignore|nopassdown|passdown}]\n" - "\t[-h|-?|--help]\n" - "\t[--ignoremonitoring]\n" - "\t[--monitor {y|n}]\n" - "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" - "\t[-k|--setactivationskip {y|n}]\n" - "\t[-K|--ignoreactivationskip]\n" - "\t{-l|--extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] |\n" - "\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - //"\t[--pooldatasize DataVolumeSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--poolmetadatasize MetadataVolumeSize[bBsSkKmMgG]]\n" - "\t[-M|--persistent {y|n}] [-j|--major major] [--minor minor]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[-n|--name LogicalVolumeName]\n" - "\t[--noudevsync]\n" - "\t[-p|--permission {r|rw}]\n" - "\t[-r|--readahead ReadAheadSectors|auto|none]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[{--thinpool ThinPoolLogicalVolume[Path] |\n" - "\t --cachepool CachePoolLogicalVolume[Path]}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[PhysicalVolumePath...]\n\n", - - addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, available_ARG, - cache_ARG, cachemode_ARG, cachepool_ARG, cachepolicy_ARG, cachesettings_ARG, - chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG, errorwhenfull_ARG, - extents_ARG, ignoreactivationskip_ARG, ignoremonitoring_ARG, major_ARG, - metadataprofile_ARG, minor_ARG, mirrorlog_ARG, mirrors_ARG, monitor_ARG, - minrecoveryrate_ARG, maxrecoveryrate_ARG, name_ARG, nosync_ARG, - noudevsync_ARG, permission_ARG, persistent_ARG, - //pooldatasize_ARG, - poolmetadatasize_ARG, poolmetadataspare_ARG, - raidminrecoveryrate_ARG, raidmaxrecoveryrate_ARG, - readahead_ARG, regionsize_ARG, reportformat_ARG, setactivationskip_ARG, - size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, thin_ARG, - thinpool_ARG, type_ARG, virtualoriginsize_ARG, virtualsize_ARG, - wipesignatures_ARG, zero_ARG) + 0) xx(lvdisplay, "Display information about a logical volume", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "lvdisplay\n" - "\t[-a|--all]\n" - "\t[-c|--colon]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[-H|--history]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[-m|--maps]\n" - "\t[--nosuffix]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n" - "\n" - "lvdisplay --columns|-C\n" - "\t[--aligned]\n" - "\t[-a|--all]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[-H|--history]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-S|--select Selection]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--segments]\n" - "\t[--separator Separator]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n", - - aligned_ARG, all_ARG, binary_ARG, colon_ARG, columns_ARG, - configreport_ARG, foreign_ARG, history_ARG, ignorelockingfailure_ARG, - ignoreskippedcluster_ARG, logonly_ARG, maps_ARG, noheadings_ARG, - nosuffix_ARG, options_ARG, sort_ARG, partial_ARG, readonly_ARG, - reportformat_ARG, segments_ARG, select_ARG, separator_ARG, - shared_ARG, unbuffered_ARG, units_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(lvextend, "Add space to a logical volume", - 0, - "lvextend\n" - "\t[-A|--autobackup y|n]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" - "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE|ORIGIN}] |\n" - "\t -L|--size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - "\t --poolmetadatasize [+]MetadataVolumeSize[bBsSkKmMgG]}\n" - "\t[-m|--mirrors Mirrors]\n" - "\t[--nosync]\n" - "\t[--use-policies]\n" - "\t[-n|--nofsck]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-r|--resizefs]\n" - "\t[-t|--test]\n" - "\t[--type VolumeType]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", - - alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, mirrors_ARG, - nofsck_ARG, nosync_ARG, noudevsync_ARG, poolmetadatasize_ARG, - reportformat_ARG, resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG, - test_ARG, type_ARG, usepolicies_ARG) + 0) xx(lvmchange, "With the device mapper, this is obsolete and does nothing.", - 0, - "lvmchange\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-R|--reset]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n", - - reset_ARG) + 0) xx(lvmconfig, "Display and manipulate configuration information", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "lvmconfig\n" - "\t[-f|--file filename]\n" - "\t[--type {current|default|diff|full|list|missing|new|profilable|profilable-command|profilable-metadata}]\n" - "\t[--atversion version]\n" - "\t[--ignoreadvanced]\n" - "\t[--ignoreunsupported]\n" - "\t[--ignorelocal]\n" - "\t[-l|--list]\n" - "\t[--config ConfigurationString]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--profile ProfileName]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[--mergedconfig]\n" - "\t[--sinceversion version]\n" - "\t[--showdeprecated]\n" - "\t[--showunsupported]\n" - "\t[--validate]\n" - "\t[--withsummary]\n" - "\t[--withcomments]\n" - "\t[--withspaces]\n" - "\t[--unconfigured]\n" - "\t[--withversions]\n" - "\t[ConfigurationNode...]\n", - atversion_ARG, configtype_ARG, file_ARG, ignoreadvanced_ARG, - ignoreunsupported_ARG, ignorelocal_ARG, list_ARG, mergedconfig_ARG, metadataprofile_ARG, - sinceversion_ARG, showdeprecated_ARG, showunsupported_ARG, validate_ARG, withsummary_ARG, - withcomments_ARG, withspaces_ARG, unconfigured_ARG, withversions_ARG) + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(lvmdiskscan, "List devices that may be used as physical volumes", - PERMITTED_READ_ONLY | ENABLE_ALL_DEVS, - "lvmdiskscan\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-l|--lvmpartition]\n" - "\t[--readonly]\n" - "\t[--version]\n", - - lvmpartition_ARG, readonly_ARG) + PERMITTED_READ_ONLY | ENABLE_ALL_DEVS) xx(lvmsadc, "Collect activity data", - 0, - "lvmsadc\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[LogFilePath]\n") + 0) xx(lvmsar, "Create activity report", - 0, - "lvmsar\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--full]\n" - "\t[-h|--help]\n" - "\t[-s|--stdin]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tLogFilePath\n", - - full_ARG, stdin_ARG) + 0) xx(lvreduce, "Reduce the size of a logical volume", - 0, - "lvreduce\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE|ORIGIN}] |\n" - "\t -L|--size [-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - "\t[-n|--nofsck]\n" - "\t[--noudevsync]\n" - "\t[-r|--resizefs]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[-y|--yes]\n" - "\tLogicalVolume[Path]\n", - - autobackup_ARG, force_ARG, extents_ARG, nofsck_ARG, noudevsync_ARG, - reportformat_ARG, resizefs_ARG, size_ARG, test_ARG) + 0) xx(lvremove, "Remove logical volume(s) from the system", - ALL_VGS_IS_DEFAULT, /* all VGs only with --select */ - "lvremove\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--nohistory]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", - - autobackup_ARG, force_ARG, nohistory_ARG, noudevsync_ARG, - reportformat_ARG, select_ARG, test_ARG) + ALL_VGS_IS_DEFAULT) /* all VGs only with --select */ xx(lvrename, "Rename a logical volume", - 0, - "lvrename\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|-?|--help]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t{ OldLogicalVolumePath NewLogicalVolumePath |\n" - "\t VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName }\n", - - autobackup_ARG, noudevsync_ARG, reportformat_ARG, test_ARG) + 0) xx(lvresize, "Resize a logical volume", - 0, - "lvresize\n" - "\t[-A|--autobackup y|n]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" - "\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|PVS|FREE|ORIGIN}] |\n" - "\t -L|--size [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n" - "\t --poolmetadatasize [+]MetadataVolumeSize[bBsSkKmMgG]}\n" - "\t[-n|--nofsck]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-r|--resizefs]\n" - "\t[-t|--test]\n" - "\t[--type VolumeType]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", - - alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, nofsck_ARG, - noudevsync_ARG, reportformat_ARG, resizefs_ARG, - poolmetadatasize_ARG, size_ARG, stripes_ARG, stripesize_ARG, - test_ARG, type_ARG) + 0) xx(lvs, "Display information about logical volumes", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "lvs\n" - "\t[-a|--all]\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[-H|--history]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--nameprefixes]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--rows]\n" - "\t[--segments]\n" - "\t[-S|--select Selection]\n" - "\t[--separator Separator]\n" - "\t[--trustcache]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--unquoted]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n", - - aligned_ARG, all_ARG, binary_ARG, configreport_ARG, foreign_ARG, history_ARG, - ignorelockingfailure_ARG, ignoreskippedcluster_ARG, logonly_ARG, - nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, - options_ARG, partial_ARG, readonly_ARG, reportformat_ARG, rows_ARG, - segments_ARG, select_ARG, separator_ARG, shared_ARG, sort_ARG, - trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(lvscan, "List all logical volumes in all volume groups", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN, - "lvscan\n" - "\t[-a|--all]\n" - "\t[-b|--blockdevice]\n" - "\t[--cache]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|-?|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n", - - all_ARG, blockdevice_ARG, ignorelockingfailure_ARG, partial_ARG, - readonly_ARG, reportformat_ARG, cache_long_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN) xx(pvchange, "Change attributes of physical volume(s)", - 0, - "pvchange\n" - "\t[-a|--all]\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--metadataignore y|n]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-t|--test]\n" - "\t[-u|--uuid]\n" - "\t[-x|--allocatable y|n]\n" - "\t[-v|--verbose]\n" - "\t[--addtag Tag]\n" - "\t[--deltag Tag]\n" - "\t[--version]\n" - "\t[PhysicalVolumePath...]\n", - - all_ARG, allocatable_ARG, allocation_ARG, autobackup_ARG, deltag_ARG, - addtag_ARG, force_ARG, ignoreskippedcluster_ARG, metadataignore_ARG, - reportformat_ARG, select_ARG, test_ARG, uuid_ARG) + 0) xx(pvresize, "Resize physical volume(s)", - 0, - "pvresize\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|-?|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tPhysicalVolume [PhysicalVolume...]\n", - - physicalvolumesize_ARG, reportformat_ARG, test_ARG) + 0) xx(pvck, "Check the consistency of physical volume(s)", - LOCKD_VG_SH, - "pvck " - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--labelsector sector]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tPhysicalVolume [PhysicalVolume...]\n", - - labelsector_ARG) + LOCKD_VG_SH) xx(pvcreate, "Initialize physical volume(s) for use by LVM", - ENABLE_ALL_DEVS, - "pvcreate\n" - "\t[--norestorefile]\n" - "\t[--restorefile file]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f[f]|--force [--force]]\n" - "\t[-h|-?|--help]\n" - "\t[--labelsector sector]\n" - "\t[-M|--metadatatype 1|2]\n" - "\t[--pvmetadatacopies #copies]\n" - "\t[--bootloaderareasize BootLoaderAreaSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--dataalignment Alignment[bBsSkKmMgGtTpPeE]]\n" - "\t[--dataalignmentoffset AlignmentOffset[bBsSkKmMgGtTpPeE]]\n" - "\t[--setphysicalvolumesize PhysicalVolumeSize[bBsSkKmMgGtTpPeE]\n" - "\t[-t|--test]\n" - "\t[-u|--uuid uuid]\n" - "\t[-v|--verbose]\n" - "\t[-y|--yes]\n" - "\t[-Z|--zero {y|n}]\n" - "\t[--version]\n" - "\tPhysicalVolume [PhysicalVolume...]\n", - - dataalignment_ARG, dataalignmentoffset_ARG, bootloaderareasize_ARG, - force_ARG, test_ARG, labelsector_ARG, metadatatype_ARG, - metadatacopies_ARG, metadatasize_ARG, metadataignore_ARG, - norestorefile_ARG, physicalvolumesize_ARG, pvmetadatacopies_ARG, - reportformat_ARG, restorefile_ARG, uuidstr_ARG, zero_ARG) + ENABLE_ALL_DEVS) xx(pvdata, "Display the on-disk metadata for physical volume(s)", - 0, - "pvdata\n" - "\t[-a|--all]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-E|--physicalextent]\n" - "\t[-h|-?|--help]\n" - "\t[-L|--logicalvolume]\n" - "\t[-P[P]|--physicalvolume [--physicalvolume]]\n" - "\t[-U|--uuidlist]\n" - "\t[-v[v]|--verbose [--verbose]]\n" - "\t[-V|--volumegroup]\n" - "\t[--version]\n" - "\tPhysicalVolume [PhysicalVolume...]\n", - - all_ARG, logicalextent_ARG, physicalextent_ARG, - physicalvolume_ARG, uuidlist_ARG, volumegroup_ARG) + 0) xx(pvdisplay, "Display various attributes of physical volume(s)", - CACHE_VGMETADATA | PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH, - "pvdisplay\n" - "\t[-c|--colon]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[-m|--maps]\n" - "\t[--nosuffix]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-s|--short]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[PhysicalVolumePath [PhysicalVolumePath...]]\n" - "\n" - "pvdisplay --columns|-C\n" - "\t[--aligned]\n" - "\t[-a|--all]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[--readonly]\n" - "\t[--separator Separator]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[PhysicalVolumePath [PhysicalVolumePath...]]\n", - - aligned_ARG, all_ARG, binary_ARG, colon_ARG, columns_ARG, configreport_ARG, - foreign_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, - logonly_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG, options_ARG, - readonly_ARG, reportformat_ARG, select_ARG, separator_ARG, shared_ARG, - short_ARG, sort_ARG, unbuffered_ARG, units_ARG) + CACHE_VGMETADATA | PERMITTED_READ_ONLY | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH) /* ALL_VGS_IS_DEFAULT is for polldaemon to find pvmoves in-progress using process_each_vg. */ xx(pvmove, "Move extents from one physical volume to another", - ALL_VGS_IS_DEFAULT | DISALLOW_TAG_ARGS, - "pvmove\n" - "\t[--abort]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[--atomic]\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[-b|--background]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n " - "\t[-h|-?|--help]\n" - "\t[-i|--interval seconds]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n " - "\t[-v|--verbose]\n " - "\t[--version]\n" - "\t[{-n|--name} LogicalVolume]\n" -/* "\t[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n" */ - "\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n" - "\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n", - - abort_ARG, alloc_ARG, atomic_ARG, autobackup_ARG, background_ARG, - interval_ARG, name_ARG, noudevsync_ARG, reportformat_ARG, test_ARG) + ALL_VGS_IS_DEFAULT | DISALLOW_TAG_ARGS) xx(lvpoll, "Continue already initiated poll operation on a logical volume", - 0, - "\t[--abort]\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n " - "\t[-h|-?|--help]\n" - "\t[--handlemissingpvs]\n" - "\t[-i|--interval seconds]\n" - "\t[--polloperation]\n" - "\t[-t|--test]\n " - "\t[-v|--verbose]\n " - "\t[--version]\n", - - abort_ARG, autobackup_ARG, handlemissingpvs_ARG, interval_ARG, polloperation_ARG, - test_ARG) + 0) xx(pvremove, "Remove LVM label(s) from physical volume(s)", - ENABLE_ALL_DEVS, - "pvremove\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f[f]|--force [--force]]\n" - "\t[-h|-?|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[-y|--yes]\n" - "\tPhysicalVolume [PhysicalVolume...]\n", - - force_ARG, reportformat_ARG, test_ARG) + ENABLE_ALL_DEVS) xx(pvs, "Display information about physical volumes", - CACHE_VGMETADATA | PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH, - "pvs\n" - "\t[-a|--all]\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|-?|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--nameprefixes]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--rows]\n" - "\t[--segments]\n" - "\t[-S|--select Selection]\n" - "\t[--separator Separator]\n" - "\t[--trustcache]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--unquoted]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[PhysicalVolume [PhysicalVolume...]]\n", - - aligned_ARG, all_ARG, binary_ARG, configreport_ARG, foreign_ARG, - ignorelockingfailure_ARG, ignoreskippedcluster_ARG, logonly_ARG, - nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, - options_ARG, partial_ARG, readonly_ARG, reportformat_ARG, rows_ARG, - segments_ARG, select_ARG, separator_ARG, shared_ARG, sort_ARG, - trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) + CACHE_VGMETADATA | PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | ENABLE_ALL_DEVS | ENABLE_DUPLICATE_DEVS | LOCKD_VG_SH) xx(pvscan, "List all physical volumes", - PERMITTED_READ_ONLY | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN, - "pvscan\n" - "\t[-b|--background]\n" - "\t[--cache [-a|--activate ay] [ DevicePath | -j|--major major --minor minor]...]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t{-e|--exported | -n|--novolumegroup}\n" - "\t[-h|-?|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-s|--short]\n" - "\t[-u|--uuid]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n", - - activate_ARG, available_ARG, backgroundfork_ARG, cache_long_ARG, - exported_ARG, ignorelockingfailure_ARG, major_ARG, minor_ARG, - novolumegroup_ARG, partial_ARG, readonly_ARG, reportformat_ARG, - short_ARG, uuid_ARG) + PERMITTED_READ_ONLY | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN) xx(segtypes, "List available segment types", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "segtypes\n") + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(systemid, "Display the system ID, if any, currently set on this host", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "systemid\n") + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(tags, "List tags defined on this host", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "tags\n") + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) xx(vgcfgbackup, "Backup volume group configuration(s)", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "vgcfgbackup\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--file filename]\n" - "\t[--foreign]\n" - "\t[-h|-?|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName...]\n", - - file_ARG, foreign_ARG, ignorelockingfailure_ARG, partial_ARG, readonly_ARG, - reportformat_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(vgcfgrestore, "Restore volume group configuration", - 0, - "vgcfgrestore\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--file filename]\n" - "\t[--force]\n" - "\t[-l[l]|--list [--list]]\n" - "\t[-M|--metadatatype 1|2]\n" - "\t[-h|--help]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName", - - file_ARG, force_long_ARG, list_ARG, metadatatype_ARG, test_ARG) + 0) xx(vgchange, "Change volume group attributes", - CACHE_VGMETADATA | PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT, - "vgchange\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[-P|--partial]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[--detachprofile]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoremonitoring]\n" - "\t[--ignoreskippedcluster]\n" - "\t[-K|--ignoreactivationskip]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[--monitor {y|n}]\n" - "\t[--[vg]metadatacopies #copies]\n" - "\t[--poll {y|n}]\n" - "\t[--noudevsync]\n" - "\t[--refresh]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[--sysinit]\n" - "\t[--systemid SystemID]\n" - "\t[-t|--test]\n" - "\t[-u|--uuid]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t{-a|--activate [a|e|l]{y|n} |\n" - "\t[--activationmode {complete|degraded|partial}]\n" - "\t -c|--clustered {y|n} |\n" - "\t -x|--resizeable {y|n} |\n" - "\t -l|--logicalvolume MaxLogicalVolumes |\n" - "\t -p|--maxphysicalvolumes MaxPhysicalVolumes |\n" - "\t -s|--physicalextentsize PhysicalExtentSize[bBsSkKmMgGtTpPeE] |\n" - "\t --addtag Tag |\n" - "\t --deltag Tag}\n" - "\t[VolumeGroupName...]\n", - - activationmode_ARG, addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, - activate_ARG, available_ARG, clustered_ARG, deltag_ARG, detachprofile_ARG, - ignoreactivationskip_ARG, ignorelockingfailure_ARG, ignoremonitoring_ARG, - ignoreskippedcluster_ARG, logicalvolume_ARG, maxphysicalvolumes_ARG, - metadataprofile_ARG, monitor_ARG, noudevsync_ARG, metadatacopies_ARG, - vgmetadatacopies_ARG, partial_ARG, physicalextentsize_ARG, poll_ARG, - refresh_ARG, reportformat_ARG, resizeable_ARG, resizable_ARG, select_ARG, - sysinit_ARG, systemid_ARG, test_ARG, uuid_ARG, lockstart_ARG, lockstop_ARG, - locktype_ARG, lockopt_ARG, force_ARG) + CACHE_VGMETADATA | PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT) xx(vgck, "Check the consistency of volume group(s)", - ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "vgck " - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName...]\n", - - reportformat_ARG) + ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(vgconvert, "Change volume group metadata format", - 0, - "vgconvert\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--labelsector sector]\n" - "\t[-M|--metadatatype 1|2]\n" - "\t[--pvmetadatacopies #copies]\n" - "\t[--metadatasize MetadataSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--bootloaderareasize BootLoaderAreaSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName [VolumeGroupName...]\n", - - force_ARG, test_ARG, labelsector_ARG, bootloaderareasize_ARG, - metadatatype_ARG, metadatacopies_ARG, pvmetadatacopies_ARG, - metadatasize_ARG, reportformat_ARG) + 0) xx(vgcreate, "Create a volume group", - MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS, - "vgcreate\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--addtag Tag]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[-c|--clustered {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-l|--maxlogicalvolumes MaxLogicalVolumes]\n" - "\t[--metadataprofile ProfileName]\n" - "\t[-M|--metadatatype 1|2]\n" - "\t[--[vg]metadatacopies #copies]\n" - "\t[-p|--maxphysicalvolumes MaxPhysicalVolumes]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-s|--physicalextentsize PhysicalExtentSize[bBsSkKmMgGtTpPeE]]\n" - "\t[--systemid SystemID]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[-y|--yes]\n" - "\t[ PHYSICAL DEVICE OPTIONS ]\n" - "\tVolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]\n", - - addtag_ARG, alloc_ARG, autobackup_ARG, clustered_ARG, maxlogicalvolumes_ARG, - maxphysicalvolumes_ARG, metadataprofile_ARG, metadatatype_ARG, - physicalextentsize_ARG, test_ARG, force_ARG, zero_ARG, labelsector_ARG, - metadatasize_ARG, pvmetadatacopies_ARG, reportformat_ARG, metadatacopies_ARG, - vgmetadatacopies_ARG, dataalignment_ARG, dataalignmentoffset_ARG, - shared_ARG, systemid_ARG, locktype_ARG, lockopt_ARG) + MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS) xx(vgdisplay, "Display volume group information", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "vgdisplay\n" - "\t[-A|--activevolumegroups]\n" - "\t[-c|--colon | -s|--short | -v|--verbose]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--nosuffix]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--version]\n" - "\t[VolumeGroupName [VolumeGroupName...]]\n" - "\n" - "vgdisplay --columns|-C\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-P|--partial]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[--readonly]\n" - "\t[--separator Separator]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName [VolumeGroupName...]]\n", - - activevolumegroups_ARG, aligned_ARG, binary_ARG, colon_ARG, columns_ARG, - configreport_ARG, foreign_ARG, ignorelockingfailure_ARG, - ignoreskippedcluster_ARG, logonly_ARG, noheadings_ARG, nosuffix_ARG, - options_ARG, partial_ARG, readonly_ARG, reportformat_ARG, select_ARG, - shared_ARG, short_ARG, separator_ARG, sort_ARG, unbuffered_ARG, units_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(vgexport, "Unregister volume group(s) from the system", - ALL_VGS_IS_DEFAULT, - "vgexport\n" - "\t[-a|--all]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName [VolumeGroupName...]\n", - - all_ARG, reportformat_ARG, select_ARG, test_ARG) + ALL_VGS_IS_DEFAULT) xx(vgextend, "Add physical volumes to a volume group", - MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS, - "vgextend\n" - "\t[-A|--autobackup y|n]\n" - "\t[--restoremissing]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[-y|--yes]\n" - "\t[ PHYSICAL DEVICE OPTIONS ]\n" - "\tVolumeGroupName PhysicalDevicePath [PhysicalDevicePath...]\n", - - autobackup_ARG, test_ARG, - force_ARG, zero_ARG, labelsector_ARG, metadatatype_ARG, - metadatasize_ARG, pvmetadatacopies_ARG, metadatacopies_ARG, - metadataignore_ARG, dataalignment_ARG, dataalignmentoffset_ARG, - reportformat_ARG, restoremissing_ARG) + MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS) xx(vgimport, "Register exported volume group with system", - ALL_VGS_IS_DEFAULT | NO_LVMETAD_AUTOSCAN, - "vgimport\n" - "\t[-a|--all]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName...\n", - - all_ARG, force_ARG, reportformat_ARG, select_ARG, test_ARG) + ALL_VGS_IS_DEFAULT | NO_LVMETAD_AUTOSCAN) xx(vgimportclone, "Import a VG from cloned PVs", - NO_LVMETAD_AUTOSCAN, - "vgimportclone\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-i|--import]\n" - "\t[-n|--basevgname]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[PhysicalVolumePath...]\n", - - basevgname_ARG, test_ARG, import_ARG) + NO_LVMETAD_AUTOSCAN) xx(vgmerge, "Merge volume groups", - 0, - "vgmerge\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-l|--list]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tDestinationVolumeGroupName SourceVolumeGroupName\n", - - autobackup_ARG, list_ARG, test_ARG) + 0) xx(vgmknodes, "Create the special files for volume group devices in /dev", - ALL_VGS_IS_DEFAULT, - "vgmknodes\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--refresh]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName...]\n", - - ignorelockingfailure_ARG, refresh_ARG, reportformat_ARG) + ALL_VGS_IS_DEFAULT) xx(vgreduce, "Remove physical volume(s) from a volume group", - 0, - "vgreduce\n" - "\t[-a|--all]\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--mirrorsonly]\n" - "\t[--removemissing]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-f|--force]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName\n" - "\t[PhysicalVolumePath...]\n", - - all_ARG, autobackup_ARG, force_ARG, mirrorsonly_ARG, removemissing_ARG, - reportformat_ARG, test_ARG) + 0) xx(vgremove, "Remove volume group(s)", - ALL_VGS_IS_DEFAULT, /* all VGs only with select */ - "vgremove\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-f|--force]\n" - "\t[-h|--help]\n" - "\t[--noudevsync]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-S|--select Selection]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tVolumeGroupName [VolumeGroupName...]\n", - - force_ARG, noudevsync_ARG, reportformat_ARG, select_ARG, test_ARG) + ALL_VGS_IS_DEFAULT) /* all VGs only with select */ xx(vgrename, "Rename a volume group", - ALLOW_UUID_AS_NAME | REQUIRES_FULL_LABEL_SCAN, - "vgrename\n" - "\t[-A|--autobackup y|n]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tOldVolumeGroupPath NewVolumeGroupPath |\n" - "\tOldVolumeGroupName NewVolumeGroupName\n", - - autobackup_ARG, force_ARG, reportformat_ARG, test_ARG) + ALLOW_UUID_AS_NAME | REQUIRES_FULL_LABEL_SCAN) xx(vgs, "Display information about volume groups", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH, - "vgs\n" - "\t[--aligned]\n" - "\t[--binary]\n" - "\t[-a|--all]\n" - "\t[--commandprofile ProfileName]\n" - "\t[--configreport ReportName]\n" - "\t[-d|--debug]\n" - "\t[--foreign]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--ignoreskippedcluster]\n" - "\t[--logonly]\n" - "\t[--nameprefixes]\n" - "\t[--noheadings]\n" - "\t[--nosuffix]\n" - "\t[-o|--options [+|-|#]Field[,Field]]\n" - "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" - "\t[-P|--partial]\n" - "\t[--readonly]\n" - "\t[--reportformat {basic|json}]\n" - "\t[--rows]\n" - "\t[-S|--select Selection]\n" - "\t[--separator Separator]\n" - "\t[--trustcache]\n" - "\t[--unbuffered]\n" - "\t[--units hHbBsSkKmMgGtTpPeE]\n" - "\t[--unquoted]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\t[VolumeGroupName [VolumeGroupName...]]\n", - - aligned_ARG, all_ARG, binary_ARG, configreport_ARG, foreign_ARG, - ignorelockingfailure_ARG, ignoreskippedcluster_ARG, logonly_ARG, - nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, - options_ARG, partial_ARG, readonly_ARG, reportformat_ARG, rows_ARG, - select_ARG, separator_ARG, shared_ARG, sort_ARG, trustcache_ARG, - unbuffered_ARG, units_ARG, unquoted_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH) xx(vgscan, "Search for all volume groups", - PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN, - "vgscan " - "\t[--cache]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[--ignorelockingfailure]\n" - "\t[--mknodes]\n" - "\t[--notifydbus]\n" - "\t[-P|--partial]\n" - "\t[--reportformat {basic|json}]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n", - - cache_long_ARG, ignorelockingfailure_ARG, mknodes_ARG, notifydbus_ARG, - partial_ARG, reportformat_ARG) + PERMITTED_READ_ONLY | ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | NO_LVMETAD_AUTOSCAN) xx(vgsplit, "Move physical volumes into a new or existing volume group", - 0, - "vgsplit\n" - "\t[-A|--autobackup {y|n}]\n" - "\t[--alloc AllocationPolicy]\n" - "\t[-c|--clustered {y|n}]\n" - "\t[--commandprofile ProfileName]\n" - "\t[-d|--debug]\n" - "\t[-h|--help]\n" - "\t[-l|--maxlogicalvolumes MaxLogicalVolumes]\n" - "\t[-M|--metadatatype 1|2]\n" - "\t[--[vg]metadatacopies #copies]\n" - "\t[-n|--name LogicalVolumeName]\n" - "\t[-p|--maxphysicalvolumes MaxPhysicalVolumes]\n" - "\t[-t|--test]\n" - "\t[-v|--verbose]\n" - "\t[--version]\n" - "\tSourceVolumeGroupName DestinationVolumeGroupName\n" - "\t[PhysicalVolumePath...]\n", - - alloc_ARG, autobackup_ARG, clustered_ARG, - maxlogicalvolumes_ARG, maxphysicalvolumes_ARG, - metadatatype_ARG, vgmetadatacopies_ARG, name_ARG, test_ARG) + 0) xx(version, "Display software and driver version information", - PERMITTED_READ_ONLY | NO_METADATA_PROCESSING, - "version\n") + PERMITTED_READ_ONLY | NO_METADATA_PROCESSING) diff --git a/tools/lvmcmdlib.c b/tools/lvmcmdlib.c index 276c8b357..02cfffaa9 100644 --- a/tools/lvmcmdlib.c +++ b/tools/lvmcmdlib.c @@ -57,7 +57,7 @@ int lvm2_run(void *handle, const char *cmdline) cmd = (struct cmd_context *) handle; - cmd->argv = argv; + cmd->pos_arg_values = argv; if (!(cmdcopy = dm_strdup(cmdline))) { log_error("Cmdline copy failed."); diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 9a4deb7d5..cfce57182 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -49,6 +49,11 @@ extern char *optarg; # define OPTIND_INIT 1 #endif +#if 0 +#include "command-lines-count.h" /* #define COMMAND_COUNT, generated from command-lines.in */ +#endif +#define COMMAND_COUNT 128 + /* * Table of valid switches */ @@ -58,12 +63,32 @@ static struct arg_props _arg_props[ARG_COUNT + 1] = { #undef arg }; +/* + * Table of valid command names + */ +#define MAX_COMMAND_NAMES 64 +struct command_name { + const char *name; + const char *desc; + unsigned int flags; +}; + +struct command_name command_names[MAX_COMMAND_NAMES] = { +#define xx(a, b, c...) { # a, b, c } +#include "commands.h" +#undef xx +} + +/* + * Table of valid command lines + */ +static struct command commands[COMMAND_COUNT]; static struct cmdline_context _cmdline; /* Command line args */ unsigned arg_count(const struct cmd_context *cmd, int a) { - return cmd->arg_values ? cmd->arg_values[a].count : 0; + return cmd->opt_arg_values ? cmd->opt_arg_values[a].count : 0; } unsigned grouped_arg_count(const struct arg_values *av, int a) @@ -182,12 +207,12 @@ const char *arg_long_option_name(int a) const char *arg_value(const struct cmd_context *cmd, int a) { - return cmd->arg_values ? cmd->arg_values[a].value : NULL; + return cmd->opt_arg_values ? cmd->opt_arg_values[a].value : NULL; } const char *arg_str_value(const struct cmd_context *cmd, int a, const char *def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].value : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].value : def; } const char *grouped_arg_str_value(const struct arg_values *av, int a, const char *def) @@ -217,44 +242,44 @@ int32_t first_grouped_arg_int_value(const struct cmd_context *cmd, int a, const int32_t arg_int_value(const struct cmd_context *cmd, int a, const int32_t def) { return (_cmdline.arg_props[a].flags & ARG_GROUPABLE) ? - first_grouped_arg_int_value(cmd, a, def) : (arg_is_set(cmd, a) ? cmd->arg_values[a].i_value : def); + first_grouped_arg_int_value(cmd, a, def) : (arg_is_set(cmd, a) ? cmd->opt_arg_values[a].i_value : def); } uint32_t arg_uint_value(const struct cmd_context *cmd, int a, const uint32_t def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].ui_value : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ui_value : def; } int64_t arg_int64_value(const struct cmd_context *cmd, int a, const int64_t def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].i64_value : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].i64_value : def; } uint64_t arg_uint64_value(const struct cmd_context *cmd, int a, const uint64_t def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].ui64_value : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ui64_value : def; } /* No longer used. const void *arg_ptr_value(struct cmd_context *cmd, int a, const void *def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].ptr : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ptr : def; } */ sign_t arg_sign_value(const struct cmd_context *cmd, int a, const sign_t def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].sign : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].sign : def; } percent_type_t arg_percent_value(const struct cmd_context *cmd, int a, const percent_type_t def) { - return arg_is_set(cmd, a) ? cmd->arg_values[a].percent : def; + return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].percent : def; } int arg_count_increment(struct cmd_context *cmd, int a) { - return cmd->arg_values[a].count++; + return cmd->opt_arg_values[a].count++; } int yes_no_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) @@ -709,104 +734,227 @@ int metadatacopies_arg(struct cmd_context *cmd, struct arg_values *av) return int_arg(cmd, av); } -static void __alloc(int size) +static struct command_name *_find_command_name(char *name) { - if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) { - log_fatal("Couldn't allocate memory."); - exit(ECMD_FAILED); + int i; + + for (i = 0; i < MAX_COMMAND_NAMES; i++) { + if (!command_names[i].name) + break; + if (!strcmp(command_names[i].name, name)) + return &command_names[i]; } + return NULL; +} - _cmdline.commands_size = size; +void _define_commands(void) +{ +/* command-lines.h defines command[] structs, generated from command-lines.in */ +#include "command-lines.h" /* generated from command-lines.in */ } -static void _alloc_command(void) +void lvm_register_commands(void) { - if (!_cmdline.commands_size) - __alloc(32); + struct command_name *cname; + int i; + + _define_commands(); + + _cmdline.commands = &commands; + _cmdline.num_commands = COMMAND_COUNT; - if (_cmdline.commands_size <= _cmdline.num_commands) - __alloc(2 * _cmdline.commands_size); + for (i = 0; i < COMMAND_COUNT; i++) { + if (!(cname = _find_command_name(commands[i].name))) + log_error(INTERNAL_ERROR "Failed to find command name %s.", commands[i].name); + commands[i].flags = cname->flags; + } } -static void _create_new_command(const char *name, command_fn command, - unsigned flags, - const char *desc, const char *usagestr, - int nargs, int *args) +/* + * Match what the user typed with a one specific command definition/prototype + * from commands[]. If nothing matches, it's not a valid command. The match + * is based on command name, required opt args and required pos args. + * + * Find an entry in the commands array that matches based the arg values. + * + * If the cmd has opt or pos args set that are not accepted by command, + * we can: silently ignore them, warn they are not being used, or fail. + * Default should probably be to warn and continue. + * + * For each command[i], check how many required opt/pos args cmd matches. + * Save the command[i] that matches the most. + * + * commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT means + * any one item from commands[i].required_opt_args needs to be + * set to match. + * + * required_pos_args[0].flags & ARG_DEF_TYPE_SELECT means + * cmd->pos_arg_values[0] can be NULL if arg_is_set(select_ARG) + */ + +static int _opt_equivalent_is_set(struct cmd_context *cmd, int opt) { - struct command *nc; + if ((opt == mirrorlog_ARG) && arg_is_set(cmd, corelog_ARG, NULL)) + return 1; + + if ((opt == resizeable_ARG) && arg_is_set(cmd, resizable_ARG, NULL)) + return 1; + + if ((opt == allocatable_ARG) && arg_is_set(cmd, allocation_ARG, NULL)) + return 1; - _alloc_command(); + if ((opt == resizeable_ARG) && arg_is_set(cmd, allocation_ARG, NULL)) + return 1; - nc = _cmdline.commands + _cmdline.num_commands++; + if ((opt == activate_ARG) && arg_is_set(cmd, available_ARG, NULL)) + return 1; + + if ((opt == rebuild_ARG) && arg_is_set(cmd, raidrebuild_ARG, NULL)) + return 1; + + if ((opt == syncaction_ARG) && arg_is_set(cmd, raidsyncaction_ARG, NULL)) + return 1; + + if ((opt == writemostly_ARG) && arg_is_set(cmd, raidwritemostly_ARG, NULL)) + return 1; - nc->name = name; - nc->desc = desc; - nc->usage = usagestr; - nc->fn = command; - nc->flags = flags; - nc->num_args = nargs; - nc->valid_args = args; + if ((opt == minrecoveryrate_ARG) && arg_is_set(cmd, raidminrecoveryrate_ARG, NULL)) + return 1; + + if ((opt == maxrecoveryrate_ARG) && arg_is_set(cmd, raidmaxrecoveryrate_ARG, NULL)) + return 1; + + if ((opt == writebehind_ARG) && arg_is_set(cmd, raidwritebehind_ARG, NULL)) + return 1; + + return 0; } -static void _register_command(const char *name, command_fn fn, const char *desc, - unsigned flags, const char *usagestr, ...) +static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro) { - int nargs = 0, i; - int *args; - va_list ap; - - /* count how many arguments we have */ - va_start(ap, usagestr); - while (va_arg(ap, int) >= 0) - nargs++; - va_end(ap); + if (arg_is_set(cmd, commands[ci].required_opt_args[ro].opt, NULL)) + return 1; - /* allocate space for them */ - if (!(args = dm_malloc(sizeof(*args) * nargs))) { - log_fatal("Out of memory."); - exit(ECMD_FAILED); + /* + * For some commands, --size and --extents are interchanable, + * but command[] definitions use only --size. + */ + if ((commands[ci].required_opt_args[ro].opt == size_ARG) && arg_is_set(cmd, extents_ARG, NULL)) { + if (!strcmp(commands[i].name, "lvcreate") || + !strcmp(commands[i].name, "lvresize") + !strcmp(commands[i].name, "lvextend") + !strcmp(commands[i].name, "lvreduce")) + return 1; } - /* fill them in */ - va_start(ap, usagestr); - for (i = 0; i < nargs; i++) - args[i] = va_arg(ap, int); - va_end(ap); + /* TODO: for lvmconfig, recognize --type in place of --typeconfig? */ - /* enter the command in the register */ - _create_new_command(name, fn, flags, desc, usagestr, nargs, args); + if (_opt_equivalent_is_set(cmd, commands[ci].required_opt_args[ro].opt)) + return 1; } -void lvm_register_commands(void) +static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp) { -#define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \ - driverloaded_ARG, \ - debug_ARG, help_ARG, help2_ARG, \ - version_ARG, verbose_ARG, \ - yes_ARG, \ - quiet_ARG, config_ARG, \ - commandprofile_ARG, \ - profile_ARG, -1); -#include "commands.h" -#undef xx + if (cmd->pos_arg_values[rp]) { + /* FIXME: can we match object type better than just checking something exists? */ + /* Some cases could be validated by looking at defs.types and at the value. */ + return 1; + } + + /* + * If Select is specified as a pos arg, then that pos arg can be + * empty if --select is used. + */ + if ((commands[ci].required_pos_args[rp].def.types & ARG_DEF_TYPE_SELECT) && + arg_is_set(cmd, select_ARG, NULL)) + return 1; + + return 0; } -static struct command *_find_command(const char *name) +static struct command *_find_command(struct cmd_context *cmd, const char *path) { + const char *name; + int ro, rp; + int found = 0; int i; - const char *base; - base = last_path_component(name); + name = last_path_component(path); - for (i = 0; i < _cmdline.num_commands; i++) { - if (!strcmp(base, _cmdline.commands[i].name)) - break; + for (i = 0; i < COMMAND_COUNT; i++) { + if (strcmp(name, commands[i].name)) + continue; + + match_count = 1; /* for command name matching */ + mismatch_count = 0; + + /* match required_opt_args */ + + for (ro = 0; ro < commands[i].ro_count; ro++) { + if (_command_required_opt_matches(cmd, i, ro)) + match_count++; + else + mismatch_count++; + } + + /* + * One item in required_opt_args must be set for + * a match, and the rest are optional (don't count + * as mismatches). + */ + if (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) { + if (match_count >= 2) { + match_count = 2; + mismatch_count = 0; + } + } + + /* match required_pos_args */ + + for (rp = 0; rp < commands[i].rp_count; rp++) { + if (_command_required_pos_matches(cmd, i, rp)) + match_count++; + else + mismatch_count++; + } + + if (mismatch_count) { + /* save i/match_count for "closest" command that doesn't match */ + if (!closest_count || (match_count > closest_count)) { + closest_i = i; + closest_count = match_count; + } + continue; + } + + if (!best_match_count || (match_count > best_match_count)) { + best_match_i = i; + best_match_count = match_count; + } } - if (i >= _cmdline.num_commands) - return 0; + if (!best_match_count) { + /* nothing matches */ + /* TODO: report closest matching command and report missing required opt/pos args for that? */ + log_error("Failed to find a matching command definition."); + if (closest_count) { + log_warn("Closest command usage is:"); + log_warn("%s", commands[closest_i].usage); + } + return NULL; + } + + /* + * Check if all arg_is_set values from cmd are accepted as + * optional_opt_args, and warn (or fail per config?) if options are set + * in cmd that are not accepted by the chosen command[i]. + * + * Same for pos args. + */ - return _cmdline.commands + i; + log_debug("matched command usage: %.80s ...", commands[best_match_i].usage); + + return &commands[best_match_i]; } static void _short_usage(const char *name) @@ -816,14 +964,16 @@ static void _short_usage(const char *name) static int _usage(const char *name) { - struct command *com = _find_command(name); + struct command_name *cname = _find_command_name(name); - if (!com) { + if (!cname) { log_print("%s: no such command.", name); return 0; } - log_print("%s: %s\n\n%s", com->name, com->desc, com->usage); + /* FIXME: print usage strings from matching commands[] entries? */ + + log_print("%s: %s", cname->name, cname->desc); return 1; } @@ -890,7 +1040,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, struct arg_values *av; struct arg_value_group_list *current_group = NULL; - if (!(cmd->arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->arg_values) * ARG_COUNT))) { + if (!(cmd->opt_arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->opt_arg_values) * ARG_COUNT))) { log_fatal("Unable to allocate memory for command line arguments."); return 0; } @@ -917,7 +1067,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, a = _cmdline.arg_props + arg; - av = &cmd->arg_values[arg]; + av = &cmd->opt_arg_values[arg]; if (a->flags & ARG_GROUPABLE) { /* @@ -930,7 +1080,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, (current_group->arg_values[arg].count && !(a->flags & ARG_COUNTABLE)) || (current_group->prio < a->prio)) { /* FIXME Reduce size including only groupable args */ - if (!(current_group = dm_pool_zalloc(cmd->mem, sizeof(struct arg_value_group_list) + sizeof(*cmd->arg_values) * ARG_COUNT))) { + if (!(current_group = dm_pool_zalloc(cmd->mem, sizeof(struct arg_value_group_list) + sizeof(*cmd->opt_arg_values) * ARG_COUNT))) { log_fatal("Unable to allocate memory for command line arguments."); return 0; } @@ -1002,12 +1152,12 @@ static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg) /* Not groupable? */ if (!(_cmdline.arg_props[oldarg].flags & ARG_GROUPABLE)) { if (arg_is_set(cmd, oldarg)) - _copy_arg_values(cmd->arg_values, oldarg, newarg); + _copy_arg_values(cmd->opt_arg_values, oldarg, newarg); return 1; } if (arg_is_set(cmd, oldarg)) - cmd->arg_values[newarg].count = cmd->arg_values[oldarg].count; + cmd->opt_arg_values[newarg].count = cmd->opt_arg_values[oldarg].count; /* Groupable */ dm_list_iterate_items(current_group, &cmd->arg_value_groups) { @@ -1431,7 +1581,7 @@ static int _prepare_profiles(struct cmd_context *cmd) log_debug(_setting_global_profile_msg, _command_profile_source_name, profile->name); cmd->profile_params->global_command_profile = profile; - if (!cmd->arg_values) + if (!cmd->opt_arg_values) cmd->profile_params->shell_profile = profile; } @@ -1553,14 +1703,14 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) log_debug("Parsing: %s", cmd->cmd_line); - if (!(cmd->command = _find_command(argv[0]))) - return ENO_SUCH_CMD; - if (!_process_command_line(cmd, &argc, &argv)) { log_error("Error during parsing of command line."); return EINVALID_CMD_LINE; } + if (!(cmd->command = _find_command(cmd, argv[0]))) + return ENO_SUCH_CMD; + set_cmd_name(cmd->command->name); if (arg_is_set(cmd, backgroundfork_ARG)) { @@ -2040,23 +2190,8 @@ struct cmd_context *init_lvm(unsigned set_connections, unsigned set_filters) return cmd; } -static void _fin_commands(void) -{ - int i; - - for (i = 0; i < _cmdline.num_commands; i++) - dm_free(_cmdline.commands[i].valid_args); - - dm_free(_cmdline.commands); - - _cmdline.commands = NULL; - _cmdline.num_commands = 0; - _cmdline.commands_size = 0; -} - void lvm_fin(struct cmd_context *cmd) { - _fin_commands(); destroy_toolcontext(cmd); udev_fin_library_context(); } @@ -2202,7 +2337,8 @@ int lvm2_main(int argc, char **argv) if (!(cmd = init_lvm(0, 0))) return -1; - cmd->argv = argv; + cmd->pos_arg_values = argv; + lvm_register_commands(); if (_lvm1_fallback(cmd)) { diff --git a/tools/toollib.c b/tools/toollib.c index 4f8cbb4af..f800872e1 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -105,7 +105,7 @@ int become_daemon(struct cmd_context *cmd, int skip_lvm) init_verbose(VERBOSE_BASE_LEVEL); #endif /* DEBUG_CHILD */ - strncpy(*cmd->argv, "(lvm2)", strlen(*cmd->argv)); + strncpy(*cmd->pos_arg_values, "(lvm2)", strlen(*cmd->pos_arg_values)); lvmetad_disconnect(); diff --git a/tools/tools.h b/tools/tools.h index f6d224fb1..d54e5a011 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -44,6 +44,8 @@ #include "toollib.h" #include "lvmnotify.h" +#include "command.h" + #include #include @@ -51,8 +53,6 @@ #define MAX_ARGS 64 /* command functions */ -typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv); - #define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv); #include "commands.h" #undef xx @@ -118,19 +118,6 @@ struct arg_value_group_list { #define ENABLE_DUPLICATE_DEVS 0x00000400 /* Command does not accept tags as args. */ #define DISALLOW_TAG_ARGS 0x00000800 - -/* a register of the lvm commands */ -struct command { - const char *name; - const char *desc; - const char *usage; - command_fn fn; - - unsigned flags; - - int num_args; - int *valid_args; -}; void usage(const char *name); -- cgit v1.2.1