Richard W.M. Jones
2018-Sep-10 15:27 UTC
[Libguestfs] [PATCH nbdkit v3 0/6] plugins: Implement magic config key.
v1: https://www.redhat.com/archives/libguestfs/2018-September/msg00024.html v2: https://www.redhat.com/archives/libguestfs/2018-September/msg00034.html v3: - Fixed is_config_key zero length test. - Fixed is_config_key so it uses strspn and is not O(n^2). - Changed >= 1.7 to >= 1.8 in the documentation. Rich.
Richard W.M. Jones
2018-Sep-10 15:27 UTC
[Libguestfs] [PATCH nbdkit v3 1/6] plugins: Implement magic config key.
This extends the concept of the magic script parameter. In existing
nbdkit plugins if the first parameter is "bare" (does not contain
'='), then it is parsed magically to allow scripting languages to
work:
nbdkit perl foo.pl
is parsed as:
nbdkit perl script=foo.pl
This generalises the concept, allowing a plugin.magic_config_key to be
defined. If this is non-NULL then any bare parameters on the command
line:
nbdkit file foo
where file_plugin.magic_config_key = "file" is parsed as:
nbdkit file file=foo
If magic_config_key == NULL then the previous behaviour is used.
There is a small (but hopefully not noticable) change to the behaviour
of ‘--dump-plugin’. It is now handled after all command line
parameters have been parsed but before the .config_complete method is
called (whereas previously it would be called after the first command
line parameter was parsed).
Note this change only applies to plugin parameters.
---
docs/nbdkit-plugin.pod | 17 +++++++++++
docs/nbdkit.pod | 8 +++---
include/nbdkit-plugin.h | 2 ++
src/filters.c | 12 ++++++++
src/internal.h | 1 +
src/main.c | 62 ++++++++++++++++++++++++-----------------
src/plugins.c | 9 ++++++
7 files changed, 81 insertions(+), 30 deletions(-)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 515c032..570a142 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -396,6 +396,23 @@ with an error.
If there is an error, C<.config> should call C<nbdkit_error> with
an
error message and return C<-1>.
+=head2 C<.magic_config_key>
+
+ const char *magic_config_key;
+
+This optional string can be used to set a "magic" key used when
+parsing plugin parameters. It affects how "bare parameters" (those
+which do not contain an C<=> character) are parsed on the command
+line.
+
+If C<magic_config_key != NULL> then any bare parameters are passed to
+the C<.config> method as: S<C<config (magic_config_key,
argv[i]);>>.
+
+If C<magic_config_key> is not set then we behave as in nbdkit E<lt>
+1.7: If the first parameter on the command line is bare then it is
+passed to the C<.config> method as: S<C<config ("script",
value);>>.
+Any other bare parameters give errors.
+
=head2 C<.config_complete>
int config_complete (void);
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index 981e571..cf1c5ca 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -404,11 +404,11 @@ To dump information about a plugin, do:
=head2 Magic script parameter
-As a special case, if the first plugin argument does not contain an
-C<'='> character then it is assumed to be C<script=value>.
+For some plugins, especially those supporting scripting languages like
+Perl, if the first plugin argument does not contain an C<'='>
+character then it is assumed to be C<script=value>.
-That allows scripting language plugins like L<nbdkit-perl-plugin(1)>
-to do:
+That allows scripting language plugins to do:
nbdkit perl foo.pl [args...]
diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h
index c95e26c..31aa6c7 100644
--- a/include/nbdkit-plugin.h
+++ b/include/nbdkit-plugin.h
@@ -121,6 +121,8 @@ struct nbdkit_plugin {
int (*trim) (void *handle, uint32_t count, uint64_t offset, uint32_t flags);
int (*zero) (void *handle, uint32_t count, uint64_t offset, uint32_t flags);
#endif
+
+ const char *magic_config_key;
};
extern void nbdkit_set_error (int err);
diff --git a/src/filters.c b/src/filters.c
index e6826f2..3626742 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -205,6 +205,17 @@ filter_config_complete (struct backend *b)
f->backend.next->config_complete (f->backend.next);
}
+/* magic_config_key only applies to plugins, so this passes the
+ * request through to the plugin (hence the name).
+ */
+static const char *
+plugin_magic_config_key (struct backend *b)
+{
+ struct backend_filter *f = container_of (b, struct backend_filter, backend);
+
+ return f->backend.next->magic_config_key (f->backend.next);
+}
+
static int
next_open (void *nxdata, int readonly)
{
@@ -619,6 +630,7 @@ static struct backend filter_functions = {
.dump_fields = filter_dump_fields,
.config = filter_config,
.config_complete = filter_config_complete,
+ .magic_config_key = plugin_magic_config_key,
.open = filter_open,
.prepare = filter_prepare,
.finalize = filter_finalize,
diff --git a/src/internal.h b/src/internal.h
index 1c5aa72..d4fc534 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -171,6 +171,7 @@ struct backend {
void (*dump_fields) (struct backend *);
void (*config) (struct backend *, const char *key, const char *value);
void (*config_complete) (struct backend *);
+ const char *(*magic_config_key) (struct backend *);
int (*open) (struct backend *, struct connection *conn, int readonly);
int (*prepare) (struct backend *, struct connection *conn);
int (*finalize) (struct backend *, struct connection *conn);
diff --git a/src/main.c b/src/main.c
index 8a83a32..9c18d6f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -231,6 +231,7 @@ main (int argc, char *argv[])
const char *filename;
} *filter_filenames = NULL;
size_t i;
+ const char *magic_config_key;
threadlocal_init ();
@@ -680,37 +681,46 @@ main (int argc, char *argv[])
exit (EXIT_SUCCESS);
}
- /* Find key=value configuration parameters for this plugin.
- * The first one is magical in that if it doesn't contain '='
then
- * we assume it is 'script=...'.
+ /* Call config and config_complete to parse the parameters.
+ *
+ * If the plugin provides magic_config_key then any "bare" values
+ * (ones not containing "=") are prefixed with this key.
+ *
+ * For backwards compatibility with old plugins, and to support
+ * scripting languages, if magic_config_key == NULL then if the
+ * first parameter is bare it is prefixed with the key "script",
and
+ * any other bare parameters are errors.
*/
- if (optind < argc && (p = strchr (argv[optind], '=')) ==
NULL) {
- backend->config (backend, "script", argv[optind]);
- ++optind;
- }
-
- /* This must run after parsing the possible script parameter so that
- * the script can be loaded for scripting languages. Note that all
- * scripting languages load the script as soon as they see the
- * script=... parameter (and do not wait for config_complete).
- */
- if (dump_plugin) {
- backend->dump_fields (backend);
- exit (EXIT_SUCCESS);
- }
-
- while (optind < argc) {
- if ((p = strchr (argv[optind], '=')) != NULL) {
+ magic_config_key = backend->magic_config_key (backend);
+ for (i = 0; optind < argc; ++i, ++optind) {
+ p = strchr (argv[optind], '=');
+ if (p) { /* key=value */
*p = '\0';
backend->config (backend, argv[optind], p+1);
- ++optind;
}
- else {
- fprintf (stderr,
- "%s: expecting key=value on the command line but got:
%s\n",
- program_name, argv[optind]);
- exit (EXIT_FAILURE);
+ else if (magic_config_key == NULL) {
+ if (i == 0) /* magic script parameter */
+ backend->config (backend, "script", argv[optind]);
+ else {
+ fprintf (stderr,
+ "%s: expecting key=value on the command line but got:
%s\n",
+ program_name, argv[optind]);
+ exit (EXIT_FAILURE);
+ }
}
+ else { /* magic config key */
+ backend->config (backend, magic_config_key, argv[optind]);
+ }
+ }
+
+ /* This must run after parsing the parameters so that the script can
+ * be loaded for scripting languages. But it must be called before
+ * config_complete so that the plugin doesn't check for missing
+ * parameters.
+ */
+ if (dump_plugin) {
+ backend->dump_fields (backend);
+ exit (EXIT_SUCCESS);
}
backend->config_complete (backend);
diff --git a/src/plugins.c b/src/plugins.c
index 780bbd9..2bea6ac 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -232,6 +232,14 @@ plugin_config_complete (struct backend *b)
exit (EXIT_FAILURE);
}
+static const char *
+plugin_magic_config_key (struct backend *b)
+{
+ struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
+
+ return p->plugin.magic_config_key;
+}
+
static int
plugin_open (struct backend *b, struct connection *conn, int readonly)
{
@@ -630,6 +638,7 @@ static struct backend plugin_functions = {
.dump_fields = plugin_dump_fields,
.config = plugin_config,
.config_complete = plugin_config_complete,
+ .magic_config_key = plugin_magic_config_key,
.open = plugin_open,
.prepare = plugin_prepare,
.finalize = plugin_finalize,
--
2.18.0
Richard W.M. Jones
2018-Sep-10 15:27 UTC
[Libguestfs] [PATCH nbdkit v3 2/6] main: Tighten up characters permitted in config keys.
Previously key=value on the command line allowed the key to be pretty
much anything that didn't contain an '=' character. Even empty
strings were permitted.
This tightens up the permitted keys so they must contain only ASCII
alphanumeric, period, underscore or dash characters; must not be an
empty string; and must start with an ASCII alphabetic character.
---
docs/nbdkit-plugin.pod | 24 +++++++++++++++---------
src/main.c | 36 +++++++++++++++++++++++++++++++++++-
2 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 570a142..fb5c7d7 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -376,15 +376,21 @@ optional list of C<key=value> arguments. These are
passed to the
plugin through this callback when the plugin is first loaded and
before any connections are accepted.
-This callback may be called zero or more times. Both C<key> and
-C<value> parameters will be non-NULL, but it is possible for either to
-be empty strings. The strings are owned by nbdkit but will remain
-valid for the lifetime of the plugin, so the plugin does not need to
-copy them.
-
-The format of the C<key> accepted by plugins is up to the plugin, but
-you should probably look at other plugins and follow the same
-conventions.
+This callback may be called zero or more times.
+
+Both C<key> and C<value> parameters will be non-NULL.
+
+They key will be a non-empty string beginning with an ASCII alphabetic
+character (C<A-Z> C<a-z>). The rest of the key must contain only
+ASCII alphanumeric plus period, underscore or dash characters (C<A-Z>
+C<a-z> C<0-9> C<.> C<_> C<->).
+
+The value may be an arbitrary string, including an empty string. The
+strings are owned by nbdkit but will remain valid for the lifetime of
+the plugin, so the plugin does not need to copy them.
+
+The names of C<key>s accepted by plugins is up to the plugin, but you
+should probably look at other plugins and follow the same conventions.
If the value is a relative path, then note that the server changes
directory when it starts up. See L</FILENAMES AND PATHS> above.
diff --git a/src/main.c b/src/main.c
index 9c18d6f..f4a800f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -72,6 +72,7 @@ static void fork_into_background (void);
static uid_t parseuser (const char *);
static gid_t parsegroup (const char *);
static unsigned int get_socket_activation (void);
+static int is_config_key (const char *key, size_t len);
struct debug_flag *debug_flags; /* -D */
int exit_with_parent; /* --exit-with-parent */
@@ -694,7 +695,7 @@ main (int argc, char *argv[])
magic_config_key = backend->magic_config_key (backend);
for (i = 0; optind < argc; ++i, ++optind) {
p = strchr (argv[optind], '=');
- if (p) { /* key=value */
+ if (p && is_config_key (argv[optind], p - argv[optind])) { /*
key=value */
*p = '\0';
backend->config (backend, argv[optind], p+1);
}
@@ -1281,3 +1282,36 @@ get_socket_activation (void)
return nr_fds;
}
+
+/* When parsing plugin and filter config key=value from the command
+ * line, check that the key is a simple alphanumeric with period,
+ * underscore or dash.
+ *
+ * Note this doesn't return an error. If the key is not valid then we
+ * return false and the parsing code will assume that this is a bare
+ * value instead.
+ */
+static int
+is_config_key (const char *key, size_t len)
+{
+ static const char allowed_first[] + "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ static const char allowed[] + "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "._-";
+
+ if (len == 0)
+ return 0;
+
+ if (strchr (allowed_first, key[0]) == NULL)
+ return 0;
+
+ /* This works in context of the caller since key[len] == '='. */
+ if (strspn (key, allowed) != len)
+ return 0;
+
+ return 1;
+}
--
2.18.0
Richard W.M. Jones
2018-Sep-10 15:28 UTC
[Libguestfs] [PATCH nbdkit v3 3/6] file: Make the file= parameter into a magic config key.
---
docs/nbdkit-captive.pod | 4 ++--
docs/nbdkit-plugin.pod | 2 +-
docs/nbdkit-service.pod | 2 +-
docs/nbdkit-tls.pod | 2 +-
filters/cow/nbdkit-cow-filter.pod | 4 ++--
filters/delay/nbdkit-delay-filter.pod | 2 +-
filters/error/nbdkit-error-filter.pod | 6 +++---
filters/fua/nbdkit-fua-filter.pod | 8 ++++----
filters/log/nbdkit-log-filter.pod | 4 ++--
filters/nozero/nbdkit-nozero-filter.pod | 4 ++--
filters/offset/nbdkit-offset-filter.pod | 4 ++--
filters/partition/nbdkit-partition-filter.pod | 2 +-
plugins/file/file.c | 1 +
plugins/file/nbdkit-file-plugin.pod | 7 ++++++-
tests/test-blocksize.sh | 4 ++--
tests/test-cache.sh | 2 +-
tests/test-cow.sh | 2 +-
tests/test-file-block.c | 3 +--
tests/test-file.c | 2 +-
tests/test-fua.sh | 8 ++++----
tests/test-log.sh | 2 +-
tests/test-nbd.c | 2 +-
tests/test-newstyle.c | 2 +-
tests/test-nozero.sh | 10 +++++-----
tests/test-offset.c | 2 +-
tests/test-oldstyle.c | 2 +-
tests/test-parallel-file.sh | 4 ++--
tests/test-parallel-nbd.sh | 2 +-
tests/test-partition.c | 2 +-
tests/test-single.sh | 2 +-
30 files changed, 54 insertions(+), 49 deletions(-)
diff --git a/docs/nbdkit-captive.pod b/docs/nbdkit-captive.pod
index 6db9520..340374f 100644
--- a/docs/nbdkit-captive.pod
+++ b/docs/nbdkit-captive.pod
@@ -26,7 +26,7 @@ Some examples should make this clear.
To run nbdkit captive under qemu:
- nbdkit file file=disk.img --run 'qemu -drive file=$nbd,if=virtio'
+ nbdkit file disk.img --run 'qemu -drive file=$nbd,if=virtio'
On the qemu command line, C<$nbd> is substituted automatically with
the right NBD path so it can connect to nbdkit. When qemu exits,
@@ -34,7 +34,7 @@ nbdkit is killed and cleaned up automatically.
Running nbdkit captive under guestfish:
- nbdkit file file=disk.img --run 'guestfish --format=raw -a $nbd -i'
+ nbdkit file disk.img --run 'guestfish --format=raw -a $nbd -i'
When guestfish exits, nbdkit is killed.
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index fb5c7d7..380565b 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -267,7 +267,7 @@ an indication of failure. It has the following prototype:
The server usually (not always) changes directory to C</> before it
starts serving connections. This means that any relative paths passed
during configuration will not work when the server is running
-(example: S<C<nbdkit plugin.so file=disk.img>>).
+(example: S<C<nbdkit plugin.so disk.img>>).
To avoid problems, prepend relative paths with the current directory
before storing them in the handle. Or open files and store the file
diff --git a/docs/nbdkit-service.pod b/docs/nbdkit-service.pod
index 956b4ab..c0d275f 100644
--- a/docs/nbdkit-service.pod
+++ b/docs/nbdkit-service.pod
@@ -45,7 +45,7 @@ Also create a service unit (eg.
C</etc/systemd/system/nbdkit.service>)
containing:
[Service]
- ExecStart=/usr/sbin/nbdkit file file=/path/to/serve
+ ExecStart=/usr/sbin/nbdkit file /path/to/serve
For more information on systemd and socket activation, see
L<http://0pointer.de/blog/projects/socket-activation.html>
diff --git a/docs/nbdkit-tls.pod b/docs/nbdkit-tls.pod
index 2e70739..ecca87a 100644
--- a/docs/nbdkit-tls.pod
+++ b/docs/nbdkit-tls.pod
@@ -194,7 +194,7 @@ client which can read this file will be able to connect to
the server.
Use the nbdkit I<--tls-psk> option to start the server:
- nbdkit --tls=require --tls-psk=/tmp/keys/keys.psk -e / file file=disk.img
+ nbdkit --tls=require --tls-psk=/tmp/keys/keys.psk -e / file disk.img
This option overrides X.509 certificate authentication.
diff --git a/filters/cow/nbdkit-cow-filter.pod
b/filters/cow/nbdkit-cow-filter.pod
index ed48f2b..80100e7 100644
--- a/filters/cow/nbdkit-cow-filter.pod
+++ b/filters/cow/nbdkit-cow-filter.pod
@@ -59,7 +59,7 @@ normal way.
Serve the file F<disk.img>, allowing writes, but do not save any
changes into the file:
- nbdkit --filter=cow file file=disk.img
+ nbdkit --filter=cow file disk.img
L<nbdkit-xz-plugin(1)> only supports read access, but you can provide
temporary write access by doing (although this does B<not> save
@@ -76,7 +76,7 @@ otherwise all changes will be lost>.
Run nbdkit:
- nbdkit --filter=cow file file=disk.img
+ nbdkit --filter=cow file disk.img
and then connect with a client and make whatever changes you need.
At the end, disconnect the client.
diff --git a/filters/delay/nbdkit-delay-filter.pod
b/filters/delay/nbdkit-delay-filter.pod
index 3bfb039..62c0093 100644
--- a/filters/delay/nbdkit-delay-filter.pod
+++ b/filters/delay/nbdkit-delay-filter.pod
@@ -16,7 +16,7 @@ remote server, or to test certain kinds of race conditions in
Linux.
=head1 EXAMPLE
- nbdkit --filter=delay file file=disk.img rdelay=100ms wdelay=100ms
+ nbdkit --filter=delay file disk.img rdelay=100ms wdelay=100ms
=head1 PARAMETERS
diff --git a/filters/error/nbdkit-error-filter.pod
b/filters/error/nbdkit-error-filter.pod
index 0f02282..76003c7 100644
--- a/filters/error/nbdkit-error-filter.pod
+++ b/filters/error/nbdkit-error-filter.pod
@@ -27,12 +27,12 @@ B<otherwise this filter will do nothing>.
Inject a low rate of errors randomly into the connection:
- nbdkit --filter=error file file=disk.img error-rate=1%
+ nbdkit --filter=error file disk.img error-rate=1%
Reading and trimming requests will be successful, but all
writes and zeroing will return "No space left on device":
- nbdkit --filter=error file file=disk.img \
+ nbdkit --filter=error file disk.img \
error=ENOSPC \
error-pwrite-rate=100% \
error-zero-rate=100%
@@ -41,7 +41,7 @@ To make all connections fail hard 60 seconds after the server
is
started, use:
rm -f /tmp/inject
- nbdkit --filter=error file file=disk.img \
+ nbdkit --filter=error file disk.img \
error-rate=100% \
error-file=/tmp/inject
sleep 60; touch /tmp/inject
diff --git a/filters/fua/nbdkit-fua-filter.pod
b/filters/fua/nbdkit-fua-filter.pod
index 8822a45..e0b3c4d 100644
--- a/filters/fua/nbdkit-fua-filter.pod
+++ b/filters/fua/nbdkit-fua-filter.pod
@@ -42,23 +42,23 @@ C<NBDKIT_FUA_NONE>).
Serve the file F<disk.img>, but force the client to submit explicit
flush requests instead of using C<NBD_CMD_FLAG_FUA>:
- nbdkit --filter=fua file file=disk.img
+ nbdkit --filter=fua file disk.img
Observe that the blocksize filter optimizes its handling of the FUA
flag based on whether it knows nbdkit will be emulating FUA with a
flush, by comparing the log filter output on top of different fua
filter modes:
- nbdkit --filter=blocksize --filter=log --filter=fua file file=disk.img \
+ nbdkit --filter=blocksize --filter=log --filter=fua file disk.img \
maxlen=4k logfile=fua_emulated fuamode=emulate
- nbdkit --filter=blocksize --filter=log --filter=fua file file=disk.img \
+ nbdkit --filter=blocksize --filter=log --filter=fua file disk.img \
maxlen=4k logfile=fua_native fuamode=native
Serve the file F<disk.img> in write-through mode, where all writes
from the client are immediately flushed to disk as if the client had
always requested FUA:
- nbdkit --filter=fua file fuamode=force file=disk.img
+ nbdkit --filter=fua file fuamode=force disk.img
=head1 SEE ALSO
diff --git a/filters/log/nbdkit-log-filter.pod
b/filters/log/nbdkit-log-filter.pod
index 89ea551..0903329 100644
--- a/filters/log/nbdkit-log-filter.pod
+++ b/filters/log/nbdkit-log-filter.pod
@@ -29,12 +29,12 @@ already exists, it will be truncated.
Serve the file F<disk.img>, and log each client transaction in the
file F<disk.log>:
- nbdkit --filter=log file file=disk.img logfile=disk.log
+ nbdkit --filter=log file disk.img logfile=disk.log
Repeat the task, but with the cow (copy-on-write) filter to perform
local caching of data served from the original plugin:
- nbdkit --filter=cow --filter=log file file=disk.img logfile=disk.log2
+ nbdkit --filter=cow --filter=log file disk.img logfile=disk.log2
After running a client that performs the same operations under each of
the two servers, you can compare F<disk.log> and F<disk.log2> to
see
diff --git a/filters/nozero/nbdkit-nozero-filter.pod
b/filters/nozero/nbdkit-nozero-filter.pod
index 1301432..715605f 100644
--- a/filters/nozero/nbdkit-nozero-filter.pod
+++ b/filters/nozero/nbdkit-nozero-filter.pod
@@ -34,13 +34,13 @@ way to write zeros.
Serve the file F<disk.img>, but force the client to write zeroes
explicitly rather than with C<NBD_CMD_WRITE_ZEROES>:
- nbdkit --filter=nozero file file=disk.img
+ nbdkit --filter=nozero file disk.img
Serve the file F<disk.img>, allowing the client to take advantage of
less network traffic via C<NBD_CMD_WRITE_ZEROES>, but still forcing
the data to be written explicitly rather than punching any holes:
- nbdkit --filter=nozero file zeromode=emulate file=disk.img
+ nbdkit --filter=nozero file zeromode=emulate disk.img
=head1 SEE ALSO
diff --git a/filters/offset/nbdkit-offset-filter.pod
b/filters/offset/nbdkit-offset-filter.pod
index 61496d2..a232e46 100644
--- a/filters/offset/nbdkit-offset-filter.pod
+++ b/filters/offset/nbdkit-offset-filter.pod
@@ -44,7 +44,7 @@ Using L<nbdkit-file-plugin(1)>, serve the file
C<disk.img> starting at
offset C<1M>. The total length served is C<100M> (the underlying
file
must therefore be at least C<101M> in length):
- nbdkit --filter=offset file file=disk.img offset=1M range=100M
+ nbdkit --filter=offset file disk.img offset=1M range=100M
=head2 Serve a single partition
@@ -60,7 +60,7 @@ and length of the partition, eg using:
You can then serve the partition only using:
- nbdkit --filter=offset file file=disk.img offset=65536 range=104727040
+ nbdkit --filter=offset file disk.img offset=65536 range=104727040
=head1 SEE ALSO
diff --git a/filters/partition/nbdkit-partition-filter.pod
b/filters/partition/nbdkit-partition-filter.pod
index 0256e52..ae72f3f 100644
--- a/filters/partition/nbdkit-partition-filter.pod
+++ b/filters/partition/nbdkit-partition-filter.pod
@@ -38,7 +38,7 @@ This parameter is required.
F<disk.img> is a partitioned disk image (eg. a virtual machine disk
image). To serve the first partition only use:
- nbdkit --filter=partition file file=disk.img partition=1
+ nbdkit --filter=partition file disk.img partition=1
=head1 SEE ALSO
diff --git a/plugins/file/file.c b/plugins/file/file.c
index e7cbff6..9d03f18 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -476,6 +476,7 @@ static struct nbdkit_plugin plugin = {
.config = file_config,
.config_complete = file_config_complete,
.config_help = file_config_help,
+ .magic_config_key = "file",
.dump_plugin = file_dump_plugin,
.open = file_open,
.close = file_close,
diff --git a/plugins/file/nbdkit-file-plugin.pod
b/plugins/file/nbdkit-file-plugin.pod
index b2c25d1..7d5c71b 100644
--- a/plugins/file/nbdkit-file-plugin.pod
+++ b/plugins/file/nbdkit-file-plugin.pod
@@ -4,7 +4,7 @@ nbdkit-file-plugin - nbdkit file plugin
=head1 SYNOPSIS
- nbdkit file file=FILENAME
+ nbdkit file [file=]FILENAME
=head1 DESCRIPTION
@@ -26,6 +26,11 @@ be used here.
This parameter is required.
+In nbdkit E<ge> 1.8, C<file=> may be omitted. To ensure that the
+filename does not end up being parsed accidentally as C<key=value>,
+prefix relative paths with C<./> (absolute paths do not need
+modification).
+
=item B<rdelay>
=item B<wdelay>
diff --git a/tests/test-blocksize.sh b/tests/test-blocksize.sh
index d239c9b..cb9b09f 100755
--- a/tests/test-blocksize.sh
+++ b/tests/test-blocksize.sh
@@ -73,9 +73,9 @@ trap cleanup INT QUIT TERM EXIT ERR
# Run two parallel nbdkit; to compare the logs and see what changes.
nbdkit -P blocksize1.pid -U blocksize1.sock \
- --filter=log file logfile=blocksize1.log file=blocksize1.img
+ --filter=log file logfile=blocksize1.log blocksize1.img
nbdkit -P blocksize2.pid -U blocksize2.sock --filter=blocksize \
- --filter=log file logfile=blocksize2.log file=blocksize2.img \
+ --filter=log file logfile=blocksize2.log blocksize2.img \
minblock=1024 maxdata=512k maxlen=1M
# We may have to wait a short time for the pid files to appear.
diff --git a/tests/test-cache.sh b/tests/test-cache.sh
index 6f058b8..215bab1 100755
--- a/tests/test-cache.sh
+++ b/tests/test-cache.sh
@@ -41,7 +41,7 @@ rm -f $files
truncate -s 1G cache.img
# Run nbdkit with the caching filter.
-nbdkit -P cache.pid -U cache.sock --filter=cache file file=cache.img
+nbdkit -P cache.pid -U cache.sock --filter=cache file cache.img
# We may have to wait a short time for the pid file to appear.
for i in `seq 1 10`; do
diff --git a/tests/test-cow.sh b/tests/test-cow.sh
index 5bde829..f9b0649 100755
--- a/tests/test-cow.sh
+++ b/tests/test-cow.sh
@@ -42,7 +42,7 @@ guestfish -N cow-base.img=fs exit
lastmod="$(stat -c "%y" cow-base.img)"
# Run nbdkit with a COW overlay.
-nbdkit -P cow.pid -U cow.sock --filter=cow file file=cow-base.img
+nbdkit -P cow.pid -U cow.sock --filter=cow file cow-base.img
# We may have to wait a short time for the pid file to appear.
for i in `seq 1 10`; do
diff --git a/tests/test-file-block.c b/tests/test-file-block.c
index f053242..e2ea068 100644
--- a/tests/test-file-block.c
+++ b/tests/test-file-block.c
@@ -124,9 +124,8 @@ main (int argc, char *argv[])
atexit (detach_loopdev);
/* Start nbdkit. */
- snprintf (buf, sizeof buf, "file=%s", loopdev);
if (test_start_nbdkit ("-D", "file.zero=1",
- "file", buf, NULL) == -1)
+ "file", loopdev, NULL) == -1)
exit (EXIT_FAILURE);
g = guestfs_create ();
diff --git a/tests/test-file.c b/tests/test-file.c
index 65a2568..9382ed2 100644
--- a/tests/test-file.c
+++ b/tests/test-file.c
@@ -52,7 +52,7 @@ main (int argc, char *argv[])
char *data;
size_t i, size;
- if (test_start_nbdkit ("file", "file=file-data", NULL) ==
-1)
+ if (test_start_nbdkit ("file", "file-data", NULL) == -1)
exit (EXIT_FAILURE);
g = guestfs_create ();
diff --git a/tests/test-fua.sh b/tests/test-fua.sh
index 98b1e84..f95aa18 100755
--- a/tests/test-fua.sh
+++ b/tests/test-fua.sh
@@ -84,13 +84,13 @@ trap cleanup INT QUIT TERM EXIT ERR
# 3: fuamode=native: log shows that blocksize preserves fua
# 4: fuamode=force: log shows that fua is always enabled
nbdkit -P fua1.pid -U fua1.sock --filter=log --filter=fua \
- file logfile=fua1.log file=fua.img
+ file logfile=fua1.log fua.img
nbdkit -P fua2.pid -U fua2.sock --filter=blocksize --filter=log --filter=fua \
- file logfile=fua2.log file=fua.img fuamode=emulate maxdata=4k maxlen=4k
+ file logfile=fua2.log fua.img fuamode=emulate maxdata=4k maxlen=4k
nbdkit -P fua3.pid -U fua3.sock --filter=blocksize --filter=log --filter=fua \
- file logfile=fua3.log file=fua.img fuamode=native maxdata=4k maxlen=4k
+ file logfile=fua3.log fua.img fuamode=native maxdata=4k maxlen=4k
nbdkit -P fua4.pid -U fua4.sock --filter=fua --filter=log \
- file logfile=fua4.log file=fua.img fuamode=force
+ file logfile=fua4.log fua.img fuamode=force
# We may have to wait a short time for the pid files to appear.
for i in `seq 1 10`; do
diff --git a/tests/test-log.sh b/tests/test-log.sh
index 877f9cc..f811de4 100755
--- a/tests/test-log.sh
+++ b/tests/test-log.sh
@@ -44,7 +44,7 @@ if ! qemu-io -f raw -c 'w 1M 2M' log.img; then
fi
# Run nbdkit with logging enabled to file.
-nbdkit -P log.pid -U log.sock --filter=log file file=log.img logfile=log.log
+nbdkit -P log.pid -U log.sock --filter=log file log.img logfile=log.log
# We may have to wait a short time for the pid file to appear.
for i in `seq 1 10`; do
diff --git a/tests/test-nbd.c b/tests/test-nbd.c
index 646c0c3..a09a0d5 100644
--- a/tests/test-nbd.c
+++ b/tests/test-nbd.c
@@ -55,7 +55,7 @@ main (int argc, char *argv[])
/* If wrapping once is good, why not do it twice! Shows that we can
* convert between either style of server options. */
- if (test_start_nbdkit ("-o", "file",
"file=file-data", NULL) == -1)
+ if (test_start_nbdkit ("-o", "file",
"file-data", NULL) == -1)
exit (EXIT_FAILURE);
if (asprintf (&sockarg, "socket=%s", sock) < 0) {
diff --git a/tests/test-newstyle.c b/tests/test-newstyle.c
index cd0ba72..cadccec 100644
--- a/tests/test-newstyle.c
+++ b/tests/test-newstyle.c
@@ -55,7 +55,7 @@ main (int argc, char *argv[])
size_t i, size;
if (test_start_nbdkit ("-e", EXPORTNAME,
- "-n", "file",
"file=file-data", NULL) == -1)
+ "-n", "file",
"file-data", NULL) == -1)
exit (EXIT_FAILURE);
g = guestfs_create ();
diff --git a/tests/test-nozero.sh b/tests/test-nozero.sh
index 781b196..904d822 100755
--- a/tests/test-nozero.sh
+++ b/tests/test-nozero.sh
@@ -102,15 +102,15 @@ trap cleanup INT QUIT TERM EXIT ERR
# 5a/b: both sides of nbd plugin: even though server side does not advertise
# ZERO, the client side still exposes it, and just skips calling nbd's
.zero
nbdkit -P nozero1.pid -U nozero1.sock --filter=log \
- file logfile=nozero1.log file=nozero1.img
+ file logfile=nozero1.log nozero1.img
nbdkit -P nozero2.pid -U nozero2.sock --filter=log --filter=nozero \
- file logfile=nozero2.log file=nozero2.img
+ file logfile=nozero2.log nozero2.img
nbdkit -P nozero3.pid -U nozero3.sock --filter=log --filter=nozero \
- file logfile=nozero3.log file=nozero3.img zeromode=emulate
+ file logfile=nozero3.log nozero3.img zeromode=emulate
nbdkit -P nozero4.pid -U nozero4.sock --filter=nozero --filter=log \
- file logfile=nozero4.log file=nozero4.img zeromode=emulate
+ file logfile=nozero4.log nozero4.img zeromode=emulate
nbdkit -P nozero5a.pid -U nozero5a.sock --filter=log --filter=nozero \
- file logfile=nozero5a.log file=nozero5.img
+ file logfile=nozero5a.log nozero5.img
nbdkit -P nozero5b.pid -U nozero5b.sock --filter=log \
nbd logfile=nozero5b.log socket=nozero5a.sock
diff --git a/tests/test-offset.c b/tests/test-offset.c
index d47066f..a7f467f 100644
--- a/tests/test-offset.c
+++ b/tests/test-offset.c
@@ -78,7 +78,7 @@ main (int argc, char *argv[])
* has not been overwritten.
*/
if (test_start_nbdkit ("--filter", "offset",
- "file", "file=offset-data",
+ "file", "offset-data",
"offset=1M", "range=8M",
NULL) == -1)
exit (EXIT_FAILURE);
diff --git a/tests/test-oldstyle.c b/tests/test-oldstyle.c
index bcffbe4..b3f3c4e 100644
--- a/tests/test-oldstyle.c
+++ b/tests/test-oldstyle.c
@@ -52,7 +52,7 @@ main (int argc, char *argv[])
char *data;
size_t i, size;
- if (test_start_nbdkit ("-o", "file",
"file=file-data", NULL) == -1)
+ if (test_start_nbdkit ("-o", "file",
"file-data", NULL) == -1)
exit (EXIT_FAILURE);
g = guestfs_create ();
diff --git a/tests/test-parallel-file.sh b/tests/test-parallel-file.sh
index fdc8a1b..fd88faa 100755
--- a/tests/test-parallel-file.sh
+++ b/tests/test-parallel-file.sh
@@ -56,7 +56,7 @@ qemu-io -f raw -c "aio_write -P 1 0 512" -c
"aio_write -P 2 512 512" \
# tuning the delays may help.
# With --threads=1, the write should complete first because it was issued first
-nbdkit -v -t 1 -U - --filter=delay file file=test-parallel-file.data \
+nbdkit -v -t 1 -U - --filter=delay file test-parallel-file.data \
wdelay=2 rdelay=1 --run 'qemu-io -f raw -c "aio_write -P 2 512
512" \
-c "aio_read -P 1 0 512" -c aio_flush
$nbd' |
tee test-parallel-file.out
@@ -67,7 +67,7 @@ read 512/512 bytes at offset 0"; then
fi
# With default --threads, the faster read should complete first
-nbdkit -v -U - --filter=delay file file=test-parallel-file.data \
+nbdkit -v -U - --filter=delay file test-parallel-file.data \
wdelay=2 rdelay=1 --run 'qemu-io -f raw -c "aio_write -P 2 512
512" \
-c "aio_read -P 1 0 512" -c aio_flush
$nbd' |
tee test-parallel-file.out
diff --git a/tests/test-parallel-nbd.sh b/tests/test-parallel-nbd.sh
index e793c11..cb70f46 100755
--- a/tests/test-parallel-nbd.sh
+++ b/tests/test-parallel-nbd.sh
@@ -64,7 +64,7 @@ qemu-io -f raw -c "aio_write -P 1 0 512" -c
"aio_write -P 2 512 512" \
nbdkit --exit-with-parent -v \
-U test-parallel-nbd.sock -P test-parallel-nbd.pid \
--filter=delay \
- file file=test-parallel-nbd.data wdelay=2 rdelay=1 &
+ file test-parallel-nbd.data wdelay=2 rdelay=1 &
# We may have to wait a short time for the pid file to appear.
for i in `seq 1 10`; do
if test -f test-parallel-nbd.pid; then
diff --git a/tests/test-partition.c b/tests/test-partition.c
index 0087548..1064293 100644
--- a/tests/test-partition.c
+++ b/tests/test-partition.c
@@ -53,7 +53,7 @@ main (int argc, char *argv[])
if (test_start_nbdkit ("-r",
"--filter", "partition",
- "file", "file=disk",
+ "file", "disk",
"partition=1",
NULL) == -1)
exit (EXIT_FAILURE);
diff --git a/tests/test-single.sh b/tests/test-single.sh
index dc6ce34..35017c8 100755
--- a/tests/test-single.sh
+++ b/tests/test-single.sh
@@ -51,7 +51,7 @@ rm -f $files
truncate -s 1G single.disk
socat unix-listen:single.sock,reuseaddr,fork \
- exec:'nbdkit -r -s file file=single.disk' &
+ exec:'nbdkit -r -s file single.disk' &
pid=$!
cleanup ()
--
2.18.0
Richard W.M. Jones
2018-Sep-10 15:28 UTC
[Libguestfs] [PATCH nbdkit v3 4/6] split: Make the file= parameter(s) into a magic config key.
---
plugins/split/nbdkit-split-plugin.pod | 9 +++++++--
plugins/split/split.c | 3 ++-
tests/test-split.c | 3 ++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/plugins/split/nbdkit-split-plugin.pod
b/plugins/split/nbdkit-split-plugin.pod
index 6a6a01a..6f62eb3 100644
--- a/plugins/split/nbdkit-split-plugin.pod
+++ b/plugins/split/nbdkit-split-plugin.pod
@@ -4,12 +4,12 @@ nbdkit-split-plugin - nbdkit plugin to concatenate split files
into one disk
=head1 SYNOPSIS
- nbdkit split file=file1 [file=file2 file=file3 ...]
+ nbdkit split [file=]file1 [[file=]file2 [file=]file3 ...]
=head1 DESCRIPTION
C<nbdkit-split-plugin> is a file plugin for L<nbdkit(1)>. One or
more
-filenames may be given using the C<file=FILENAME> parameter. These
+filenames may be given using the C<FILENAME> parameter. These
files are logically concatenated into a single disk image.
=head2 Differences from nbdkit-file-plugin
@@ -62,6 +62,11 @@ the order they appear on the command line.
This parameter must appear at least once.
+In nbdkit E<ge> 1.8, C<file=> may be omitted. To ensure that the
+filename does not end up being parsed accidentally as C<key=value>,
+prefix relative paths with C<./> (absolute paths do not need
+modification).
+
=back
=head1 SEE ALSO
diff --git a/plugins/split/split.c b/plugins/split/split.c
index bdcdcf7..7572316 100644
--- a/plugins/split/split.c
+++ b/plugins/split/split.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2017 Red Hat Inc.
+ * Copyright (C) 2017-2018 Red Hat Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -286,6 +286,7 @@ static struct nbdkit_plugin plugin = {
.unload = split_unload,
.config = split_config,
.config_help = split_config_help,
+ .magic_config_key = "file",
.open = split_open,
.close = split_close,
.get_size = split_get_size,
diff --git a/tests/test-split.c b/tests/test-split.c
index f20e64b..c4f2a74 100644
--- a/tests/test-split.c
+++ b/tests/test-split.c
@@ -53,7 +53,8 @@ main (int argc, char *argv[])
size_t i, size;
if (test_start_nbdkit ("split",
- "file=split1", "file=split2",
"file=split3",
+ "split1", "split2",
+ "file=split3" /* leave file= to test */,
NULL) == -1)
exit (EXIT_FAILURE);
--
2.18.0
Richard W.M. Jones
2018-Sep-10 15:28 UTC
[Libguestfs] [PATCH nbdkit v3 5/6] gzip: Make the file= parameter into a magic config key.
---
plugins/gzip/gzip.c | 3 ++-
plugins/gzip/nbdkit-gzip-plugin.pod | 19 ++++++++++++++++++-
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/plugins/gzip/gzip.c b/plugins/gzip/gzip.c
index 09dd629..26d5e3c 100644
--- a/plugins/gzip/gzip.c
+++ b/plugins/gzip/gzip.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013 Red Hat Inc.
+ * Copyright (C) 2013-2018 Red Hat Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -217,6 +217,7 @@ static struct nbdkit_plugin plugin = {
.config = gzip_config,
.config_complete = gzip_config_complete,
.config_help = gzip_config_help,
+ .magic_config_key = "file",
.open = gzip_open,
.close = gzip_close,
.get_size = gzip_get_size,
diff --git a/plugins/gzip/nbdkit-gzip-plugin.pod
b/plugins/gzip/nbdkit-gzip-plugin.pod
index a5f6b79..bd8dbda 100644
--- a/plugins/gzip/nbdkit-gzip-plugin.pod
+++ b/plugins/gzip/nbdkit-gzip-plugin.pod
@@ -4,7 +4,7 @@ nbdkit-gzip-plugin - nbdkit gzip plugin
=head1 SYNOPSIS
- nbdkit gzip file=FILENAME.gz
+ nbdkit gzip [file=]FILENAME.gz
=head1 DESCRIPTION
@@ -18,6 +18,23 @@ files because seeking to a position in the gzip file involves
uncompressing lots of data. A more practical method to compress large
disk images is to use the L<xz(1)> format and
L<nbdkit-xz-plugin(1)>.
+=head1 PARAMETERS
+
+=over 4
+
+=item B<file=>FILENAME.gz
+
+Serve the compressed file named C<FILENAME.gz>.
+
+This parameter is required.
+
+In nbdkit E<ge> 1.8, C<file=> may be omitted. To ensure that the
+filename does not end up being parsed accidentally as C<key=value>,
+prefix relative paths with C<./> (absolute paths do not need
+modification).
+
+=back
+
=head1 SEE ALSO
L<nbdkit-xz-plugin(1)>,
--
2.18.0
Richard W.M. Jones
2018-Sep-10 15:28 UTC
[Libguestfs] [PATCH nbdkit v3 6/6] xz: Make the file= parameter into a magic config key.
---
docs/nbdkit.pod | 8 ++++----
filters/cow/nbdkit-cow-filter.pod | 2 +-
plugins/xz/nbdkit-xz-plugin.pod | 7 ++++++-
plugins/xz/xz.c | 3 ++-
tests/test-xz.c | 2 +-
5 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
index cf1c5ca..d650283 100644
--- a/docs/nbdkit.pod
+++ b/docs/nbdkit.pod
@@ -75,7 +75,7 @@ Serve only the first partition from compressed disk image
F<disk.img.xz>, combining L<nbdkit-xz-plugin(1)> and
L<nbdkit-partition-filter(1)>:
- nbdkit --filter=partition xz file=disk.img.xz partition=1
+ nbdkit --filter=partition xz disk.img.xz partition=1
To understand this command line:
@@ -83,9 +83,9 @@ To understand this command line:
│
┌─────┴────┐
│ │
- nbdkit --filter=partition xz file=disk.img.xz partition=1
- │ │
- └───────────────┬───────────────────┘
+ nbdkit --filter=partition xz disk.img.xz partition=1
+ │ │
+ └─────────────┬─────────────────┘
│
filter name and filter parameter
diff --git a/filters/cow/nbdkit-cow-filter.pod
b/filters/cow/nbdkit-cow-filter.pod
index 80100e7..d5cd735 100644
--- a/filters/cow/nbdkit-cow-filter.pod
+++ b/filters/cow/nbdkit-cow-filter.pod
@@ -65,7 +65,7 @@ L<nbdkit-xz-plugin(1)> only supports read access, but
you can provide
temporary write access by doing (although this does B<not> save
changes to the file):
- nbdkit --filter=cow xz file=disk.xz
+ nbdkit --filter=cow xz disk.xz
=head1 CREATING A DIFF WITH QEMU-IMG
diff --git a/plugins/xz/nbdkit-xz-plugin.pod b/plugins/xz/nbdkit-xz-plugin.pod
index 2c9ab6e..2bd0a1c 100644
--- a/plugins/xz/nbdkit-xz-plugin.pod
+++ b/plugins/xz/nbdkit-xz-plugin.pod
@@ -4,7 +4,7 @@ nbdkit-xz-plugin - nbdkit xz plugin
=head1 SYNOPSIS
- nbdkit xz file=FILENAME.xz
+ nbdkit xz [file=]FILENAME.xz
=head1 DESCRIPTION
@@ -59,6 +59,11 @@ Serve the file named C<FILENAME.xz>.
This parameter is required.
+In nbdkit E<ge> 1.8, C<file=> may be omitted. To ensure that the
+filename does not end up being parsed accidentally as C<key=value>,
+prefix relative paths with C<./> (absolute paths do not need
+modification).
+
=item B<maxblock=>SIZE
The maximum block size that the plugin will read. The plugin will
diff --git a/plugins/xz/xz.c b/plugins/xz/xz.c
index f45e489..a88d713 100644
--- a/plugins/xz/xz.c
+++ b/plugins/xz/xz.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013 Red Hat Inc.
+ * Copyright (C) 2013-2018 Red Hat Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -250,6 +250,7 @@ static struct nbdkit_plugin plugin = {
.config = xz_config,
.config_complete = xz_config_complete,
.config_help = xz_config_help,
+ .magic_config_key = "file",
.open = xz_open,
.close = xz_close,
.get_size = xz_get_size,
diff --git a/tests/test-xz.c b/tests/test-xz.c
index ef58d59..46b1d04 100644
--- a/tests/test-xz.c
+++ b/tests/test-xz.c
@@ -51,7 +51,7 @@ main (int argc, char *argv[])
int r;
char *data;
- if (test_start_nbdkit ("xz", "-r",
"file=disk.xz", NULL) == -1)
+ if (test_start_nbdkit ("xz", "-r", "disk.xz",
NULL) == -1)
exit (EXIT_FAILURE);
g = guestfs_create ();
--
2.18.0
Eric Blake
2018-Sep-10 15:42 UTC
Re: [Libguestfs] [PATCH nbdkit v3 2/6] main: Tighten up characters permitted in config keys.
On 9/10/18 10:27 AM, Richard W.M. Jones wrote:> Previously key=value on the command line allowed the key to be pretty > much anything that didn't contain an '=' character. Even empty > strings were permitted. > > This tightens up the permitted keys so they must contain only ASCII > alphanumeric, period, underscore or dash characters; must not be an > empty string; and must start with an ASCII alphabetic character. > --- > docs/nbdkit-plugin.pod | 24 +++++++++++++++--------- > src/main.c | 36 +++++++++++++++++++++++++++++++++++- > 2 files changed, 50 insertions(+), 10 deletions(-) >> +Both C<key> and C<value> parameters will be non-NULL. > + > +They key will be a non-empty string beginning with an ASCII alphabetics/They/The/> +character (C<A-Z> C<a-z>). The rest of the key must contain only > +ASCII alphanumeric plus period, underscore or dash characters (C<A-Z> > +C<a-z> C<0-9> C<.> C<_> C<->).No leading underscore? I'm okay with that, but it is slightly stricter than C and Shell variables (then again, accepting '.' and '-' already makes us different). And we can always add stuff later if it proves useful (it's easier to start strict and relax later, compared to starting relaxed and then tightening down when we realize the problems it caused).> +/* When parsing plugin and filter config key=value from the command > + * line, check that the key is a simple alphanumeric with period, > + * underscore or dash. > + * > + * Note this doesn't return an error. If the key is not valid then we > + * return false and the parsing code will assume that this is a bare > + * value instead. > + */ > +static int > +is_config_key (const char *key, size_t len) > +{ > + static const char allowed_first[] > + "abcdefghijklmnopqrstuvwxyz" > + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; > + static const char allowed[] > + "abcdefghijklmnopqrstuvwxyz" > + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" > + "0123456789" > + "._-";Crazy me is thinking of the micro-optimization: static const char allowed[] "0123456789" ".-_" "abc..z" "ABC..Z"; ...> + > + if (len == 0) > + return 0; > + > + if (strchr (allowed_first, key[0]) == NULL) > + return 0;where this is: 'strchr(allowed + 13, key[0])' (or allowed + 12, if you allow leading underscore). But please don't - while it's clever, I don't think it's friendly to future readers, and the optimization is not in hot code, nor is shaving 52 bytes of .data by avoiding repetition between the two 'allowed' constants really a deal-breaker.> + > + /* This works in context of the caller since key[len] == '='. */ > + if (strspn (key, allowed) != len) > + return 0;I like it. With the one typo fix, Reviewed-by: Eric Blake <eblake@redhat.com> -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Apparently Analagous Threads
- [PATCH nbdkit v3 2/6] main: Tighten up characters permitted in config keys.
- Re: [PATCH nbdkit v2 2/6] main: Tighten up characters permitted in config keys.
- [PATCH nbdkit v2 2/6] main: Tighten up characters permitted in config keys.
- [PATCH nbdkit v3 0/6] plugins: Implement magic config key.
- [PATCH nbdkit v2 0/6] plugins: Implement magic config key.