[libvirt] [PATCH] Enhance qemuParseCommandLineKeywords

Daniel P. Berrange berrange at redhat.com
Thu Jan 14 12:35:02 UTC 2010


On Wed, Jan 13, 2010 at 04:48:30PM +0100, Jiri Denemark wrote:
> Current version expects name=value,... list and when an incorrect string
> such as "a,b,c=d" would be parsed as "a,b,c" keyword with "d" value
> without reporting any error, which is probably not the expected
> behavior.
> 
> This patch adds an extra argument called allowEmptyValue, which if
> non-zero will permit keywords with no value; "a,b=c,,d=" will be parsed
> as follows:
>     keyword value
>     "a"     NULL
>     "b"     "c"
>     ""      NULL
>     "d"     ""
> 
> In case allowEmptyValue is zero, the string is required to contain
> name=value pairs only; retvalues is guaranteed to contain non-NULL
> pointers. Now, "a,b,c=d" will result in an error.
> 
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
>  src/qemu/qemu_conf.c |   51 ++++++++++++++++++++++++++++++-------------------
>  1 files changed, 31 insertions(+), 20 deletions(-)
> 
> diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
> index d3da776..9f35217 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -3066,47 +3066,58 @@ static const char *qemuFindEnv(const char **progenv,
>  /*
>   * Takes a string containing a set of key=value,key=value,key...
>   * parameters and splits them up, returning two arrays with
> - * the individual keys and values
> + * the individual keys and values. If allowEmptyValue is nonzero,
> + * the "=value" part is optional and if a key with no value is found,
> + * NULL is be placed into corresponding place in retvalues.
>   */
>  static int
>  qemuParseCommandLineKeywords(virConnectPtr conn,
>                               const char *str,
>                               char ***retkeywords,
> -                             char ***retvalues)
> +                             char ***retvalues,
> +                             int allowEmptyValue)
>  {
>      int keywordCount = 0;
>      int keywordAlloc = 0;
>      char **keywords = NULL;
>      char **values = NULL;
>      const char *start = str;
> +    const char *end;
>      int i;
>  
>      *retkeywords = NULL;
>      *retvalues = NULL;
> +    end = start + strlen(str);
>  
>      while (start) {
>          const char *separator;
>          const char *endmark;
>          char *keyword;
> -        char *value;
> +        char *value = NULL;
>  
> -        if (!(separator = strchr(start, '='))) {
> -            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> -                             _("malformed keyword arguments in '%s'"), str);
> -            goto error;
> +        if (!(endmark = strchr(start, ',')))
> +            endmark = end;
> +        if (!(separator = strchr(start, '=')))
> +            separator = end;
> +
> +        if (separator >= endmark) {
> +            if (!allowEmptyValue) {
> +                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> +                                 _("malformed keyword arguments in '%s'"), str);
> +                goto error;
> +            }
> +            separator = endmark;
>          }
> +
>          if (!(keyword = strndup(start, separator - start)))
>              goto no_memory;
>  
> -        separator++;
> -        endmark = strchr(separator, ',');
> -
> -        value = endmark ?
> -            strndup(separator, endmark - separator) :
> -            strdup(separator);
> -        if (!value) {
> -            VIR_FREE(keyword);
> -            goto no_memory;
> +        if (separator < endmark) {
> +            separator++;
> +            if (!(value = strndup(separator, endmark - separator))) {
> +                VIR_FREE(keyword);
> +                goto no_memory;
> +            }
>          }
>  
>          if (keywordAlloc == keywordCount) {
> @@ -3123,7 +3134,7 @@ qemuParseCommandLineKeywords(virConnectPtr conn,
>          values[keywordCount] = value;
>          keywordCount++;
>  
> -        start = endmark ? endmark + 1 : NULL;
> +        start = endmark < end ? endmark + 1 : NULL;
>      }
>  
>      *retkeywords = keywords;
> @@ -3163,7 +3174,7 @@ qemuParseCommandLineDisk(virConnectPtr conn,
>  
>      if ((nkeywords = qemuParseCommandLineKeywords(conn, val,
>                                                    &keywords,
> -                                                  &values)) < 0)
> +                                                  &values, 0)) < 0)
>          return NULL;
>  
>      if (VIR_ALLOC(def) < 0) {
> @@ -3347,7 +3358,7 @@ qemuParseCommandLineNet(virConnectPtr conn,
>          if ((nkeywords = qemuParseCommandLineKeywords(conn,
>                                                        tmp+1,
>                                                        &keywords,
> -                                                      &values)) < 0)
> +                                                      &values, 0)) < 0)
>              return NULL;
>      } else {
>          nkeywords = 0;
> @@ -3420,7 +3431,7 @@ qemuParseCommandLineNet(virConnectPtr conn,
>          if ((nkeywords = qemuParseCommandLineKeywords(conn,
>                                                        nic + strlen("nic,"),
>                                                        &keywords,
> -                                                      &values)) < 0) {
> +                                                      &values, 0)) < 0) {
>              virDomainNetDefFree(def);
>              def = NULL;
>              goto cleanup;

ACK

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list