This source file includes following definitions.
- hwloc__nolibxml_import_ignore_spaces
- hwloc__nolibxml_import_next_attr
- hwloc__nolibxml_import_find_child
- hwloc__nolibxml_import_close_tag
- hwloc__nolibxml_import_close_child
- hwloc__nolibxml_import_get_content
- hwloc__nolibxml_import_close_content
- hwloc_nolibxml_look_init
- hwloc_nolibxml_free_buffers
- hwloc_nolibxml_look_done
- hwloc_nolibxml_backend_exit
- hwloc_nolibxml_read_file
- hwloc_nolibxml_backend_init
- hwloc_nolibxml_import_diff
- hwloc__nolibxml_export_update_buffer
- hwloc__nolibxml_export_escape_string
- hwloc__nolibxml_export_new_child
- hwloc__nolibxml_export_new_prop
- hwloc__nolibxml_export_end_object
- hwloc__nolibxml_export_add_content
- hwloc___nolibxml_prepare_export
- hwloc_nolibxml_export_buffer
- hwloc_nolibxml_export_file
- hwloc___nolibxml_prepare_export_diff
- hwloc_nolibxml_export_diff_buffer
- hwloc_nolibxml_export_diff_file
- hwloc_nolibxml_free_buffer
1
2
3
4
5
6
7
8
9 #include <private/autogen/config.h>
10 #include <hwloc.h>
11 #include <hwloc/plugins.h>
12 #include <private/private.h>
13 #include <private/misc.h>
14 #include <private/xml.h>
15 #include <private/debug.h>
16
17 #include <string.h>
18 #include <assert.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24
25
26
27
28
29 struct hwloc__nolibxml_backend_data_s {
30 size_t buflen;
31 char *buffer;
32 char *copy;
33 };
34
35 typedef struct hwloc__nolibxml_import_state_data_s {
36 char *tagbuffer;
37 char *attrbuffer;
38 char *tagname;
39 int closed;
40 } __hwloc_attribute_may_alias * hwloc__nolibxml_import_state_data_t;
41
42 static char *
43 hwloc__nolibxml_import_ignore_spaces(char *buffer)
44 {
45 return buffer + strspn(buffer, " \t\n");
46 }
47
48 static int
49 hwloc__nolibxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep)
50 {
51 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
52 size_t namelen;
53 size_t len, escaped;
54 char *buffer, *value, *end;
55
56 if (!nstate->attrbuffer)
57 return -1;
58
59
60 buffer = hwloc__nolibxml_import_ignore_spaces(nstate->attrbuffer);
61 namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz_");
62 if (buffer[namelen] != '=' || buffer[namelen+1] != '\"')
63 return -1;
64 buffer[namelen] = '\0';
65 *namep = buffer;
66
67
68 *valuep = value = buffer+namelen+2;
69 len = 0; escaped = 0;
70 while (value[len+escaped] != '\"') {
71 if (value[len+escaped] == '&') {
72 if (!strncmp(&value[1+len+escaped], "#10;", 4)) {
73 escaped += 4;
74 value[len] = '\n';
75 } else if (!strncmp(&value[1+len+escaped], "#13;", 4)) {
76 escaped += 4;
77 value[len] = '\r';
78 } else if (!strncmp(&value[1+len+escaped], "#9;", 3)) {
79 escaped += 3;
80 value[len] = '\t';
81 } else if (!strncmp(&value[1+len+escaped], "quot;", 5)) {
82 escaped += 5;
83 value[len] = '\"';
84 } else if (!strncmp(&value[1+len+escaped], "lt;", 3)) {
85 escaped += 3;
86 value[len] = '<';
87 } else if (!strncmp(&value[1+len+escaped], "gt;", 3)) {
88 escaped += 3;
89 value[len] = '>';
90 } else if (!strncmp(&value[1+len+escaped], "amp;", 4)) {
91 escaped += 4;
92 value[len] = '&';
93 } else {
94 return -1;
95 }
96 } else {
97 value[len] = value[len+escaped];
98 }
99 len++;
100 if (value[len+escaped] == '\0')
101 return -1;
102 }
103 value[len] = '\0';
104
105
106 end = &value[len+escaped+1];
107 nstate->attrbuffer = hwloc__nolibxml_import_ignore_spaces(end);
108 return 0;
109 }
110
111 static int
112 hwloc__nolibxml_import_find_child(hwloc__xml_import_state_t state,
113 hwloc__xml_import_state_t childstate,
114 char **tagp)
115 {
116 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
117 hwloc__nolibxml_import_state_data_t nchildstate = (void*) childstate->data;
118 char *buffer = nstate->tagbuffer;
119 char *end;
120 char *tag;
121 size_t namelen;
122
123 childstate->parent = state;
124 childstate->global = state->global;
125
126
127 if (nstate->closed)
128 return 0;
129
130
131 buffer = hwloc__nolibxml_import_ignore_spaces(buffer);
132 if (buffer[0] != '<')
133 return -1;
134 buffer++;
135
136
137 if (buffer[0] == '/')
138 return 0;
139
140
141 tag = nchildstate->tagname = buffer;
142
143
144 end = strchr(buffer, '>');
145 if (!end)
146 return -1;
147 end[0] = '\0';
148 nchildstate->tagbuffer = end+1;
149
150
151 if (end[-1] == '/') {
152 nchildstate->closed = 1;
153 end[-1] = '\0';
154 } else
155 nchildstate->closed = 0;
156
157
158 namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz1234567890_");
159
160 if (buffer[namelen] == '\0') {
161
162 nchildstate->attrbuffer = NULL;
163 *tagp = tag;
164 return 1;
165 }
166
167 if (buffer[namelen] != ' ')
168 return -1;
169
170
171 buffer[namelen] = '\0';
172 nchildstate->attrbuffer = buffer+namelen+1;
173 *tagp = tag;
174 return 1;
175 }
176
177 static int
178 hwloc__nolibxml_import_close_tag(hwloc__xml_import_state_t state)
179 {
180 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
181 char *buffer = nstate->tagbuffer;
182 char *end;
183
184
185 if (nstate->closed)
186 return 0;
187
188
189 buffer = hwloc__nolibxml_import_ignore_spaces(buffer);
190 if (buffer[0] != '<')
191 return -1;
192 buffer++;
193
194
195 end = strchr(buffer, '>');
196 if (!end)
197 return -1;
198 end[0] = '\0';
199 nstate->tagbuffer = end+1;
200
201
202 if (buffer[0] != '/' || strcmp(buffer+1, nstate->tagname) )
203 return -1;
204 return 0;
205 }
206
207 static void
208 hwloc__nolibxml_import_close_child(hwloc__xml_import_state_t state)
209 {
210 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
211 hwloc__nolibxml_import_state_data_t nparent = (void*) state->parent->data;
212 nparent->tagbuffer = nstate->tagbuffer;
213 }
214
215 static int
216 hwloc__nolibxml_import_get_content(hwloc__xml_import_state_t state,
217 char **beginp, size_t expected_length)
218 {
219 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
220 char *buffer = nstate->tagbuffer;
221 size_t length;
222 char *end;
223
224
225 if (nstate->closed) {
226 if (expected_length)
227 return -1;
228 *beginp = (char *) "";
229 return 0;
230 }
231
232
233 end = strchr(buffer, '<');
234 if (!end)
235 return -1;
236
237 length = (size_t) (end-buffer);
238 if (length != expected_length)
239 return -1;
240 nstate->tagbuffer = end;
241 *end = '\0';
242 *beginp = buffer;
243 return 1;
244 }
245
246 static void
247 hwloc__nolibxml_import_close_content(hwloc__xml_import_state_t state)
248 {
249
250 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
251 if (!nstate->closed)
252 *nstate->tagbuffer = '<';
253 }
254
255 static int
256 hwloc_nolibxml_look_init(struct hwloc_xml_backend_data_s *bdata,
257 struct hwloc__xml_import_state_s *state)
258 {
259 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
260 struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data;
261 unsigned major, minor;
262 char *end;
263 char *buffer;
264
265 HWLOC_BUILD_ASSERT(sizeof(*nstate) <= sizeof(state->data));
266
267
268 buffer = nbdata->copy;
269 memcpy(buffer, nbdata->buffer, nbdata->buflen);
270
271
272 while (!strncmp(buffer, "<?xml ", 6) || !strncmp(buffer, "<!DOCTYPE ", 10)) {
273 buffer = strchr(buffer, '\n');
274 if (!buffer)
275 goto failed;
276 buffer++;
277 }
278
279
280 if (sscanf(buffer, "<topology version=\"%u.%u\">", &major, &minor) == 2) {
281 bdata->version_major = major;
282 bdata->version_minor = minor;
283 end = strchr(buffer, '>') + 1;
284 } else if (!strncmp(buffer, "<topology>", 10)) {
285 bdata->version_major = 1;
286 bdata->version_minor = 0;
287 end = buffer + 10;
288 } else if (!strncmp(buffer, "<root>", 6)) {
289 bdata->version_major = 0;
290 bdata->version_minor = 9;
291 end = buffer + 6;
292 } else
293 goto failed;
294
295 state->global->next_attr = hwloc__nolibxml_import_next_attr;
296 state->global->find_child = hwloc__nolibxml_import_find_child;
297 state->global->close_tag = hwloc__nolibxml_import_close_tag;
298 state->global->close_child = hwloc__nolibxml_import_close_child;
299 state->global->get_content = hwloc__nolibxml_import_get_content;
300 state->global->close_content = hwloc__nolibxml_import_close_content;
301 state->parent = NULL;
302 nstate->closed = 0;
303 nstate->tagbuffer = end;
304 nstate->tagname = (char *) "topology";
305 nstate->attrbuffer = NULL;
306 return 0;
307
308 failed:
309 return -1;
310 }
311
312
313
314
315 static void
316 hwloc_nolibxml_free_buffers(struct hwloc_xml_backend_data_s *bdata)
317 {
318 struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data;
319 if (nbdata->buffer) {
320 free(nbdata->buffer);
321 nbdata->buffer = NULL;
322 }
323 if (nbdata->copy) {
324 free(nbdata->copy);
325 nbdata->copy = NULL;
326 }
327 }
328
329 static void
330 hwloc_nolibxml_look_done(struct hwloc_xml_backend_data_s *bdata, int result)
331 {
332 hwloc_nolibxml_free_buffers(bdata);
333
334 if (result < 0 && hwloc__xml_verbose())
335 fprintf(stderr, "Failed to parse XML input with the minimalistic parser. If it was not\n"
336 "generated by hwloc, try enabling full XML support with libxml2.\n");
337 }
338
339
340
341
342
343 static void
344 hwloc_nolibxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
345 {
346 struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data;
347 hwloc_nolibxml_free_buffers(bdata);
348 free(nbdata);
349 }
350
351 static int
352 hwloc_nolibxml_read_file(const char *xmlpath, char **bufferp, size_t *buflenp)
353 {
354 FILE * file;
355 size_t buflen, offset, readlen;
356 struct stat statbuf;
357 char *buffer, *tmp;
358 size_t ret;
359
360 if (!strcmp(xmlpath, "-"))
361 xmlpath = "/dev/stdin";
362
363 file = fopen(xmlpath, "r");
364 if (!file)
365 goto out;
366
367
368 buflen = 4096;
369 if (!stat(xmlpath, &statbuf))
370 if (S_ISREG(statbuf.st_mode))
371 buflen = statbuf.st_size+1;
372
373 buffer = malloc(buflen+1);
374 if (!buffer)
375 goto out_with_file;
376
377 offset = 0; readlen = buflen;
378 while (1) {
379 ret = fread(buffer+offset, 1, readlen, file);
380
381 offset += ret;
382 buffer[offset] = 0;
383
384 if (ret != readlen)
385 break;
386
387 buflen *= 2;
388 tmp = realloc(buffer, buflen+1);
389 if (!tmp)
390 goto out_with_buffer;
391 buffer = tmp;
392 readlen = buflen/2;
393 }
394
395 fclose(file);
396 *bufferp = buffer;
397 *buflenp = offset+1;
398 return 0;
399
400 out_with_buffer:
401 free(buffer);
402 out_with_file:
403 fclose(file);
404 out:
405 return -1;
406 }
407
408 static int
409 hwloc_nolibxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
410 const char *xmlpath, const char *xmlbuffer, int xmlbuflen)
411 {
412 struct hwloc__nolibxml_backend_data_s *nbdata = malloc(sizeof(*nbdata));
413
414 if (!nbdata)
415 goto out;
416 bdata->data = nbdata;
417
418 if (xmlbuffer) {
419 nbdata->buffer = malloc(xmlbuflen);
420 if (!nbdata->buffer)
421 goto out_with_nbdata;
422 nbdata->buflen = xmlbuflen;
423 memcpy(nbdata->buffer, xmlbuffer, xmlbuflen);
424
425 } else {
426 int err = hwloc_nolibxml_read_file(xmlpath, &nbdata->buffer, &nbdata->buflen);
427 if (err < 0)
428 goto out_with_nbdata;
429 }
430
431
432 nbdata->copy = malloc(nbdata->buflen);
433 if (!nbdata->copy)
434 goto out_with_buffer;
435
436 bdata->look_init = hwloc_nolibxml_look_init;
437 bdata->look_done = hwloc_nolibxml_look_done;
438 bdata->backend_exit = hwloc_nolibxml_backend_exit;
439 return 0;
440
441 out_with_buffer:
442 free(nbdata->buffer);
443 out_with_nbdata:
444 free(nbdata);
445 out:
446 return -1;
447 }
448
449 static int
450 hwloc_nolibxml_import_diff(struct hwloc__xml_import_state_s *state,
451 const char *xmlpath, const char *xmlbuffer, int xmlbuflen,
452 hwloc_topology_diff_t *firstdiffp, char **refnamep)
453 {
454 hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
455 struct hwloc__xml_import_state_s childstate;
456 char *refname = NULL;
457 char *buffer, *tmp, *tag;
458 size_t buflen;
459 int ret;
460
461 HWLOC_BUILD_ASSERT(sizeof(*nstate) <= sizeof(state->data));
462
463 if (xmlbuffer) {
464 buffer = malloc(xmlbuflen);
465 if (!buffer)
466 goto out;
467 memcpy(buffer, xmlbuffer, xmlbuflen);
468 buflen = xmlbuflen;
469
470 } else {
471 ret = hwloc_nolibxml_read_file(xmlpath, &buffer, &buflen);
472 if (ret < 0)
473 goto out;
474 }
475
476
477 tmp = buffer;
478 while (!strncmp(tmp, "<?xml ", 6) || !strncmp(tmp, "<!DOCTYPE ", 10)) {
479 tmp = strchr(tmp, '\n');
480 if (!tmp)
481 goto out_with_buffer;
482 tmp++;
483 }
484
485 state->global->next_attr = hwloc__nolibxml_import_next_attr;
486 state->global->find_child = hwloc__nolibxml_import_find_child;
487 state->global->close_tag = hwloc__nolibxml_import_close_tag;
488 state->global->close_child = hwloc__nolibxml_import_close_child;
489 state->global->get_content = hwloc__nolibxml_import_get_content;
490 state->global->close_content = hwloc__nolibxml_import_close_content;
491 state->parent = NULL;
492 nstate->closed = 0;
493 nstate->tagbuffer = tmp;
494 nstate->tagname = NULL;
495 nstate->attrbuffer = NULL;
496
497
498 ret = hwloc__nolibxml_import_find_child(state, &childstate, &tag);
499 if (ret < 0)
500 goto out_with_buffer;
501 if (strcmp(tag, "topologydiff"))
502 goto out_with_buffer;
503
504 while (1) {
505 char *attrname, *attrvalue;
506 if (hwloc__nolibxml_import_next_attr(&childstate, &attrname, &attrvalue) < 0)
507 break;
508 if (!strcmp(attrname, "refname")) {
509 free(refname);
510 refname = strdup(attrvalue);
511 } else
512 goto out_with_buffer;
513 }
514
515 ret = hwloc__xml_import_diff(&childstate, firstdiffp);
516 if (refnamep && !ret)
517 *refnamep = refname;
518 else
519 free(refname);
520
521 free(buffer);
522 return ret;
523
524 out_with_buffer:
525 free(buffer);
526 out:
527 return -1;
528 }
529
530
531
532
533
534 typedef struct hwloc__nolibxml_export_state_data_s {
535 char *buffer;
536 size_t written;
537 size_t remaining;
538 unsigned indent;
539 unsigned nr_children;
540 unsigned has_content;
541 } __hwloc_attribute_may_alias * hwloc__nolibxml_export_state_data_t;
542
543 static void
544 hwloc__nolibxml_export_update_buffer(hwloc__nolibxml_export_state_data_t ndata, int res)
545 {
546 if (res >= 0) {
547 ndata->written += res;
548 if (res >= (int) ndata->remaining)
549 res = ndata->remaining>0 ? (int)ndata->remaining-1 : 0;
550 ndata->buffer += res;
551 ndata->remaining -= res;
552 }
553 }
554
555 static char *
556 hwloc__nolibxml_export_escape_string(const char *src)
557 {
558 size_t fulllen, sublen;
559 char *escaped, *dst;
560
561 fulllen = strlen(src);
562
563 sublen = strcspn(src, "\n\r\t\"<>&");
564 if (sublen == fulllen)
565 return NULL;
566
567 escaped = malloc(fulllen*6+1);
568 dst = escaped;
569
570 memcpy(dst, src, sublen);
571 src += sublen;
572 dst += sublen;
573
574 while (*src) {
575 int replen;
576 switch (*src) {
577 case '\n': strcpy(dst, " "); replen=5; break;
578 case '\r': strcpy(dst, " "); replen=5; break;
579 case '\t': strcpy(dst, "	"); replen=4; break;
580 case '\"': strcpy(dst, """); replen=6; break;
581 case '<': strcpy(dst, "<"); replen=4; break;
582 case '>': strcpy(dst, ">"); replen=4; break;
583 case '&': strcpy(dst, "&"); replen=5; break;
584 default: replen=0; break;
585 }
586 dst+=replen; src++;
587
588 sublen = strcspn(src, "\n\r\t\"<>&");
589 memcpy(dst, src, sublen);
590 src += sublen;
591 dst += sublen;
592 }
593
594 *dst = 0;
595 return escaped;
596 }
597
598 static void
599 hwloc__nolibxml_export_new_child(hwloc__xml_export_state_t parentstate,
600 hwloc__xml_export_state_t state,
601 const char *name)
602 {
603 hwloc__nolibxml_export_state_data_t npdata = (void *) parentstate->data;
604 hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
605 int res;
606
607 assert(!npdata->has_content);
608 if (!npdata->nr_children) {
609 res = hwloc_snprintf(npdata->buffer, npdata->remaining, ">\n");
610 hwloc__nolibxml_export_update_buffer(npdata, res);
611 }
612 npdata->nr_children++;
613
614 state->parent = parentstate;
615 state->new_child = parentstate->new_child;
616 state->new_prop = parentstate->new_prop;
617 state->add_content = parentstate->add_content;
618 state->end_object = parentstate->end_object;
619 state->global = parentstate->global;
620
621 ndata->buffer = npdata->buffer;
622 ndata->written = npdata->written;
623 ndata->remaining = npdata->remaining;
624 ndata->indent = npdata->indent + 2;
625
626 ndata->nr_children = 0;
627 ndata->has_content = 0;
628
629 res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s<%s", (int) npdata->indent, "", name);
630 hwloc__nolibxml_export_update_buffer(ndata, res);
631 }
632
633 static void
634 hwloc__nolibxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value)
635 {
636 hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
637 char *escaped = hwloc__nolibxml_export_escape_string(value);
638 int res = hwloc_snprintf(ndata->buffer, ndata->remaining, " %s=\"%s\"", name, escaped ? (const char *) escaped : value);
639 hwloc__nolibxml_export_update_buffer(ndata, res);
640 free(escaped);
641 }
642
643 static void
644 hwloc__nolibxml_export_end_object(hwloc__xml_export_state_t state, const char *name)
645 {
646 hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
647 hwloc__nolibxml_export_state_data_t npdata = (void *) state->parent->data;
648 int res;
649
650 assert (!(ndata->has_content && ndata->nr_children));
651 if (ndata->has_content) {
652 res = hwloc_snprintf(ndata->buffer, ndata->remaining, "</%s>\n", name);
653 } else if (ndata->nr_children) {
654 res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s</%s>\n", (int) npdata->indent, "", name);
655 } else {
656 res = hwloc_snprintf(ndata->buffer, ndata->remaining, "/>\n");
657 }
658 hwloc__nolibxml_export_update_buffer(ndata, res);
659
660 npdata->buffer = ndata->buffer;
661 npdata->written = ndata->written;
662 npdata->remaining = ndata->remaining;
663 }
664
665 static void
666 hwloc__nolibxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length)
667 {
668 hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
669 int res;
670
671 assert(!ndata->nr_children);
672 if (!ndata->has_content) {
673 res = hwloc_snprintf(ndata->buffer, ndata->remaining, ">");
674 hwloc__nolibxml_export_update_buffer(ndata, res);
675 }
676 ndata->has_content = 1;
677
678 res = hwloc_snprintf(ndata->buffer, ndata->remaining, buffer, length);
679 hwloc__nolibxml_export_update_buffer(ndata, res);
680 }
681
682 static size_t
683 hwloc___nolibxml_prepare_export(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
684 char *xmlbuffer, int buflen, unsigned long flags)
685 {
686 struct hwloc__xml_export_state_s state, childstate;
687 hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data;
688 int v1export = flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1;
689 int res;
690
691 HWLOC_BUILD_ASSERT(sizeof(*ndata) <= sizeof(state.data));
692
693 state.new_child = hwloc__nolibxml_export_new_child;
694 state.new_prop = hwloc__nolibxml_export_new_prop;
695 state.add_content = hwloc__nolibxml_export_add_content;
696 state.end_object = hwloc__nolibxml_export_end_object;
697 state.global = edata;
698
699 ndata->indent = 0;
700 ndata->written = 0;
701 ndata->buffer = xmlbuffer;
702 ndata->remaining = buflen;
703
704 ndata->nr_children = 1;
705 ndata->has_content = 0;
706
707 res = hwloc_snprintf(ndata->buffer, ndata->remaining,
708 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
709 "<!DOCTYPE topology SYSTEM \"%s\">\n", v1export ? "hwloc.dtd" : "hwloc2.dtd");
710 hwloc__nolibxml_export_update_buffer(ndata, res);
711 hwloc__nolibxml_export_new_child(&state, &childstate, "topology");
712 if (!(flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1))
713 hwloc__nolibxml_export_new_prop(&childstate, "version", "2.0");
714 hwloc__xml_export_topology (&childstate, topology, flags);
715 hwloc__nolibxml_export_end_object(&childstate, "topology");
716
717 return ndata->written+1;
718 }
719
720 static int
721 hwloc_nolibxml_export_buffer(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
722 char **bufferp, int *buflenp, unsigned long flags)
723 {
724 char *buffer;
725 size_t bufferlen, res;
726
727 bufferlen = 16384;
728 buffer = malloc(bufferlen);
729 if (!buffer)
730 return -1;
731 res = hwloc___nolibxml_prepare_export(topology, edata, buffer, (int)bufferlen, flags);
732
733 if (res > bufferlen) {
734 char *tmp = realloc(buffer, res);
735 if (!tmp) {
736 free(buffer);
737 return -1;
738 }
739 buffer = tmp;
740 hwloc___nolibxml_prepare_export(topology, edata, buffer, (int)res, flags);
741 }
742
743 *bufferp = buffer;
744 *buflenp = (int)res;
745 return 0;
746 }
747
748 static int
749 hwloc_nolibxml_export_file(hwloc_topology_t topology, struct hwloc__xml_export_data_s *edata,
750 const char *filename, unsigned long flags)
751 {
752 FILE *file;
753 char *buffer;
754 int bufferlen;
755 int ret;
756
757 ret = hwloc_nolibxml_export_buffer(topology, edata, &buffer, &bufferlen, flags);
758 if (ret < 0)
759 return -1;
760
761 if (!strcmp(filename, "-")) {
762 file = stdout;
763 } else {
764 file = fopen(filename, "w");
765 if (!file) {
766 free(buffer);
767 return -1;
768 }
769 }
770
771 ret = (int)fwrite(buffer, 1, bufferlen-1 , file);
772 if (ret == bufferlen-1) {
773 ret = 0;
774 } else {
775 errno = ferror(file);
776 ret = -1;
777 }
778
779 free(buffer);
780
781 if (file != stdout)
782 fclose(file);
783 return ret;
784 }
785
786 static size_t
787 hwloc___nolibxml_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname, char *xmlbuffer, int buflen)
788 {
789 struct hwloc__xml_export_state_s state, childstate;
790 hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data;
791 int res;
792
793 HWLOC_BUILD_ASSERT(sizeof(*ndata) <= sizeof(state.data));
794
795 state.new_child = hwloc__nolibxml_export_new_child;
796 state.new_prop = hwloc__nolibxml_export_new_prop;
797 state.add_content = hwloc__nolibxml_export_add_content;
798 state.end_object = hwloc__nolibxml_export_end_object;
799
800 ndata->indent = 0;
801 ndata->written = 0;
802 ndata->buffer = xmlbuffer;
803 ndata->remaining = buflen;
804
805 ndata->nr_children = 1;
806 ndata->has_content = 0;
807
808 res = hwloc_snprintf(ndata->buffer, ndata->remaining,
809 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
810 "<!DOCTYPE topologydiff SYSTEM \"hwloc2-diff.dtd\">\n");
811 hwloc__nolibxml_export_update_buffer(ndata, res);
812 hwloc__nolibxml_export_new_child(&state, &childstate, "topologydiff");
813 if (refname)
814 hwloc__nolibxml_export_new_prop(&childstate, "refname", refname);
815 hwloc__xml_export_diff (&childstate, diff);
816 hwloc__nolibxml_export_end_object(&childstate, "topologydiff");
817
818 return ndata->written+1;
819 }
820
821 static int
822 hwloc_nolibxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **bufferp, int *buflenp)
823 {
824 char *buffer;
825 size_t bufferlen, res;
826
827 bufferlen = 16384;
828 buffer = malloc(bufferlen);
829 if (!buffer)
830 return -1;
831 res = hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, (int)bufferlen);
832
833 if (res > bufferlen) {
834 char *tmp = realloc(buffer, res);
835 if (!tmp) {
836 free(buffer);
837 return -1;
838 }
839 buffer = tmp;
840 hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, (int)res);
841 }
842
843 *bufferp = buffer;
844 *buflenp = (int)res;
845 return 0;
846 }
847
848 static int
849 hwloc_nolibxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename)
850 {
851 FILE *file;
852 char *buffer;
853 int bufferlen;
854 int ret;
855
856 ret = hwloc_nolibxml_export_diff_buffer(diff, refname, &buffer, &bufferlen);
857 if (ret < 0)
858 return -1;
859
860 if (!strcmp(filename, "-")) {
861 file = stdout;
862 } else {
863 file = fopen(filename, "w");
864 if (!file) {
865 free(buffer);
866 return -1;
867 }
868 }
869
870 ret = (int)fwrite(buffer, 1, bufferlen-1 , file);
871 if (ret == bufferlen-1) {
872 ret = 0;
873 } else {
874 errno = ferror(file);
875 ret = -1;
876 }
877
878 free(buffer);
879
880 if (file != stdout)
881 fclose(file);
882 return ret;
883 }
884
885 static void
886 hwloc_nolibxml_free_buffer(void *xmlbuffer)
887 {
888 free(xmlbuffer);
889 }
890
891
892
893
894
895 static struct hwloc_xml_callbacks hwloc_xml_nolibxml_callbacks = {
896 hwloc_nolibxml_backend_init,
897 hwloc_nolibxml_export_file,
898 hwloc_nolibxml_export_buffer,
899 hwloc_nolibxml_free_buffer,
900 hwloc_nolibxml_import_diff,
901 hwloc_nolibxml_export_diff_file,
902 hwloc_nolibxml_export_diff_buffer
903 };
904
905 static struct hwloc_xml_component hwloc_nolibxml_xml_component = {
906 &hwloc_xml_nolibxml_callbacks,
907 NULL
908 };
909
910 const struct hwloc_component hwloc_xml_nolibxml_component = {
911 HWLOC_COMPONENT_ABI,
912 NULL, NULL,
913 HWLOC_COMPONENT_TYPE_XML,
914 0,
915 &hwloc_nolibxml_xml_component
916 };