/* -*- mode: c; c-file-style: "openbsd" -*- */ /* * Copyright (c) 2010 Andreas Hofmeister * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdocumentation" #endif #include #include #if defined(__clang__) # pragma clang diagnostic pop #endif #include "writer.h" #include "../log.h" struct xml_writer_private { FILE *fh; ssize_t depth; xmlTextWriterPtr xw; xmlDocPtr doc; }; static void xml_new_writer(struct xml_writer_private *priv) { priv->xw = xmlNewTextWriterDoc(&(priv->doc), 0); if (!priv->xw) fatalx("lldpctl", "cannot create xml writer"); xmlTextWriterSetIndent(priv->xw, 4); if (xmlTextWriterStartDocument(priv->xw, NULL, "UTF-8", NULL) < 0) fatalx("lldpctl", "cannot start xml document"); } static void xml_start(struct writer *w, const char *tag, const char *descr) { struct xml_writer_private *p = w->priv; if (p->depth == 0) xml_new_writer(p); if (xmlTextWriterStartElement(p->xw, BAD_CAST tag) < 0) log_warnx("lldpctl", "cannot start '%s' element", tag); if (descr && (strlen(descr) > 0)) { if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST "label", "%s", descr) < 0) log_warnx("lldpctl", "cannot add attribute 'label' to element %s", tag); } p->depth++; } static void xml_attr(struct writer *w, const char *tag, const char *descr, const char *value) { struct xml_writer_private *p = w->priv; if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST tag, "%s", value ? value : "") < 0) log_warnx("lldpctl", "cannot add attribute %s with value %s", tag, value ? value : "(none)"); } static void xml_data(struct writer *w, const char *data) { struct xml_writer_private *p = w->priv; if (xmlTextWriterWriteString(p->xw, BAD_CAST(data ? data : "")) < 0) log_warnx("lldpctl", "cannot add '%s' as data to element", data ? data : "(none)"); } static void xml_end(struct writer *w) { struct xml_writer_private *p = w->priv; if (xmlTextWriterEndElement(p->xw) < 0) log_warnx("lldpctl", "cannot end element"); if (--p->depth == 0) { int failed = 0; if (xmlTextWriterEndDocument(p->xw) < 0) { log_warnx("lldpctl", "cannot finish document"); failed = 1; } xmlFreeTextWriter(p->xw); if (!failed) { xmlDocDump(p->fh, p->doc); fflush(p->fh); } xmlFreeDoc(p->doc); } } static void xml_finish(struct writer *w) { struct xml_writer_private *p = w->priv; if (p->depth != 0) { log_warnx("lldpctl", "unbalanced tags"); /* memory leak... */ } free(p); free(w); } struct writer * xml_init(FILE *fh) { struct writer *result; struct xml_writer_private *priv; priv = malloc(sizeof(*priv)); if (!priv) { fatalx("lldpctl", "out of memory"); return NULL; } priv->fh = fh; priv->depth = 0; result = malloc(sizeof(struct writer)); if (!result) fatalx("lldpctl", "out of memory"); result->priv = priv; result->start = xml_start; result->attr = xml_attr; result->data = xml_data; result->end = xml_end; result->finish = xml_finish; return result; }