1 /*
2  * Copyright © 2013-2019 Inria.  All rights reserved.
3  * See COPYING in top-level directory.
4  */
5 
6 #include <private/private.h>
7 #include <hwloc.h>
8 #include <hwloc/diff.h>
9 
10 #include "misc.h"
11 
usage(const char * callname __hwloc_attribute_unused,FILE * where)12 void usage(const char *callname __hwloc_attribute_unused, FILE *where)
13 {
14 	fprintf(where, "Usage: hwloc-diff [options] <old.xml> <new.xml> [<output.diff.xml>]\n");
15 	fprintf(where, "Options:\n");
16 	fprintf(where, "  --refname <name>  Change the XML reference identifier to <name> in the output\n");
17 	fprintf(where, "                    (default is the filename of the first topology\n");
18 	fprintf(where, "  --version         Report version and exit\n");
19 }
20 
main(int argc,char * argv[])21 int main(int argc, char *argv[])
22 {
23 	hwloc_topology_t topo1, topo2;
24 	hwloc_topology_diff_t firstdiff = NULL, diff;
25 	unsigned long flags = HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM | HWLOC_TOPOLOGY_FLAG_WHOLE_IO | HWLOC_TOPOLOGY_FLAG_ICACHES;
26 	char *callname, *input1, *input2, *output, *outputname, *refname = NULL;
27 	char *xmlbuffer;
28 	int xmlbuflen;
29 	unsigned i, j;
30 	int err;
31 
32 	putenv((char *) "HWLOC_XML_VERBOSE=1");
33 	callname = argv[0];
34 	/* skip argv[0], handle options */
35 	argc--;
36 	argv++;
37 
38 	while (argc && *argv[0] == '-') {
39 		if (!strcmp (argv[0], "--refname")) {
40 			if (argc < 2) {
41 				usage(callname, stderr);
42 				exit(EXIT_FAILURE);
43 			}
44 			refname = argv[1];
45 			argc--;
46 			argv++;
47 		} else if (!strcmp (argv[0], "--version")) {
48 			printf("%s %s\n", callname, HWLOC_VERSION);
49 			exit(EXIT_SUCCESS);
50 		} else {
51 			fprintf(stderr, "Unrecognized options: %s\n", argv[0]);
52 			usage(callname, stderr);
53 			exit(EXIT_FAILURE);
54 		}
55 		argc--;
56 		argv++;
57 	}
58 
59 	if (argc < 2) {
60 		usage(callname, stderr);
61 		exit(EXIT_FAILURE);
62 	}
63 	input1 = argv[0];
64 	input2 = argv[1];
65 	argc -= 2;
66 	argv += 2;
67 	if (argc >= 1) {
68 		output = argv[0];
69 		outputname = argv[0];
70 		argc--;
71 		argv++;
72 	} else  {
73 		output = NULL;
74 		outputname = (char *) "stdout";
75 	}
76 
77 	hwloc_topology_init(&topo1);
78 	hwloc_topology_set_flags(topo1, flags);
79 	err = hwloc_topology_set_xml(topo1, input1);
80 	if (err < 0) {
81 		fprintf(stderr, "Failed to load 1st XML topology %s\n", input1);
82 		goto out_with_topo1;
83 	}
84 	err = hwloc_topology_load(topo1);
85 	if (err < 0) {
86 		fprintf(stderr, "Failed to load 1st topology %s\n", input1);
87 		goto out_with_topo1;
88 	}
89 
90 	hwloc_topology_init(&topo2);
91 	hwloc_topology_set_flags(topo2, flags);
92 	err = hwloc_topology_set_xml(topo2, input2);
93 	if (err < 0) {
94 		fprintf(stderr, "Failed to load 2nd XML topology %s\n", input2);
95 		goto out_with_topo2;
96 	}
97 	err = hwloc_topology_load(topo2);
98 	if (err < 0) {
99 		fprintf(stderr, "Failed to load 2nd topology %s\n", input2);
100 		goto out_with_topo2;
101 	}
102 
103 	if (!refname) {
104 		refname = strrchr(input1, '/');
105 		if (refname)
106 			refname++;
107 		else
108 			refname = input1;
109 	}
110 
111 	err = hwloc_topology_diff_build(topo1, topo2, 0, &firstdiff);
112 	if (err < 0) {
113 		fprintf(stderr, "Failed to compute the diff (%s)\n", strerror(errno));
114 		goto out_with_topo2;
115 	}
116 
117 	diff = firstdiff;
118 	i = 0, j = 0;
119 	while (diff) {
120 		i++;
121 		if (diff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX)
122 			j++;
123 		diff = diff->generic.next;
124 	}
125 	if (!i) {
126 		fprintf(stderr, "Found no difference, exporting empty topology diff to %s\n", outputname);
127 	} else if (!j) {
128 		fprintf(stderr, "Found %u differences, exporting to %s\n", i, outputname);
129 	} else {
130 		fprintf(stderr, "Found %u differences, including %u too complex ones.\n", i, j);
131 		fprintf(stderr, "Cannot export differences to %s\n", outputname);
132 	}
133 	if (!j) {
134 		if (output) {
135 			err = hwloc_topology_diff_export_xml(topo1, firstdiff, refname, output);
136 		} else {
137 			err = hwloc_topology_diff_export_xmlbuffer(topo1, firstdiff, refname, &xmlbuffer, &xmlbuflen);
138 			if (!err) {
139 				printf("%s\n", xmlbuffer);
140 				hwloc_free_xmlbuffer(topo1, xmlbuffer);
141 			}
142 		}
143 		if (err < 0)
144 			fprintf(stderr, "Failed to export topology diff %s\n", output);
145 	}
146 
147 	hwloc_topology_diff_destroy(topo1, firstdiff);
148 
149 	hwloc_topology_destroy(topo2);
150 	hwloc_topology_destroy(topo1);
151 
152 	if (j)
153 	  exit(EXIT_FAILURE);
154 	else
155 	  exit(EXIT_SUCCESS);
156 
157 out_with_topo2:
158 	hwloc_topology_destroy(topo2);
159 out_with_topo1:
160 	hwloc_topology_destroy(topo1);
161 	exit(EXIT_FAILURE);
162 }
163