chiark / gitweb /
bootchart: use _cleanup_close_
[elogind.git] / src / bootchart / svg.c
index 414d7af9b98451584362f367c397c53e4ebe505c..79476716a6bfe20563c9c06486c7043d0acc004b 100644 (file)
@@ -103,7 +103,7 @@ static void svg_header(void)
         svg("<!-- your browser to file:///run/log/ and click. This bootchart was      -->\n\n");
 
         svg("<!-- generated by bootchart version %s, running with options:  -->\n", VERSION);
-        svg("<!-- hz=\"%f\" n=\"%d\" -->\n", hz, len);
+        svg("<!-- hz=\"%f\" n=\"%d\" -->\n", hz, samples_len);
         svg("<!-- x=\"%f\" y=\"%f\" -->\n", scale_x, scale_y);
         svg("<!-- rel=\"%d\" f=\"%d\" -->\n", relative, filter);
         svg("<!-- p=\"%d\" e=\"%d\" -->\n", pss, entropy);
@@ -150,7 +150,7 @@ static void svg_title(const char *build)
         char date[256] = "Unknown";
         char cpu[256] = "Unknown";
         char *c;
-        FILE *f;
+        FILE _cleanup_fclose_ *f = NULL;
         time_t t;
         int fd;
         struct utsname uts;
@@ -161,22 +161,21 @@ static void svg_title(const char *build)
         if (f) {
                 if (!fgets(cmdline, 255, f))
                         sprintf(cmdline, "Unknown");
-                fclose(f);
         }
 
         /* extract root fs so we can find disk model name in sysfs */
+        /* FIXME: this works only in the simple case */
         c = strstr(cmdline, "root=/dev/");
         if (c) {
                 strncpy(rootbdev, &c[10], 3);
                 rootbdev[3] = '\0';
-        }
-        sprintf(filename, "block/%s/device/model", rootbdev);
-        fd = openat(sysfd, filename, O_RDONLY);
-        f = fdopen(fd, "r");
-        if (f) {
-                if (!fgets(model, 255, f))
-                        fprintf(stderr, "Error reading disk model for %s\n", rootbdev);
-                fclose(f);
+                sprintf(filename, "block/%s/device/model", rootbdev);
+                fd = openat(sysfd, filename, O_RDONLY);
+                f = fdopen(fd, "r");
+                if (f) {
+                        if (!fgets(model, 255, f))
+                                fprintf(stderr, "Error reading disk model for %s\n", rootbdev);
+                }
         }
 
         /* various utsname parameters */
@@ -197,7 +196,6 @@ static void svg_title(const char *build)
                                 break;
                         }
                 }
-                fclose(f);
         }
 
         svg("<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
@@ -221,7 +219,7 @@ static void svg_title(const char *build)
                 svg("Not detected");
         svg("</text>\n");
         svg("<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
-            hz, len, overrun, pscount, pfiltered);
+            hz, samples_len, overrun, pscount, pfiltered);
 }
 
 
@@ -266,6 +264,20 @@ static void svg_graph_box(int height)
         }
 }
 
+/* xml comments must not contain "--" */
+static char* xml_comment_encode(const char* name) {
+        char *enc_name, *p;
+
+        enc_name = strdup(name);
+        if (!enc_name)
+                return NULL;
+
+        for (p = enc_name; *p; p++)
+                if (p[0] == '-' && p[1] == '-')
+                        p[1] = '_';
+
+        return enc_name;
+}
 
 static void svg_pss_graph(void)
 {
@@ -368,7 +380,7 @@ static void svg_pss_graph(void)
                                 top = bottom + ps->sample[i].pss;
                                 /* draw a label with the process / PID */
                                 if ((i == 1) || (ps->sample[i - 1].pss <= (100 * scale_y)))
-                                        svg("  <text x=\"%.03f\" y=\"%.03f\">%s [%i]</text>\n",
+                                        svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
                                             time_to_graph(sampletime[i] - graph_start),
                                             kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
                                             ps->name,
@@ -382,10 +394,17 @@ static void svg_pss_graph(void)
         svg("\n\n<!-- PSS map - csv format -->\n");
         ps = ps_first;
         while (ps->next_ps) {
+                char _cleanup_free_*enc_name;
                 ps = ps->next_ps;
                 if (!ps)
                         continue;
-                svg("<!-- %s [%d] pss=", ps->name, ps->pid);
+
+                enc_name = xml_comment_encode(ps->name);
+                if(!enc_name)
+                        continue;
+
+                svg("<!-- %s [%d] pss=", enc_name, ps->pid);
+
                 for (i = 0; i < samples ; i++) {
                         svg("%d," , ps->sample[i].pss);
                 }
@@ -815,14 +834,20 @@ static void svg_ps_bars(void)
         /* pass 2 - ps boxes */
         ps = ps_first;
         while ((ps = get_next_ps(ps))) {
+                char _cleanup_free_*enc_name;
+
                 double starttime;
                 int t;
 
                 if (!ps)
                         continue;
 
+                enc_name = xml_comment_encode(ps->name);
+                if(!enc_name)
+                        continue;
+
                 /* leave some trace of what we actually filtered etc. */
-                svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", ps->name, ps->pid,
+                svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
                     ps->ppid, ps->total);
 
                 /* it would be nice if we could use exec_start from /proc/pid/sched,
@@ -897,7 +922,7 @@ static void svg_ps_bars(void)
                         w = ps->first;
 
                 /* text label of process name */
-                svg("  <text x=\"%.03f\" y=\"%.03f\">%s [%i] <tspan class=\"run\">%.03fs</tspan></text>\n",
+                svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan></text>\n",
                     time_to_graph(sampletime[w] - graph_start) + 5.0,
                     ps_to_graph(j) + 14.0,
                     ps->name,
@@ -1001,7 +1026,7 @@ static void svg_top_ten_cpu(void)
 
         svg("<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - %s[%d]</text>\n",
+                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
                     20 + (n * 13),
                     top[n]->total,
                     top[n]->name,
@@ -1036,7 +1061,7 @@ static void svg_top_ten_pss(void)
 
         svg("<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - %s[%d]</text>\n",
+                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
                     20 + (n * 13),
                     top[n]->pss_max,
                     top[n]->name,