1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
14 #include "os_xml_internal.h"
17 static int _oswcomment(FILE *fp_in, FILE *fp_out) __attribute__((nonnull));
18 static int _WReadElem(FILE *fp_in, FILE *fp_out, unsigned int position, unsigned int parent,
19 const char **node, const char *value, unsigned int node_pos) __attribute__((nonnull));
20 static int _xml_wfgetc(FILE *fp_in, FILE *fp_out) __attribute__((nonnull));
24 static int _xml_wfgetc(FILE *fp_in, FILE *fp_out)
28 /* Putting on fp_out, whatever we read */
37 /* Write an XML file, based on the input and values to change */
38 int OS_WriteXML(const char *infile, const char *outfile, const char **nodes,
39 const char *oldval, const char *newval)
46 fp_in = fopen(infile, "r");
52 fp_out = fopen(outfile, "w");
58 if ((r = _WReadElem(fp_in, fp_out, 0, 0,
59 nodes, newval, 0)) < 0) { /* First position */
65 /* We didn't find an entry, add at the end */
66 if (!oldval && r == 0) {
70 fseek(fp_out, 0, SEEK_END);
71 fprintf(fp_out, "\n");
75 fprintf(fp_out, "%*c<%s>", rwidth, ' ', nodes[s]);
80 fprintf(fp_out, "\n");
87 fprintf(fp_out, "%s</%s>\n", newval, nodes[s]);
92 fprintf(fp_out, "%*c</%s>\n", rwidth, ' ', nodes[s]);
104 static int _oswcomment(FILE *fp_in, FILE *fp_out)
107 if ((c = fgetc(fp_in)) == _R_COM) {
109 while ((c = _xml_wfgetc(fp_in, fp_out)) != EOF) {
111 if ((c = fgetc(fp_in)) == _R_CONFE) {
116 } else if (c == '-') { /* W3C way of finishing comments */
117 if ((c = fgetc(fp_in)) == '-') {
119 if ((c = fgetc(fp_in)) == _R_CONFE) {
139 static int _WReadElem(FILE *fp_in, FILE *fp_out, unsigned int position,
140 unsigned int parent, const char **nodes,
141 const char *val, unsigned int node_pos)
145 unsigned int count = 0;
146 short int location = -1;
148 char elem[XML_MAXSIZE + 1];
149 char cont[XML_MAXSIZE + 1];
150 char closedelim[XML_MAXSIZE + 1];
152 memset(elem, '\0', XML_MAXSIZE + 1);
153 memset(cont, '\0', XML_MAXSIZE + 1);
154 memset(closedelim, '\0', XML_MAXSIZE + 1);
156 while ((c = _xml_wfgetc(fp_in, fp_out)) != EOF) {
158 if (count >= XML_MAXSIZE) {
162 /* Check for comments */
165 if ((r = _oswcomment(fp_in, fp_out)) < 0) {
173 if (location == -1) {
174 /* Must be the opening element */
176 if ((c = fgetc(fp_in)) == '/') {
187 /* Look for the closure */
188 else if ((location == 0) && ((c == _R_CONFE) || (c == ' '))) {
192 /* Remove the / at the end of the element name */
193 if (count > 0 && elem[count - 1] == '/') {
195 elem[count - 1] = '\0';
198 /* If we may have more attributes */
200 /* Write the attributes */
201 while ((c = _xml_wfgetc(fp_in, fp_out)) != EOF) {
208 /* If the element is closed already (finished in />) */
213 memset(elem, '\0', XML_MAXSIZE);
214 memset(closedelim, '\0', XML_MAXSIZE);
215 memset(cont, '\0', XML_MAXSIZE);
221 /* Location == means we are getting the content */
227 /* Check position of the node */
228 if (node_pos > position) {
232 /* Check if the element name matches */
233 if (node_pos == position &&
234 nodes[node_pos] && strcmp(elem, nodes[node_pos]) == 0) {
237 /* Latest node, print value */
238 if (!nodes[node_pos]) {
240 fprintf(fp_out, "%s", val);
242 while ((c = fgetc(fp_in)) != EOF) {
252 else if ((location == 2) && (c == _R_CONFE)) {
253 closedelim[count] = '\0';
254 if (strcmp(closedelim, elem) != 0) {
258 memset(elem, '\0', XML_MAXSIZE);
259 memset(closedelim, '\0', XML_MAXSIZE);
260 memset(cont, '\0', XML_MAXSIZE);
269 /* If we are reading the element */
270 else if ((location == 1) && (c == _R_CONFS)) {
271 if ((c = fgetc(fp_in)) == '/') {
280 ungetc(_R_CONFS, fp_in);
281 if (fseek(fp_out, -1, SEEK_CUR)) {
285 if ((wret_code = _WReadElem(fp_in, fp_out, position + 1, parent + 1,
286 nodes, val, node_pos)) < 0) {
290 /* Set final return code */
291 if (wret_code == 1) {
299 elem[count++] = (char) c;
300 } else if (location == 1) {
301 cont[count++] = (char) c;
302 } else if (location == 2) {
303 closedelim[count++] = (char) c;
308 if (location == -1) {