[libvirt] PATCH: 2/14: Generic network XML parser/formatter

Jim Meyering jim at meyering.net
Wed Jul 9 14:34:39 UTC 2008


Modulo some minor problems, ACK.
Even though I reviewed only the incremental diffs, there was a bit of
new material.  BTW, nice catch, with the new uses of virBufferEscapeString.

> +virNetworkDefPtr virNetworkDefParseNode(virConnectPtr conn,
> +                                        xmlDocPtr xml,
> +                                        xmlNodePtr root)
> +{
> +    xmlXPathContextPtr ctxt = NULL;
> +    virNetworkDefPtr def = NULL;
> +
> +    if (!xmlStrEqual(root->name, BAD_CAST "network")) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              "%s", _("incorrect root element"));
> +        goto cleanup;
> +    }

No big deal, but the above goto could be "return NULL;".

> +    ctxt = xmlXPathNewContext(xml);
> +    if (ctxt == NULL) {
> +        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +        goto cleanup;
> +    }
> +
> +    ctxt->node = root;
> +    def = virNetworkDefParseXML(conn, ctxt);
> +
> +cleanup:
> +    xmlXPathFreeContext(ctxt);
> +    return def;
> +}
...
> +int virNetworkSaveConfig(virConnectPtr conn,
> +                         const char *configDir,
> +                         const char *autostartDir,
> +                         virNetworkObjPtr net)
> +{
> +    char *xml;
> +    int fd = -1, ret = -1;
> +    int towrite;

Use size_t, not int.

> +    int err;
> +
> +    if (!net->configFile &&
> +        asprintf(&net->configFile, "%s/%s.xml",
> +                 configDir, net->def->name) < 0) {

Upon failure, set net->autostartFile to NULL.
Otherwise, when the caller frees "net", it will free a potentially
undefined pointer.

> +        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +        goto cleanup;
> +    }
> +    if (!net->autostartLink &&
> +        asprintf(&net->autostartLink, "%s/%s.xml",
> +                 autostartDir, net->def->name) < 0) {

Likewise for net->autostartLink.

> +        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +        goto cleanup;
> +    }
> +
> +    if (!(xml = virNetworkDefFormat(conn,
> +                                    net->newDef ? net->newDef : net->def)))
> +        return -1;

No real problem, but each of the above two goto statements could be
"return -1;", or maybe just change this return -1 to "goto cleanup;".
Otherwise, the inconsistency looks suspicious.

> +    if ((err = virFileMakePath(configDir))) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot create config directory %s: %s"),
> +                              configDir, strerror(err));
> +        goto cleanup;
> +    }
> +
> +    if ((err = virFileMakePath(autostartDir))) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot create autostart directory %s: %s"),
> +                              autostartDir, strerror(err));
> +        goto cleanup;
> +    }
> +
> +    if ((fd = open(net->configFile,
> +                   O_WRONLY | O_CREAT | O_TRUNC,
> +                   S_IRUSR | S_IWUSR )) < 0) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot create config file %s: %s"),
> +                              net->configFile, strerror(errno));
> +        goto cleanup;
> +    }
> +
> +    towrite = strlen(xml);
> +    if (safewrite(fd, xml, towrite) < 0) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot write config file %s: %s"),
> +                              net->configFile, strerror(errno));
> +        goto cleanup;
> +    }
> +
> +    if (close(fd) < 0) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot save config file %s: %s"),
> +                              net->configFile, strerror(errno));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> + cleanup:
> +    VIR_FREE(xml);
> +    close(fd);

It's better not to close(-1), so as not to
raise flags via tools like valgrind or strace:

    if (fd >= 0)
        close(fd);

> +    return ret;
> +}
> +
> +virNetworkObjPtr virNetworkLoadConfig(virConnectPtr conn,
> +                                      virNetworkObjPtr *nets,
> +                                      const char *configDir,
> +                                      const char *autostartDir,
> +                                      const char *file)
> +{
> +    char *configFile, *autostartLink;
> +    virNetworkDefPtr def = NULL;
> +    virNetworkObjPtr net;
> +    int autostart;
> +
> +    if (asprintf(&configFile, "%s/%s",
> +                 configDir, file) < 0) {

Upon failed asprintf, here, you need to set configFile = NULL.
Otherwise, the VIR_FREE(configFile) below will free a potentially
undefined pointer.

> +        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +        goto error;
> +    }
> +    if (asprintf(&autostartLink, "%s/%s",
> +                 autostartDir, file) < 0) {

Same for autostartLink.

> +        virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +        goto error;
> +    }
...
> +error:
> +    VIR_FREE(configFile);
> +    VIR_FREE(autostartLink);
> +    virNetworkDefFree(def);
> +    return NULL;
> +}
...
> +int virNetworkDeleteConfig(virConnectPtr conn,
> +                           virNetworkObjPtr net)
> +{
> +    if (!net->configFile || !net->autostartLink) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("no config file for %s"), net->def->name);
> +        return -1;
> +    }
> +
> +    /* Not fatal if this doesn't work */
> +    unlink(net->autostartLink);
> +
> +    if (unlink(net->configFile) < 0) {
> +        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                              _("cannot remove config for %s"), net->def->name);

Please include strerror(errno), so people know why it fails.

> +        return -1;
> +    }
> +
> +    return 0;
> +}
> diff -r 097ed9d9ae46 src/network_conf.h
...
> +typedef struct _virNetworkDef virNetworkDef;
> +typedef virNetworkDef *virNetworkDefPtr;
> +struct _virNetworkDef {
> +    unsigned char uuid[VIR_UUID_BUFLEN];
> +    char *name;
> +
> +    char *bridge;       /* Name of bridge device */
> +    int stp : 1; /* Spanning tree protocol */
> +    unsigned long delay;   /* Bridge forward delay (ms) */

Not that it matters, but...
Swapping the two preceding lines should decrease the size of this
struct by 8 bytes on a system with 8-byte pointers and longs.

> +
> +    int forwardType;    /* One of virNetworkForwardType constants */
> +    char *forwardDev;   /* Destination device for forwarding */
> +
> +    char *ipAddress;    /* Bridge IP address */
> +    char *netmask;
> +    char *network;
> +
> +    unsigned int nranges;        /* Zero or more dhcp ranges */
> +    virNetworkDHCPRangeDefPtr ranges;
> +};




More information about the libvir-list mailing list