Message ID | 1345463283-9684-4-git-send-email-benoit@irqsave.net |
---|---|
State | New |
Headers | show |
On Mon, Aug 20, 2012 at 11:47 AM, Benoît Canet <benoit.canet@gmail.com> wrote: > Valid quorum resources look like: > quorum:threshold/total:path/to/image_1: ... :path/to/image_total > > '\' can escape the ':' character. > > Signed-off-by: Benoit Canet <benoit@irqsave.net> > --- > block/quorum.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 110 insertions(+) > > diff --git a/block/quorum.c b/block/quorum.c > index 19a9a44..70e7216 100644 > --- a/block/quorum.c > +++ b/block/quorum.c > @@ -52,11 +52,121 @@ struct QuorumAIOCB { > int vote_ret; > }; > > +/* Valid quorum resources look like > + * quorum:threshold/total:path/to/image_1: ... :path/to/image_total > + */ > +static int quorum_open(BlockDriverState *bs, const char *filename, int flags) > +{ > + BDRVQuorumState *s = bs->opaque; > + int i, j, len, ret = 0; > + char *a, *b, *names; > + bool escape; > + > + /* Parse the quorum: prefix */ > + if (strncmp(filename, "quorum:", strlen("quorum:"))) { > + return -EINVAL; > + } > + > + filename += strlen("quorum:"); > + > + /* Get n */ Here's still 'n' instead of threshold. > + errno = 0; > + s->threshold = strtoul(filename, &a, 10); > + if (*a != '/' || errno) { > + return -EINVAL; > + } > + a++; > + > + /* Get m */ Also 'm' here. > + errno = 0; > + s->total = strtoul(a, &b, 10); > + if (*b != ':' || errno) { > + return -EINVAL; > + } > + b++; > + > + if (s->threshold < 1 || s->total < 2) { > + return -EINVAL; > + } > + > + if (s->threshold > s->total) { > + return -EINVAL; > + } > + > + s->bs = g_malloc0(sizeof(BlockDriverState *) * s->total); > + /* Two allocations for all filenames: simpler to free */ > + s->filenames = g_malloc0(sizeof(char *) * s->total); > + names = g_strdup(b); > + > + /* Get the filenames pointers */ > + escape = false; > + s->filenames[0] = names; > + len = strlen(names); > + for (i = 0, j = 1; i < len && j < s->total; i++) { > + if (!escape && names[i] == ':') { > + names[i] = '\0'; > + s->filenames[j] = names + i + 1; > + j++; > + } > + > + escape = !escape && names[i] == '\\'; > + } > + > + if (j != s->total) { > + ret = -EINVAL; > + goto free_exit; > + } > + > + /* Open files */ > + for (i = 0; i < s->total; i++) { > + s->bs[i] = bdrv_new(""); > + ret = bdrv_open(s->bs[i], s->filenames[i], flags, NULL); > + if (ret < 0) { > + goto error_exit; > + } > + } > + > + goto exit; > + > +error_exit: > + for (; i >= 0; i--) { > + bdrv_delete(s->bs[i]); > + s->bs[i] = NULL; > + } > +free_exit: > + g_free(s->filenames[0]); > + g_free(s->filenames); > + s->filenames = NULL; > + g_free(s->bs); > +exit: > + return ret; > +} > + > +static void quorum_close(BlockDriverState *bs) > +{ > + BDRVQuorumState *s = bs->opaque; > + int i; > + > + for (i = 0; i < s->total; i++) { > + /* Ensure writes reach stable storage */ > + bdrv_flush(s->bs[i]); > + bdrv_delete(s->bs[i]); > + } > + > + g_free(s->filenames[0]); > + g_free(s->filenames); > + s->filenames = NULL; > + g_free(s->bs); > +} > + > static BlockDriver bdrv_quorum = { > .format_name = "quorum", > .protocol_name = "quorum", > > .instance_size = sizeof(BDRVQuorumState), > + > + .bdrv_file_open = quorum_open, > + .bdrv_close = quorum_close, > }; > > static void bdrv_quorum_init(void) > -- > 1.7.9.5 >
On 08/20/2012 01:47 PM, Blue Swirl wrote: > On Mon, Aug 20, 2012 at 11:47 AM, Benoît Canet <benoit.canet@gmail.com> wrote: >> Valid quorum resources look like: >> quorum:threshold/total:path/to/image_1: ... :path/to/image_total >> >> '\' can escape the ':' character. Also, \ escapes itself (although admittedly : is more likely than \ in a file name needing escaping).
Le Monday 20 Aug 2012 à 14:37:08 (-0600), Eric Blake a écrit : > On 08/20/2012 01:47 PM, Blue Swirl wrote: > > On Mon, Aug 20, 2012 at 11:47 AM, Benoît Canet <benoit.canet@gmail.com> wrote: > >> Valid quorum resources look like: > >> quorum:threshold/total:path/to/image_1: ... :path/to/image_total > >> > >> '\' can escape the ':' character. > > Also, \ escapes itself (although admittedly : is more likely than \ in a > file name needing escaping). After a few tests this escaping code seems broken. Will fix it. Benoît > > -- > Eric Blake eblake@redhat.com +1-919-301-3266 > Libvirt virtualization library http://libvirt.org >
diff --git a/block/quorum.c b/block/quorum.c index 19a9a44..70e7216 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -52,11 +52,121 @@ struct QuorumAIOCB { int vote_ret; }; +/* Valid quorum resources look like + * quorum:threshold/total:path/to/image_1: ... :path/to/image_total + */ +static int quorum_open(BlockDriverState *bs, const char *filename, int flags) +{ + BDRVQuorumState *s = bs->opaque; + int i, j, len, ret = 0; + char *a, *b, *names; + bool escape; + + /* Parse the quorum: prefix */ + if (strncmp(filename, "quorum:", strlen("quorum:"))) { + return -EINVAL; + } + + filename += strlen("quorum:"); + + /* Get n */ + errno = 0; + s->threshold = strtoul(filename, &a, 10); + if (*a != '/' || errno) { + return -EINVAL; + } + a++; + + /* Get m */ + errno = 0; + s->total = strtoul(a, &b, 10); + if (*b != ':' || errno) { + return -EINVAL; + } + b++; + + if (s->threshold < 1 || s->total < 2) { + return -EINVAL; + } + + if (s->threshold > s->total) { + return -EINVAL; + } + + s->bs = g_malloc0(sizeof(BlockDriverState *) * s->total); + /* Two allocations for all filenames: simpler to free */ + s->filenames = g_malloc0(sizeof(char *) * s->total); + names = g_strdup(b); + + /* Get the filenames pointers */ + escape = false; + s->filenames[0] = names; + len = strlen(names); + for (i = 0, j = 1; i < len && j < s->total; i++) { + if (!escape && names[i] == ':') { + names[i] = '\0'; + s->filenames[j] = names + i + 1; + j++; + } + + escape = !escape && names[i] == '\\'; + } + + if (j != s->total) { + ret = -EINVAL; + goto free_exit; + } + + /* Open files */ + for (i = 0; i < s->total; i++) { + s->bs[i] = bdrv_new(""); + ret = bdrv_open(s->bs[i], s->filenames[i], flags, NULL); + if (ret < 0) { + goto error_exit; + } + } + + goto exit; + +error_exit: + for (; i >= 0; i--) { + bdrv_delete(s->bs[i]); + s->bs[i] = NULL; + } +free_exit: + g_free(s->filenames[0]); + g_free(s->filenames); + s->filenames = NULL; + g_free(s->bs); +exit: + return ret; +} + +static void quorum_close(BlockDriverState *bs) +{ + BDRVQuorumState *s = bs->opaque; + int i; + + for (i = 0; i < s->total; i++) { + /* Ensure writes reach stable storage */ + bdrv_flush(s->bs[i]); + bdrv_delete(s->bs[i]); + } + + g_free(s->filenames[0]); + g_free(s->filenames); + s->filenames = NULL; + g_free(s->bs); +} + static BlockDriver bdrv_quorum = { .format_name = "quorum", .protocol_name = "quorum", .instance_size = sizeof(BDRVQuorumState), + + .bdrv_file_open = quorum_open, + .bdrv_close = quorum_close, }; static void bdrv_quorum_init(void)
Valid quorum resources look like: quorum:threshold/total:path/to/image_1: ... :path/to/image_total '\' can escape the ':' character. Signed-off-by: Benoit Canet <benoit@irqsave.net> --- block/quorum.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+)