[PATCH libnbd] lib: Copy nbd-protocol.h from nbdkit 1.15.3.
by Richard W.M. Jones
Eventually nbdkit will install this as a public header file and we
will be able to consume it from $includedir. In the mean time
synchronize with the copy in nbdkit.
---
lib/nbd-protocol.h | 57 +++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/lib/nbd-protocol.h b/lib/nbd-protocol.h
index 699aa22..7df411a 100644
--- a/lib/nbd-protocol.h
+++ b/lib/nbd-protocol.h
@@ -30,21 +30,22 @@
* SUCH DAMAGE.
*/
-/* This is derived from nbdkit's common/protocol/protocol.h. In time
- * we expect that this library, nbdkit (and maybe others) should use
- * the exact same header.
- */
-
#ifndef NBD_PROTOCOL_H
#define NBD_PROTOCOL_H
#include <stdint.h>
/* Note that all NBD fields are sent on the wire in network byte
- * order, so we must use beXXtoh or htobeXX when reading or writing
+ * order, so you must use beXXtoh or htobeXX when reading or writing
* these structures.
*/
+#if defined(__GNUC__) || defined(__clang__)
+#define NBD_ATTRIBUTE_PACKED __attribute__((__packed__))
+#else
+#define NBD_ATTRIBUTE_PACKED
+#endif
+
#define NBD_MAX_STRING 4096 /* Maximum length of a string field */
/* Old-style handshake. */
@@ -55,7 +56,7 @@ struct nbd_old_handshake {
uint16_t gflags; /* global flags */
uint16_t eflags; /* per-export flags */
char zeroes[124]; /* must be sent as zero bytes */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
#define NBD_OLD_VERSION UINT64_C(0x420281861253)
@@ -64,7 +65,7 @@ struct nbd_new_handshake {
char nbdmagic[8]; /* "NBDMAGIC" */
uint64_t version; /* NBD_NEW_VERSION */
uint16_t gflags; /* global flags */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
#define NBD_NEW_VERSION UINT64_C(0x49484156454F5054)
@@ -74,14 +75,14 @@ struct nbd_new_option {
uint32_t option; /* NBD_OPT_* */
uint32_t optlen; /* option data length */
/* option data follows */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* Newstyle handshake OPT_EXPORT_NAME reply message. */
struct nbd_export_name_option_reply {
uint64_t exportsize; /* size of export */
uint16_t eflags; /* per-export flags */
char zeroes[124]; /* optional zeroes */
-} __attribute__((packed));;
+} NBD_ATTRIBUTE_PACKED;;
/* Fixed newstyle handshake reply message. */
struct nbd_fixed_new_option_reply {
@@ -89,14 +90,13 @@ struct nbd_fixed_new_option_reply {
uint32_t option; /* option we are replying to */
uint32_t reply; /* NBD_REP_* */
uint32_t replylen;
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
#define NBD_REP_MAGIC UINT64_C(0x3e889045565a9)
-/* Global flags. Exposed by the generator as LIBNBD_HANDSHAKE_FLAG_* instead
+/* Global flags. */
#define NBD_FLAG_FIXED_NEWSTYLE 1
#define NBD_FLAG_NO_ZEROES 2
- */
/* Per-export flags. */
#define NBD_FLAG_HAS_FLAGS (1 << 0)
@@ -146,19 +146,19 @@ struct nbd_fixed_new_option_reply_info_export {
uint16_t info; /* NBD_INFO_EXPORT */
uint64_t exportsize; /* size of export */
uint16_t eflags; /* per-export flags */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* NBD_REP_META_CONTEXT reply (follows fixed_new_option_reply). */
struct nbd_fixed_new_option_reply_meta_context {
uint32_t context_id; /* metadata context ID */
/* followed by a string */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* NBD_REPLY_TYPE_BLOCK_STATUS block descriptor. */
struct nbd_block_descriptor {
uint32_t length; /* length of block */
uint32_t status_flags; /* block type (hole etc) */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* New-style handshake server reply when using NBD_OPT_EXPORT_NAME.
* Modern clients use NBD_OPT_GO instead of this.
@@ -167,7 +167,7 @@ struct nbd_new_handshake_finish {
uint64_t exportsize;
uint16_t eflags; /* per-export flags */
char zeroes[124]; /* must be sent as zero bytes */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* Request (client -> server). */
struct nbd_request {
@@ -177,14 +177,14 @@ struct nbd_request {
uint64_t handle; /* Opaque handle. */
uint64_t offset; /* Request offset. */
uint32_t count; /* Request length. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* Simple reply (server -> client). */
struct nbd_simple_reply {
uint32_t magic; /* NBD_SIMPLE_REPLY_MAGIC. */
uint32_t error; /* NBD_SUCCESS or one of NBD_E*. */
uint64_t handle; /* Opaque handle. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
/* Structured reply (server -> client). */
struct nbd_structured_reply {
@@ -193,23 +193,23 @@ struct nbd_structured_reply {
uint16_t type; /* NBD_REPLY_TYPE_* */
uint64_t handle; /* Opaque handle. */
uint32_t length; /* Length of payload which follows. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
struct nbd_structured_reply_offset_data {
uint64_t offset; /* offset */
/* Followed by data. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
struct nbd_structured_reply_offset_hole {
uint64_t offset;
uint32_t length; /* Length of hole. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
struct nbd_structured_reply_error {
uint32_t error; /* NBD_E* error number */
uint16_t len; /* Length of human readable error. */
/* Followed by human readable error string, and possibly more structure. */
-} __attribute__((packed));
+} NBD_ATTRIBUTE_PACKED;
#define NBD_REQUEST_MAGIC 0x25609513
#define NBD_SIMPLE_REPLY_MAGIC 0x67446698
@@ -239,12 +239,11 @@ struct nbd_structured_reply_error {
#define NBD_CMD_WRITE_ZEROES 6
#define NBD_CMD_BLOCK_STATUS 7
-/* Command flags. Exposed by the generator as LIBNBD_CMD_FLAG_* instead
-#define NBD_CMD_FLAG_FUA (1<<0)
-#define NBD_CMD_FLAG_NO_HOLE (1<<1)
-#define NBD_CMD_FLAG_DF (1<<2)
-#define NBD_CMD_FLAG_REQ_ONE (1<<3)
-*/
+#define NBD_CMD_FLAG_FUA (1<<0)
+#define NBD_CMD_FLAG_NO_HOLE (1<<1)
+#define NBD_CMD_FLAG_DF (1<<2)
+#define NBD_CMD_FLAG_REQ_ONE (1<<3)
+#define NBD_CMD_FLAG_FAST_ZERO (1<<4)
/* NBD error codes. */
#define NBD_SUCCESS 0
--
2.23.0
5 years, 1 month
[p2v PATCH] doc: start filling release notes
by Pino Toscano
Add a minimal release note text for the first standalone version,
virt-p2v 1.41.0; in addition, add the first items for the future
1.42.0.
---
docs/p2v-release-notes.pod | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/docs/p2v-release-notes.pod b/docs/p2v-release-notes.pod
index ee0dd98..21d736d 100644
--- a/docs/p2v-release-notes.pod
+++ b/docs/p2v-release-notes.pod
@@ -4,7 +4,7 @@ p2v-release-notes - virt-p2v Release Notes
=begin comment
-UPDATED TO <commit id>
+UPDATED TO 9b009aa4a3898648fe68301d1c5ed774a0bf2e38
=end comment
@@ -17,19 +17,39 @@ document.body.style.backgroundRepeat = "no-repeat";
=end comment
-=head1 RELEASE NOTES FOR VIRT-P2V 1.XX
+=head1 RELEASE NOTES FOR VIRT-P2V 1.42.0
These release notes only cover the differences from the previous
-stable/dev branch split (1.40.0). For detailed changelogs, please see
-the git repository, or the ChangeLog file distributed in the tarball.
+version. For detailed changelogs, please see the git repository.
-...
+=over 4
+
+=item
+
+The C<rhv-upload> output mode of virt-v2v is not listed as output
+driver, as virt-p2v does not provide all the GUI elements to properly
+use it (Pino Toscano).
+
+=item
+
+Virt-v2v is checked as requirement for the functional tests, in
+addition to guestfish, and virt-customize (Pino Toscano).
+
+=back
=for comment ################################################################
+=head1 RELEASE NOTES FOR VIRT-P2V 1.41.0
+
+This is the first standalone release of virt-p2v, split from the
+libguestfs sources.
+
+There are no functionality changes compared to virt-p2v shipped as
+part of libguestfs 1.40.
+
=head1 RELEASE NOTES FOR HISTORICAL VERSIONS OF VIRT-P2V
-Before 1.XX virt-p2v was released as part of libguestfs. Therefore,
+Before 1.41.0 virt-p2v was released as part of libguestfs. Therefore,
release notes for these older versions are found as part of the
L<release notes of libguestfs|guestfs-release-notes(1)>.
--
2.21.0
5 years, 1 month
[PATCH v2 0/5] remove unused gnulib modules
by Pino Toscano
This is an extended version of:
https://www.redhat.com/archives/libguestfs/2019-September/msg00178.html
It adds a couple of simple code changes, so it makes it possible to
drop more modules. In addition, more unused modules were dropped.
Pino Toscano (5):
tests: switch away from xgetcwd
daemon: move read_whole_file to common utils
daemon: switch from read_file to read_whole_file
daemon: remove unused include
build: remove unused gnulib modules
bootstrap | 17 ---------
daemon/9p.c | 58 +-----------------------------
daemon/Makefile.am | 4 ---
daemon/cpio.c | 2 --
daemon/daemon.h | 1 +
daemon/ntfsclone.c | 4 +--
daemon/tar.c | 4 +--
daemon/utils.c | 58 ++++++++++++++++++++++++++++++
lib/Makefile.am | 5 ---
m4/.gitignore | 52 ---------------------------
tests/c-api/test-add-libvirt-dom.c | 10 +++---
11 files changed, 66 insertions(+), 149 deletions(-)
--
2.21.0
5 years, 1 month
[libnbd PATCH] ocaml: Fix tests when ocamlopt is not available
by Pino Toscano
Fixes commit 42cb77be8c29de57f2f523688ea375762715d23f.
---
ocaml/tests/Makefile.am | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/ocaml/tests/Makefile.am b/ocaml/tests/Makefile.am
index dfb23ff..56519c0 100644
--- a/ocaml/tests/Makefile.am
+++ b/ocaml/tests/Makefile.am
@@ -100,7 +100,10 @@ endif
TESTS_ENVIRONMENT = LIBNBD_DEBUG=1 OCAMLRUNPARAM=b
LOG_COMPILER = $(top_builddir)/run
-TESTS = $(tests_bc) $(tests_opt)
+TESTS = $(tests_bc)
+if HAVE_OCAMLOPT
+TESTS += $(tests_opt)
+endif
endif HAVE_NBDKIT
endif HAVE_OCAML
--
2.21.0
5 years, 1 month
[PATCH nbdkit] server: public: Add nbdkit_parse_* functions for safely parsing integers.
by Richard W.M. Jones
sscanf is sadly not safe (because it doesn't handle integer overflow
correctly), and strto*l functions are a pain to use correctly.
Therefore add some functions to hide the pain of parsing integers from
the command line.
The simpler uses of sscanf and strto*l are replaced. There are still
a few where we are using advanced features of sscanf.
---
docs/nbdkit-plugin.pod | 48 ++++++
filters/cache/cache.c | 16 +-
filters/cache/cache.h | 2 +-
filters/partition/partition.c | 8 +-
filters/partition/partition.h | 2 +-
filters/retry/retry.c | 14 +-
filters/xz/xz.c | 10 +-
include/nbdkit-common.h | 22 +++
plugins/curl/curl.c | 4 +-
plugins/nbd/nbd-standalone.c | 9 +-
plugins/nbd/nbd.c | 9 +-
plugins/partitioning/partitioning.c | 4 +-
plugins/random/random.c | 4 +-
plugins/ssh/ssh.c | 6 +-
plugins/vddk/vddk.c | 8 +-
server/internal.h | 2 +-
server/main.c | 21 +--
server/nbdkit.syms | 12 ++
server/public.c | 218 ++++++++++++++++++++++++++++
server/socket-activation.c | 10 +-
server/test-public.c | 181 ++++++++++++++++++++++-
server/usergroup.c | 4 +-
22 files changed, 527 insertions(+), 87 deletions(-)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 2a84444..2e1913f 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -1013,6 +1013,54 @@ might be killed by C<SIGKILL> or segfault).
=head1 PARSING COMMAND LINE PARAMETERS
+=head2 Parsing numbers
+
+There are several functions for parsing numbers. These all deal
+correctly with overflow, out of range and parse errors, and you should
+use them instead of unsafe functions like L<sscanf(3)>, L<atoi(3)> and
+similar.
+
+ int nbdkit_parse_int (const char *what, const char *str, int *r);
+ int nbdkit_parse_unsigned (const char *what,
+ const char *str, unsigned *r);
+ int nbdkit_parse_long (const char *what, const char *str, long *r);
+ int nbdkit_parse_unsigned_long (const char *what,
+ const char *str, unsigned long *r);
+ int nbdkit_parse_int16_t (const char *what,
+ const char *str, int16_t *r);
+ int nbdkit_parse_uint16_t (const char *what,
+ const char *str, uint16_t *r);
+ int nbdkit_parse_int32_t (const char *what,
+ const char *str, int32_t *r);
+ int nbdkit_parse_uint32_t (const char *what,
+ const char *str, uint32_t *r);
+ int nbdkit_parse_int64_t (const char *what,
+ const char *str, int64_t *r);
+ int nbdkit_parse_uint64_t (const char *what,
+ const char *str, uint64_t *r);
+ int nbdkit_parse_ssize_t (const char *what,
+ const char *str, ssize_t *r);
+ int nbdkit_parse_size_t (const char *what,
+ const char *str, size_t *r);
+
+Parse string C<str> into an integer of various types. These functions
+parse a decimal, hexadecimal (C<"0x...">) or octal (C<"0...">) number.
+
+On success the functions return C<0> and set C<*r> to the parsed value
+(unless C<*r == NULL> in which case the result is discarded). On
+error, C<nbdkit_error> is called and the functions return C<-1>.
+
+The C<what> parameter is printed in error messages to provide context.
+It should usually be a short descriptive string of what you are trying
+to parse, eg:
+
+ if (nbdkit_parse_int ("random seed", argv[1], &seed) == -1)
+ return -1;
+
+might print an error:
+
+ random seed: could not parse number: "lalala"
+
=head2 Parsing sizes
Use the C<nbdkit_parse_size> utility function to parse human-readable
diff --git a/filters/cache/cache.c b/filters/cache/cache.c
index 14a3c0a..faf6023 100644
--- a/filters/cache/cache.c
+++ b/filters/cache/cache.c
@@ -70,7 +70,7 @@ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
unsigned blksize;
enum cache_mode cache_mode = CACHE_MODE_WRITEBACK;
int64_t max_size = -1;
-int hi_thresh = 95, lo_thresh = 80;
+unsigned hi_thresh = 95, lo_thresh = 80;
bool cache_on_read = false;
static int cache_flush (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle, uint32_t flags, int *err);
@@ -129,22 +129,20 @@ cache_config (nbdkit_next_config *next, void *nxdata,
return 0;
}
else if (strcmp (key, "cache-high-threshold") == 0) {
- if (sscanf (value, "%d", &hi_thresh) != 1) {
- nbdkit_error ("invalid cache-high-threshold parameter: %s", value);
+ if (nbdkit_parse_unsigned ("cache-high-threshold",
+ value, &hi_thresh) == -1)
return -1;
- }
- if (hi_thresh <= 0) {
+ if (hi_thresh == 0) {
nbdkit_error ("cache-high-threshold must be greater than zero");
return -1;
}
return 0;
}
else if (strcmp (key, "cache-low-threshold") == 0) {
- if (sscanf (value, "%d", &lo_thresh) != 1) {
- nbdkit_error ("invalid cache-low-threshold parameter: %s", value);
+ if (nbdkit_parse_unsigned ("cache-low-threshold",
+ value, &lo_thresh) == -1)
return -1;
- }
- if (lo_thresh <= 0) {
+ if (lo_thresh == 0) {
nbdkit_error ("cache-low-threshold must be greater than zero");
return -1;
}
diff --git a/filters/cache/cache.h b/filters/cache/cache.h
index c67e173..2b72221 100644
--- a/filters/cache/cache.h
+++ b/filters/cache/cache.h
@@ -47,7 +47,7 @@ extern unsigned blksize;
/* Maximum size of the cache and high/low thresholds. */
extern int64_t max_size;
-extern int hi_thresh, lo_thresh;
+extern unsigned hi_thresh, lo_thresh;
/* Cache read requests. */
extern bool cache_on_read;
diff --git a/filters/partition/partition.c b/filters/partition/partition.c
index 15f785e..17dd33a 100644
--- a/filters/partition/partition.c
+++ b/filters/partition/partition.c
@@ -45,7 +45,7 @@
#include "partition.h"
-int partnum = -1;
+unsigned partnum = 0;
/* Called for each key=value passed on the command line. */
static int
@@ -53,7 +53,9 @@ partition_config (nbdkit_next_config *next, void *nxdata,
const char *key, const char *value)
{
if (strcmp (key, "partition") == 0) {
- if (sscanf (value, "%d", &partnum) != 1 || partnum <= 0) {
+ if (nbdkit_parse_unsigned ("partition", value, &partnum) == -1)
+ return -1;
+ if (partnum == 0) {
nbdkit_error ("invalid partition number");
return -1;
}
@@ -67,7 +69,7 @@ partition_config (nbdkit_next_config *next, void *nxdata,
static int
partition_config_complete (nbdkit_next_config_complete *next, void *nxdata)
{
- if (partnum == -1) {
+ if (partnum == 0) {
nbdkit_error ("you must supply the partition parameter on the command line");
return -1;
}
diff --git a/filters/partition/partition.h b/filters/partition/partition.h
index e25a695..b20d39f 100644
--- a/filters/partition/partition.h
+++ b/filters/partition/partition.h
@@ -37,7 +37,7 @@
#define SECTOR_SIZE 512
-extern int partnum;
+extern unsigned partnum;
extern int find_mbr_partition (struct nbdkit_next_ops *next_ops, void *nxdata,
int64_t size, uint8_t *mbr,
diff --git a/filters/retry/retry.c b/filters/retry/retry.c
index b1864fa..4d73f17 100644
--- a/filters/retry/retry.c
+++ b/filters/retry/retry.c
@@ -44,8 +44,8 @@
#include "cleanup.h"
-static int retries = 5; /* 0 = filter is disabled */
-static int initial_delay = 2;
+static unsigned retries = 5; /* 0 = filter is disabled */
+static unsigned initial_delay = 2;
static bool exponential_backoff = true;
static bool force_readonly = false;
@@ -67,15 +67,15 @@ retry_config (nbdkit_next_config *next, void *nxdata,
int r;
if (strcmp (key, "retries") == 0) {
- if (sscanf (value, "%d", &retries) != 1 || retries < 0) {
- nbdkit_error ("cannot parse retries: %s", value);
+ if (nbdkit_parse_unsigned ("retries", value, &retries) == -1)
return -1;
- }
return 0;
}
else if (strcmp (key, "retry-delay") == 0) {
- if (sscanf (value, "%d", &initial_delay) != 1 || initial_delay <= 0) {
- nbdkit_error ("cannot parse retry-delay: %s", value);
+ if (nbdkit_parse_unsigned ("retry-delay", value, &initial_delay) == -1)
+ return -1;
+ if (initial_delay == 0) {
+ nbdkit_error ("retry-delay cannot be 0");
return -1;
}
return 0;
diff --git a/filters/xz/xz.c b/filters/xz/xz.c
index a420d38..3a030c6 100644
--- a/filters/xz/xz.c
+++ b/filters/xz/xz.c
@@ -63,18 +63,12 @@ xz_config (nbdkit_next_config *next, void *nxdata,
return 0;
}
else if (strcmp (key, "xz-max-depth") == 0) {
- size_t r;
-
- if (sscanf (value, "%zu", &r) != 1) {
- nbdkit_error ("could not parse 'xz-max-depth' parameter");
+ if (nbdkit_parse_size_t ("xz-max-depth", value, &maxdepth) == -1)
return -1;
- }
- if (r == 0) {
+ if (maxdepth == 0) {
nbdkit_error ("'xz-max-depth' parameter must be >= 1");
return -1;
}
-
- maxdepth = r;
return 0;
}
else
diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h
index aac63fb..274da8c 100644
--- a/include/nbdkit-common.h
+++ b/include/nbdkit-common.h
@@ -84,6 +84,28 @@ extern void nbdkit_vdebug (const char *msg, va_list args);
extern char *nbdkit_absolute_path (const char *path);
extern int64_t nbdkit_parse_size (const char *str);
extern int nbdkit_parse_bool (const char *str);
+extern int nbdkit_parse_int (const char *what, const char *str,
+ int *r);
+extern int nbdkit_parse_unsigned (const char *what, const char *str,
+ unsigned *r);
+extern int nbdkit_parse_long (const char *what, const char *str,
+ long *r);
+extern int nbdkit_parse_unsigned_long (const char *what, const char *str,
+ unsigned long *r);
+extern int nbdkit_parse_int16_t (const char *what, const char *str,
+ int16_t *r);
+extern int nbdkit_parse_uint16_t (const char *what, const char *str,
+ uint16_t *r);
+extern int nbdkit_parse_int32_t (const char *what, const char *str,
+ int32_t *r);
+extern int nbdkit_parse_uint32_t (const char *what, const char *str,
+ uint32_t *r);
+extern int nbdkit_parse_int64_t (const char *what, const char *str,
+ int64_t *r);
+extern int nbdkit_parse_uint64_t (const char *what, const char *str,
+ uint64_t *r);
+extern int nbdkit_parse_ssize_t (const char *what, const char *str, ssize_t *r);
+extern int nbdkit_parse_size_t (const char *what, const char *str, size_t *r);
extern int nbdkit_read_password (const char *value, char **password);
extern char *nbdkit_realpath (const char *path);
extern int nbdkit_nanosleep (unsigned sec, unsigned nsec);
diff --git a/plugins/curl/curl.c b/plugins/curl/curl.c
index 0ed3984..be087ca 100644
--- a/plugins/curl/curl.c
+++ b/plugins/curl/curl.c
@@ -204,7 +204,9 @@ curl_config (const char *key, const char *value)
}
else if (strcmp (key, "timeout") == 0) {
- if (sscanf (value, "%ld", &timeout) != 1 || timeout < 0) {
+ if (nbdkit_parse_long ("timeout", value, &timeout) == -1)
+ return -1;
+ if (timeout < 0) {
nbdkit_error ("'timeout' must be 0 or a positive timeout in seconds");
return -1;
}
diff --git a/plugins/nbd/nbd-standalone.c b/plugins/nbd/nbd-standalone.c
index 1468098..0fabbfe 100644
--- a/plugins/nbd/nbd-standalone.c
+++ b/plugins/nbd/nbd-standalone.c
@@ -102,7 +102,7 @@ static char *servname;
static const char *export;
/* Number of retries */
-static unsigned long retry;
+static unsigned retry;
/* True to share single server connection among all clients */
static bool shared;
@@ -128,7 +128,6 @@ nbd_unload (void)
static int
nbd_config (const char *key, const char *value)
{
- char *end;
int r;
if (strcmp (key, "socket") == 0) {
@@ -145,12 +144,8 @@ nbd_config (const char *key, const char *value)
else if (strcmp (key, "export") == 0)
export = value;
else if (strcmp (key, "retry") == 0) {
- errno = 0;
- retry = strtoul (value, &end, 0);
- if (value == end || errno) {
- nbdkit_error ("could not parse retry as integer (%s)", value);
+ if (nbdkit_parse_unsigned ("retry", value, &retry) == -1)
return -1;
- }
}
else if (strcmp (key, "shared") == 0) {
r = nbdkit_parse_bool (value);
diff --git a/plugins/nbd/nbd.c b/plugins/nbd/nbd.c
index cddcfde..3215636 100644
--- a/plugins/nbd/nbd.c
+++ b/plugins/nbd/nbd.c
@@ -89,7 +89,7 @@ static const char *uri;
static const char *export;
/* Number of retries */
-static unsigned long retry;
+static unsigned retry;
/* True to share single server connection among all clients */
static bool shared;
@@ -124,7 +124,6 @@ nbdplug_unload (void)
static int
nbdplug_config (const char *key, const char *value)
{
- char *end;
int r;
if (strcmp (key, "socket") == 0) {
@@ -143,12 +142,8 @@ nbdplug_config (const char *key, const char *value)
else if (strcmp (key, "export") == 0)
export = value;
else if (strcmp (key, "retry") == 0) {
- errno = 0;
- retry = strtoul (value, &end, 0);
- if (value == end || errno) {
- nbdkit_error ("could not parse retry as integer (%s)", value);
+ if (nbdkit_parse_unsigned ("retry", value, &retry) == -1)
return -1;
- }
}
else if (strcmp (key, "shared") == 0) {
r = nbdkit_parse_bool (value);
diff --git a/plugins/partitioning/partitioning.c b/plugins/partitioning/partitioning.c
index 0b4e66b..05f9ad3 100644
--- a/plugins/partitioning/partitioning.c
+++ b/plugins/partitioning/partitioning.c
@@ -211,10 +211,8 @@ partitioning_config (const char *key, const char *value)
else if (strcmp (key, "mbr-id") == 0) {
if (strcasecmp (value, "default") == 0)
mbr_id = DEFAULT_MBR_ID;
- else if (sscanf (value, "%i", &mbr_id) != 1) {
- nbdkit_error ("could not parse mbr-id: %s", value);
+ else if (nbdkit_parse_int ("mbr-id", value, &mbr_id) == -1)
return -1;
- }
}
else if (strcmp (key, "type-guid") == 0) {
if (strcasecmp (value, "default") == 0)
diff --git a/plugins/random/random.c b/plugins/random/random.c
index 6377310..cdebdf9 100644
--- a/plugins/random/random.c
+++ b/plugins/random/random.c
@@ -67,10 +67,8 @@ random_config (const char *key, const char *value)
int64_t r;
if (strcmp (key, "seed") == 0) {
- if (sscanf (value, "%" SCNu32, &seed) != 1) {
- nbdkit_error ("could not parse seed parameter");
+ if (nbdkit_parse_uint32_t ("seed", value, &seed) == -1)
return -1;
- }
}
else if (strcmp (key, "size") == 0) {
r = nbdkit_parse_size (value);
diff --git a/plugins/ssh/ssh.c b/plugins/ssh/ssh.c
index ee42ee1..6fc6ed0 100644
--- a/plugins/ssh/ssh.c
+++ b/plugins/ssh/ssh.c
@@ -59,7 +59,7 @@ static bool verify_remote_host = true;
static const char *known_hosts = NULL;
static const char **identity = NULL;
static size_t nr_identities = 0;
-static long timeout = 0;
+static unsigned long timeout = 0;
/* config can be:
* NULL => parse options from default file
@@ -151,10 +151,8 @@ ssh_config (const char *key, const char *value)
}
else if (strcmp (key, "timeout") == 0) {
- if (sscanf (value, "%ld", &timeout) != 1) {
- nbdkit_error ("cannot parse timeout: %s", value);
+ if (nbdkit_parse_unsigned_long ("timeout", value, &timeout) == -1)
return -1;
- }
}
else {
diff --git a/plugins/vddk/vddk.c b/plugins/vddk/vddk.c
index 8ea05b1..2e56b4a 100644
--- a/plugins/vddk/vddk.c
+++ b/plugins/vddk/vddk.c
@@ -271,10 +271,8 @@ vddk_config (const char *key, const char *value)
return -1;
}
else if (strcmp (key, "nfchostport") == 0) {
- if (sscanf (value, "%d", &nfc_host_port) != 1) {
- nbdkit_error ("cannot parse nfchostport: %s", value);
+ if (nbdkit_parse_int ("nfchostport", value, &nfc_host_port) == -1)
return -1;
- }
}
else if (strcmp (key, "password") == 0) {
free (password);
@@ -282,10 +280,8 @@ vddk_config (const char *key, const char *value)
return -1;
}
else if (strcmp (key, "port") == 0) {
- if (sscanf (value, "%d", &port) != 1) {
- nbdkit_error ("cannot parse port: %s", value);
+ if (nbdkit_parse_int ("port", value, &port) == -1)
return -1;
- }
}
else if (strcmp (key, "server") == 0) {
server_name = value;
diff --git a/server/internal.h b/server/internal.h
index 043a13d..fbabce6 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -98,7 +98,7 @@ extern bool read_only;
extern const char *run;
extern bool listen_stdin;
extern const char *selinux_label;
-extern int threads;
+extern unsigned threads;
extern int tls;
extern const char *tls_certificates_dir;
extern const char *tls_psk;
diff --git a/server/main.c b/server/main.c
index d433c1f..975716d 100644
--- a/server/main.c
+++ b/server/main.c
@@ -76,7 +76,7 @@ bool read_only; /* -r */
const char *run; /* --run */
bool listen_stdin; /* -s */
const char *selinux_label; /* --selinux-label */
-int threads; /* -t */
+unsigned threads; /* -t */
int tls; /* --tls : 0=off 1=on 2=require */
const char *tls_certificates_dir; /* --tls-certificates */
const char *tls_psk; /* --tls-psk */
@@ -149,7 +149,6 @@ main (int argc, char *argv[])
} *filter_filenames = NULL;
size_t i;
const char *magic_config_key;
- char *end;
/* Refuse to run if stdin/out/err are closed, whether or not -s is used. */
if (fcntl (STDERR_FILENO, F_GETFL) == -1) {
@@ -217,7 +216,8 @@ main (int argc, char *argv[])
if (!flag->name) goto debug_flag_perror;
flag->flag = strndup (p, q-p-1);
if (!flag->flag) goto debug_flag_perror;
- if (sscanf (q, "%d", &flag->value) != 1) goto bad_debug_flag;
+ if (nbdkit_parse_int ("flag", q, &flag->value) == -1)
+ goto bad_debug_flag;
flag->used = false;
/* Add flag to the linked list. */
@@ -351,13 +351,9 @@ main (int argc, char *argv[])
break;
case MASK_HANDSHAKE_OPTION:
- errno = 0;
- mask_handshake = strtoul (optarg, &end, 0);
- if (errno || *end) {
- fprintf (stderr, "%s: cannot parse '%s' into mask-handshake\n",
- program_name, optarg);
+ if (nbdkit_parse_unsigned ("mask-handshake",
+ optarg, &mask_handshake) == -1)
exit (EXIT_FAILURE);
- }
break;
case 'n':
@@ -401,13 +397,8 @@ main (int argc, char *argv[])
break;
case 't':
- errno = 0;
- threads = strtoul (optarg, &end, 0);
- if (errno || *end) {
- fprintf (stderr, "%s: cannot parse '%s' into threads\n",
- program_name, optarg);
+ if (nbdkit_parse_unsigned ("threads", optarg, &threads) == -1)
exit (EXIT_FAILURE);
- }
/* XXX Worth a maximimum limit on threads? */
break;
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index d792a5f..3bf62e8 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -49,7 +49,19 @@
nbdkit_get_extent;
nbdkit_nanosleep;
nbdkit_parse_bool;
+ nbdkit_parse_int16_t;
+ nbdkit_parse_int32_t;
+ nbdkit_parse_int64_t;
+ nbdkit_parse_int;
+ nbdkit_parse_long;
nbdkit_parse_size;
+ nbdkit_parse_size_t;
+ nbdkit_parse_ssize_t;
+ nbdkit_parse_uint16_t;
+ nbdkit_parse_uint32_t;
+ nbdkit_parse_uint64_t;
+ nbdkit_parse_unsigned;
+ nbdkit_parse_unsigned_long;
nbdkit_peer_name;
nbdkit_read_password;
nbdkit_realpath;
diff --git a/server/public.c b/server/public.c
index d0d9ff4..fc097d2 100644
--- a/server/public.c
+++ b/server/public.c
@@ -45,6 +45,7 @@
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#include <ctype.h>
#include <termios.h>
#include <errno.h>
#include <poll.h>
@@ -108,6 +109,223 @@ nbdkit_realpath (const char *path)
return ret;
}
+/* Common code for parsing integers. */
+#define PARSE_COMMON_TAIL \
+ if (errno != 0) { \
+ nbdkit_error ("%s: could not parse number: \"%s\": %m", \
+ what, str); \
+ return -1; \
+ } \
+ if (end == str) { \
+ nbdkit_error ("%s: empty string where we expected a number", \
+ what); \
+ return -1; \
+ } \
+ if (*end) { \
+ nbdkit_error ("%s: could not parse number: \"%s\": trailing garbage", \
+ what, str); \
+ return -1; \
+ } \
+ \
+ if (rp) \
+ *rp = r; \
+ return 0
+
+/* Functions for parsing signed integers. */
+int
+nbdkit_parse_int (const char *what, const char *str, int *rp)
+{
+ long r;
+ char *end;
+
+ errno = 0;
+ r = strtol (str, &end, 0);
+#if INT_MAX != LONG_MAX
+ if (r < INT_MIN || r > INT_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_long (const char *what, const char *str, long *rp)
+{
+ long r;
+ char *end;
+
+ errno = 0;
+ r = strtol (str, &end, 0);
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_int16_t (const char *what, const char *str, int16_t *rp)
+{
+ long r;
+ char *end;
+
+ errno = 0;
+ r = strtol (str, &end, 0);
+ if (r < INT16_MIN || r > INT16_MAX)
+ errno = ERANGE;
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_int32_t (const char *what, const char *str, int32_t *rp)
+{
+ long r;
+ char *end;
+
+ errno = 0;
+ r = strtol (str, &end, 0);
+#if INT32_MAX != LONG_MAX
+ if (r < INT32_MIN || r > INT32_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_int64_t (const char *what, const char *str, int64_t *rp)
+{
+ long long r;
+ char *end;
+
+ errno = 0;
+ r = strtoll (str, &end, 0);
+#if INT64_MAX != LONGLONG_MAX
+ if (r < INT64_MIN || r > INT64_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_ssize_t (const char *what, const char *str, ssize_t *rp)
+{
+ long long r;
+ char *end;
+
+ errno = 0;
+ r = strtoll (str, &end, 0);
+#if SSIZE_MAX != LONGLONG_MAX
+#ifndef SSIZE_MIN
+#define SSIZE_MIN (-SSIZE_MAX-1)
+#endif
+ if (r < SSIZE_MIN || r > SSIZE_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+/* Functions for parsing unsigned integers. */
+
+/* strtou* functions have surprising behaviour if the first character
+ * (after whitespace) is '-', so deny this.
+ */
+#define PARSE_ERROR_IF_NEGATIVE \
+ do { \
+ const char *p = str; \
+ while (isspace (*p)) \
+ p++; \
+ if (*p == '-') { \
+ nbdkit_error ("%s: negative numbers are not allowed", what); \
+ return -1; \
+ } \
+ } while (0)
+
+int
+nbdkit_parse_unsigned (const char *what, const char *str, unsigned *rp)
+{
+ unsigned long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoul (str, &end, 0);
+#if UINT_MAX != ULONG_MAX
+ if (r > UINT_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_unsigned_long (const char *what, const char *str,
+ unsigned long *rp)
+{
+ unsigned long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoul (str, &end, 0);
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_uint16_t (const char *what, const char *str, uint16_t *rp)
+{
+ unsigned long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoul (str, &end, 0);
+ if (r > UINT16_MAX)
+ errno = ERANGE;
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_uint32_t (const char *what, const char *str, uint32_t *rp)
+{
+ unsigned long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoul (str, &end, 0);
+#if UINT32_MAX != ULONG_MAX
+ if (r > UINT32_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_uint64_t (const char *what, const char *str, uint64_t *rp)
+{
+ unsigned long long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoull (str, &end, 0);
+#if UINT64_MAX != ULONGLONG_MAX
+ if (r > UINT64_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
+int
+nbdkit_parse_size_t (const char *what, const char *str, size_t *rp)
+{
+ unsigned long long r;
+ char *end;
+
+ PARSE_ERROR_IF_NEGATIVE;
+ errno = 0;
+ r = strtoull (str, &end, 0);
+#if SIZE_MAX != ULONGLONG_MAX
+ if (r > SIZE_MAX)
+ errno = ERANGE;
+#endif
+ PARSE_COMMON_TAIL;
+}
+
/* Parse a string as a size with possible scaling suffix, or return -1
* after reporting the error.
*/
diff --git a/server/socket-activation.c b/server/socket-activation.c
index b9db67c..50df4ca 100644
--- a/server/socket-activation.c
+++ b/server/socket-activation.c
@@ -59,11 +59,8 @@ get_socket_activation (void)
s = getenv ("LISTEN_PID");
if (s == NULL)
return 0;
- if (sscanf (s, "%u", &pid) != 1) {
- fprintf (stderr, "%s: malformed %s environment variable (ignored)\n",
- program_name, "LISTEN_PID");
+ if (nbdkit_parse_unsigned ("LISTEN_PID", s, &pid) == -1)
return 0;
- }
if (pid != getpid ()) {
fprintf (stderr, "%s: %s was not for us (ignored)\n",
program_name, "LISTEN_PID");
@@ -73,11 +70,8 @@ get_socket_activation (void)
s = getenv ("LISTEN_FDS");
if (s == NULL)
return 0;
- if (sscanf (s, "%u", &nr_fds) != 1) {
- fprintf (stderr, "%s: malformed %s environment variable (ignored)\n",
- program_name, "LISTEN_FDS");
+ if (nbdkit_parse_unsigned ("LISTEN_FDS", s, &nr_fds) == -1)
return 0;
- }
/* So these are not passed to any child processes we might start. */
unsetenv ("LISTEN_FDS");
diff --git a/server/test-public.c b/server/test-public.c
index 4a01936..cd35434 100644
--- a/server/test-public.c
+++ b/server/test-public.c
@@ -33,10 +33,14 @@
#include <config.h>
#include <stdio.h>
-#include <inttypes.h>
+#include <stdlib.h>
#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <limits.h>
#include <string.h>
#include <unistd.h>
+#include <assert.h>
#include "internal.h"
@@ -153,6 +157,180 @@ test_nbdkit_parse_size (void)
return pass;
}
+static bool
+test_nbdkit_parse_ints (void)
+{
+ bool pass = true;
+ char s[64];
+
+#define PARSE(TYPE, FORMAT, TEST, RET, EXPECTED) \
+ do { \
+ error_flagged = false; \
+ TYPE i = 0; \
+ int r = nbdkit_parse_##TYPE ("test", TEST, &i); \
+ if (r != RET || i != EXPECTED) { \
+ fprintf (stderr, \
+ "%s: %d: wrong parse for %s: r=%d i=" FORMAT "\n", \
+ __FILE__, __LINE__, TEST, r, i); \
+ pass = false; \
+ } \
+ if ((r == -1) != error_flagged) { \
+ fprintf (stderr, \
+ "%s: %d: wrong error message handling for %s\n", \
+ __FILE__, __LINE__, TEST); \
+ pass = false; \
+ } \
+ } while (0)
+#define OK 0
+#define BAD -1
+
+ /* Test the basic parsing of decimals, hexadecimal, octal and
+ * negative numbers.
+ */
+ PARSE (int, "%d", "0", OK, 0);
+ PARSE (int, "%d", "1", OK, 1);
+ PARSE (int, "%d", "99", OK, 99);
+ PARSE (int, "%d", "0x1", OK, 1);
+ PARSE (int, "%d", "0xf", OK, 15);
+ PARSE (int, "%d", "0x10", OK, 16);
+ PARSE (int, "%d", "0xff", OK, 255);
+ PARSE (int, "%d", "01", OK, 1);
+ PARSE (int, "%d", "07", OK, 7);
+ PARSE (int, "%d", "010", OK, 8);
+ PARSE (int, "%d", "+0", OK, 0);
+ PARSE (int, "%d", "+99", OK, 99);
+ PARSE (int, "%d", "+0xf", OK, 15);
+ PARSE (int, "%d", "+010", OK, 8);
+ PARSE (int, "%d", "-0", OK, 0);
+ PARSE (int, "%d", "-99", OK, -99);
+ PARSE (int, "%d", "-0xf", OK, -15);
+ PARSE (int, "%d", "-010", OK, -8);
+ PARSE (int, "%d", "2147483647", OK, 2147483647); /* INT_MAX */
+ PARSE (int, "%d", "-2147483648", OK, -2147483648); /* INT_MIN */
+ PARSE (int, "%d", "0x7fffffff", OK, 0x7fffffff);
+ PARSE (int, "%d", "-0x80000000", OK, -0x80000000);
+
+ /* Test basic error handling. */
+ PARSE (int, "%d", "", BAD, 0);
+ PARSE (int, "%d", "-", BAD, 0);
+ PARSE (int, "%d", "+", BAD, 0);
+ PARSE (int, "%d", "++", BAD, 0);
+ PARSE (int, "%d", "++0", BAD, 0);
+ PARSE (int, "%d", "--0", BAD, 0);
+ PARSE (int, "%d", "0x", BAD, 0);
+ PARSE (int, "%d", "42x", BAD, 0);
+ PARSE (int, "%d", "42-", BAD, 0);
+ PARSE (int, "%d", "garbage", BAD, 0);
+ PARSE (int, "%d", "2147483648", BAD, 0); /* INT_MAX + 1 */
+ PARSE (int, "%d", "-2147483649", BAD, 0); /* INT_MIN - 1 */
+ PARSE (int, "%d", "999999999999999999999999", BAD, 0);
+ PARSE (int, "%d", "-999999999999999999999999", BAD, 0);
+
+ /* Test nbdkit_parse_unsigned. */
+ PARSE (unsigned, "%u", "0", OK, 0);
+ PARSE (unsigned, "%u", "1", OK, 1);
+ PARSE (unsigned, "%u", "99", OK, 99);
+ PARSE (unsigned, "%u", "0x1", OK, 1);
+ PARSE (unsigned, "%u", "0xf", OK, 15);
+ PARSE (unsigned, "%u", "0x10", OK, 16);
+ PARSE (unsigned, "%u", "0xff", OK, 255);
+ PARSE (unsigned, "%u", "01", OK, 1);
+ PARSE (unsigned, "%u", "07", OK, 7);
+ PARSE (unsigned, "%u", "010", OK, 8);
+ PARSE (unsigned, "%u", "+0", OK, 0);
+ PARSE (unsigned, "%u", "+99", OK, 99);
+ PARSE (unsigned, "%u", "+0xf", OK, 15);
+ PARSE (unsigned, "%u", "+010", OK, 8);
+ PARSE (unsigned, "%u", "-0", BAD, 0);
+ PARSE (unsigned, "%u", "-99", BAD, 0);
+ PARSE (unsigned, "%u", "-0xf", BAD, 0);
+ PARSE (unsigned, "%u", "-010", BAD, 0);
+ PARSE (unsigned, "%u", "2147483647", OK, 2147483647); /* INT_MAX */
+ PARSE (unsigned, "%u", "-2147483648", BAD, 0); /* INT_MIN */
+ PARSE (unsigned, "%u", "0x7fffffff", OK, 0x7fffffff);
+ PARSE (unsigned, "%u", "-0x80000000", BAD, 0);
+
+ /* Test nbdkit_parse_long. */
+ PARSE (long, "%ld", "0", OK, 0);
+ assert (snprintf (s, sizeof s, "%" PRIi64, (int64_t) LONG_MAX) != -1);
+ PARSE (long, "%ld", s, OK, LONG_MAX);
+ assert (snprintf (s, sizeof s, "%" PRIi64, (int64_t) LONG_MIN) != -1);
+ PARSE (long, "%ld", s, OK, LONG_MIN);
+ PARSE (long, "%ld", "999999999999999999999999", BAD, 0);
+ PARSE (long, "%ld", "-999999999999999999999999", BAD, 0);
+
+ /* Test nbdkit_parse_unsigned_long. */
+ typedef unsigned long unsigned_long;
+ PARSE (unsigned_long, "%lu", "0", OK, 0);
+ assert (snprintf (s, sizeof s, "%" PRIu64, (uint64_t) ULONG_MAX) != -1);
+ PARSE (unsigned_long, "%lu", s, OK, ULONG_MAX);
+ PARSE (unsigned_long, "%lu", "999999999999999999999999", BAD, 0);
+ PARSE (unsigned_long, "%lu", "-1", BAD, 0);
+
+ /* Test nbdkit_parse_int16_t. */
+ PARSE (int16_t, "%" PRIi16, "0", OK, 0);
+ PARSE (int16_t, "%" PRIi16, "0x7fff", OK, 0x7fff);
+ PARSE (int16_t, "%" PRIi16, "-0x8000", OK, -0x8000);
+ PARSE (int16_t, "%" PRIi16, "0x8000", BAD, 0);
+ PARSE (int16_t, "%" PRIi16, "-0x8001", BAD, 0);
+
+ /* Test nbdkit_parse_uint16_t. */
+ PARSE (uint16_t, "%" PRIu16, "0", OK, 0);
+ PARSE (uint16_t, "%" PRIu16, "0xffff", OK, 0xffff);
+ PARSE (uint16_t, "%" PRIu16, "0x10000", BAD, 0);
+ PARSE (uint16_t, "%" PRIu16, "-1", BAD, 0);
+
+ /* Test nbdkit_parse_int32_t. */
+ PARSE (int32_t, "%" PRIi32, "0", OK, 0);
+ PARSE (int32_t, "%" PRIi32, "0x7fffffff", OK, 0x7fffffff);
+ PARSE (int32_t, "%" PRIi32, "-0x80000000", OK, -0x80000000);
+ PARSE (int32_t, "%" PRIi32, "0x80000000", BAD, 0);
+ PARSE (int32_t, "%" PRIi32, "-0x80000001", BAD, 0);
+
+ /* Test nbdkit_parse_uint32_t. */
+ PARSE (uint32_t, "%" PRIu32, "0", OK, 0);
+ PARSE (uint32_t, "%" PRIu32, "0xffffffff", OK, 0xffffffff);
+ PARSE (uint32_t, "%" PRIu32, "0x100000000", BAD, 0);
+ PARSE (uint32_t, "%" PRIu32, "-1", BAD, 0);
+
+ /* Test nbdkit_parse_int64_t. */
+ PARSE (int64_t, "%" PRIi64, "0", OK, 0);
+ PARSE (int64_t, "%" PRIi64, "0x7fffffffffffffff", OK, 0x7fffffffffffffff);
+ PARSE (int64_t, "%" PRIi64, "-0x8000000000000000", OK, -0x8000000000000000);
+ PARSE (int64_t, "%" PRIi64, "0x8000000000000000", BAD, 0);
+ PARSE (int64_t, "%" PRIi64, "-0x8000000000000001", BAD, 0);
+
+ /* Test nbdkit_parse_uint64_t. */
+ PARSE (uint64_t, "%" PRIu64, "0", OK, 0);
+ PARSE (uint64_t, "%" PRIu64, "0xffffffffffffffff", OK, 0xffffffffffffffff);
+ PARSE (uint64_t, "%" PRIu64, "0x10000000000000000", BAD, 0);
+ PARSE (uint64_t, "%" PRIu64, "-1", BAD, 0);
+
+ /* Test nbdkit_parse_ssize_t. */
+ PARSE (ssize_t, "%zd", "0", OK, 0);
+ assert (snprintf (s, sizeof s, "%" PRIi64, (int64_t) SSIZE_MAX) != -1);
+ PARSE (ssize_t, "%zd", s, OK, SSIZE_MAX);
+#ifndef SSIZE_MIN
+#define SSIZE_MIN (-SSIZE_MAX-1)
+#endif
+ assert (snprintf (s, sizeof s, "%" PRIi64, (int64_t) SSIZE_MIN) != -1);
+ PARSE (ssize_t, "%zd", s, OK, SSIZE_MIN);
+ PARSE (ssize_t, "%zd", "999999999999999999999999", BAD, 0);
+ PARSE (ssize_t, "%zd", "-999999999999999999999999", BAD, 0);
+
+ /* Test nbdkit_parse_size_t. */
+ PARSE (size_t, "%zu", "0", OK, 0);
+ assert (snprintf (s, sizeof s, "%" PRIu64, (uint64_t) SIZE_MAX) != -1);
+ PARSE (size_t, "%zu", s, OK, SIZE_MAX);
+ PARSE (size_t, "%zu", "999999999999999999999999", BAD, 0);
+ PARSE (size_t, "%zu", "-1", BAD, 0);
+
+#undef PARSE
+#undef OK
+#undef BAD
+ return pass;
+}
+
static bool
test_nbdkit_read_password (void)
{
@@ -228,6 +406,7 @@ main (int argc, char *argv[])
{
bool pass = true;
pass &= test_nbdkit_parse_size ();
+ pass &= test_nbdkit_parse_ints ();
pass &= test_nbdkit_read_password ();
/* nbdkit_absolute_path and nbdkit_nanosleep not unit-tested here, but
* get plenty of coverage in the main testsuite.
diff --git a/server/usergroup.c b/server/usergroup.c
index 719c816..11bafce 100644
--- a/server/usergroup.c
+++ b/server/usergroup.c
@@ -97,7 +97,7 @@ parseuser (const char *id)
saved_errno = errno;
- if (sscanf (id, "%d", &val) == 1)
+ if (nbdkit_parse_int ("parseuser", id, &val) == 0)
return val;
fprintf (stderr, "%s: -u option: %s is not a valid user name or uid",
@@ -125,7 +125,7 @@ parsegroup (const char *id)
saved_errno = errno;
- if (sscanf (id, "%d", &val) == 1)
+ if (nbdkit_parse_int ("parsegroup", id, &val) == 0)
return val;
fprintf (stderr, "%s: -g option: %s is not a valid group name or gid",
--
2.23.0
5 years, 1 month
[PATCH nbdkit] docs: Suggest how to detect if a filter is installed.
by Richard W.M. Jones
Thanks: Eric Blake, Martin Kletzander.
---
docs/nbdkit-probing.pod | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/docs/nbdkit-probing.pod b/docs/nbdkit-probing.pod
index 94bdfb4..46a7c47 100644
--- a/docs/nbdkit-probing.pod
+++ b/docs/nbdkit-probing.pod
@@ -80,6 +80,17 @@ installed. A complete shell script which does this is:
fi
done
+=head2 Detect if a filter is installed
+
+To find out if a filter is installed (and working) use
+I<--dump-plugin> with the C<null> plugin and the name of the filter to
+test:
+
+ nbdkit --dump-plugin --filter=foo null
+
+This will fail with an error and non-zero exit code if the C<foo>
+filter cannot be loaded.
+
=head1 SEE ALSO
L<nbdkit(1)>.
--
2.23.0
5 years, 1 month
[nbdkit PATCH] curl: Compile with libcurl even without smb(s) protocols
by Martin Kletzander
I needed to compile nbdkit on CentOS 7 which is missing these protocols in curl,
so hence the conditional compilation.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
I have this patch so that I can compile it on CentOS 7 (fully updated), but I'm
not sure what is the support policy and I didn't even check whether the libcurl
there is old or whether the SMB support is removed on purpose.
plugins/curl/curl.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/plugins/curl/curl.c b/plugins/curl/curl.c
index 7e3e8c923721..acd3333d5b88 100644
--- a/plugins/curl/curl.c
+++ b/plugins/curl/curl.c
@@ -118,8 +118,12 @@ static struct { const char *name; long bitmask; } curl_protocols[] = {
{ "rtmps", CURLPROTO_RTMPS },
{ "rtmpts", CURLPROTO_RTMPTS },
{ "gopher", CURLPROTO_GOPHER },
+#ifdef CURLPROTO_SMB
{ "smb", CURLPROTO_SMB },
+#endif /* CURLPROTO_SMB */
+#ifdef CURLPROTO_SMBS
{ "smbs", CURLPROTO_SMBS },
+#endif /* CURLPROTO_SMBS */
{ NULL }
};
--
2.23.0
5 years, 1 month
[PATCH 1/2] v2v: add optional tmpdir parameter for Python_script
by Pino Toscano
Add an optional parameter for Python_script.create, to specific the
temporary directory to use instead of creating a new one.
---
v2v/python_script.ml | 13 ++++++++-----
v2v/python_script.mli | 5 ++++-
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/v2v/python_script.ml b/v2v/python_script.ml
index 3159373a1..6bb14ec1f 100644
--- a/v2v/python_script.ml
+++ b/v2v/python_script.ml
@@ -31,12 +31,15 @@ type script = {
path : string; (* Path to script. *)
}
-let create ?(name = "script.py") code =
+let create ?(name = "script.py") ?tmpdir code =
let tmpdir =
- let base_dir = (open_guestfs ())#get_cachedir () in
- let t = Mkdtemp.temp_dir ~base_dir "v2v." in
- rmdir_on_exit t;
- t in
+ match tmpdir with
+ | None ->
+ let base_dir = (open_guestfs ())#get_cachedir () in
+ let t = Mkdtemp.temp_dir ~base_dir "v2v." in
+ rmdir_on_exit t;
+ t
+ | Some dir -> dir in
let path = tmpdir // name in
with_open_out path (fun chan -> output_string chan code);
{ tmpdir; path }
diff --git a/v2v/python_script.mli b/v2v/python_script.mli
index c008eec1a..496ac60d0 100644
--- a/v2v/python_script.mli
+++ b/v2v/python_script.mli
@@ -20,11 +20,14 @@
type script
-val create : ?name:string -> string -> script
+val create : ?name:string -> ?tmpdir:string -> string -> script
(** Create a Python script object.
The optional parameter [?name] is a hint for the name of the script.
+ The optional parameter [?tmpdir] is the temporary directory to use
+ (instead of creating a new one).
+
The parameter is the Python code. Usually this is
[Some_source.code] where [some_source.ml] is generated from
the Python file by [v2v/embed.sh] (see also [v2v/Makefile.am]). *)
--
2.21.0
5 years, 1 month
[PATCH] v2v: Use cacheextents if possible for vddk input
by Martin Kletzander
It does not need configuring and speeds up the process of requesting extents if
the client asks for them one by one (like qemu-img).
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
v2v/input_libvirt_vddk.ml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/v2v/input_libvirt_vddk.ml b/v2v/input_libvirt_vddk.ml
index a8e4fd5ac78e..cc63f77ce825 100644
--- a/v2v/input_libvirt_vddk.ml
+++ b/v2v/input_libvirt_vddk.ml
@@ -284,6 +284,9 @@ object (self)
add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_socket_t:s0"
);
+ if shell_command "nbdkit --filter cacheextents memory 1M --run true 2>/dev/null" = 0
+ then add_arg "--filter=cacheextents";
+
(* Name of the plugin. Everything following is a plugin parameter. *)
add_arg "vddk";
--
2.23.0
5 years, 1 month