mkfs: allow overridable option values
If an option value ends with the string '?', treat it as a value that
can be respecified later.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 3548c5c..da9ebff 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -121,6 +121,10 @@
.PP
Many feature options allow an optional argument of 0 or 1, to explicitly
disable or enable the functionality.
+.PP
+Normally, options cannot be specified more than once.
+If, however, an option has not yet been specified and its argument ends with
+a question mark ('?'), the option can be specified one additional time.
.SH OPTIONS
.TP
.BI \-b " block_size_options"
@@ -218,6 +222,8 @@
.BI uuid= value
Use the given value as the filesystem UUID for the newly created filesystem.
The default is to generate a random UUID.
+
+This option does not require '?' to respecify the argument value.
.TP
.BI rmapbt= value
This option enables the creation of a reverse-mapping btree index in each
@@ -889,6 +895,8 @@
always terminated with the dollar (
.B $
) token.
+
+This option cannot be respecified.
.TP
.B \-q
Quiet option. Normally
@@ -963,6 +971,8 @@
will not proceed with creating the filesystem. Refer to the
.BR mount "(8) and " xfs_admin (8)
manual entries for additional information.
+
+This option does not require '?' to respecify the argument value.
.TP
.B \-N
Causes the file system parameters to be printed out without really
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index bad92f2..5475aef 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -161,6 +161,10 @@
* Do not set. It is used internally for respecification, when some options
* has to be parsed twice - at first as a string, then later as a number.
*
+ * seen_can_respect INTERNAL
+ * Do not set. It is used internally to indicate that an option has been
+ * seen but is allowed to be respecified later on in the command line.
+ *
* convert OPTIONAL
* A flag signalling whether the user-given value can use suffixes.
* If you want to allow the use of user-friendly values like 13k, 42G,
@@ -203,6 +207,7 @@
int index;
bool seen;
bool str_seen;
+ bool seen_can_respec;
bool convert;
bool is_power_2;
struct _conflict {
@@ -716,6 +721,7 @@
int subopt)
{
return opts->subopt_params[subopt].seen ||
+ opts->subopt_params[subopt].seen_can_respec ||
opts->subopt_params[subopt].str_seen;
}
@@ -1266,7 +1272,8 @@
check_opt(
struct opt_params *opts,
int index,
- bool str_seen)
+ bool str_seen,
+ bool allow_respec)
{
struct subopt_param *sp = &opts->subopt_params[index];
int i;
@@ -1286,14 +1293,18 @@
* used to track the different uses based on the @str parameter passed
* to us.
*/
+ if (allow_respec)
+ sp->seen_can_respec = true;
if (!str_seen) {
if (sp->seen)
respec(opts->name, opts->subopts, index);
- sp->seen = true;
+ if (!allow_respec)
+ sp->seen = true;
} else {
if (sp->str_seen)
respec(opts->name, opts->subopts, index);
- sp->str_seen = true;
+ if (!allow_respec)
+ sp->str_seen = true;
}
/* check for conflicts with the option */
@@ -1302,22 +1313,45 @@
if (con->subopt == LAST_CONFLICT)
break;
- if (con->opts->subopt_params[con->subopt].seen ||
- con->opts->subopt_params[con->subopt].str_seen)
+ if (cli_opt_set(con->opts, con->subopt))
conflict(opts, index, con->opts, con->subopt);
}
}
+/*
+ * If an option value has a '?' at the end, we treat that as an option that
+ * can be respecified later, and truncate the end of @str.
+ */
+static inline bool
+check_allow_respec(
+ char *str)
+{
+ char *s_end;
+
+ if (!str)
+ return false;
+
+ s_end = str + strlen(str) - 1;
+ if (*s_end != '?')
+ return false;
+
+ *s_end = 0;
+ return true;
+}
+
static long long
getnum(
- const char *str,
+ char *str,
struct opt_params *opts,
int index)
{
struct subopt_param *sp = &opts->subopt_params[index];
long long c;
+ bool allow_respec;
- check_opt(opts, index, false);
+ allow_respec = check_allow_respec(str);
+ check_opt(opts, index, false, allow_respec);
+
/* empty strings might just return a default value */
if (!str || *str == '\0') {
if (sp->defaultval == SUBOPT_NEEDS_VAL)
@@ -1379,7 +1413,10 @@
struct opt_params *opts,
int index)
{
- check_opt(opts, index, true);
+ bool allow_respec;
+
+ allow_respec = check_allow_respec(str);
+ check_opt(opts, index, true, allow_respec);
/* empty strings for string options are not valid */
if (!str || *str == '\0')