2017-02-10 20:36:11 +03:00
/*
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2024-04-27 12:36:55 +03:00
* Copyright ( C ) 2004 - 2024 Red Hat , Inc . All rights reserved .
2017-02-10 20:36:11 +03:00
*
* 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
*/
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <stdio.h>
# include <stdlib.h>
# include <stddef.h>
# include <stdint.h>
# include <unistd.h>
# include <dirent.h>
# include <ctype.h>
2024-04-27 12:36:55 +03:00
# ifndef MAN_PAGE_GENERATOR
2017-02-10 20:36:11 +03:00
# include "tools.h"
2017-02-17 13:51:24 +03:00
# endif /* MAN_PAGE_GENERATOR */
2017-02-10 20:36:11 +03:00
/* see cmd_names[] below, one for each unique "ID" in command-lines.in */
struct cmd_name {
2024-05-11 23:27:36 +03:00
const char name [ 68 ] ; /* "foo" from string after ID: */
uint16_t cmd_enum ; /* foo_CMD */
2017-02-10 20:36:11 +03:00
} ;
/* create table of value names, e.g. String, and corresponding enum from vals.h */
2024-04-28 20:52:26 +03:00
static const struct val_name val_names [ VAL_COUNT + 1 ] = {
2017-02-10 20:36:11 +03:00
# define val(a, b, c, d) { # a, a, b, c, d },
# include "vals.h"
# undef val
} ;
/* create table of option names, e.g. --foo, and corresponding enum from args.h */
2024-05-01 15:36:28 +03:00
static const struct opt_name opt_names [ ARG_COUNT + 1 ] = {
2024-05-01 13:45:10 +03:00
# define arg(a, b, c, d, e, f, g) { # a, b, a, "--" c, d, e, f, g },
2017-02-10 20:36:11 +03:00
# include "args.h"
# undef arg
} ;
/* create table of lv property names, e.g. lv_is_foo, and corresponding enum from lv_props.h */
2024-04-28 20:52:26 +03:00
static const struct lv_prop lv_props [ LVP_COUNT + 1 ] = {
2017-03-07 21:08:23 +03:00
# define lvp(a, b, c) { # a, a, b, c },
2017-02-10 20:36:11 +03:00
# include "lv_props.h"
# undef lvp
} ;
/* create table of lv type names, e.g. linear and corresponding enum from lv_types.h */
2024-04-28 20:52:26 +03:00
static const struct lv_type lv_types [ LVT_COUNT + 1 ] = {
2017-03-07 21:08:23 +03:00
# define lvt(a, b, c) { # a, a, b, c },
2017-02-10 20:36:11 +03:00
# include "lv_types.h"
# undef lvt
} ;
/* create table of command IDs */
2024-04-28 20:52:26 +03:00
static const struct cmd_name cmd_names [ CMD_COUNT + 1 ] = {
2024-05-11 23:27:36 +03:00
# define cmd(a, b) { # b, a },
2022-09-27 17:06:06 +03:00
# include "../include/cmds.h"
2017-02-10 20:36:11 +03:00
# undef cmd
} ;
/*
* command_names [ ] and commands [ ] are defined in lvmcmdline . c when building lvm ,
* but need to be defined here when building the stand - alone man page generator .
*/
# ifdef MAN_PAGE_GENERATOR
2017-03-07 21:08:23 +03:00
2024-05-12 02:14:14 +03:00
static const struct command_name command_names [ ] = {
2024-05-01 15:36:28 +03:00
# define xx(a, b, c...) { # a, b, c, NULL, a ## _COMMAND },
2017-02-10 20:36:11 +03:00
# include "commands.h"
# undef xx
} ;
2024-04-28 21:14:42 +03:00
static struct command commands [ COMMAND_COUNT ] ;
2017-03-07 21:08:23 +03:00
# else /* MAN_PAGE_GENERATOR */
2024-05-12 02:14:14 +03:00
const struct command_name command_names [ ] = {
2024-05-01 15:36:28 +03:00
# define xx(a, b, c...) { # a, b, c, a, a ## _COMMAND },
2017-03-07 21:08:23 +03:00
# include "commands.h"
# undef xx
} ;
2024-05-12 02:14:14 +03:00
2017-02-10 20:36:11 +03:00
extern struct command commands [ COMMAND_COUNT ] ; /* defined in lvmcmdline.c */
2017-03-07 21:08:23 +03:00
2024-04-28 20:52:26 +03:00
const struct opt_name * get_opt_name ( int opt )
{
return & opt_names [ opt ] ;
}
const struct val_name * get_val_name ( int val )
{
return & val_names [ val ] ;
}
const struct lv_prop * get_lv_prop ( int lvp_enum )
{
if ( ! lvp_enum )
return NULL ;
return & lv_props [ lvp_enum ] ;
}
const struct lv_type * get_lv_type ( int lvt_enum )
{
if ( ! lvt_enum )
return NULL ;
return & lv_types [ lvt_enum ] ;
}
2017-03-07 21:08:23 +03:00
# endif /* MAN_PAGE_GENERATOR */
2017-02-10 20:36:11 +03:00
2024-05-12 02:14:14 +03:00
struct command_name_args command_names_args [ LVM_COMMAND_COUNT ] = { 0 } ;
2017-02-10 20:36:11 +03:00
/* array of pointers into opt_names[] that is sorted alphabetically (by long opt name) */
2024-05-01 15:36:28 +03:00
static const struct opt_name * opt_names_alpha [ ARG_COUNT + 1 ] ;
2017-02-10 20:36:11 +03:00
/* lvm_all is for recording options that are common for all lvm commands */
2024-04-28 21:14:42 +03:00
static struct command lvm_all ;
2017-02-10 20:36:11 +03:00
/* saves OO_FOO lines (groups of optional options) to include in multiple defs */
2017-10-18 17:57:46 +03:00
static int _oo_line_count ;
2017-02-10 20:36:11 +03:00
# define MAX_OO_LINES 256
struct oo_line {
char * name ;
char * line ;
} ;
2017-10-18 17:57:46 +03:00
static struct oo_line _oo_lines [ MAX_OO_LINES ] ;
2017-02-10 20:36:11 +03:00
# define REQUIRED 1 /* required option */
# define OPTIONAL 0 /* optional option */
2017-07-19 17:17:30 +03:00
# define IGNORE (-1) /* ignore option */
2017-02-10 20:36:11 +03:00
# define MAX_LINE 1024
# define MAX_LINE_ARGC 256
# define DESC_LINE 1024
/*
* Contains _command_input [ ] which is command - lines . in with comments
* removed and wrapped as a string . The _command_input [ ] string is
* used to populate commands [ ] .
*/
# include "command-lines-input.h"
2024-04-28 21:15:10 +03:00
static void _add_optional_opt_line ( struct cmd_context * cmdtool , struct command * cmd , int argc , char * argv [ ] ) ;
2017-02-10 20:36:11 +03:00
2021-04-11 01:47:00 +03:00
static unsigned _was_hyphen = 0 ;
static void printf_hyphen ( char c )
{
/* When .hy 1 was printed, we do not want to emit empty space */
printf ( " %c%c \n " , _was_hyphen ? ' \n ' : ' ' , c ) ;
_was_hyphen = 0 ;
}
2017-02-10 20:36:11 +03:00
/*
* modifies buf , replacing the sep characters with \ 0
* argv pointers point to positions in buf
*/
2024-03-20 00:40:47 +03:00
static void _split_line ( char * buf , int * argc , char * * argv , char sep )
2017-02-10 20:36:11 +03:00
{
2024-03-20 00:40:47 +03:00
char * p = buf ;
2017-02-10 20:36:11 +03:00
int i ;
argv [ 0 ] = p ;
for ( i = 1 ; i < MAX_LINE_ARGC ; i + + ) {
2024-03-20 00:40:47 +03:00
p = strchr ( p , sep ) ;
2017-02-10 20:36:11 +03:00
if ( ! p )
break ;
2024-03-20 00:40:47 +03:00
* p + + = ' \0 ' ;
2017-02-10 20:36:11 +03:00
2024-03-20 00:40:47 +03:00
argv [ i ] = p ;
2017-02-10 20:36:11 +03:00
}
* argc = i ;
}
/* convert value string, e.g. Number, to foo_VAL enum */
2017-10-18 17:57:46 +03:00
static int _val_str_to_num ( char * str )
2017-02-10 20:36:11 +03:00
{
2018-02-28 18:57:53 +03:00
char name [ MAX_LINE_ARGC ] ;
2017-02-10 20:36:11 +03:00
char * new ;
int i ;
/* compare the name before any suffix like _new or _<lvtype> */
2024-04-04 19:42:24 +03:00
if ( ! _dm_strncpy ( name , str , sizeof ( name ) ) )
2018-02-28 18:57:53 +03:00
return 0 ; /* Buffer is too short */
2017-02-17 15:09:06 +03:00
if ( ( new = strchr ( name , ' _ ' ) ) )
2017-02-10 20:36:11 +03:00
* new = ' \0 ' ;
2024-05-01 13:45:10 +03:00
for ( i = 0 ; i < VAL_COUNT ; + + i )
2017-02-10 20:36:11 +03:00
if ( ! strncmp ( name , val_names [ i ] . name , strlen ( val_names [ i ] . name ) ) )
return val_names [ i ] . val_enum ;
return 0 ;
}
/* convert "--option" to foo_ARG enum */
2017-02-14 01:11:04 +03:00
# define MAX_LONG_OPT_NAME_LEN 32
2024-03-24 02:06:45 +03:00
static int _opt_str_to_num ( struct command * cmd , const char * str )
2017-02-10 20:36:11 +03:00
{
2017-02-14 01:11:04 +03:00
char long_name [ MAX_LONG_OPT_NAME_LEN ] ;
2023-07-13 22:56:47 +03:00
char * p = NULL ;
2017-02-10 20:36:11 +03:00
int i ;
2017-02-17 12:00:43 +03:00
int first = 0 , last = ARG_COUNT - 1 , middle ;
2017-02-10 20:36:11 +03:00
2024-04-04 19:42:24 +03:00
if ( ! _dm_strncpy ( long_name , str , sizeof ( long_name ) ) )
2023-07-04 12:26:46 +03:00
goto err ;
2017-02-10 20:36:11 +03:00
2017-02-17 12:00:43 +03:00
if ( ( p = strstr ( long_name , " _long " ) ) )
/*
* - - 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 ( = = 0 ) .
*/
* p = ' \0 ' ;
2017-02-10 20:36:11 +03:00
2017-02-17 12:00:43 +03:00
/* Binary search in sorted array of long options (with duplicates) */
while ( first < = last ) {
middle = first + ( last - first ) / 2 ;
if ( ( i = strcmp ( opt_names_alpha [ middle ] - > long_opt , long_name ) ) < 0 )
first = middle + 1 ;
else if ( i > 0 )
last = middle - 1 ;
else {
/* Matching long option string found.
* As sorted array contains duplicates , we need to also
* check left & right side for possible match
*/
for ( i = middle ; ; ) {
if ( ( ! p & & ! strstr ( opt_names_alpha [ i ] - > name , " _long_ARG " ) ) | |
( p & & ! opt_names_alpha [ i ] - > short_opt ) )
return opt_names_alpha [ i ] - > opt_enum ; /* Found */
/* Check if there is something on the 'left-side' */
if ( ( i < = first ) | | strcmp ( opt_names_alpha [ - - i ] - > long_opt , long_name ) )
break ;
}
/* Nothing on the left, so look on the 'right-side' */
for ( i = middle + 1 ; i < = last ; + + i ) {
if ( strcmp ( opt_names_alpha [ i ] - > long_opt , long_name ) )
break ;
if ( ( ! p & & ! strstr ( opt_names_alpha [ i ] - > name , " _long_ARG " ) ) | |
( p & & ! opt_names_alpha [ i ] - > short_opt ) )
return opt_names_alpha [ i ] - > opt_enum ; /* Found */
}
break ; /* Nothing... */
}
2017-02-10 20:36:11 +03:00
}
2023-07-04 12:26:46 +03:00
err :
2017-02-17 12:00:43 +03:00
log_error ( " Parsing command defs: unknown opt str: \" %s \" %s%s. " ,
str , p ? " " : " " , p ? long_name : " " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
2017-02-17 12:00:43 +03:00
2017-02-17 00:26:42 +03:00
return ARG_UNUSED ;
2017-02-10 20:36:11 +03:00
}
/* "foo" string to foo_CMD int */
2024-05-12 17:00:48 +03:00
unsigned command_id_to_enum ( const char * str )
2017-02-10 20:36:11 +03:00
{
int i ;
2024-05-12 17:00:48 +03:00
unsigned first = 1 , last = CMD_COUNT - 1 , middle ;
2017-02-10 20:36:11 +03:00
2021-02-25 20:09:52 +03:00
while ( first < = last ) {
middle = first + ( last - first ) / 2 ;
if ( ( i = strcmp ( cmd_names [ middle ] . name , str ) ) < 0 )
first = middle + 1 ;
else if ( i > 0 )
last = middle - 1 ;
else
return cmd_names [ middle ] . cmd_enum ;
2017-02-10 20:36:11 +03:00
}
2017-02-17 00:26:42 +03:00
2021-02-25 20:09:52 +03:00
log_error ( " Cannot find command %s. " , str ) ;
2017-02-17 00:26:42 +03:00
return CMD_NONE ;
2017-02-10 20:36:11 +03:00
}
2024-05-12 17:00:48 +03:00
const char * command_enum ( unsigned command_enum )
{
return cmd_names [ command_enum ] . name ;
}
2017-02-10 20:36:11 +03:00
/* "lv_is_prop" to is_prop_LVP */
2024-03-24 02:06:45 +03:00
static int _lvp_name_to_enum ( struct command * cmd , const char * str )
2017-02-10 20:36:11 +03:00
{
int i ;
for ( i = 1 ; i < LVP_COUNT ; i + + ) {
2017-03-07 21:08:23 +03:00
if ( ! strcmp ( str , lv_props [ i ] . name ) )
return lv_props [ i ] . lvp_enum ;
2017-02-10 20:36:11 +03:00
}
2017-02-17 00:26:42 +03:00
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: unknown lv property %s. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return LVP_NONE ;
2017-02-10 20:36:11 +03:00
}
/* "type" to type_LVT */
2024-03-24 02:06:45 +03:00
static int _lvt_name_to_enum ( struct command * cmd , const char * str )
2017-02-10 20:36:11 +03:00
{
int i ;
for ( i = 1 ; i < LVT_COUNT ; i + + ) {
2017-03-07 21:08:23 +03:00
if ( ! strcmp ( str , lv_types [ i ] . name ) )
return lv_types [ i ] . lvt_enum ;
2017-02-10 20:36:11 +03:00
}
2017-02-17 00:26:42 +03:00
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: unknown lv type %s. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return LVT_NONE ;
2017-02-10 20:36:11 +03:00
}
/* LV_<type> to <type>_LVT */
2024-03-24 02:06:45 +03:00
static int _lv_to_enum ( struct command * cmd , const char * name )
2017-02-10 20:36:11 +03:00
{
2017-10-18 17:57:46 +03:00
return _lvt_name_to_enum ( cmd , name + 3 ) ;
2017-02-10 20:36:11 +03:00
}
/*
* LV_ < type1 > _ < type2 > to lvt_bits
*
* type1 to lvt_enum
* lvt_bits | = lvt_enum_to_bit ( lvt_enum )
* type2 to lvt_enum
* lvt_bits | = lvt_enum_to_bit ( lvt_enum )
*/
2023-07-04 12:26:46 +03:00
# define LVTYPE_LEN 128
2017-02-14 01:11:04 +03:00
2017-10-18 17:57:46 +03:00
static uint64_t _lv_to_bits ( struct command * cmd , char * name )
2017-02-10 20:36:11 +03:00
{
2017-02-14 01:11:04 +03:00
char buf [ LVTYPE_LEN ] ;
2017-02-10 20:36:11 +03:00
char * argv [ MAX_LINE_ARGC ] ;
uint64_t lvt_bits = 0 ;
int lvt_enum ;
int argc ;
int i ;
2024-04-04 18:03:30 +03:00
dm_strncpy ( buf , name , sizeof ( buf ) ) ;
2017-02-10 20:36:11 +03:00
2017-10-18 17:57:46 +03:00
_split_line ( buf , & argc , argv , ' _ ' ) ;
2017-02-10 20:36:11 +03:00
/* 0 is "LV" */
for ( i = 1 ; i < argc ; i + + ) {
if ( ! strcmp ( argv [ i ] , " new " ) )
continue ;
2017-10-18 17:57:46 +03:00
lvt_enum = _lvt_name_to_enum ( cmd , argv [ i ] ) ;
2017-02-10 20:36:11 +03:00
lvt_bits | = lvt_enum_to_bit ( lvt_enum ) ;
}
return lvt_bits ;
}
2024-05-12 16:39:18 +03:00
static unsigned _find_lvm_command_enum ( const char * name )
2017-02-10 20:36:11 +03:00
{
2021-02-25 20:09:52 +03:00
static int _command_names_count = - 1 ;
int first = 0 , last , middle ;
2017-02-10 20:36:11 +03:00
int i ;
2021-02-25 20:09:52 +03:00
if ( _command_names_count = = - 1 ) {
/* Validate cmd_names & command_names arrays are properly sorted */
for ( i = 1 ; i < CMD_COUNT - 2 ; i + + )
if ( strcmp ( cmd_names [ i ] . name , cmd_names [ i + 1 ] . name ) > 0 ) {
log_error ( " File cmds.h has unsorted name entry %s. " ,
cmd_names [ i ] . name ) ;
return 0 ;
}
2024-05-02 02:31:51 +03:00
for ( i = 1 ; i < LVM_COMMAND_COUNT ; + + i ) /* assume > 1 */
2021-02-25 20:09:52 +03:00
if ( strcmp ( command_names [ i - 1 ] . name , command_names [ i ] . name ) > 0 ) {
log_error ( " File commands.h has unsorted name entry %s. " ,
command_names [ i ] . name ) ;
return 0 ;
}
_command_names_count = i - 1 ;
}
last = _command_names_count ;
2017-02-17 13:52:37 +03:00
2021-02-25 20:09:52 +03:00
while ( first < = last ) {
middle = first + ( last - first ) / 2 ;
if ( ( i = strcmp ( command_names [ middle ] . name , name ) ) < 0 )
first = middle + 1 ;
else if ( i > 0 )
last = middle - 1 ;
else
2024-05-12 16:39:18 +03:00
return middle ;
2021-02-25 20:09:52 +03:00
}
2017-02-17 13:52:37 +03:00
2024-05-12 16:39:18 +03:00
return - 1 ;
2021-02-25 20:09:52 +03:00
}
2024-05-12 16:39:18 +03:00
const struct command_name * find_command_name ( const char * name )
2017-02-10 20:36:11 +03:00
{
2024-05-12 16:39:18 +03:00
int r = _find_lvm_command_enum ( name ) ;
2017-02-10 20:36:11 +03:00
2024-05-12 16:39:18 +03:00
return ( r < LVM_COMMAND_COUNT ) ? & command_names [ r ] : NULL ;
2017-02-10 20:36:11 +03:00
}
2017-10-18 17:57:46 +03:00
static int _is_opt_name ( char * str )
2017-02-10 20:36:11 +03:00
{
2017-02-17 13:52:37 +03:00
if ( ( str [ 0 ] = = ' - ' ) & & ( str [ 1 ] = = ' - ' ) )
2017-02-10 20:36:11 +03:00
return 1 ;
2017-02-17 00:26:42 +03:00
if ( ( str [ 0 ] = = ' - ' ) & & ( str [ 1 ] ! = ' - ' ) )
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: options must be specified in long form: %s. " , str ) ;
2017-02-10 20:36:11 +03:00
return 0 ;
}
/*
* " Select " as a pos name means that the position
* can be empty if the - - select option is used .
*/
2017-10-18 17:57:46 +03:00
static int _is_pos_name ( char * str )
2017-02-10 20:36:11 +03:00
{
2017-02-17 13:52:37 +03:00
switch ( str [ 0 ] ) {
case ' V ' : return ( str [ 1 ] = = ' G ' ) ; /* VG */
case ' L ' : return ( str [ 1 ] = = ' V ' ) ; /* LV */
case ' P ' : return ( str [ 1 ] = = ' V ' ) ; /* PV */
case ' T ' : return ( strncmp ( str , " Tag " , 3 ) = = 0 ) ;
case ' S ' : return ( ( strncmp ( str , " String " , 6 ) = = 0 ) | |
( strncmp ( str , " Select " , 6 ) = = 0 ) ) ;
}
2017-02-10 20:36:11 +03:00
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_oo_definition ( char * str )
2017-02-10 20:36:11 +03:00
{
2017-02-17 15:09:06 +03:00
if ( ! strncmp ( str , " OO_ " , 3 ) & & strchr ( str , ' : ' ) )
2017-02-10 20:36:11 +03:00
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_oo_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " OO: " , 3 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_io_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " IO: " , 3 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_op_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " OP: " , 3 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_desc_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " DESC: " , 5 ) )
return 1 ;
return 0 ;
}
2021-04-21 01:03:09 +03:00
static int _is_autotype_line ( char * str )
{
if ( ! strncmp ( str , " AUTOTYPE: " , 6 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_flags_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " FLAGS: " , 6 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_rule_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " RULE: " , 5 ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _is_id_line ( char * str )
2017-02-10 20:36:11 +03:00
{
if ( ! strncmp ( str , " ID: " , 3 ) )
return 1 ;
return 0 ;
}
/*
* Save a positional arg in a struct arg_def .
* Parse str for anything that can appear in a position ,
* like VG , VG | LV , VG | LV_linear | LV_striped , etc .
*/
2017-10-18 17:57:46 +03:00
static void _set_pos_def ( struct command * cmd , char * str , struct arg_def * def )
2017-02-10 20:36:11 +03:00
{
char * argv [ MAX_LINE_ARGC ] ;
int argc ;
char * name ;
int val_enum ;
int i ;
2017-10-18 17:57:46 +03:00
_split_line ( str , & argc , argv , ' | ' ) ;
2017-02-10 20:36:11 +03:00
for ( i = 0 ; i < argc ; i + + ) {
name = argv [ i ] ;
2017-10-18 17:57:46 +03:00
val_enum = _val_str_to_num ( name ) ;
2017-02-10 20:36:11 +03:00
if ( ! val_enum ) {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: unknown pos arg: %s. " , name ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
def - > val_bits | = val_enum_to_bit ( val_enum ) ;
2017-02-17 15:09:06 +03:00
if ( ( val_enum = = lv_VAL ) & & strchr ( name , ' _ ' ) )
2017-10-18 17:57:46 +03:00
def - > lvt_bits = _lv_to_bits ( cmd , name ) ;
2017-02-10 20:36:11 +03:00
if ( strstr ( name , " _new " ) ) {
if ( val_enum = = lv_VAL )
def - > flags | = ARG_DEF_FLAG_NEW_LV ;
else if ( val_enum = = vg_VAL )
def - > flags | = ARG_DEF_FLAG_NEW_VG ;
}
}
}
/*
* Save an option arg in a struct arg_def .
* Parse str for anything that can follow - - option .
*/
2017-10-18 17:57:46 +03:00
static void _set_opt_def ( struct cmd_context * cmdtool , struct command * cmd , char * str , struct arg_def * def )
2017-02-10 20:36:11 +03:00
{
char * argv [ MAX_LINE_ARGC ] ;
int argc ;
char * name ;
int val_enum ;
int i ;
2017-10-18 17:57:46 +03:00
_split_line ( str , & argc , argv , ' | ' ) ;
2017-02-10 20:36:11 +03:00
for ( i = 0 ; i < argc ; i + + ) {
name = argv [ i ] ;
2017-10-18 17:57:46 +03:00
val_enum = _val_str_to_num ( name ) ;
2017-02-10 20:36:11 +03:00
if ( ! val_enum ) {
/* a literal number or string */
if ( isdigit ( name [ 0 ] ) )
val_enum = constnum_VAL ;
else if ( isalpha ( name [ 0 ] ) )
val_enum = conststr_VAL ;
else {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: unknown opt arg: %s. " , name ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
}
def - > val_bits | = val_enum_to_bit ( val_enum ) ;
if ( val_enum = = constnum_VAL )
def - > num = ( uint64_t ) atoi ( name ) ;
2017-05-03 22:46:07 +03:00
if ( val_enum = = conststr_VAL ) {
2021-09-19 21:27:34 +03:00
# ifdef MAN_PAGE_GENERATOR
free ( ( void * ) def - > str ) ;
# endif
2017-04-29 00:27:19 +03:00
def - > str = dm_pool_strdup ( cmdtool - > libmem , name ) ;
2017-02-10 20:36:11 +03:00
2017-05-03 22:46:07 +03:00
if ( ! def - > str ) {
/* FIXME */
stack ;
return ;
}
}
2017-02-10 20:36:11 +03:00
if ( val_enum = = lv_VAL ) {
2017-02-17 15:09:06 +03:00
if ( strchr ( name , ' _ ' ) )
2017-10-18 17:57:46 +03:00
def - > lvt_bits = _lv_to_bits ( cmd , name ) ;
2017-02-10 20:36:11 +03:00
}
if ( strstr ( name , " _new " ) ) {
if ( val_enum = = lv_VAL )
def - > flags | = ARG_DEF_FLAG_NEW_LV ;
else if ( val_enum = = vg_VAL )
def - > flags | = ARG_DEF_FLAG_NEW_VG ;
}
}
}
/*
* Save a set of common options so they can be included in
* multiple command defs .
*
* OO_FOO : - - opt1 . . .
*
* oo - > name = " OO_FOO " ;
* oo - > line = " --opt1 ... " ;
*/
2017-10-18 17:57:46 +03:00
static void _add_oo_definition_line ( const char * name , const char * line )
2017-02-10 20:36:11 +03:00
{
struct oo_line * oo ;
char * colon ;
char * start ;
2017-10-18 17:57:46 +03:00
oo = & _oo_lines [ _oo_line_count + + ] ;
2017-06-27 11:18:00 +03:00
2018-06-08 15:40:53 +03:00
if ( ! ( oo - > name = strdup ( name ) ) ) {
2024-04-30 14:49:45 +03:00
log_error ( " Failed to duplicate name %s. " , name ) ;
2017-06-27 11:18:00 +03:00
return ; /* FIXME: return code */
}
2017-02-10 20:36:11 +03:00
2017-02-17 15:09:06 +03:00
if ( ( colon = strchr ( oo - > name , ' : ' ) ) )
2017-02-10 20:36:11 +03:00
* colon = ' \0 ' ;
else {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: invalid OO definition. " ) ;
2017-02-17 00:26:42 +03:00
return ;
2017-02-10 20:36:11 +03:00
}
2017-02-17 15:09:06 +03:00
start = strchr ( line , ' : ' ) + 2 ;
2018-06-08 15:40:53 +03:00
if ( ! ( oo - > line = strdup ( start ) ) ) {
2024-04-30 14:49:45 +03:00
log_error ( " Filler to duplicate line %s. " , start ) ;
2017-06-27 11:18:00 +03:00
return ;
}
2017-02-10 20:36:11 +03:00
}
/* Support OO_FOO: continuing on multiple lines. */
2017-10-18 17:57:46 +03:00
static void _append_oo_definition_line ( const char * new_line )
2017-02-10 20:36:11 +03:00
{
struct oo_line * oo ;
char * old_line ;
char * line ;
int len ;
2017-10-18 17:57:46 +03:00
oo = & _oo_lines [ _oo_line_count - 1 ] ;
2017-02-10 20:36:11 +03:00
old_line = oo - > line ;
/* +2 = 1 space between old and new + 1 terminating \0 */
len = strlen ( old_line ) + strlen ( new_line ) + 2 ;
2018-06-08 15:40:53 +03:00
line = malloc ( len ) ;
2017-02-14 01:11:04 +03:00
if ( ! line ) {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: no memory. " ) ;
2017-02-17 00:26:42 +03:00
return ;
2017-02-14 01:11:04 +03:00
}
2017-02-10 20:36:11 +03:00
2017-02-17 11:59:29 +03:00
( void ) dm_snprintf ( line , len , " %s %s " , old_line , new_line ) ;
2018-06-08 15:40:53 +03:00
free ( oo - > line ) ;
2017-02-10 20:36:11 +03:00
oo - > line = line ;
}
/* Find a saved OO_FOO definition. */
2023-07-04 12:26:46 +03:00
# define OO_NAME_LEN 128
2017-02-14 01:11:04 +03:00
2017-10-18 17:57:46 +03:00
static char * _get_oo_line ( const char * str )
2017-02-10 20:36:11 +03:00
{
char * name ;
char * end ;
2017-02-14 01:11:04 +03:00
char str2 [ OO_NAME_LEN ] ;
2017-02-10 20:36:11 +03:00
int i ;
2024-04-04 18:03:30 +03:00
dm_strncpy ( str2 , str , sizeof ( str2 ) ) ;
2017-02-17 15:09:06 +03:00
if ( ( end = strchr ( str2 , ' : ' ) ) )
2017-02-10 20:36:11 +03:00
* end = ' \0 ' ;
2017-02-17 15:09:06 +03:00
if ( ( end = strchr ( str2 , ' , ' ) ) )
2017-02-10 20:36:11 +03:00
* end = ' \0 ' ;
2017-10-18 17:57:46 +03:00
for ( i = 0 ; i < _oo_line_count ; i + + ) {
name = _oo_lines [ i ] . name ;
2017-02-10 20:36:11 +03:00
if ( ! strcmp ( name , str2 ) )
2017-10-18 17:57:46 +03:00
return _oo_lines [ i ] . line ;
2017-02-10 20:36:11 +03:00
}
return NULL ;
}
/*
* Add optional_opt_args entries when OO_FOO appears on OO : line ,
* i . e . include common options from an OO_FOO definition .
*/
2017-10-18 17:57:46 +03:00
static void _include_optional_opt_args ( struct cmd_context * cmdtool , struct command * cmd , const char * str )
2017-02-10 20:36:11 +03:00
{
char * oo_line ;
char * line ;
char * line_argv [ MAX_LINE_ARGC ] ;
int line_argc ;
2017-10-18 17:57:46 +03:00
if ( ! ( oo_line = _get_oo_line ( str ) ) ) {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: no OO line found for %s. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
2018-06-08 15:40:53 +03:00
if ( ! ( line = strdup ( oo_line ) ) ) {
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
}
2017-02-10 20:36:11 +03:00
2017-10-18 17:57:46 +03:00
_split_line ( line , & line_argc , line_argv , ' ' ) ;
2024-04-28 21:15:10 +03:00
_add_optional_opt_line ( cmdtool , cmd , line_argc , line_argv ) ;
2018-06-08 15:40:53 +03:00
free ( line ) ;
2017-02-10 20:36:11 +03:00
}
/*
* When an - - option is seen , add a new opt_args entry for it .
* This function sets the opt_args . opt value for it .
*/
2017-10-18 17:57:46 +03:00
static void _add_opt_arg ( struct command * cmd , char * str ,
2017-03-02 22:52:06 +03:00
int * takes_arg , int * already , int required )
2017-02-10 20:36:11 +03:00
{
char * comma ;
int opt ;
2017-03-02 22:52:06 +03:00
int i ;
2017-02-10 20:36:11 +03:00
/* opt_arg.opt set here */
2017-10-18 17:57:46 +03:00
/* opt_arg.def will be set in _update_prev_opt_arg() if needed */
2017-02-10 20:36:11 +03:00
2017-02-17 15:09:06 +03:00
if ( ( comma = strchr ( str , ' , ' ) ) )
2017-02-10 20:36:11 +03:00
* 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 ;
}
2017-10-18 17:57:46 +03:00
opt = _opt_str_to_num ( cmd , str ) ;
2017-02-17 15:57:59 +03:00
/* If the binary-search finds uuidstr_ARG switch to uuid_ARG */
if ( opt = = uuidstr_ARG )
opt = uuid_ARG ;
2017-03-02 22:52:06 +03:00
/* Skip adding an optional opt if it is already included. */
if ( already & & ! required ) {
for ( i = 0 ; i < cmd - > oo_count ; i + + ) {
if ( cmd - > optional_opt_args [ i ] . opt = = opt ) {
* already = 1 ;
* takes_arg = opt_names [ opt ] . val_enum ? 1 : 0 ;
return ;
}
}
}
2017-02-10 20:36:11 +03:00
skip :
2024-03-28 19:04:37 +03:00
if ( required > 0 ) {
if ( cmd - > ro_count > = CMD_RO_ARGS ) {
log_error ( " Too many args, increase CMD_RO_ARGS. " ) ;
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
}
2017-02-10 20:36:11 +03:00
cmd - > required_opt_args [ cmd - > ro_count + + ] . opt = opt ;
2024-03-28 19:04:37 +03:00
} else if ( ! required ) {
if ( cmd - > oo_count > = CMD_OO_ARGS ) {
log_error ( " Too many args, increase CMD_OO_ARGS. " ) ;
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
}
2017-02-10 20:36:11 +03:00
cmd - > optional_opt_args [ cmd - > oo_count + + ] . opt = opt ;
2024-03-28 19:04:37 +03:00
} else if ( required < 0 ) {
if ( cmd - > io_count > = CMD_IO_ARGS ) {
log_error ( " Too many args, increase CMD_IO_ARGS. " ) ;
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
}
2017-02-10 20:36:11 +03:00
cmd - > ignore_opt_args [ cmd - > io_count + + ] . opt = opt ;
2024-03-28 19:04:37 +03:00
}
2017-02-10 20:36:11 +03:00
* takes_arg = opt_names [ opt ] . val_enum ? 1 : 0 ;
}
/*
* After - - option has been seen , this function sets opt_args . def value
* for the value that appears after - - option .
*/
2017-10-18 17:57:46 +03:00
static void _update_prev_opt_arg ( struct cmd_context * cmdtool , struct command * cmd , char * str , int required )
2017-02-10 20:36:11 +03:00
{
struct arg_def def = { 0 } ;
char * comma ;
if ( str [ 0 ] = = ' - ' ) {
log_error ( " Parsing command defs: option %s must be followed by an arg. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
/* opt_arg.def set here */
2017-10-18 17:57:46 +03:00
/* opt_arg.opt was previously set in _add_opt_arg() when --foo was read */
2017-02-10 20:36:11 +03:00
2017-02-17 15:09:06 +03:00
if ( ( comma = strchr ( str , ' , ' ) ) )
2017-02-10 20:36:11 +03:00
* comma = ' \0 ' ;
2017-10-18 17:57:46 +03:00
_set_opt_def ( cmdtool , cmd , str , & def ) ;
2017-02-10 20:36:11 +03:00
if ( required > 0 )
cmd - > required_opt_args [ cmd - > ro_count - 1 ] . def = def ;
else if ( ! required )
cmd - > optional_opt_args [ cmd - > oo_count - 1 ] . def = def ;
else if ( required < 0 )
cmd - > ignore_opt_args [ cmd - > io_count - 1 ] . def = def ;
}
/*
* When an position arg is seen , add a new pos_args entry for it .
* This function sets the pos_args . pos and pos_args . def .
*/
2017-10-18 17:57:46 +03:00
static void _add_pos_arg ( struct command * cmd , char * str , int required )
2017-02-10 20:36:11 +03:00
{
struct arg_def def = { 0 } ;
/* pos_arg.pos and pos_arg.def are set here */
2017-10-18 17:57:46 +03:00
_set_pos_def ( cmd , str , & def ) ;
2017-02-10 20:36:11 +03:00
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. */
2017-10-18 17:57:46 +03:00
static void _update_prev_pos_arg ( struct command * cmd , char * str , int required )
2017-02-10 20:36:11 +03:00
{
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 {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: unknown pos arg: %s. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
}
/* Process what follows OO:, which are the optional opt args for the cmd def. */
2024-04-28 21:15:10 +03:00
static void _add_optional_opt_line ( struct cmd_context * cmdtool , struct command * cmd , int argc , char * argv [ ] )
2017-02-10 20:36:11 +03:00
{
2017-02-14 01:11:04 +03:00
int takes_arg = 0 ;
2017-03-02 22:52:06 +03:00
int already ;
2017-02-10 20:36:11 +03:00
int i ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! i & & ! strncmp ( argv [ i ] , " OO: " , 3 ) )
continue ;
2017-03-02 22:52:06 +03:00
already = 0 ;
2017-10-18 17:57:46 +03:00
if ( _is_opt_name ( argv [ i ] ) )
_add_opt_arg ( cmd , argv [ i ] , & takes_arg , & already , OPTIONAL ) ;
2017-02-10 20:36:11 +03:00
else if ( ! strncmp ( argv [ i ] , " OO_ " , 3 ) )
2017-10-18 17:57:46 +03:00
_include_optional_opt_args ( cmdtool , cmd , argv [ i ] ) ;
2017-02-10 20:36:11 +03:00
else if ( takes_arg )
2017-10-18 17:57:46 +03:00
_update_prev_opt_arg ( cmdtool , cmd , argv [ i ] , OPTIONAL ) ;
2017-02-10 20:36:11 +03:00
else {
2020-01-30 17:08:30 +03:00
log_error ( " Parsing command defs: can't parse argc %d argv %s%s%s. " ,
i , argv [ i ] , ( i > 0 ) ? " prev " : " " , ( i > 0 ) ? argv [ i - 1 ] : " " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
2017-03-02 22:52:06 +03:00
if ( already & & takes_arg )
i + + ;
2017-02-10 20:36:11 +03:00
}
}
/* Process what follows IO:, which are the ignore options for the cmd def. */
2017-10-18 17:57:46 +03:00
static void _add_ignore_opt_line ( struct cmd_context * cmdtool , struct command * cmd , int argc , char * argv [ ] )
2017-02-10 20:36:11 +03:00
{
2017-02-14 01:11:04 +03:00
int takes_arg = 0 ;
2017-02-10 20:36:11 +03:00
int i ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! i & & ! strncmp ( argv [ i ] , " IO: " , 3 ) )
continue ;
2017-10-18 17:57:46 +03:00
if ( _is_opt_name ( argv [ i ] ) )
_add_opt_arg ( cmd , argv [ i ] , & takes_arg , NULL , IGNORE ) ;
2017-02-10 20:36:11 +03:00
else if ( takes_arg )
2017-10-18 17:57:46 +03:00
_update_prev_opt_arg ( cmdtool , cmd , argv [ i ] , IGNORE ) ;
2017-02-10 20:36:11 +03:00
else {
2020-01-30 17:08:30 +03:00
log_error ( " Parsing command defs: can't parse argc %d argv %s%s%s. " ,
i , argv [ i ] , ( i > 0 ) ? " prev " : " " , ( i > 0 ) ? argv [ i - 1 ] : " " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
}
}
/* Process what follows OP:, which are optional pos args for the cmd def. */
2017-10-18 17:57:46 +03:00
static void _add_optional_pos_line ( struct command * cmd , int argc , char * argv [ ] )
2017-02-10 20:36:11 +03:00
{
int i ;
for ( i = 0 ; i < argc ; i + + ) {
if ( ! i & & ! strncmp ( argv [ i ] , " OP: " , 3 ) )
continue ;
2017-10-18 17:57:46 +03:00
if ( _is_pos_name ( argv [ i ] ) )
_add_pos_arg ( cmd , argv [ i ] , OPTIONAL ) ;
2017-02-10 20:36:11 +03:00
else
2017-10-18 17:57:46 +03:00
_update_prev_pos_arg ( cmd , argv [ i ] , OPTIONAL ) ;
2017-02-10 20:36:11 +03:00
}
}
2017-10-18 17:57:46 +03:00
static void _add_required_opt_line ( struct cmd_context * cmdtool , struct command * cmd , int argc , char * argv [ ] )
2017-02-10 20:36:11 +03:00
{
2017-02-14 01:11:04 +03:00
int takes_arg = 0 ;
2017-02-10 20:36:11 +03:00
int i ;
for ( i = 0 ; i < argc ; i + + ) {
2017-10-18 17:57:46 +03:00
if ( _is_opt_name ( argv [ i ] ) )
_add_opt_arg ( cmd , argv [ i ] , & takes_arg , NULL , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
else if ( takes_arg )
2017-10-18 17:57:46 +03:00
_update_prev_opt_arg ( cmdtool , cmd , argv [ i ] , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
else {
2020-01-30 17:08:30 +03:00
log_error ( " Parsing command defs: can't parse argc %d argv %s%s%s. " ,
i , argv [ i ] , ( i > 0 ) ? " prev " : " " , ( i > 0 ) ? argv [ i - 1 ] : " " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
}
}
/*
* Add to required_opt_args from an OO_FOO definition .
* ( This is the special case of vgchange / lvchange where one
* optional option is required , and others are then optional . )
* The set of options from OO_FOO are saved in required_opt_args ,
2019-06-10 19:35:26 +03:00
* and flag CMD_FLAG_ANY_REQUIRED_OPT is set on the cmd indicating
2017-02-10 20:36:11 +03:00
* this special case .
*/
2017-10-18 17:57:46 +03:00
static void _include_required_opt_args ( struct cmd_context * cmdtool , struct command * cmd , char * str )
2017-02-10 20:36:11 +03:00
{
char * oo_line ;
char * line ;
char * line_argv [ MAX_LINE_ARGC ] ;
int line_argc ;
2017-10-18 17:57:46 +03:00
if ( ! ( oo_line = _get_oo_line ( str ) ) ) {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: no OO line found for %s. " , str ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
2018-06-08 15:40:53 +03:00
if ( ! ( line = strdup ( oo_line ) ) ) {
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
}
2017-02-10 20:36:11 +03:00
2017-10-18 17:57:46 +03:00
_split_line ( line , & line_argc , line_argv , ' ' ) ;
_add_required_opt_line ( cmdtool , cmd , line_argc , line_argv ) ;
2018-06-08 15:40:53 +03:00
free ( line ) ;
2017-02-10 20:36:11 +03:00
}
/* Process what follows command_name, which are required opt/pos args. */
2017-10-18 17:57:46 +03:00
static void _add_required_line ( struct cmd_context * cmdtool , struct command * cmd , int argc , char * argv [ ] )
2017-02-10 20:36:11 +03:00
{
int i ;
2024-04-04 00:59:21 +03:00
int takes_arg = 0 ;
2017-02-10 20:36:11 +03:00
int prev_was_opt = 0 , prev_was_pos = 0 ;
2019-06-10 19:35:26 +03:00
int orig_ro_count = 0 ;
2017-02-10 20:36:11 +03:00
/* argv[0] is command name */
for ( i = 1 ; i < argc ; i + + ) {
2017-10-18 17:57:46 +03:00
if ( _is_opt_name ( argv [ i ] ) ) {
2017-02-10 20:36:11 +03:00
/* add new required_opt_arg */
2017-10-18 17:57:46 +03:00
_add_opt_arg ( cmd , argv [ i ] , & takes_arg , NULL , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
prev_was_opt = 1 ;
prev_was_pos = 0 ;
} else if ( prev_was_opt & & takes_arg ) {
/* set value for previous required_opt_arg */
2017-10-18 17:57:46 +03:00
_update_prev_opt_arg ( cmdtool , cmd , argv [ i ] , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
prev_was_opt = 0 ;
prev_was_pos = 0 ;
2017-10-18 17:57:46 +03:00
} else if ( _is_pos_name ( argv [ i ] ) ) {
2017-02-10 20:36:11 +03:00
/* add new required_pos_arg */
2017-10-18 17:57:46 +03:00
_add_pos_arg ( cmd , argv [ i ] , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
prev_was_opt = 0 ;
prev_was_pos = 1 ;
} else if ( ! strncmp ( argv [ i ] , " OO_ " , 3 ) ) {
2019-06-10 19:35:26 +03:00
/*
* the first ro_count entries in required_opt_arg required ,
* after which one or more of the next any_ro_count entries
* in required_opt_arg are required . required_opt_arg
* has a total of ro_count + any_ro_count entries .
*/
cmd - > cmd_flags | = CMD_FLAG_ANY_REQUIRED_OPT ;
orig_ro_count = cmd - > ro_count ;
2017-10-18 17:57:46 +03:00
_include_required_opt_args ( cmdtool , cmd , argv [ i ] ) ;
2017-02-10 20:36:11 +03:00
2019-06-10 19:35:26 +03:00
cmd - > any_ro_count = cmd - > ro_count - orig_ro_count ;
cmd - > ro_count = orig_ro_count ;
2017-02-10 20:36:11 +03:00
} else if ( prev_was_pos ) {
/* set property for previous required_pos_arg */
2017-10-18 17:57:46 +03:00
_update_prev_pos_arg ( cmd , argv [ i ] , REQUIRED ) ;
2017-02-10 20:36:11 +03:00
} else {
2020-01-30 17:08:30 +03:00
log_error ( " Parsing command defs: can't parse argc %d argv %s%s%s. " ,
i , argv [ i ] , ( i > 0 ) ? " prev " : " " , ( i > 0 ) ? argv [ i - 1 ] : " " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
}
}
2024-03-24 02:06:45 +03:00
static void _add_flags ( struct command * cmd , const char * line )
2017-02-10 20:36:11 +03:00
{
if ( strstr ( line , " SECONDARY_SYNTAX " ) )
cmd - > cmd_flags | = CMD_FLAG_SECONDARY_SYNTAX ;
2017-02-17 20:45:13 +03:00
if ( strstr ( line , " PREVIOUS_SYNTAX " ) )
cmd - > cmd_flags | = CMD_FLAG_PREVIOUS_SYNTAX ;
2017-02-10 20:36:11 +03:00
}
2024-03-24 02:06:45 +03:00
static void _add_autotype ( struct cmd_context * cmdtool , struct command * cmd ,
int line_argc , char * line_argv [ ] )
2021-04-21 01:03:09 +03:00
{
if ( cmd - > autotype )
cmd - > autotype2 = dm_pool_strdup ( cmdtool - > libmem , line_argv [ 1 ] ) ;
else
cmd - > autotype = dm_pool_strdup ( cmdtool - > libmem , line_argv [ 1 ] ) ;
}
2024-03-24 02:06:45 +03:00
static void _add_rule ( struct cmd_context * cmdtool , struct command * cmd ,
int line_argc , char * line_argv [ ] )
2017-02-10 20:36:11 +03:00
{
struct cmd_rule * rule ;
2024-03-24 02:06:45 +03:00
const char * arg ;
2017-02-10 20:36:11 +03:00
int i , lvt_enum , lvp_enum ;
int check = 0 ;
if ( cmd - > rule_count = = CMD_MAX_RULES ) {
2024-05-11 01:42:49 +03:00
log_error ( " Parsing command defs: too many rules for cmd, increate CMD_MAX_RULES. " ) ;
2017-02-17 00:26:42 +03:00
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
rule = & cmd - > rules [ cmd - > rule_count + + ] ;
for ( i = 0 ; i < line_argc ; i + + ) {
arg = line_argv [ i ] ;
if ( ! strcmp ( arg , " not " ) ) {
rule - > rule = RULE_INVALID ;
check = 1 ;
}
else if ( ! strcmp ( arg , " and " ) ) {
rule - > rule = RULE_REQUIRE ;
check = 1 ;
}
else if ( ! strncmp ( arg , " all " , 3 ) ) {
/* opt/lvt_bits/lvp_bits all remain 0 to mean all */
continue ;
}
else if ( ! strncmp ( arg , " -- " , 2 ) ) {
2024-05-11 01:42:49 +03:00
if ( rule - > opts_count > = MAX_RULE_OPTS | | rule - > check_opts_count > = MAX_RULE_OPTS ) {
log_error ( " Parsing command defs: too many cmd_rule options for cmd, increase MAX_RULE_OPTS. " ) ;
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
return ;
2017-02-10 20:36:11 +03:00
}
if ( check )
2017-10-18 17:57:46 +03:00
rule - > check_opts [ rule - > check_opts_count + + ] = _opt_str_to_num ( cmd , arg ) ;
2017-02-10 20:36:11 +03:00
else
2017-10-18 17:57:46 +03:00
rule - > opts [ rule - > opts_count + + ] = _opt_str_to_num ( cmd , arg ) ;
2017-02-10 20:36:11 +03:00
}
else if ( ! strncmp ( arg , " LV_ " , 3 ) ) {
2017-10-18 17:57:46 +03:00
lvt_enum = _lv_to_enum ( cmd , arg ) ;
2017-02-10 20:36:11 +03:00
if ( check )
rule - > check_lvt_bits | = lvt_enum_to_bit ( lvt_enum ) ;
else
rule - > lvt_bits | = lvt_enum_to_bit ( lvt_enum ) ;
}
else if ( ! strncmp ( arg , " lv_is_ " , 6 ) ) {
2017-10-18 17:57:46 +03:00
lvp_enum = _lvp_name_to_enum ( cmd , arg ) ;
2017-02-10 20:36:11 +03:00
if ( check )
rule - > check_lvp_bits | = lvp_enum_to_bit ( lvp_enum ) ;
else
rule - > lvp_bits | = lvp_enum_to_bit ( lvp_enum ) ;
}
}
}
/* The given option is common to all lvm commands (set in lvm_all). */
2017-10-18 17:57:46 +03:00
static int _is_lvm_all_opt ( int opt )
2017-02-10 20:36:11 +03:00
{
int oo ;
for ( oo = 0 ; oo < lvm_all . oo_count ; oo + + ) {
if ( lvm_all . optional_opt_args [ oo ] . opt = = opt )
return 1 ;
}
return 0 ;
}
/* Find common options for all variants of each command name. */
2017-02-21 20:40:51 +03:00
void factor_common_options ( void )
2017-02-10 20:36:11 +03:00
{
int cn , opt_enum , ci , oo , ro , found ;
struct command * cmd ;
2024-05-02 02:31:51 +03:00
for ( cn = 0 ; cn < LVM_COMMAND_COUNT ; + + cn ) {
2024-05-12 11:17:11 +03:00
2024-05-12 02:14:14 +03:00
if ( command_names_args [ cn ] . variants )
2024-05-12 11:17:11 +03:00
return ; /* already factored */
2017-02-16 18:36:55 +03:00
2017-02-10 20:36:11 +03:00
for ( ci = 0 ; ci < COMMAND_COUNT ; ci + + ) {
cmd = & commands [ ci ] ;
2024-05-12 19:29:31 +03:00
2024-05-12 18:12:19 +03:00
if ( cmd - > lvm_command_enum ! = command_names [ cn ] . lvm_command_enum )
2017-02-10 20:36:11 +03:00
continue ;
2024-05-12 02:14:14 +03:00
command_names_args [ cn ] . variants + + ;
2024-05-12 19:29:31 +03:00
if ( cmd - > ro_count | | cmd - > any_ro_count )
command_names_args [ cn ] . variant_has_ro = 1 ;
if ( cmd - > rp_count )
command_names_args [ cn ] . variant_has_rp = 1 ;
if ( cmd - > oo_count )
command_names_args [ cn ] . variant_has_oo = 1 ;
if ( cmd - > op_count )
command_names_args [ cn ] . variant_has_op = 1 ;
for ( ro = 0 ; ro < cmd - > ro_count + cmd - > any_ro_count ; ro + + ) {
command_names_args [ cn ] . all_options [ cmd - > required_opt_args [ ro ] . opt ] = 1 ;
if ( ( cmd - > required_opt_args [ ro ] . opt = = size_ARG ) & & ! strncmp ( cmd - > name , " lv " , 2 ) )
command_names_args [ cn ] . all_options [ extents_ARG ] = 1 ;
}
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + )
command_names_args [ cn ] . all_options [ cmd - > optional_opt_args [ oo ] . opt ] = 1 ;
2017-02-10 20:36:11 +03:00
}
for ( opt_enum = 0 ; opt_enum < ARG_COUNT ; opt_enum + + ) {
for ( ci = 0 ; ci < COMMAND_COUNT ; ci + + ) {
cmd = & commands [ ci ] ;
2024-05-12 18:12:19 +03:00
if ( cmd - > lvm_command_enum ! = command_names [ cn ] . lvm_command_enum )
2017-02-10 20:36:11 +03:00
continue ;
found = 0 ;
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + ) {
if ( cmd - > optional_opt_args [ oo ] . opt = = opt_enum ) {
found = 1 ;
break ;
}
}
if ( ! found )
goto next_opt ;
}
/* all commands starting with this name use this option */
2024-05-12 02:14:14 +03:00
command_names_args [ cn ] . common_options [ opt_enum ] = 1 ;
2017-02-10 20:36:11 +03:00
next_opt :
;
}
}
}
2017-03-03 23:21:36 +03:00
/* FIXME: use a flag in command_name struct? */
int command_has_alternate_extents ( const char * name )
{
if ( name [ 0 ] ! = ' l ' )
return 0 ;
if ( ! strcmp ( name , " lvcreate " ) | |
! strcmp ( name , " lvresize " ) | |
! strcmp ( name , " lvextend " ) | |
! strcmp ( name , " lvreduce " ) )
return 1 ;
return 0 ;
}
2017-10-18 17:57:46 +03:00
static int _long_name_compare ( const void * on1 , const void * on2 )
2017-02-10 20:36:11 +03:00
{
2017-07-20 10:57:09 +03:00
const struct opt_name * const * optname1 = on1 ;
const struct opt_name * const * optname2 = on2 ;
2017-10-18 17:57:46 +03:00
2017-02-10 20:36:11 +03:00
return strcmp ( ( * optname1 ) - > long_opt + 2 , ( * optname2 ) - > long_opt + 2 ) ;
}
/* Create list of option names for printing alphabetically. */
2017-10-18 17:57:46 +03:00
static void _create_opt_names_alpha ( void )
2017-02-10 20:36:11 +03:00
{
int i ;
for ( i = 0 ; i < ARG_COUNT ; i + + )
opt_names_alpha [ i ] = & opt_names [ i ] ;
2017-10-18 17:57:46 +03:00
qsort ( opt_names_alpha , ARG_COUNT , sizeof ( long ) , _long_name_compare ) ;
2017-02-10 20:36:11 +03:00
}
2024-03-27 02:36:33 +03:00
static int _copy_line ( const char * * line , size_t max_line , int * position )
2017-02-10 20:36:11 +03:00
{
2024-03-24 02:06:45 +03:00
size_t len ;
2017-02-10 20:36:11 +03:00
2024-03-24 02:06:45 +03:00
* line = _command_input + * position ;
len = strlen ( * line ) ;
* position + = len + 1 ;
if ( len > = max_line )
return 0 ;
2024-03-20 00:40:47 +03:00
2024-03-24 02:06:45 +03:00
return len ;
2017-02-10 20:36:11 +03:00
}
2017-04-29 00:27:19 +03:00
int define_commands ( struct cmd_context * cmdtool , const char * run_name )
2017-02-10 20:36:11 +03:00
{
2017-02-17 15:16:27 +03:00
struct command * cmd = NULL ;
2024-03-24 02:06:45 +03:00
const char * line_orig ;
2017-02-10 20:36:11 +03:00
char line [ MAX_LINE ] ;
char * line_argv [ MAX_LINE_ARGC ] ;
const char * name ;
2024-03-24 02:06:45 +03:00
size_t line_orig_len ;
2017-02-10 20:36:11 +03:00
int line_argc ;
int cmd_count = 0 ;
int prev_was_oo_def = 0 ;
int prev_was_oo = 0 ;
int prev_was_op = 0 ;
int copy_pos = 0 ;
2017-02-14 19:16:13 +03:00
int skip = 0 ;
2017-02-17 00:26:42 +03:00
int i ;
2024-05-12 16:39:18 +03:00
int lvm_command_enum ;
2017-02-14 19:16:13 +03:00
2024-03-25 00:44:53 +03:00
memset ( & commands , 0 , sizeof ( commands ) ) ;
2017-02-14 19:16:13 +03:00
if ( run_name & & ! strcmp ( run_name , " help " ) )
run_name = NULL ;
2017-02-10 20:36:11 +03:00
2017-10-18 17:57:46 +03:00
_create_opt_names_alpha ( ) ;
2017-02-10 20:36:11 +03:00
/* Process each line of command-lines-input.h (from command-lines.in) */
2024-03-24 02:06:45 +03:00
while ( ( line_orig_len = _copy_line ( & line_orig , MAX_LINE , & copy_pos ) ) > 0 ) {
if ( line_orig [ 0 ] = = ' - ' & & line_orig [ 1 ] = = ' - ' & &
( ! line_orig [ 2 ] | | ( line_orig [ 2 ] = = ' - ' & & ! line_orig [ 3 ] ) ) )
2024-03-20 00:40:47 +03:00
continue ; /* "---" or "--" */
2017-02-10 20:36:11 +03:00
2024-03-24 02:06:45 +03:00
memcpy ( line , line_orig , line_orig_len + 1 ) ;
2017-10-18 17:57:46 +03:00
_split_line ( line , & line_argc , line_argv , ' ' ) ;
2017-02-10 20:36:11 +03:00
if ( ! line_argc )
continue ;
/* New cmd def begins: command_name <required opt/pos args> */
2024-05-12 16:39:18 +03:00
if ( islower ( line_argv [ 0 ] [ 0 ] ) & & /* All commands are lower-case only */
( ( lvm_command_enum = _find_lvm_command_enum ( line_argv [ 0 ] ) ) < LVM_COMMAND_COUNT ) ) {
if ( cmd_count > = COMMAND_COUNT )
2017-02-10 20:36:11 +03:00
return 0 ;
/*
* FIXME : when running one specific command name ,
* we can optimize by not parsing command defs
* that don ' t start with that command name .
*/
cmd = & commands [ cmd_count ] ;
cmd - > command_index = cmd_count ;
cmd_count + + ;
2024-05-12 16:39:18 +03:00
cmd - > lvm_command_enum = lvm_command_enum ;
cmd - > name = name = command_names [ lvm_command_enum ] . name ;
2017-05-03 22:46:07 +03:00
2017-02-14 19:16:13 +03:00
if ( run_name & & strcmp ( run_name , name ) ) {
skip = 1 ;
prev_was_oo_def = 0 ;
prev_was_oo = 0 ;
prev_was_op = 0 ;
continue ;
}
skip = 0 ;
2017-02-10 20:36:11 +03:00
cmd - > pos_count = 1 ;
2017-10-18 17:57:46 +03:00
_add_required_line ( cmdtool , cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
/* Every cmd gets the OO_ALL options */
2017-10-18 17:57:46 +03:00
_include_optional_opt_args ( cmdtool , cmd , " OO_ALL: " ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
/*
* All other kinds of lines are processed in the
* context of the existing command [ ] .
*/
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_desc_line ( line_argv [ 0 ] ) ) {
2021-09-19 21:27:34 +03:00
if ( cmd - > desc ) {
2024-03-24 02:06:45 +03:00
size_t newlen = strlen ( cmd - > desc ) + line_orig_len + 2 ;
2017-04-29 00:27:19 +03:00
char * newdesc = dm_pool_alloc ( cmdtool - > libmem , newlen ) ;
2021-09-19 21:27:34 +03:00
if ( ! newdesc ) {
2017-05-03 22:46:07 +03:00
/* FIXME */
stack ;
return 0 ;
2017-02-14 01:11:04 +03:00
}
2021-09-19 21:27:34 +03:00
snprintf ( newdesc , newlen , " %s %s " , cmd - > desc , line_orig ) ;
# ifdef MAN_PAGE_GENERATOR
free ( ( void * ) cmd - > desc ) ;
# endif
cmd - > desc = newdesc ;
} else if ( ! ( cmd - > desc = dm_pool_strdup ( cmdtool - > libmem , line_orig ) ) ) {
/* FIXME */
stack ;
return 0 ;
}
2017-02-10 20:36:11 +03:00
continue ;
}
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_autotype_line ( line_argv [ 0 ] ) ) {
2024-03-24 02:06:45 +03:00
_add_autotype ( cmdtool , cmd , line_argc , line_argv ) ;
2021-04-21 01:03:09 +03:00
continue ;
}
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_flags_line ( line_argv [ 0 ] ) ) {
2017-10-18 17:57:46 +03:00
_add_flags ( cmd , line_orig ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_rule_line ( line_argv [ 0 ] ) ) {
2024-03-24 02:06:45 +03:00
_add_rule ( cmdtool , cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
2024-03-20 00:40:47 +03:00
if ( cmd & & _is_id_line ( line_argv [ 0 ] ) ) {
2024-05-12 17:00:48 +03:00
cmd - > command_enum = command_id_to_enum ( line_argv [ 1 ] ) ;
if ( cmd - > command_enum = = CMD_NONE ) {
cmd - > cmd_flags | = CMD_FLAG_PARSE_ERROR ;
2017-05-03 22:46:07 +03:00
return 0 ;
}
2017-02-10 20:36:11 +03:00
continue ;
}
/* OO_FOO: ... */
2017-10-18 17:57:46 +03:00
if ( _is_oo_definition ( line_argv [ 0 ] ) ) {
_add_oo_definition_line ( line_argv [ 0 ] , line_orig ) ;
2017-02-10 20:36:11 +03:00
prev_was_oo_def = 1 ;
prev_was_oo = 0 ;
prev_was_op = 0 ;
continue ;
}
/* OO: ... */
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_oo_line ( line_argv [ 0 ] ) ) {
2024-04-28 21:15:10 +03:00
_add_optional_opt_line ( cmdtool , cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
prev_was_oo_def = 0 ;
prev_was_oo = 1 ;
prev_was_op = 0 ;
continue ;
}
/* OP: ... */
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_op_line ( line_argv [ 0 ] ) ) {
2017-10-18 17:57:46 +03:00
_add_optional_pos_line ( cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
prev_was_oo_def = 0 ;
prev_was_oo = 0 ;
prev_was_op = 1 ;
continue ;
}
/* IO: ... */
2024-03-20 00:40:47 +03:00
if ( cmd & & ! skip & & _is_io_line ( line_argv [ 0 ] ) ) {
2017-10-18 17:57:46 +03:00
_add_ignore_opt_line ( cmdtool , cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
prev_was_oo = 0 ;
prev_was_op = 0 ;
continue ;
}
/* handle OO_FOO:, OO:, OP: continuing on multiple lines */
if ( prev_was_oo_def ) {
2017-10-18 17:57:46 +03:00
_append_oo_definition_line ( line_orig ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
2017-03-10 19:19:21 +03:00
if ( prev_was_oo & & cmd ) {
2024-04-28 21:15:10 +03:00
_add_optional_opt_line ( cmdtool , cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
2017-03-10 19:19:21 +03:00
if ( prev_was_op & & cmd ) {
2017-10-18 17:57:46 +03:00
_add_optional_pos_line ( cmd , line_argc , line_argv ) ;
2017-02-10 20:36:11 +03:00
continue ;
}
2017-03-10 19:19:21 +03:00
2023-07-04 12:26:46 +03:00
if ( ! skip ) {
2017-03-30 18:54:36 +03:00
log_error ( " Parsing command defs: can't process input line %s. " , line_orig ) ;
2023-07-04 12:26:46 +03:00
return 0 ;
}
2017-02-10 20:36:11 +03:00
}
2017-02-17 00:26:42 +03:00
for ( i = 0 ; i < COMMAND_COUNT ; i + + ) {
if ( commands [ i ] . cmd_flags & CMD_FLAG_PARSE_ERROR )
return 0 ;
}
2017-10-18 17:57:46 +03:00
_include_optional_opt_args ( cmdtool , & lvm_all , " OO_ALL " ) ;
2017-04-29 00:27:19 +03:00
2017-10-18 17:57:46 +03:00
for ( i = 0 ; i < _oo_line_count ; i + + ) {
struct oo_line * oo = & _oo_lines [ i ] ;
2018-06-08 15:40:53 +03:00
free ( oo - > name ) ;
free ( oo - > line ) ;
2017-04-29 00:27:19 +03:00
}
2017-10-18 17:57:46 +03:00
memset ( & _oo_lines , 0 , sizeof ( _oo_lines ) ) ;
_oo_line_count = 0 ;
2017-02-10 20:36:11 +03:00
return 1 ;
}
2024-05-01 15:36:28 +03:00
# ifndef MAN_PAGE_GENERATOR
2017-03-08 01:55:07 +03:00
/*
2017-07-21 00:54:40 +03:00
* The opt_names [ ] table describes each option . It is indexed by the
* option typedef , e . g . size_ARG . The size_ARG entry specifies the
* option name , e . g . - - size , and the kind of value it accepts ,
* e . g . sizemb_VAL .
2017-03-08 01:55:07 +03:00
*
2017-07-21 00:54:40 +03:00
* The val_names [ ] table describes each option value type . It is indexed by
* the value typedef , e . g . sizemb_VAL . The sizemb_VAL entry specifies the
* function used to parse the value , e . g . size_mb_arg ( ) , the string used to
* refer to the value in the command - lines . in specifications , e . g . SizeMB ,
* and how the value should be displayed in a man page , e . g . Size [ m | UNIT ] .
*
* A problem is that these tables are independent of a particular command
* ( they are created at build time ) , but different commands accept different
* types of values for the same option , e . g . one command will accept
* signed size values ( ssizemb_VAL ) , while another does not accept a signed
2024-05-01 15:36:28 +03:00
* number , ( sizemb_VAL ) .
*
* To resolve the issue , at run time command ' reconfigures ' its opt_names [ ]
* values by querying particular arg_enum for particular command .
2017-07-21 00:54:40 +03:00
* i . e . it changes size_ARG to accept sizemb_VAL or ssizemb_VAL depending
* on the command .
*
* By default , size_ARG in opt_names [ ] is set up to accept a standard
* sizemb_VAL . The same is done for other opt_names [ ] entries that
* take different option values .
*
* This function overrides default opt_names [ ] entries at run time according
* to the command name , adjusting the value types accepted by various options .
2020-10-03 14:52:37 +03:00
* So , for lvresize , opt_names [ sizemb_VAL ] is overridden to accept
2017-07-21 00:54:40 +03:00
* the relative ( + or - ) value type ssizemb_VAL , instead of the default
* sizemb_VAL . This way , when lvresize processes the - - size value , it
* will use the ssize_mb_arg ( ) function which accepts relative size values .
* When lvcreate processes the - - size value , it uses size_mb_arg ( ) which
* rejects signed values .
*
2020-10-03 14:52:37 +03:00
* The command defs in commands [ ] do not need to be overridden because
2017-07-21 00:54:40 +03:00
* the command - lines . in defs have the context of a command , and are
* described using the proper value type , e . g . this cmd def already
* uses the relative size value : " lvresize --size SSizeMB LV " ,
* so the commands [ ] entry for the cmd def already references the
* correct ssizemb_VAL .
2017-03-08 01:55:07 +03:00
*/
2024-05-01 15:36:28 +03:00
int configure_command_option_values ( const struct command_name * cname , int arg_enum , int val_enum )
2017-03-08 01:55:07 +03:00
{
2024-05-01 15:36:28 +03:00
switch ( cname - > lvm_command_enum ) {
case lvconvert_COMMAND :
switch ( arg_enum ) {
case mirrors_ARG : return snumber_VAL ;
}
break ;
case lvcreate_COMMAND :
2017-03-08 01:55:07 +03:00
/*
2024-05-01 15:36:28 +03:00
* lvcreate is accepts also sizes with + ( positive ) value ,
* so we have to recognize it . But we don ' t want to show
* the + option in man / help as it can be seen confusing ,
2017-03-08 01:55:07 +03:00
* so there ' s a special case when printing man / help
* output to show sizemb_VAL / extents_VAL rather than
* psizemb_VAL / pextents_VAL . )
*/
2024-05-01 15:36:28 +03:00
switch ( arg_enum ) {
case size_ARG : return psizemb_VAL ;
case extents_ARG : return pextents_VAL ;
case poolmetadatasize_ARG : return psizemb_VAL ;
case mirrors_ARG : return pnumber_VAL ;
}
break ;
case lvextend_COMMAND :
/* relative + allowed */
switch ( arg_enum ) {
case size_ARG : return psizemb_VAL ;
case extents_ARG : return pextents_VAL ;
case poolmetadatasize_ARG : return psizemb_VAL ;
}
break ;
case lvreduce_COMMAND :
/* relative - allowed */
switch ( arg_enum ) {
case size_ARG : return nsizemb_VAL ;
case extents_ARG : return nextents_VAL ;
}
break ;
case lvresize_COMMAND :
switch ( arg_enum ) {
case size_ARG : return ssizemb_VAL ;
case extents_ARG : return sextents_VAL ;
case poolmetadatasize_ARG : return psizemb_VAL ;
}
break ;
2017-03-08 01:55:07 +03:00
}
2024-05-01 15:36:28 +03:00
return val_enum ;
2017-03-08 01:55:07 +03:00
}
2024-05-01 15:36:28 +03:00
# endif
2017-03-08 01:55:07 +03:00
2017-02-10 20:36:11 +03:00
/* type_LVT to "type" */
static void _print_usage_description ( struct command * cmd )
{
const char * desc = cmd - > desc ;
char buf [ MAX_LINE ] = { 0 } ;
2017-02-18 21:45:17 +03:00
unsigned di = 0 ;
2017-02-10 20:36:11 +03:00
int bi = 0 ;
2024-04-27 14:04:25 +03:00
for ( di = 0 ; desc [ di ] ; di + + ) {
2017-02-10 20:36:11 +03:00
if ( ! strncmp ( & desc [ di ] , " DESC: " , 5 ) ) {
if ( bi ) {
buf [ bi ] = ' \0 ' ;
printf ( " %s \n " , buf ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
bi = 0 ;
}
/* skip DESC: */
di + = 5 ;
continue ;
}
if ( ! bi & & desc [ di ] = = ' ' )
continue ;
2017-03-24 17:14:21 +03:00
if ( desc [ di ] ! = ' \\ ' )
buf [ bi + + ] = desc [ di ] ;
2017-02-10 20:36:11 +03:00
if ( bi = = ( MAX_LINE - 1 ) )
break ;
}
if ( bi ) {
buf [ bi ] = ' \0 ' ;
printf ( " %s \n " , buf ) ;
}
}
2024-05-01 15:36:28 +03:00
/* Function remappas existing command definitions val_enums for printing
* within man pages or command ' s help lines */
static int _update_relative_opt ( const char * name , int opt_enum , int val_enum )
2017-03-03 23:21:36 +03:00
{
2024-04-27 20:26:32 +03:00
/* check for relative sign */
2024-05-01 15:36:28 +03:00
if ( ! strcmp ( name , " lvconvert " ) )
switch ( opt_enum ) {
case mirrors_ARG : return snumber_VAL ;
}
else if ( ! strcmp ( name , " lvcreate " ) )
2024-04-27 20:26:32 +03:00
/*
* Suppress the [ + ] prefix for lvcreate which we have to
* accept for backwards compat , but don ' t want to advertise .
2024-05-01 15:36:28 +03:00
* ' command - lines . in ' currently uses PNumber in definition
2024-04-27 20:26:32 +03:00
*/
2024-05-01 15:36:28 +03:00
switch ( opt_enum ) {
case mirrors_ARG : return number_VAL ;
2024-04-27 20:26:32 +03:00
}
2024-05-01 15:36:28 +03:00
else if ( ! strcmp ( name , " lvextend " ) )
switch ( opt_enum ) {
case extents_ARG : return pextents_VAL ;
case poolmetadatasize_ARG :
case size_ARG : return psizemb_VAL ;
}
else if ( ! strcmp ( name , " lvreduce " ) )
switch ( opt_enum ) {
case extents_ARG : return nextents_VAL ;
case size_ARG : return nsizemb_VAL ;
}
else if ( ! strcmp ( name , " lvresize " ) )
switch ( opt_enum ) {
case extents_ARG : return sextents_VAL ;
case poolmetadatasize_ARG :
2024-05-02 14:18:08 +03:00
return psizemb_VAL ;
2024-05-01 15:36:28 +03:00
case size_ARG : return ssizemb_VAL ;
}
return val_enum ;
2024-04-27 20:26:32 +03:00
}
static void _print_val_usage ( struct command * cmd , int opt_enum , int val_enum )
{
2024-05-01 15:36:28 +03:00
val_enum = _update_relative_opt ( cmd - > name , opt_enum , val_enum ) ;
2017-03-03 23:21:36 +03:00
if ( ! val_names [ val_enum ] . usage )
printf ( " %s " , val_names [ val_enum ] . name ) ;
else
printf ( " %s " , val_names [ val_enum ] . usage ) ;
}
2017-10-18 17:57:46 +03:00
static void _print_usage_def ( struct command * cmd , int opt_enum , struct arg_def * def )
2017-02-10 20:36:11 +03:00
{
int val_enum ;
int sep = 0 ;
for ( val_enum = 0 ; val_enum < VAL_COUNT ; val_enum + + ) {
if ( def - > val_bits & val_enum_to_bit ( val_enum ) ) {
if ( val_enum = = conststr_VAL )
printf ( " %s " , def - > str ) ;
else if ( val_enum = = constnum_VAL )
printf ( " %llu " , ( unsigned long long ) def - > num ) ;
else {
if ( sep ) printf ( " | " ) ;
2017-10-18 17:57:46 +03:00
_print_val_usage ( cmd , opt_enum , val_enum ) ;
2017-02-10 20:36:11 +03:00
sep = 1 ;
}
2021-04-15 00:34:04 +03:00
/* Too many types have made this too long. man page has this info. */
/*
2017-02-10 20:36:11 +03:00
if ( val_enum = = lv_VAL & & def - > lvt_bits ) {
2021-04-15 00:34:04 +03:00
int lvt_enum ;
2017-02-10 20:36:11 +03:00
for ( lvt_enum = 1 ; lvt_enum < LVT_COUNT ; lvt_enum + + ) {
if ( lvt_bit_is_set ( def - > lvt_bits , lvt_enum ) )
2017-10-18 17:57:46 +03:00
printf ( " _%s " , _lvt_enum_to_name ( lvt_enum ) ) ;
2017-02-10 20:36:11 +03:00
}
}
2021-04-15 00:34:04 +03:00
*/
2017-02-10 20:36:11 +03:00
if ( ( val_enum = = vg_VAL ) & & ( def - > flags & ARG_DEF_FLAG_NEW_VG ) )
printf ( " _new " ) ;
if ( ( val_enum = = lv_VAL ) & & ( def - > flags & ARG_DEF_FLAG_NEW_LV ) )
printf ( " _new " ) ;
}
}
if ( def - > flags & ARG_DEF_FLAG_MAY_REPEAT )
printf ( " ... " ) ;
}
2017-03-02 18:37:54 +03:00
void print_usage ( struct command * cmd , int longhelp , int desc_first )
2017-02-10 20:36:11 +03:00
{
2024-05-12 16:39:18 +03:00
const struct command_name * cname = & command_names [ cmd - > lvm_command_enum ] ;
const struct command_name_args * cna = & command_names_args [ cname - > lvm_command_enum ] ;
2019-06-10 19:35:26 +03:00
int any_req = ( cmd - > cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT ) ? 1 : 0 ;
2017-03-03 01:33:14 +03:00
int include_extents = 0 ;
2017-02-10 20:36:11 +03:00
int ro , rp , oo , op , opt_enum , first ;
2017-02-16 18:36:55 +03:00
/*
* Looks at all variants of each command name and figures out
* which options are common to all variants ( for compact output )
*/
factor_common_options ( ) ;
2017-03-02 18:37:54 +03:00
if ( desc_first & & cmd - > desc )
2017-02-10 20:36:11 +03:00
_print_usage_description ( cmd ) ;
printf ( " %s " , cmd - > name ) ;
2019-06-10 19:35:26 +03:00
if ( any_req ) {
for ( ro = 0 ; ro < cmd - > ro_count ; ro + + ) {
opt_enum = cmd - > required_opt_args [ ro ] . opt ;
if ( opt_names [ opt_enum ] . short_opt )
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
else
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
if ( cmd - > required_opt_args [ ro ] . def . val_bits ) {
printf ( " " ) ;
_print_usage_def ( cmd , opt_enum , & cmd - > required_opt_args [ ro ] . def ) ;
}
}
2017-03-17 19:20:51 +03:00
/* one required option in a set */
2017-02-10 20:36:11 +03:00
first = 1 ;
2017-03-17 19:20:51 +03:00
/* options with short and long */
2019-06-10 19:35:26 +03:00
for ( ro = cmd - > ro_count ; ro < cmd - > ro_count + cmd - > any_ro_count ; ro + + ) {
2017-03-02 23:33:50 +03:00
opt_enum = cmd - > required_opt_args [ ro ] . opt ;
2017-03-17 19:20:51 +03:00
if ( ! opt_names [ opt_enum ] . short_opt )
continue ;
if ( first )
printf ( " \n \t ( " ) ;
else
printf ( " , \n \t " ) ;
first = 0 ;
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
if ( cmd - > required_opt_args [ ro ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > required_opt_args [ ro ] . def ) ;
2017-02-10 20:36:11 +03:00
}
2017-03-17 19:20:51 +03:00
}
/* options with only long */
2019-06-10 19:35:26 +03:00
for ( ro = cmd - > ro_count ; ro < cmd - > ro_count + cmd - > any_ro_count ; ro + + ) {
2017-03-17 19:20:51 +03:00
opt_enum = cmd - > required_opt_args [ ro ] . opt ;
if ( opt_names [ opt_enum ] . short_opt )
continue ;
if ( ( opt_enum = = size_ARG ) & & command_has_alternate_extents ( cmd - > name ) )
include_extents = 1 ;
if ( first )
printf ( " \n \t ( " ) ;
else
printf ( " , \n \t " ) ;
first = 0 ;
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
if ( cmd - > required_opt_args [ ro ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > required_opt_args [ ro ] . def ) ;
2017-03-17 19:20:51 +03:00
}
}
2021-04-11 01:47:00 +03:00
printf_hyphen ( ' ) ' ) ;
2024-04-27 12:36:42 +03:00
} else /* !any_req */
2017-03-17 19:20:51 +03:00
for ( ro = 0 ; ro < cmd - > ro_count ; ro + + ) {
opt_enum = cmd - > required_opt_args [ ro ] . opt ;
if ( ( opt_enum = = size_ARG ) & & command_has_alternate_extents ( cmd - > name ) )
include_extents = 1 ;
2017-02-10 20:36:11 +03:00
2017-03-04 00:12:46 +03:00
if ( opt_names [ opt_enum ] . short_opt )
2017-03-08 23:51:08 +03:00
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
else
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
2017-03-04 00:12:46 +03:00
if ( cmd - > required_opt_args [ ro ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > required_opt_args [ ro ] . def ) ;
2017-03-04 00:12:46 +03:00
}
}
2017-02-10 20:36:11 +03:00
if ( cmd - > rp_count ) {
2019-06-10 19:35:26 +03:00
if ( any_req )
2017-02-10 20:36:11 +03:00
printf ( " \t " ) ;
for ( rp = 0 ; rp < cmd - > rp_count ; rp + + ) {
if ( cmd - > required_pos_args [ rp ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , 0 , & cmd - > required_pos_args [ rp ] . def ) ;
2017-02-10 20:36:11 +03:00
}
}
}
2017-02-21 20:40:51 +03:00
if ( ! longhelp )
goto done ;
2017-02-10 20:36:11 +03:00
if ( cmd - > oo_count ) {
2021-04-21 01:03:09 +03:00
if ( cmd - > autotype ) {
printf ( " \n \t " ) ;
if ( ! cmd - > autotype2 )
2021-04-21 20:05:10 +03:00
printf ( " [ --type %s ] (implied) " , cmd - > autotype ) ;
2021-04-21 01:03:09 +03:00
else
2021-04-21 20:05:10 +03:00
printf ( " [ --type %s|%s ] (implied) " , cmd - > autotype , cmd - > autotype2 ) ;
2021-04-21 01:03:09 +03:00
}
2017-03-03 23:21:36 +03:00
if ( include_extents ) {
2017-03-04 00:12:46 +03:00
printf ( " \n \t [ -l|--extents " ) ;
2017-10-18 17:57:46 +03:00
_print_val_usage ( cmd , extents_ARG , opt_names [ extents_ARG ] . val_enum ) ;
2017-03-03 23:21:36 +03:00
printf ( " ] " ) ;
}
2017-03-03 01:33:14 +03:00
2017-03-04 00:12:46 +03:00
/* print optional options with short opts */
2017-02-10 20:36:11 +03:00
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + ) {
opt_enum = cmd - > optional_opt_args [ oo ] . opt ;
2017-03-04 00:12:46 +03:00
if ( ! opt_names [ opt_enum ] . short_opt )
continue ;
2017-02-10 20:36:11 +03:00
/*
2017-02-21 23:32:54 +03:00
* Skip common lvm options in lvm_all which
* are printed at the end under " Common options for lvm "
* see print_common_options_lvm ( )
2017-02-10 20:36:11 +03:00
*/
2017-10-18 17:57:46 +03:00
if ( _is_lvm_all_opt ( opt_enum ) )
2017-02-10 20:36:11 +03:00
continue ;
2017-02-21 23:32:54 +03:00
/*
* When there is more than one variant ,
* skip common command options from
* cname - > common_options ( options common
* to all variants ) , which are printed at
* the end under " Common options for command "
* see print_common_options_cmd ( )
*/
2024-05-12 02:14:14 +03:00
if ( cna & & ( cna - > variants > 1 ) & & cna - > common_options [ opt_enum ] )
2017-02-10 20:36:11 +03:00
continue ;
2017-02-21 23:59:52 +03:00
printf ( " \n \t [ " ) ;
2017-02-10 20:36:11 +03:00
2017-03-04 00:12:46 +03:00
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
if ( cmd - > optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > optional_opt_args [ oo ] . def ) ;
2017-03-04 00:12:46 +03:00
}
printf ( " ] " ) ;
}
/* print optional options without short opts */
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + ) {
opt_enum = cmd - > optional_opt_args [ oo ] . opt ;
if ( opt_names [ opt_enum ] . short_opt )
continue ;
/*
* Skip common lvm options in lvm_all which
* are printed at the end under " Common options for lvm "
* see print_common_options_lvm ( )
*/
2017-10-18 17:57:46 +03:00
if ( _is_lvm_all_opt ( opt_enum ) )
2017-03-04 00:12:46 +03:00
continue ;
/*
* When there is more than one variant ,
* skip common command options from
* cname - > common_options ( options common
* to all variants ) , which are printed at
* the end under " Common options for command "
* see print_common_options_cmd ( )
*/
2024-05-12 02:14:14 +03:00
if ( cna & & ( cna - > variants > 1 ) & & cna - > common_options [ opt_enum ] )
2017-03-04 00:12:46 +03:00
continue ;
printf ( " \n \t [ " ) ;
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
2017-02-10 20:36:11 +03:00
if ( cmd - > optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > optional_opt_args [ oo ] . def ) ;
2017-02-10 20:36:11 +03:00
}
2017-02-21 23:59:52 +03:00
printf ( " ] " ) ;
2017-02-10 20:36:11 +03:00
}
2017-02-21 23:59:52 +03:00
printf ( " \n \t [ COMMON_OPTIONS ] " ) ;
2017-02-10 20:36:11 +03:00
}
if ( cmd - > op_count ) {
2024-04-27 12:36:42 +03:00
printf ( " \n \t [ " ) ;
for ( op = 0 ; op < cmd - > op_count ; op + + )
2017-02-10 20:36:11 +03:00
if ( cmd - > optional_pos_args [ op ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , 0 , & cmd - > optional_pos_args [ op ] . def ) ;
2017-02-10 20:36:11 +03:00
}
2024-04-27 12:36:42 +03:00
printf ( " ] " ) ;
}
2017-02-10 20:36:11 +03:00
done :
2017-03-02 18:37:54 +03:00
printf ( " \n " ) ;
if ( ! desc_first & & cmd - > desc )
_print_usage_description ( cmd ) ;
2017-03-15 19:40:59 +03:00
printf ( " \n " ) ;
2017-02-10 20:36:11 +03:00
}
2024-04-28 19:14:27 +03:00
void print_usage_common_lvm ( const struct command_name * cname , struct command * cmd )
2017-02-10 20:36:11 +03:00
{
2017-02-21 23:59:52 +03:00
int oo , opt_enum ;
2017-02-10 20:36:11 +03:00
2017-02-21 23:32:54 +03:00
printf ( " Common options for lvm: " ) ;
2017-03-04 00:12:46 +03:00
/* print options with short opts */
2017-02-21 23:32:54 +03:00
for ( oo = 0 ; oo < lvm_all . oo_count ; oo + + ) {
opt_enum = lvm_all . optional_opt_args [ oo ] . opt ;
2017-03-04 00:12:46 +03:00
if ( ! opt_names [ opt_enum ] . short_opt )
continue ;
printf ( " \n \t [ " ) ;
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
if ( lvm_all . optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & lvm_all . optional_opt_args [ oo ] . def ) ;
2017-03-04 00:12:46 +03:00
}
printf ( " ] " ) ;
}
/* print options without short opts */
for ( oo = 0 ; oo < lvm_all . oo_count ; oo + + ) {
opt_enum = lvm_all . optional_opt_args [ oo ] . opt ;
if ( opt_names [ opt_enum ] . short_opt )
continue ;
2017-02-21 23:59:52 +03:00
printf ( " \n \t [ " ) ;
2017-02-21 23:32:54 +03:00
2017-03-04 00:12:46 +03:00
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
2017-02-21 23:32:54 +03:00
if ( lvm_all . optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & lvm_all . optional_opt_args [ oo ] . def ) ;
2017-02-21 23:32:54 +03:00
}
2017-02-21 23:59:52 +03:00
printf ( " ] " ) ;
2017-02-21 23:32:54 +03:00
}
2017-03-15 19:40:59 +03:00
printf ( " \n \n " ) ;
2017-02-21 23:32:54 +03:00
}
2024-04-28 19:14:27 +03:00
void print_usage_common_cmd ( const struct command_name * cname , struct command * cmd )
2017-02-21 23:32:54 +03:00
{
2024-05-12 02:14:14 +03:00
const struct command_name_args * cna = & command_names_args [ cname - > lvm_command_enum ] ;
2017-02-21 23:59:52 +03:00
int oo , opt_enum ;
2021-06-08 22:07:39 +03:00
int found_common_command = 0 ;
2017-02-10 20:36:11 +03:00
/*
* when there ' s more than one variant , options that
* are common to all commands with a common name .
*/
2024-05-12 02:14:14 +03:00
if ( cna - > variants < 2 )
2017-02-21 23:32:54 +03:00
return ;
2021-06-08 22:07:39 +03:00
for ( opt_enum = 0 ; opt_enum < ARG_COUNT ; opt_enum + + ) {
2024-05-12 02:14:14 +03:00
if ( ! cna - > common_options [ opt_enum ] )
2021-06-08 22:07:39 +03:00
continue ;
if ( _is_lvm_all_opt ( opt_enum ) )
continue ;
found_common_command = 1 ;
break ;
}
if ( ! found_common_command )
return ;
2017-02-21 23:32:54 +03:00
printf ( " Common options for command: " ) ;
2017-02-10 20:36:11 +03:00
2017-03-04 00:12:46 +03:00
/* print options with short opts */
2017-02-10 20:36:11 +03:00
for ( opt_enum = 0 ; opt_enum < ARG_COUNT ; opt_enum + + ) {
2024-05-12 02:14:14 +03:00
if ( ! cna - > common_options [ opt_enum ] )
2017-02-10 20:36:11 +03:00
continue ;
2017-10-18 17:57:46 +03:00
if ( _is_lvm_all_opt ( opt_enum ) )
2017-02-10 20:36:11 +03:00
continue ;
2017-03-04 00:12:46 +03:00
if ( ! opt_names [ opt_enum ] . short_opt )
continue ;
2017-02-21 23:59:52 +03:00
printf ( " \n \t [ " ) ;
2017-02-10 20:36:11 +03:00
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + ) {
if ( cmd - > optional_opt_args [ oo ] . opt ! = opt_enum )
continue ;
2017-03-04 00:12:46 +03:00
printf ( " -%c|%s " , opt_names [ opt_enum ] . short_opt , opt_names [ opt_enum ] . long_opt ) ;
if ( cmd - > optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > optional_opt_args [ oo ] . def ) ;
2017-03-04 00:12:46 +03:00
}
break ;
}
printf ( " ] " ) ;
}
/* print options without short opts */
for ( opt_enum = 0 ; opt_enum < ARG_COUNT ; opt_enum + + ) {
2024-05-12 02:14:14 +03:00
if ( ! cna - > common_options [ opt_enum ] )
2017-03-04 00:12:46 +03:00
continue ;
2017-10-18 17:57:46 +03:00
if ( _is_lvm_all_opt ( opt_enum ) )
2017-03-04 00:12:46 +03:00
continue ;
if ( opt_names [ opt_enum ] . short_opt )
continue ;
printf ( " \n \t [ " ) ;
for ( oo = 0 ; oo < cmd - > oo_count ; oo + + ) {
if ( cmd - > optional_opt_args [ oo ] . opt ! = opt_enum )
continue ;
printf ( " %s " , opt_names [ opt_enum ] . long_opt ) ;
2017-02-10 20:36:11 +03:00
if ( cmd - > optional_opt_args [ oo ] . def . val_bits ) {
printf ( " " ) ;
2017-10-18 17:57:46 +03:00
_print_usage_def ( cmd , opt_enum , & cmd - > optional_opt_args [ oo ] . def ) ;
2017-02-10 20:36:11 +03:00
}
break ;
}
2017-02-21 23:59:52 +03:00
printf ( " ] " ) ;
2017-02-10 20:36:11 +03:00
}
2021-06-08 22:07:39 +03:00
printf ( " \n \n " ) ;
2017-02-10 20:36:11 +03:00
}
2024-04-28 19:14:27 +03:00
void print_usage_notes ( const struct command_name * cname )
2017-03-03 01:10:40 +03:00
{
2024-04-27 14:39:33 +03:00
if ( cname & & command_has_alternate_extents ( cname - > name ) )
2024-05-09 15:05:24 +03:00
printf ( " Special options for command: \n \t "
" [ --extents Number[PERCENT] ] \n \t "
" The --extents option can be used in place of --size. \n \t "
" The number allows an optional percent suffix. \n "
" \n \t " ) ;
2024-04-27 14:39:33 +03:00
if ( cname & & ! strcmp ( cname - > name , " lvcreate " ) )
2024-05-09 15:05:24 +03:00
printf ( " [ --name String ] \n \t "
" The --name option is not required but is typically used. \n \t "
" When a name is not specified, a new LV name is generated \n \t "
" with the \" lvol \" prefix and a unique numeric suffix. \n "
2024-04-27 14:39:33 +03:00
" \n " ) ;
2017-03-03 01:10:40 +03:00
2024-05-09 15:05:24 +03:00
printf ( " Common variables for lvm: \n \t "
" Variables in option or position args are capitalized, \n \t "
" e.g. PV, VG, LV, Size, Number, String, Tag. \n "
" \n \t "
" PV \n \t "
" Physical Volume name, a device path under /dev. \n \t "
" For commands managing physical extents, a PV positional arg \n \t "
" generally accepts a suffix indicating a range (or multiple ranges) \n \t "
" of PEs. When the first PE is omitted, it defaults to the start of \n \t "
" the device, and when the last PE is omitted it defaults to the end. \n \t "
" PV[:PE-PE]... is start and end range (inclusive), \n \t "
" PV[:PE+PE]... is start and length range (counting from 0). \n "
" \n \t "
" LV \n \t "
" Logical Volume name. See lvm(8) for valid names. An LV positional \n \t "
" arg generally includes the VG name and LV name, e.g. VG/LV. \n \t "
" LV followed by _<type> indicates that an LV of the given type is \n \t "
" required. (raid represents raid<N> type). \n \t "
" The _new suffix indicates that the LV name is new. \n "
" \n \t "
" Tag \n \t "
" Tag name. See lvm(8) for information about tag names and using \n \t "
" tags in place of a VG, LV or PV. \n "
" \n \t "
" Select \n \t "
" Select indicates that a required positional arg can be omitted \n \t "
" if the --select option is used. No arg appears in this position. \n "
" \n \t "
" Size[UNIT] \n \t "
" Size is an input number that accepts an optional unit. \n \t "
" Input units are always treated as base two values, regardless of \n \t "
" capitalization, e.g. 'k' and 'K' both refer to 1024. \n \t "
" The default input unit is specified by letter, followed by |UNIT. \n \t "
" UNIT represents other possible input units: BbBsSkKmMgGtTpPeE. \n \t "
" (This should not be confused with the output control --units, where \n \t "
" capital letters mean multiple of 1000.) \n "
2024-04-27 14:39:33 +03:00
" \n " ) ;
2017-03-03 01:10:40 +03:00
}