[libvirt] [PATCHv2 9/9] phyp: another simplification

Matthias Bolte matthias.bolte at googlemail.com
Sat Apr 16 06:18:16 UTC 2011


2011/4/14 Eric Blake <eblake at redhat.com>:
> Rather than copying and pasting lots of code, factor it into a
> single helper function.
>
> * src/phyp/phyp_driver.c (phypExecInt): New function.
> (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID)
> (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot)
> (phypGetVIOSNextSlotNumber, phypAttachDevice)
> (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes)
> (phypNumOfStoragePools, phypInterfaceDestroy)
> (phypInterfaceDefineXML, phypInterfaceLookupByName)
> (phypInterfaceIsActive, phypNumOfInterfaces): Use it.
> ---
>  src/phyp/phyp_driver.c |  316 ++++++++++--------------------------------------
>  1 files changed, 67 insertions(+), 249 deletions(-)

Okay lets take a look at each instance if stricter parsing is safe or not.

> @@ -267,17 +284,7 @@ phypGetVIOSPartitionID(virConnectPtr conn)
>         virBufferVSprintf(&buf, " -m %s", managed_system);
>     virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env"
>                     "|sed -n '/vioserver/ {\n s/,.*$//\n p\n}'");
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &id);
>     return id;
>  }

In this case I'm not sure that your change is safe. The executed
command looks like it requests a table with two columns
lpar_id,lpar_env and the uses some sed construct to pick the line that
contains "vioserver". Then the lpar_id is parsed from the beginning of
that line. I'm not sure that this sed construct just returns the
number from the beginning of the line. If that is the case that your
stricter parsing it safe. But it looks like that's not that case and
ignoring content after the number in the selected line is important.

> @@ -364,17 +368,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type)
>         virBufferVSprintf(&buf, " -m %s", managed_system);
>     virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'",
>                       state);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &ndom);
>     return ndom;
>  }

Here the stricter parsing will be safe as the last grep returns a count.

But I wonder about the last grep. I thought it would be there to count
the number of lines that start with a number, but it doesn't work:

$ printf "aa\n22\n33\n" | grep -c '^[0-9]*'
3

I expected it to print 2 here.

$ printf "aa\n22\n33\n\n" | grep -c '^[0-9]*'
4

So the '^[0-9]*' pattern matches every line. But

$ printf "aa\n22\n33\n\n" | grep -c '^[0-9]+'
0

So the last grep here is just a wc -l.

> @@ -1298,27 +1292,14 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
>  {
>     phyp_driverPtr phyp_driver = conn->privateData;
>     int system_type = phyp_driver->system_type;
> -    int exit_status = 0;
>     int lpar_id = -1;
> -    char *char_ptr;
> -    char *ret = NULL;
>     virBuffer buf = VIR_BUFFER_INITIALIZER;
>
>     virBufferAddLit(&buf, "lssyscfg -r lpar");
>     if (system_type == HMC)
>         virBufferVSprintf(&buf, " -m %s", managed_system);
>     virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &lpar_id);
>     return lpar_id;
>  }

This one is safe too, as the requested output is just the lpar_id.

> @@ -1397,17 +1375,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
>     virBufferVSprintf(&buf,
>                       " -r mem --level lpar -F %s --filter lpar_ids=%d",
>                       type ? "curr_mem" : "curr_max_mem", lpar_id);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &memory);
>     return memory;
>  }

This one is safe too, as the requested output is just the curr_mem or
curr_max_mem.

> @@ -1431,17 +1396,7 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system,
>     virBufferVSprintf(&buf,
>                       " -r proc --level lpar -F %s --filter lpar_ids=%d",
>                       type ? "curr_max_procs" : "curr_procs", lpar_id);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &vcpus);
>     return vcpus;
>  }

Safe too.

> @@ -1491,17 +1443,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
>         virBufferVSprintf(&buf, " -m %s", managed_system);
>     virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F "
>                       "remote_slot_num --filter lpar_names=%s", lpar_name);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &remote_slot);
>     return remote_slot;
>  }

Safe too.

> @@ -1632,21 +1571,9 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn)
>                       "virtual_serial_adapters|sed -e 's/\"//g' -e "
>                       "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'"
>                       "|sort|tail -n 1", profile);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
> -        goto cleanup;
> -
> -    slot += 1;
> -
> -cleanup:
> -    VIR_FREE(profile);
> -    VIR_FREE(ret);
> -
> -    return slot;
> +    if (phypExecInt(session, &buf, conn, &slot) < 0)
> +        return -1;
> +    return slot + 1;
>  }

Chain of seds transform line of comma separated items into a list of
\n separated items, then strips the trailing non-number part of each
item. Finally sorts the list and takes the last number.

This makes the stricter parsing safe.

> @@ -1859,12 +1785,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml)
>     virBufferVSprintf(&buf,
>                       " slot_num,backing_device|grep %s|cut -d, -f1",
>                       dev->data.disk->src);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
> +    if (phypExecInt(session, &buf, conn, &slot) < 0)
>         goto cleanup;

