xml_token_type_t xml_get_tag_attributes(xml_reader_t *xr, xml_node_t *node) { ni_stringbuf_t tokenValue, attrName, attrValue; xml_token_type_t token; ni_stringbuf_init(&tokenValue); ni_stringbuf_init(&attrName); ni_stringbuf_init(&attrValue); token = xml_get_token(xr, &tokenValue); while (1) { if (token == RightAngle || token == RightAngleQ || token == RightAngleSlash) break; if (token != Identifier) { xml_parse_error(xr, "Unexpected token in tag attributes"); token = None; break; } ni_stringbuf_move(&attrName, &tokenValue); token = xml_get_token(xr, &tokenValue); if (token != Equals) { xml_node_add_attr(node, attrName.string, NULL); continue; } token = xml_get_token(xr, &tokenValue); if (token != QuotedString) { xml_parse_error(xr, "Attribute value not a quoted string!"); token = None; break; } xml_debug(" attr %s=%s\n", attrName.string, tokenValue.string); xml_node_add_attr(node, attrName.string, tokenValue.string); token = xml_get_token(xr, &tokenValue); } ni_stringbuf_destroy(&tokenValue); ni_stringbuf_destroy(&attrName); ni_stringbuf_destroy(&attrValue); return token; }
static char * __xpath_node_array_print_short(const xpath_result_t *na) { ni_stringbuf_t buf; unsigned int n; if (na->type == XPATH_BOOLEAN) return xstrdup(__xpath_test_boolean(na)? "[true]" : "[false]"); if (na->count == 0) return xstrdup("[]"); ni_stringbuf_init(&buf); ni_stringbuf_putc(&buf, '['); for (n = 0; n < na->count; ++n) { const char *string; if (n) ni_stringbuf_puts(&buf, ", "); if (n >= 7) { ni_stringbuf_puts(&buf, "..."); break; } switch (na->type) { case XPATH_ELEMENT: string = na->node[n].value.node->name; ni_stringbuf_printf(&buf, "<%s>", string?: "ROOT"); break; case XPATH_INTEGER: ni_stringbuf_printf(&buf, "%ld", na->node[n].value.integer); break; case XPATH_STRING: string = na->node[n].value.string; if (strlen(string) > 32) ni_stringbuf_printf(&buf, "\"%.32s ...\"", string); else ni_stringbuf_printf(&buf, "\"%s\"", string); break; default: ni_stringbuf_puts(&buf, "???"); } } ni_stringbuf_putc(&buf, ']'); return buf.string; }
static dbus_bool_t ni_objectmodel_ethtool_set_priv_flags(ni_dbus_object_t *object, const ni_dbus_property_t *property, const ni_dbus_variant_t *argument, DBusError *error) { const ni_dbus_variant_t *dict; ni_ethtool_t *ethtool; unsigned int i, len; dbus_bool_t enabled; ni_stringbuf_t buf; const char *name; if (!ni_dbus_variant_is_dict_array(argument)) return FALSE; if (!(ethtool = ni_objectmodel_ethtool_write_handle(object, error))) return FALSE; ni_ethtool_priv_flags_free(ethtool->priv_flags); if (!(ethtool->priv_flags = ni_ethtool_priv_flags_new())) return FALSE; if ((len = argument->array.len) > 32) len = 32; ni_stringbuf_init(&buf); for (i = 0; i < argument->array.len; ++i) { dict = &argument->variant_array_value[i]; if (!ni_dbus_variant_is_dict(dict)) continue; if (!ni_dbus_dict_get_string(dict, "name", &name) || !ni_dbus_dict_get_bool(dict, "enabled", &enabled)) continue; ni_stringbuf_put(&buf, name, ni_string_len(name)); ni_stringbuf_trim_head(&buf, " \t\n"); ni_stringbuf_trim_tail(&buf, " \t\n"); if (ni_string_empty(buf.string)) continue; if (ni_string_array_append(ðtool->priv_flags->names, buf.string) == 0) { if (enabled) ethtool->priv_flags->bitmap |= NI_BIT(i); } ni_stringbuf_destroy(&buf); } return TRUE; }
static inline int ni_ethtool_get_priv_flags_names(const char *ifname, ni_ethtool_t *ethtool, ni_string_array_t *names) { struct ethtool_gstrings *gstrings; unsigned int count, i; ni_stringbuf_t buf; const char *name; count = ni_ethtool_get_gstring_count(ifname, " priv-flags count", ETH_SS_PRIV_FLAGS); if (!count) { if (errno == EOPNOTSUPP && ethtool->driver_info) count = ethtool->driver_info->supports.n_priv_flags; if (!count) { ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_GET_PRIV_FLAGS, FALSE); return -EOPNOTSUPP; } } if (count > 32) count = 32; gstrings = ni_ethtool_get_gstrings(ifname, " priv-flags names", ETH_SS_PRIV_FLAGS, count); if (!gstrings) { if (errno == EOPNOTSUPP) ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_GET_PRIV_FLAGS, FALSE); free(gstrings); return errno ? -errno : -1; } ni_stringbuf_init(&buf); for (i = 0; i < gstrings->len; ++i) { name = (const char *)(gstrings->data + i * ETH_GSTRING_LEN); ni_stringbuf_put(&buf, name, ETH_GSTRING_LEN); ni_stringbuf_trim_head(&buf, " \t\n"); ni_stringbuf_trim_tail(&buf, " \t\n"); ni_string_array_append(names, buf.string); ni_stringbuf_destroy(&buf); } free(gstrings); if (names->count == count) return 0; ni_string_array_destroy(names); return -ENOMEM; /* array append */ }
const char * ni_string_join(char **str, const ni_string_array_t *nsa, const char *sep) { ni_stringbuf_t buf; unsigned int i; if (nsa == NULL || sep == NULL || str == NULL) return NULL; ni_stringbuf_init(&buf); for (i=0; i < nsa->count; ++i) { if (i) ni_stringbuf_puts(&buf, sep); ni_stringbuf_puts(&buf, nsa->data[i]); } ni_string_dup(str, buf.string); ni_stringbuf_destroy(&buf); return *str; }
ni_bool_t xml_process_element_nested(xml_reader_t *xr, xml_node_t *cur, unsigned int nesting) { ni_stringbuf_t tokenValue, identifier; xml_token_type_t token; xml_node_t *child; ni_stringbuf_init(&tokenValue); ni_stringbuf_init(&identifier); while (1) { token = xml_get_token(xr, &tokenValue); switch (token) { case CData: /* process element content */ xml_node_set_cdata(cur, tokenValue.string); break; case LeftAngleExclam: /* Most likely <!DOCTYPE ...> */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open <! not followed by identifier"); goto error; } if (strcmp(identifier.string, "DOCTYPE")) { xml_parse_error(xr, "Unexpected element: <!%s ...> not supported", identifier.string); goto error; } while (1) { token = xml_get_token(xr, &identifier); if (token == RightAngle) break; if (token == Identifier && !xr->doctype) ni_string_dup(&xr->doctype, identifier.string); if (token != Identifier && token != QuotedString) { xml_parse_error(xr, "Error parsing <!DOCTYPE ...> attributes"); goto error; } } break; case LeftAngle: /* New element start */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open < not followed by identifier"); goto error; } child = xml_node_new(identifier.string, cur); if (xr->shared_location) child->location = xml_location_new(xr->shared_location, xr->lineCount); token = xml_get_tag_attributes(xr, child); if (token == None) { xml_parse_error(xr, "Error parsing <%s ...> tag attributes", child->name); goto error; } else if (token == RightAngle) { /* Handle <foo>...</foo> */ xml_debug("%*.*s<%s>\n", nesting, nesting, "", child->name); if (!xml_process_element_nested(xr, child, nesting + 2)) goto error; } else if (token == RightAngleSlash) { /* We parsed a "<foo/>" element - nothing left to do, we're done */ xml_debug("%*.*s<%s/>\n", nesting, nesting, "", child->name); } else { xml_parse_error(xr, "Unexpected token %s at end of <%s ...", xml_token_name(token), child->name); goto error; } break; case LeftAngleSlash: /* Element end */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: end tag open </ not followed by identifier"); goto error; } if (xml_get_token(xr, &tokenValue) != RightAngle) { xml_parse_error(xr, "Bad element: </%s - missing tag close", identifier.string); goto error; } if (cur->parent == NULL) { xml_parse_error(xr, "Unexpected </%s> tag", identifier.string); goto error; } if (strcmp(cur->name, identifier.string)) { xml_parse_error(xr, "Closing tag </%s> does not match <%s>", identifier.string, cur->name); goto error; } xml_debug("%*.*s</%s>\n", nesting, nesting, "", cur->name); goto success; case LeftAngleQ: /* New PI node starts here */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open <? not followed by identifier"); goto error; } child = xml_node_new(identifier.string, NULL); if (xr->shared_location) child->location = xml_location_new(xr->shared_location, xr->lineCount); token = xml_get_tag_attributes(xr, child); if (token == None) { xml_parse_error(xr, "Error parsing <?%s ...?> tag attributes", child->name); xml_node_free(child); goto error; } else if (token == RightAngleQ) { xml_debug("%*.*s<%s>\n", nesting, nesting, "", child->name); xml_process_pi_node(xr, child); xml_node_free(child); } else { xml_parse_error(xr, "Unexpected token %s at end of <?%s ...", xml_token_name(token), child->name); xml_node_free(child); goto error; } break; case EndOfDocument: if (cur->parent) { xml_parse_error(xr, "End of document while processing element <%s>", cur->name); goto error; } goto success; case None: /* parser error */ goto error; default: xml_parse_error(xr, "Unexpected token %s", xml_token_name(token)); goto error; } } success: ni_stringbuf_destroy(&tokenValue); ni_stringbuf_destroy(&identifier); return TRUE; error: ni_stringbuf_destroy(&tokenValue); ni_stringbuf_destroy(&identifier); return FALSE; }