int loop_through_volumes(const char *xml_path, eucaVolume volumes[EUCA_MAX_VOLUMES]){ char volxpath[128] = ""; #define MKVOLPATH(_suffix) snprintf(volxpath, sizeof(volxpath), "/instance/volumes/volume[%d]/%s", (i + 1), _suffix); #define MKLIBVIRTVOLPATH(_suffix) snprintf(volxpath, sizeof(volxpath), "/instance/volumes/volume[%d]/libvirt/disk/%s", (i + 1), _suffix); #define XGET_STR_FREE(_XPATH, _dest) \ { \ if (get_xpath_content_at(xml_path, (_XPATH), 0, _dest, sizeof(_dest)) == NULL) { \ fprintf(stderr, "failed to read %s from %s\n", (_XPATH), xml_path); \ for (int z = 0; res_array[z] != NULL; z++) \ EUCA_FREE(res_array[z]); \ EUCA_FREE(res_array); \ return (EUCA_ERROR); \ } \ } char **res_array = NULL; if ((res_array = get_xpath_content(xml_path, "/instance/volumes/volume")) != NULL) { for (int i = 0; (res_array[i] != NULL) && (i < EUCA_MAX_VOLUMES); i++) { eucaVolume *v = &volumes[i]; MKVOLPATH("id"); XGET_STR_FREE(volxpath, v->id); MKVOLPATH("attachmentToken"); XGET_STR_FREE(volxpath, v->attachment_token); MKVOLPATH("stateName"); XGET_STR_FREE(volxpath, v->state); MKVOLPATH("connectionString"); XGET_STR_FREE(volxpath, v->connection_string); MKVOLPATH("devName"); XGET_STR_FREE(volxpath, v->device); MKVOLPATH("libvirt"); if (strcmp(v->state, VOL_STATE_ATTACHING) && strcmp(v->state, VOL_STATE_ATTACHING_FAILED) && get_xpath_xml(xml_path, volxpath, v->libvirt_XML, sizeof(v->libvirt_XML)) != EUCA_OK) { fprintf(stderr, "failed to read '%s' from '%s'\n", volxpath, xml_path); for (int z = 0; res_array[z] != NULL; z++) EUCA_FREE(res_array[z]); EUCA_FREE(res_array); return (EUCA_ERROR); } MKLIBVIRTVOLPATH("serial"); XGET_STR_FREE(volxpath, v->serial); MKLIBVIRTVOLPATH("target/@bus"); XGET_STR_FREE(volxpath, v->bus); } // Free our allocated memory for (int i = 0; res_array[i] != NULL; i++) EUCA_FREE(res_array[i]); EUCA_FREE(res_array); } return (EUCA_OK); }
//! //! Returns text content of the N-th result of an xpath query. //! //! If a buffer was provided, the result is copied into it and the pointer to the //! buffer is returned. If the buffer is NULL, the result is returned in a string //! that the caller must free. If there were no values or if index is out of range //! NULL is returned. //! //! To be useful, the query should point to an XML element that does not have any //! children. //! //! @param[in] xml_path a string containing the path to the XML file to parse //! @param[in] xpath a string contianing the XPATH expression to evaluate //! @param[in] index of the value to retrieve //! @param[in] buf string buffer to copy value into (if NULL, a malloced value is returned) //! @param[in] buf_len length of the buffer (irrelevant if buf is NULL) //! //! @return a pointer to a string with the first result (must be freed by caller) or to buf, if specified //! char *get_xpath_content_at(const char *xml_path, const char *xpath, int index, char *buf, int buf_len) { char **res_array = NULL; char *res = NULL; if ((res_array = get_xpath_content(xml_path, xpath)) != NULL) { for (int i = 0; res_array[i]; i++) { if (i == index) { if (buf != NULL) { strncpy(buf, res_array[i], buf_len); EUCA_FREE(res_array[i]); res = buf; } else { res = res_array[i]; // caller has to free res_array[i] } } else { EUCA_FREE(res_array[i]); // we always free all other results } } EUCA_FREE(res_array); } return (res); }
//! //! Main entry point of the application //! //! @param[in] argc the number of parameter passed on the command line //! @param[in] argv the list of arguments //! //! @return EUCA_OK on success or EUCA_ERROR on failure. //! int main(int argc, char **argv) { int j = 0; char **devs = NULL; char *inputXmlPath = NULL; if (argc != 3) { LOGERROR("please, supply a path to an XML file and an Xpath\n"); return (EUCA_ERROR); } inputXmlPath = argv[1]; if ((devs = get_xpath_content(argv[1], argv[2])) != NULL) { for (j = 0; devs[j]; j++) { LOGINFO("devs[%d] = '%s'\n", j, devs[j]); EUCA_FREE(devs[j]); } EUCA_FREE(devs); } else { LOGERROR("devs[] are empty\n"); } return (EUCA_OK); }