The cut -d, -f1 makes stricter parsing safe here.

> @@ -1893,10 +1814,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml)
>                       "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'",
>                       domain_name, domain->id, ret, slot,
>                       vios_id, vios_name);
> -    VIR_FREE(ret);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
> +    if (phypExecInt(session, &buf, conn, &slot) < 0)
>         goto cleanup;

There is no filtering of the output before parsing it here. Therefore,
I'm not sure that stricter parsing is safe here.

> @@ -2016,17 +1931,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name)
>         virBufferAddChar(&buf, '\'');
>
>     virBufferVSprintf(&buf, "|sed '1d; s/ //g'");
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &sp_size) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &sp_size);
>     return sp_size;
>  }

Here the stricter parsing might be unsafe.

> @@ -2530,21 +2432,11 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool)
>     if (system_type == HMC)
>         virBufferAddChar(&buf, '\'');
>     virBufferVSprintf(&buf, "|grep -c '^.*$'");
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &nvolumes) == -1)
> -        goto cleanup;
> +    if (phypExecInt(session, &buf, conn, &nvolumes) < 0)
> +        return -1;

Here it's safe because of grep -c, that could be replaced by wc -l, as
it doesn't have a specific pattern.

> @@ -2650,17 +2539,7 @@ phypNumOfStoragePools(virConnectPtr conn)
>         virBufferAddChar(&buf, '\'');
>
>     virBufferVSprintf(&buf, "|grep -c '^.*$'");
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &nsp) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> -
> +    phypExecInt(session, &buf, conn, &nsp);
>     return nsp;
>  }

Safe because of grep -c.

> @@ -2898,17 +2776,10 @@ phypInterfaceDestroy(virInterfacePtr iface,
>                       " -r virtualio --rsubtype eth --level lpar "
>                       " -F mac_addr,slot_num|"
>                       " sed -n '/%s/ s/^.*,//p'", iface->mac);
> -    ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1)
> +    if (phypExecInt(session, &buf, iface->conn, &slot_num) < 0)
>         goto cleanup;

The final sed makes stricter parsing safe here.

> @@ -2917,17 +2788,10 @@ phypInterfaceDestroy(virInterfacePtr iface,
>                       " -r virtualio --rsubtype eth --level lpar "
>                       " -F mac_addr,lpar_id|"
>                       " sed -n '/%s/ s/^.*,//p'", iface->mac);
> -    ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
> +    if (phypExecInt(session, &buf, iface->conn, &lpar_id) < 0)
>         goto cleanup;

Safe too.

> @@ -2980,20 +2843,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml,
>                       " -r virtualio --rsubtype slot --level slot"
>                       " -Fslot_num --filter lpar_names=%s"
>                       " |sort|tail -n 1", def->name);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
> +    if (phypExecInt(session, &buf, conn, &slot) < 0)
>         goto cleanup;

Safe because of -Fslot_num.

> @@ -3094,17 +2949,10 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name)
>                       " -r virtualio --rsubtype slot --level slot "
>                       " -F drc_name,slot_num |"
>                       " sed -n '/%s/ s/^.*,//p'", name);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1)
> +    if (phypExecInt(session, &buf, conn, &slot) < 0)
>         goto cleanup;

Safe too because of the last sed.

>         virBufferVSprintf(&buf, "-m %s ", managed_system);
> @@ -3113,12 +2961,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name)
>                       " -r virtualio --rsubtype slot --level slot "
>                       " -F drc_name,lpar_id |"
>                       " sed -n '/%s/ s/^.*,//p'", name);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1)
> +    if (phypExecInt(session, &buf, conn, &lpar_id) < 0)
>         goto cleanup;

Again, safe too because of the last sed.

> @@ -3167,16 +3006,7 @@ phypInterfaceIsActive(virInterfacePtr iface)
>                       " -r virtualio --rsubtype eth --level lpar "
>                       " -F mac_addr,state |"
>                       " sed -n '/%s/ s/^.*,//p'", iface->mac);
> -    ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> +    phypExecInt(session, &buf, iface->conn, &state);
>     return state;
>  }

Again, safe too because of the last sed.

> @@ -3260,16 +3087,7 @@ phypNumOfInterfaces(virConnectPtr conn)
>     virBufferVSprintf(&buf,
>                       "-r virtualio --rsubtype eth --level lpar|"
>                       "grep -v lpar_id=%d|grep -c lpar_name", vios_id);
> -    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
> -
> -    if (exit_status < 0 || ret == NULL)
> -        goto cleanup;
> -
> -    if (virStrToLong_i(ret, &char_ptr, 10, &nnets) == -1)
> -        goto cleanup;
> -
> -cleanup:
> -    VIR_FREE(ret);
> +    phypExecInt(session, &buf, conn, &nnets);
>     return nnets;
>  }

Safe because of grep -c.

In most cases we can see from the code that stricter parsing will be
safe, but in some places I'm not sure.

So, as long as you don't have a PHYP system at hand to really test it,
I'd suggest that we stick to the relaxed parsing.

Matthias




More information about the libvir-list mailing list