]> granicus.if.org Git - sysstat/blob - sadf_misc.c
SVG: Add SVG output for filesystems statistics
[sysstat] / sadf_misc.c
1 /*
2  * sadf_misc.c: Funtions used by sadf to display special records
3  * (C) 2011-2016 by Sebastien GODARD (sysstat <at> orange.fr)
4  *
5  ***************************************************************************
6  * This program is free software; you can redistribute it and/or modify it *
7  * under the terms of the GNU General Public License as published  by  the *
8  * Free Software Foundation; either version 2 of the License, or (at  your *
9  * option) any later version.                                              *
10  *                                                                         *
11  * This program is distributed in the hope that it  will  be  useful,  but *
12  * WITHOUT ANY WARRANTY; without the implied warranty  of  MERCHANTABILITY *
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
14  * for more details.                                                       *
15  *                                                                         *
16  * You should have received a copy of the GNU General Public License along *
17  * with this program; if not, write to the Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA              *
19  ***************************************************************************
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "sadf.h"
26 #include "sa.h"
27
28 #ifdef USE_NLS
29 #include <locale.h>
30 #include <libintl.h>
31 #define _(string) gettext(string)
32 #else
33 #define _(string) (string)
34 #endif
35
36 extern unsigned int flags;
37 extern char *seps[];
38
39 /*
40  ***************************************************************************
41  * Display restart messages (database and ppc formats).
42  *
43  * IN:
44  * @cur_date    Date string of current restart message.
45  * @cur_time    Time string of current restart message.
46  * @utc         True if @cur_time is expressed in UTC.
47  * @sep         Character used as separator.
48  * @file_hdr    System activity file standard header.
49  * @cpu_nr      CPU count associated with restart mark.
50  ***************************************************************************
51  */
52 void print_dbppc_restart(char *cur_date, char *cur_time, int utc, char sep,
53                          struct file_header *file_hdr, unsigned int cpu_nr)
54 {
55         printf("%s%c-1%c", file_hdr->sa_nodename, sep, sep);
56         if (strlen(cur_date)) {
57                 printf("%s ", cur_date);
58         }
59         printf("%s", cur_time);
60         if (strlen(cur_date) && utc) {
61                 printf(" UTC");
62         }
63         printf("%cLINUX-RESTART\t(%d CPU)\n",
64                sep, cpu_nr > 1 ? cpu_nr - 1 : 1);
65 }
66
67 /*
68  ***************************************************************************
69  * Display restart messages (ppc format).
70  *
71  * IN:
72  * @tab         Number of tabulations (unused here).
73  * @action      Action expected from current function.
74  * @cur_date    Date string of current restart message.
75  * @cur_time    Time string of current restart message.
76  * @utc         True if @cur_time is expressed in UTC.
77  * @file_hdr    System activity file standard header.
78  * @cpu_nr      CPU count associated with restart mark.
79  ***************************************************************************
80  */
81 __printf_funct_t print_db_restart(int *tab, int action, char *cur_date,
82                                   char *cur_time, int utc, struct file_header *file_hdr,
83                                   unsigned int cpu_nr)
84 {
85         /* Actions F_BEGIN and F_END ignored */
86         if (action == F_MAIN) {
87                 print_dbppc_restart(cur_date, cur_time, utc, ';', file_hdr, cpu_nr);
88         }
89 }
90
91 /*
92  ***************************************************************************
93  * Display restart messages (database format).
94  *
95  * IN:
96  * @tab         Number of tabulations (unused here).
97  * @action      Action expected from current function.
98  * @cur_date    Date string of current restart message.
99  * @cur_time    Time string of current restart message.
100  * @utc         True if @cur_time is expressed in UTC.
101  * @file_hdr    System activity file standard header.
102  * @cpu_nr      CPU count associated with restart mark.
103  ***************************************************************************
104  */
105 __printf_funct_t print_ppc_restart(int *tab, int action, char *cur_date,
106                                    char *cur_time, int utc, struct file_header *file_hdr,
107                                    unsigned int cpu_nr)
108 {
109         /* Actions F_BEGIN and F_END ignored */
110         if (action == F_MAIN) {
111                 print_dbppc_restart(cur_date, cur_time, utc, '\t', file_hdr, cpu_nr);
112         }
113 }
114
115 /*
116  ***************************************************************************
117  * Display restart messages (XML format).
118  *
119  * IN:
120  * @tab         Number of tabulations.
121  * @action      Action expected from current function.
122  * @cur_date    Date string of current restart message.
123  * @cur_time    Time string of current restart message.
124  * @utc         True if @cur_time is expressed in UTC.
125  * @file_hdr    System activity file standard header (unused here).
126  * @cpu_nr      CPU count associated with restart mark.
127  *
128  * OUT:
129  * @tab         Number of tabulations.
130  ***************************************************************************
131  */
132 __printf_funct_t print_xml_restart(int *tab, int action, char *cur_date,
133                                    char *cur_time, int utc, struct file_header *file_hdr,
134                                    unsigned int cpu_nr)
135 {
136         if (action & F_BEGIN) {
137                 xprintf((*tab)++, "<restarts>");
138         }
139         if (action & F_MAIN) {
140                 xprintf(*tab, "<boot date=\"%s\" time=\"%s\" utc=\"%d\" cpu_count=\"%d\"/>",
141                         cur_date, cur_time, utc ? 1 : 0, cpu_nr > 1 ? cpu_nr - 1 : 1);
142         }
143         if (action & F_END) {
144                 xprintf(--(*tab), "</restarts>");
145         }
146 }
147
148 /*
149  ***************************************************************************
150  * Display restart messages (JSON format).
151  *
152  * IN:
153  * @tab         Number of tabulations.
154  * @action      Action expected from current function.
155  * @cur_date    Date string of current restart message.
156  * @cur_time    Time string of current restart message.
157  * @utc         True if @cur_time is expressed in UTC.
158  * @file_hdr    System activity file standard header (unused here).
159  * @cpu_nr      CPU count associated with restart mark.
160  *
161  * OUT:
162  * @tab         Number of tabulations.
163  ***************************************************************************
164  */
165 __printf_funct_t print_json_restart(int *tab, int action, char *cur_date,
166                                     char *cur_time, int utc, struct file_header *file_hdr,
167                                     unsigned int cpu_nr)
168 {
169         static int sep = FALSE;
170
171         if (action & F_BEGIN) {
172                 printf(",\n");
173                 xprintf((*tab)++, "\"restarts\": [");
174         }
175         if (action & F_MAIN) {
176                 if (sep) {
177                         printf(",\n");
178                 }
179                 xprintf((*tab)++, "{");
180                 xprintf(*tab, "\"boot\": {\"date\": \"%s\", \"time\": \"%s\", \"utc\": %d, \"cpu_count\": %d}",
181                         cur_date, cur_time, utc ? 1 : 0, cpu_nr > 1 ? cpu_nr - 1 : 1);
182                 xprintf0(--(*tab), "}");
183                 sep = TRUE;
184         }
185         if (action & F_END) {
186                 if (sep) {
187                         printf("\n");
188                         sep = FALSE;
189                 }
190                 xprintf0(--(*tab), "]");
191         }
192 }
193
194 /*
195  ***************************************************************************
196  * Display comments (database and ppc formats).
197  *
198  * IN:
199  * @cur_date    Date string of current restart message.
200  * @cur_time    Time string of current restart message.
201  * @utc         True if @cur_time is expressed in UTC.
202  * @comment     Comment to display.
203  * @sep         Character used as separator.
204  * @file_hdr    System activity file standard header.
205  ***************************************************************************
206  */
207 void print_dbppc_comment(char *cur_date, char *cur_time, int utc,
208                          char *comment, char sep, struct file_header *file_hdr)
209 {
210         printf("%s%c-1%c", file_hdr->sa_nodename, sep, sep);
211         if (strlen(cur_date)) {
212                 printf("%s ", cur_date);
213         }
214         printf("%s", cur_time);
215         if (strlen(cur_date) && utc) {
216                 printf(" UTC");
217         }
218         printf("%cCOM %s\n", sep, comment);
219 }
220
221 /*
222  ***************************************************************************
223  * Display comments (database format).
224  *
225  * IN:
226  * @tab         Number of tabulations (unused here).
227  * @action      Action expected from current function.
228  * @cur_date    Date string of current restart message.
229  * @cur_time    Time string of current restart message.
230  * @utc         True if @cur_time is expressed in UTC.
231  * @comment     Comment to display.
232  * @file_hdr    System activity file standard header.
233  ***************************************************************************
234  */
235 __printf_funct_t print_db_comment(int *tab, int action, char *cur_date,
236                                   char *cur_time, int utc, char *comment,
237                                   struct file_header *file_hdr)
238 {
239         /* Actions F_BEGIN and F_END ignored */
240         if (action & F_MAIN) {
241                 print_dbppc_comment(cur_date, cur_time, utc, comment,
242                                     ';', file_hdr);
243         }
244 }
245
246 /*
247  ***************************************************************************
248  * Display comments (ppc format).
249  *
250  * IN:
251  * @tab         Number of tabulations (unused here).
252  * @action      Action expected from current function.
253  * @cur_date    Date string of current restart message.
254  * @cur_time    Time string of current restart message.
255  * @utc         True if @cur_time is expressed in UTC.
256  * @comment     Comment to display.
257  * @file_hdr    System activity file standard header.
258  ***************************************************************************
259  */
260 __printf_funct_t print_ppc_comment(int *tab, int action, char *cur_date,
261                                    char *cur_time, int utc, char *comment,
262                                    struct file_header *file_hdr)
263 {
264         /* Actions F_BEGIN and F_END ignored */
265         if (action & F_MAIN) {
266                 print_dbppc_comment(cur_date, cur_time, utc, comment,
267                                     '\t', file_hdr);
268         }
269 }
270
271 /*
272  ***************************************************************************
273  * Display comments (XML format).
274  *
275  * IN:
276  * @tab         Number of tabulations.
277  * @action      Action expected from current function.
278  * @cur_date    Date string of current comment.
279  * @cur_time    Time string of current comment.
280  * @utc         True if @cur_time is expressed in UTC.
281  * @comment     Comment to display.
282  * @file_hdr    System activity file standard header (unused here).
283  *
284  * OUT:
285  * @tab         Number of tabulations.
286  ***************************************************************************
287  */
288 __printf_funct_t print_xml_comment(int *tab, int action, char *cur_date,
289                                    char *cur_time, int utc, char *comment,
290                                    struct file_header *file_hdr)
291 {
292         if (action & F_BEGIN) {
293                 xprintf((*tab)++, "<comments>");
294         }
295         if (action & F_MAIN) {
296                 xprintf(*tab, "<comment date=\"%s\" time=\"%s\" utc=\"%d\" com=\"%s\"/>",
297                         cur_date, cur_time, utc ? 1 : 0, comment);
298         }
299         if (action & F_END) {
300                 xprintf(--(*tab), "</comments>");
301         }
302 }
303
304 /*
305  ***************************************************************************
306  * Display comments (JSON format).
307  *
308  * IN:
309  * @tab         Number of tabulations.
310  * @action      Action expected from current function.
311  * @cur_date    Date string of current comment.
312  * @cur_time    Time string of current comment.
313  * @utc         True if @cur_time is expressed in UTC.
314  * @comment     Comment to display.
315  * @file_hdr    System activity file standard header (unused here).
316  *
317  * OUT:
318  * @tab         Number of tabulations.
319  ***************************************************************************
320  */
321 __printf_funct_t print_json_comment(int *tab, int action, char *cur_date,
322                                     char *cur_time, int utc, char *comment,
323                                     struct file_header *file_hdr)
324 {
325         static int sep = FALSE;
326
327         if (action & F_BEGIN) {
328                 printf(",\n");
329                 xprintf((*tab)++, "\"comments\": [");
330         }
331         if (action & F_MAIN) {
332                 if (sep) {
333                         printf(",\n");
334                 }
335                 xprintf((*tab)++, "{");
336                 xprintf(*tab,
337                         "\"comment\": {\"date\": \"%s\", \"time\": \"%s\", "
338                         "\"utc\": %d, \"com\": \"%s\"}",
339                         cur_date, cur_time, utc ? 1 : 0, comment);
340                 xprintf0(--(*tab), "}");
341                 sep = TRUE;
342         }
343         if (action & F_END) {
344                 if (sep) {
345                         printf("\n");
346                         sep = FALSE;
347                 }
348                 xprintf0(--(*tab), "]");
349         }
350 }
351
352 /*
353  ***************************************************************************
354  * Display the "statistics" part of the report (XML format).
355  *
356  * IN:
357  * @tab         Number of tabulations.
358  * @action      Action expected from current function.
359  *
360  * OUT:
361  * @tab         Number of tabulations.
362  ***************************************************************************
363  */
364 __printf_funct_t print_xml_statistics(int *tab, int action)
365 {
366         if (action & F_BEGIN) {
367                 xprintf((*tab)++, "<statistics>");
368         }
369         if (action & F_END) {
370                 xprintf(--(*tab), "</statistics>");
371         }
372 }
373
374 /*
375  ***************************************************************************
376  * Display the "statistics" part of the report (JSON format).
377  *
378  * IN:
379  * @tab         Number of tabulations.
380  * @action      Action expected from current function.
381  *
382  * OUT:
383  * @tab         Number of tabulations.
384  ***************************************************************************
385  */
386 __printf_funct_t print_json_statistics(int *tab, int action)
387 {
388         static int sep = FALSE;
389
390         if (action & F_BEGIN) {
391                 printf(",\n");
392                 xprintf((*tab)++, "\"statistics\": [");
393         }
394         if (action & F_MAIN) {
395                 if (sep) {
396                         xprintf(--(*tab), "},");
397                 }
398                 xprintf((*tab)++, "{");
399                 sep = TRUE;
400         }
401         if (action & F_END) {
402                 if (sep) {
403                         xprintf(--(*tab), "}");
404                         sep = FALSE;
405                 }
406                 xprintf0(--(*tab), "]");
407         }
408 }
409
410 /*
411  ***************************************************************************
412  * Display the "timestamp" part of the report (db and ppc format).
413  *
414  * IN:
415  * @fmt         Output format (F_DB_OUTPUT or F_PPC_OUTPUT).
416  * @file_hdr    System activity file standard header.
417  * @cur_date    Date string of current record.
418  * @cur_time    Time string of current record.
419  * @utc         True if @cur_time is expressed in UTC.
420  * @itv         Interval of time with preceding record.
421  *
422  * RETURNS:
423  * Pointer on the "timestamp" string.
424  ***************************************************************************
425  */
426 char *print_dbppc_timestamp(int fmt, struct file_header *file_hdr, char *cur_date,
427                             char *cur_time, int utc, unsigned long long itv)
428 {
429         int isdb = (fmt == F_DB_OUTPUT);
430         static char pre[80];
431         char temp[80];
432
433         /* This substring appears on every output line, preformat it here */
434         snprintf(pre, 80, "%s%s%lld%s",
435                  file_hdr->sa_nodename, seps[isdb], itv, seps[isdb]);
436         if (strlen(cur_date)) {
437                 snprintf(temp, 80, "%s%s ", pre, cur_date);
438         }
439         else {
440                 strcpy(temp, pre);
441         }
442         snprintf(pre, 80, "%s%s%s", temp, cur_time,
443                  strlen(cur_date) && utc ? " UTC" : "");
444         pre[79] = '\0';
445
446         if (DISPLAY_HORIZONTALLY(flags)) {
447                 printf("%s", pre);
448         }
449
450         return pre;
451 }
452
453 /*
454  ***************************************************************************
455  * Display the "timestamp" part of the report (ppc format).
456  *
457  * IN:
458  * @parm        Pointer on specific parameters (unused here).
459  * @action      Action expected from current function.
460  * @cur_date    Date string of current record.
461  * @cur_time    Time string of current record.
462  * @itv         Interval of time with preceding record.
463  * @file_hdr    System activity file standard header.
464  * @flags       Flags for common options.
465  *
466  * RETURNS:
467  * Pointer on the "timestamp" string.
468  ***************************************************************************
469  */
470 __tm_funct_t print_ppc_timestamp(void *parm, int action, char *cur_date,
471                                  char *cur_time, unsigned long long itv,
472                                  struct file_header *file_hdr, unsigned int flags)
473 {
474         int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
475
476         if (action & F_BEGIN) {
477                 return print_dbppc_timestamp(F_PPC_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
478         }
479         if (action & F_END) {
480                 if (DISPLAY_HORIZONTALLY(flags)) {
481                         printf("\n");
482                 }
483         }
484
485         return NULL;
486 }
487
488 /*
489  ***************************************************************************
490  * Display the "timestamp" part of the report (db format).
491  *
492  * IN:
493  * @parm        Pointer on specific parameters (unused here).
494  * @action      Action expected from current function.
495  * @cur_date    Date string of current record.
496  * @cur_time    Time string of current record.
497  * @itv         Interval of time with preceding record.
498  * @file_hdr    System activity file standard header.
499  * @flags       Flags for common options.
500  *
501  * RETURNS:
502  * Pointer on the "timestamp" string.
503  ***************************************************************************
504  */
505 __tm_funct_t print_db_timestamp(void *parm, int action, char *cur_date,
506                                 char *cur_time, unsigned long long itv,
507                                 struct file_header *file_hdr, unsigned int flags)
508 {
509         int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
510
511         if (action & F_BEGIN) {
512                 return print_dbppc_timestamp(F_DB_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
513         }
514         if (action & F_END) {
515                 if (DISPLAY_HORIZONTALLY(flags)) {
516                         printf("\n");
517                 }
518         }
519
520         return NULL;
521 }
522
523 /*
524  ***************************************************************************
525  * Display the "timestamp" part of the report (XML format).
526  *
527  * IN:
528  * @parm        Specific parameter. Here: number of tabulations.
529  * @action      Action expected from current function.
530  * @cur_date    Date string of current comment.
531  * @cur_time    Time string of current comment.
532  * @utc         True if @cur_time is expressed in UTC.
533  * @itv         Interval of time with preceding record.
534  *
535  * OUT:
536  * @tab         Number of tabulations.
537  ***************************************************************************
538  */
539 __tm_funct_t print_xml_timestamp(void *parm, int action, char *cur_date,
540                                  char *cur_time, unsigned long long itv,
541                                  struct file_header *file_hdr, unsigned int flags)
542 {
543         int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
544         int *tab = (int *) parm;
545
546         if (action & F_BEGIN) {
547                 xprintf((*tab)++, "<timestamp date=\"%s\" time=\"%s\" utc=\"%d\" interval=\"%llu\">",
548                         cur_date, cur_time, utc ? 1 : 0, itv);
549         }
550         if (action & F_END) {
551                 xprintf(--(*tab), "</timestamp>");
552         }
553
554         return NULL;
555 }
556
557 /*
558  ***************************************************************************
559  * Display the "timestamp" part of the report (JSON format).
560  *
561  * IN:
562  * @parm        Specific parameter. Here: number of tabulations.
563  * @action      Action expected from current function.
564  * @cur_date    Date string of current comment.
565  * @cur_time    Time string of current comment.
566  * @utc         True if @cur_time is expressed in UTC.
567  * @itv         Interval of time with preceding record.
568  *
569  * OUT:
570  * @tab         Number of tabulations.
571  ***************************************************************************
572  */
573 __tm_funct_t print_json_timestamp(void *parm, int action, char *cur_date,
574                                   char *cur_time, unsigned long long itv,
575                                   struct file_header *file_hdr, unsigned int flags)
576 {
577         int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
578         int *tab = (int *) parm;
579
580         if (action & F_BEGIN) {
581                 xprintf0(*tab,
582                          "\"timestamp\": {\"date\": \"%s\", \"time\": \"%s\", "
583                          "\"utc\": %d, \"interval\": %llu}",
584                          cur_date, cur_time, utc ? 1 : 0, itv);
585         }
586         if (action & F_MAIN) {
587                 printf(",\n");
588         }
589         if (action & F_END) {
590                 printf("\n");
591         }
592
593         return NULL;
594 }
595
596 /*
597  ***************************************************************************
598  * Display the header of the report (XML format).
599  *
600  * IN:
601  * @parm        Specific parameter. Here: number of tabulations.
602  * @action      Action expected from current function.
603  * @dfile       Name of system activity data file.
604  * @file_magic  System activity file magic header.
605  * @file_hdr    System activity file standard header.
606  * @cpu_nr      Number of processors for current daily data file.
607  * @act         Array of activities (unused here).
608  * @id_seq      Activity sequence (unused here).
609  *
610  * OUT:
611  * @tab         Number of tabulations.
612  ***************************************************************************
613  */
614 __printf_funct_t print_xml_header(void *parm, int action, char *dfile,
615                                   struct file_magic *file_magic,
616                                   struct file_header *file_hdr, __nr_t cpu_nr,
617                                   struct activity *act[], unsigned int id_seq[])
618 {
619         struct tm rectime, *loc_t;
620         char cur_time[32];
621         int *tab = (int *) parm;
622
623         if (action & F_BEGIN) {
624                 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
625                 printf("<!DOCTYPE sysstat PUBLIC \"DTD v%s sysstat //EN\"\n",
626                        XML_DTD_VERSION);
627                 printf("\"http://pagesperso-orange.fr/sebastien.godard/sysstat-%s.dtd\">\n",
628                        XML_DTD_VERSION);
629
630                 xprintf(*tab, "<sysstat\n"
631                               "xmlns=\"http://pagesperso-orange.fr/sebastien.godard/sysstat\"\n"
632                               "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
633                               "xsi:schemaLocation=\"http://pagesperso-orange.fr/sebastien.godard sysstat.xsd\">");
634
635                 xprintf(++(*tab), "<sysdata-version>%s</sysdata-version>",
636                         XML_DTD_VERSION);
637
638                 xprintf(*tab, "<host nodename=\"%s\">", file_hdr->sa_nodename);
639                 xprintf(++(*tab), "<sysname>%s</sysname>", file_hdr->sa_sysname);
640                 xprintf(*tab, "<release>%s</release>", file_hdr->sa_release);
641
642                 xprintf(*tab, "<machine>%s</machine>", file_hdr->sa_machine);
643                 xprintf(*tab, "<number-of-cpus>%d</number-of-cpus>",
644                         cpu_nr > 1 ? cpu_nr - 1 : 1);
645
646                 /* Fill file timestmap structure (rectime) */
647                 get_file_timestamp_struct(flags, &rectime, file_hdr);
648                 strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
649                 xprintf(*tab, "<file-date>%s</file-date>", cur_time);
650
651                 if ((loc_t = gmtime((const time_t *) &file_hdr->sa_ust_time)) != NULL) {
652                         strftime(cur_time, sizeof(cur_time), "%T", loc_t);
653                         xprintf(*tab, "<file-utc-time>%s</file-utc-time>", cur_time);
654                 }
655
656         }
657         if (action & F_END) {
658                 xprintf(--(*tab), "</host>");
659                 xprintf(--(*tab), "</sysstat>");
660         }
661 }
662
663 /*
664  ***************************************************************************
665  * Display the header of the report (JSON format).
666  *
667  * IN:
668  * @parm        Specific parameter. Here: number of tabulations.
669  * @action      Action expected from current function.
670  * @dfile       Name of system activity data file.
671  * @file_magic  System activity file magic header.
672  * @file_hdr    System activity file standard header.
673  * @cpu_nr      Number of processors for current daily data file.
674  * @act         Array of activities (unused here).
675  * @id_seq      Activity sequence (unused here).
676  *
677  * OUT:
678  * @tab         Number of tabulations.
679  ***************************************************************************
680  */
681 __printf_funct_t print_json_header(void *parm, int action, char *dfile,
682                                    struct file_magic *file_magic,
683                                    struct file_header *file_hdr, __nr_t cpu_nr,
684                                    struct activity *act[], unsigned int id_seq[])
685 {
686         struct tm rectime, *loc_t;
687         char cur_time[32];
688         int *tab = (int *) parm;
689
690         if (action & F_BEGIN) {
691                 xprintf(*tab, "{\"sysstat\": {");
692
693                 xprintf(++(*tab), "\"sysdata-version\": %s,",
694                         XML_DTD_VERSION);
695
696                 xprintf(*tab, "\"hosts\": [");
697                 xprintf(++(*tab), "{");
698                 xprintf(++(*tab), "\"nodename\": \"%s\",", file_hdr->sa_nodename);
699                 xprintf(*tab, "\"sysname\": \"%s\",", file_hdr->sa_sysname);
700                 xprintf(*tab, "\"release\": \"%s\",", file_hdr->sa_release);
701
702                 xprintf(*tab, "\"machine\": \"%s\",", file_hdr->sa_machine);
703                 xprintf(*tab, "\"number-of-cpus\": %d,",
704                         cpu_nr > 1 ? cpu_nr - 1 : 1);
705
706                 /* Fill file timestmap structure (rectime) */
707                 get_file_timestamp_struct(flags, &rectime, file_hdr);
708                 strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
709                 xprintf0(*tab, "\"file-date\": \"%s\"", cur_time);
710
711                 if ((loc_t = gmtime((const time_t *) &file_hdr->sa_ust_time)) != NULL) {
712                         strftime(cur_time, sizeof(cur_time), "%T", loc_t);
713                         printf(",\n");
714                         xprintf0(*tab, "\"file-utc-time\": \"%s\"", cur_time);
715                 }
716
717         }
718         if (action & F_END) {
719                 printf("\n");
720                 xprintf(--(*tab), "}");
721                 xprintf(--(*tab), "]");
722                 xprintf(--(*tab), "}}");
723         }
724 }
725
726 /*
727  ***************************************************************************
728  * Display data file header.
729  *
730  * IN:
731  * @parm        Specific parameter (unused here).
732  * @action      Action expected from current function.
733  * @dfile       Name of system activity data file.
734  * @file_magic  System activity file magic header.
735  * @file_hdr    System activity file standard header.
736  * @cpu_nr      Number of processors for current daily data file.
737  * @act         Array of activities.
738  * @id_seq      Activity sequence.
739  ***************************************************************************
740  */
741 __printf_funct_t print_hdr_header(void *parm, int action, char *dfile,
742                                   struct file_magic *file_magic,
743                                   struct file_header *file_hdr, __nr_t cpu_nr,
744                                   struct activity *act[], unsigned int id_seq[])
745 {
746         int i, p;
747         struct tm rectime, *loc_t;
748         char cur_time[32];
749
750         /* Actions F_MAIN and F_END ignored */
751         if (action & F_BEGIN) {
752                 printf(_("System activity data file: %s (%#x)\n"),
753                        dfile, file_magic->format_magic);
754
755                 display_sa_file_version(stdout, file_magic);
756
757                 if (file_magic->format_magic != FORMAT_MAGIC) {
758                         return;
759                 }
760
761                 printf(_("Genuine sa datafile: %s (%x)\n"),
762                        file_magic->upgraded ? _("no") : _("yes"),
763                        file_magic->upgraded);
764
765                 printf(_("Host: "));
766                 print_gal_header(localtime((const time_t *) &(file_hdr->sa_ust_time)),
767                                  file_hdr->sa_sysname, file_hdr->sa_release,
768                                  file_hdr->sa_nodename, file_hdr->sa_machine,
769                                  cpu_nr > 1 ? cpu_nr - 1 : 1);
770
771                 printf(_("Number of CPU for last samples in file: %u\n"),
772                        file_hdr->sa_last_cpu_nr > 1 ? file_hdr->sa_last_cpu_nr - 1 : 1);
773
774                 /* Fill file timestmap structure (rectime) */
775                 get_file_timestamp_struct(flags, &rectime, file_hdr);
776                 strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
777                 printf(_("File date: %s\n"), cur_time);
778
779                 if ((loc_t = gmtime((const time_t *) &file_hdr->sa_ust_time)) != NULL) {
780                         printf(_("File time: "));
781                         strftime(cur_time, sizeof(cur_time), "%T", loc_t);
782                         printf("%s UTC\n", cur_time);
783                 }
784
785                 printf(_("Size of a long int: %d\n"), file_hdr->sa_sizeof_long);
786
787                 /* Number of activities (number of volatile activities) in file */
788                 printf("sa_act_nr (sa_vol_act_nr): %u (%u)\n",
789                        file_hdr->sa_act_nr, file_hdr->sa_vol_act_nr);
790
791                 printf(_("List of activities:\n"));
792
793                 for (i = 0; i < NR_ACT; i++) {
794                         if (!id_seq[i])
795                                 continue;
796
797                         p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
798
799                         printf("%02d: %s\t(x%d)", act[p]->id, act[p]->name, act[p]->nr);
800                         if (act[p]->f_count2 || (act[p]->nr2 > 1)) {
801                                 printf("\t(x%d)", act[p]->nr2);
802                         }
803                         if (act[p]->magic == ACTIVITY_MAGIC_UNKNOWN) {
804                                 printf(_("\t[Unknown activity format]"));
805                         }
806                         printf("\n");
807                 }
808         }
809 }
810
811 /*
812  ***************************************************************************
813  * Display the header of the report (SVG format).
814  *
815  * IN:
816  * @parm        Specific parameter. Here: number of graphs to display.
817  * @action      Action expected from current function.
818  * @dfile       Name of system activity data file (unused here).
819  * @file_magic  System activity file magic header (unused here).
820  * @file_hdr    System activity file standard header.
821  * @cpu_nr      Number of processors for current daily data file.
822  * @act         Array of activities (unused here).
823  * @id_seq      Activity sequence (unused here).
824  ***************************************************************************
825  */
826 __printf_funct_t print_svg_header(void *parm, int action, char *dfile,
827                                   struct file_magic *file_magic,
828                                   struct file_header *file_hdr, __nr_t cpu_nr,
829                                   struct activity *act[], unsigned int id_seq[])
830 {
831         int *graph_nr = (int *) parm;
832
833         if (action & F_BEGIN) {
834                 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
835                 printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
836                 printf("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
837                 printf("<svg xmlns=\"http://www.w3.org/2000/svg\"");
838                 if (action & F_END) {
839                         printf(">\n");
840                 }
841         }
842
843         if (action & F_MAIN) {
844                 printf(" width=\"%d\" height=\"%d\""
845                        " fill=\"black\" stroke=\"gray\" stroke-width=\"1\">\n",
846                        SVG_V_XSIZE, SVG_H_YSIZE + SVG_T_YSIZE * (*graph_nr));
847                 printf("<text x= \"0\" y=\"30\" text-anchor=\"start\" stroke=\"brown\">");
848                 print_gal_header(localtime((const time_t *) &(file_hdr->sa_ust_time)),
849                                  file_hdr->sa_sysname, file_hdr->sa_release,
850                                  file_hdr->sa_nodename, file_hdr->sa_machine,
851                                  cpu_nr > 1 ? cpu_nr - 1 : 1);
852                 printf("</text>\n");
853         }
854
855         if (action & F_END) {
856                 printf("</svg>\n");
857         }
858 }