]> granicus.if.org Git - sysstat/blob - sa_common.c
A_IRQ: sar: Always display a header line for each sample
[sysstat] / sa_common.c
1 /*
2  * sar and sadf common routines.
3  * (C) 1999-2021 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 #include <stdlib.h>
25 #include <stdint.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <unistd.h>     /* For STDOUT_FILENO, among others */
29 #include <dirent.h>
30 #include <fcntl.h>
31 #include <limits.h>
32 #include <libgen.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <ctype.h>
36
37 #include "version.h"
38 #include "sa.h"
39 #include "ioconf.h"
40
41 #ifdef USE_NLS
42 #include <locale.h>
43 #include <libintl.h>
44 #define _(string) gettext(string)
45 #else
46 #define _(string) (string)
47 #endif
48
49 int default_file_used = FALSE;
50 extern struct act_bitmap cpu_bitmap;
51 extern unsigned int dm_major;
52
53 unsigned int hdr_types_nr[] = {FILE_HEADER_ULL_NR, FILE_HEADER_UL_NR, FILE_HEADER_U_NR};
54 unsigned int act_types_nr[] = {FILE_ACTIVITY_ULL_NR, FILE_ACTIVITY_UL_NR, FILE_ACTIVITY_U_NR};
55 unsigned int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
56 unsigned int extra_desc_types_nr[] = {EXTRA_DESC_ULL_NR, EXTRA_DESC_UL_NR, EXTRA_DESC_U_NR};
57 unsigned int nr_types_nr[]  = {0, 0, 1};
58
59 /*
60  ***************************************************************************
61  * Look for activity in array.
62  *
63  * IN:
64  * @act         Array of activities.
65  * @act_flag    Activity flag to look for.
66  * @stop        TRUE if sysstat should exit when activity is not found.
67  *
68  * RETURNS:
69  * Position of activity in array, or -1 if not found (this may happen when
70  * reading data from a system activity file created by another version of
71  * sysstat).
72  ***************************************************************************
73  */
74 int get_activity_position(struct activity *act[], unsigned int act_flag, int stop)
75 {
76         int i;
77
78         for (i = 0; i < NR_ACT; i++) {
79                 if (act[i]->id == act_flag)
80                         return i;
81         }
82
83         if (stop) {
84                 PANIC((int) act_flag);
85         }
86
87         return -1;
88 }
89
90 /*
91  ***************************************************************************
92  * Count number of activities with given option.
93  *
94  * IN:
95  * @act                 Array of activities.
96  * @option              Option that activities should have to be counted
97  *                      (eg. AO_COLLECTED...)
98  * @count_outputs       TRUE if each output should be counted for activities with
99  *                      multiple outputs.
100  *
101  * RETURNS:
102  * Number of selected activities
103  ***************************************************************************
104  */
105 int get_activity_nr(struct activity *act[], unsigned int option, int count_outputs)
106 {
107         int i, n = 0;
108         unsigned int msk;
109
110         for (i = 0; i < NR_ACT; i++) {
111                 if ((act[i]->options & option) == option) {
112
113                         if (HAS_MULTIPLE_OUTPUTS(act[i]->options) && count_outputs) {
114                                 for (msk = 1; msk < 0x100; msk <<= 1) {
115                                         if ((act[i]->opt_flags & 0xff) & msk) {
116                                                 n++;
117                                         }
118                                 }
119                         }
120                         else {
121                                 n++;
122                         }
123                 }
124         }
125
126         return n;
127 }
128
129 /*
130  ***************************************************************************
131  * Look for the most recent of saDD and saYYYYMMDD to decide which one to
132  * use. If neither exists then use saDD by default.
133  *
134  * IN:
135  * @sa_dir      Directory where standard daily data files are saved.
136  * @rectime     Structure containing the current date.
137  *
138  * OUT:
139  * @sa_name     0 to use saDD data files,
140  *              1 to use saYYYYMMDD data files.
141  ***************************************************************************
142  */
143 void guess_sa_name(char *sa_dir, struct tm *rectime, int *sa_name)
144 {
145         char filename[MAX_FILE_LEN];
146         struct stat sb;
147         time_t sa_mtime;
148         long nsec;
149
150         /* Use saDD by default */
151         *sa_name = 0;
152
153         /* Look for saYYYYMMDD */
154         snprintf(filename, sizeof(filename),
155                  "%s/sa%04d%02d%02d", sa_dir,
156                  rectime->tm_year + 1900,
157                  rectime->tm_mon + 1,
158                  rectime->tm_mday);
159         filename[sizeof(filename) - 1] = '\0';
160
161         if (stat(filename, &sb) < 0)
162                 /* Cannot find or access saYYYYMMDD, so use saDD */
163                 return;
164         sa_mtime = sb.st_mtime;
165         nsec = sb.st_mtim.tv_nsec;
166
167         /* Look for saDD */
168         snprintf(filename, sizeof(filename),
169                  "%s/sa%02d", sa_dir,
170                  rectime->tm_mday);
171         filename[sizeof(filename) - 1] = '\0';
172
173         if (stat(filename, &sb) < 0) {
174                 /* Cannot find or access saDD, so use saYYYYMMDD */
175                 *sa_name = 1;
176                 return;
177         }
178
179         if ((sa_mtime > sb.st_mtime) ||
180             ((sa_mtime == sb.st_mtime) && (nsec > sb.st_mtim.tv_nsec))) {
181                 /* saYYYYMMDD is more recent than saDD, so use it */
182                 *sa_name = 1;
183         }
184 }
185
186 /*
187  ***************************************************************************
188  * Set current daily data file name.
189  *
190  * IN:
191  * @datafile    If not an empty string then this is the alternate directory
192  *              location where daily data files will be saved.
193  * @d_off       Day offset (number of days to go back in the past).
194  * @sa_name     0 for saDD data files,
195  *              1 for saYYYYMMDD data files,
196  *              -1 if unknown. In this case, will look for the most recent
197  *              of saDD and saYYYYMMDD and use it.
198  *
199  * OUT:
200  * @datafile    Name of daily data file.
201  ***************************************************************************
202  */
203 void set_default_file(char *datafile, int d_off, int sa_name)
204 {
205         char sa_dir[MAX_FILE_LEN];
206         struct tm rectime = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL};
207         int err = 0;
208
209         /* Set directory where daily data files will be saved */
210         if (datafile[0]) {
211                 strncpy(sa_dir, datafile, sizeof(sa_dir));
212         }
213         else {
214                 strncpy(sa_dir, SA_DIR, sizeof(sa_dir));
215         }
216         sa_dir[sizeof(sa_dir) - 1] = '\0';
217
218         get_time(&rectime, d_off);
219         if (sa_name < 0) {
220                 /*
221                  * Look for the most recent of saDD and saYYYYMMDD
222                  * and use it. If neither exists then use saDD.
223                  * sa_name is set accordingly.
224                  */
225                 guess_sa_name(sa_dir, &rectime, &sa_name);
226         }
227         if (sa_name) {
228                 /* Using saYYYYMMDD data files */
229                 err = snprintf(datafile, MAX_FILE_LEN,
230                                "%s/sa%04d%02d%02d", sa_dir,
231                                rectime.tm_year + 1900,
232                                rectime.tm_mon + 1,
233                                rectime.tm_mday);
234         }
235         else {
236                 /* Using saDD data files */
237                 err = snprintf(datafile, MAX_FILE_LEN,
238                                "%s/sa%02d", sa_dir,
239                                rectime.tm_mday);
240         }
241         datafile[MAX_FILE_LEN - 1] = '\0';
242
243         if ((err < 0) || (err >= MAX_FILE_LEN)) {
244                 fprintf(stderr, "%s: %s\n", __FUNCTION__, datafile);
245                 exit(1);
246         }
247
248         default_file_used = TRUE;
249
250 #ifdef DEBUG
251         fprintf(stderr, "%s: Datafile: %s\n", __FUNCTION__, datafile);
252 #endif
253 }
254
255 /*
256  ***************************************************************************
257  * Check data file type. If it is a directory then this is the alternate
258  * location where daily data files will be saved.
259  *
260  * IN:
261  * @datafile    Name of the daily data file. May be a directory.
262  * @d_off       Day offset (number of days to go back in the past).
263  * @sa_name     0 for saDD data files,
264  *              1 for saYYYYMMDD data files,
265  *              -1 if unknown. In this case, will look for the most recent
266  *              of saDD and saYYYYMMDD and use it.
267  *
268  *
269  * OUT:
270  * @datafile    Name of the daily data file. This is now a plain file, not
271  *              a directory.
272  *
273  * RETURNS:
274  * 1 if @datafile was a directory, and 0 otherwise.
275  ***************************************************************************
276  */
277 int check_alt_sa_dir(char *datafile, int d_off, int sa_name)
278 {
279         if (check_dir(datafile)) {
280                 /*
281                  * This is a directory: So append
282                  * the default file name to it.
283                  */
284                 set_default_file(datafile, d_off, sa_name);
285                 return 1;
286         }
287
288         return 0;
289 }
290
291 /*
292  ***************************************************************************
293  * Display sysstat version used to create system activity data file.
294  *
295  * IN:
296  * @st          Output stream (stderr or stdout).
297  * @file_magic  File magic header.
298  ***************************************************************************
299  */
300 void display_sa_file_version(FILE *st, struct file_magic *file_magic)
301 {
302         fprintf(st, _("File created by sar/sadc from sysstat version %d.%d.%d"),
303                 file_magic->sysstat_version,
304                 file_magic->sysstat_patchlevel,
305                 file_magic->sysstat_sublevel);
306
307         if (file_magic->sysstat_extraversion) {
308                 fprintf(st, ".%d", file_magic->sysstat_extraversion);
309         }
310         fprintf(st, "\n");
311 }
312
313 /*
314  ***************************************************************************
315  * An invalid system activity file has been opened for reading.
316  * If this file was created by an old version of sysstat, tell it to the
317  * user...
318  *
319  * IN:
320  * @fd          Descriptor of the file that has been opened.
321  * @file_magic  file_magic structure filled with file magic header data.
322  *              May contain invalid data.
323  * @file        Name of the file being read.
324  * @n           Number of bytes read while reading file magic header.
325  *              This function may also be called after failing to read file
326  *              standard header, or if CPU activity has not been found in
327  *              file. In this case, n is set to 0.
328  ***************************************************************************
329  */
330 void handle_invalid_sa_file(int fd, struct file_magic *file_magic, char *file,
331                             int n)
332 {
333         unsigned short fmt_magic;
334
335         fprintf(stderr, _("Invalid system activity file: %s\n"), file);
336
337         if (n == FILE_MAGIC_SIZE) {
338                 if ((file_magic->sysstat_magic == SYSSTAT_MAGIC) || (file_magic->sysstat_magic == SYSSTAT_MAGIC_SWAPPED)) {
339                         /* This is a sysstat file, but this file has an old format */
340                         display_sa_file_version(stderr, file_magic);
341
342                         fmt_magic = file_magic->sysstat_magic == SYSSTAT_MAGIC ?
343                                     file_magic->format_magic : __builtin_bswap16(file_magic->format_magic);
344                         fprintf(stderr,
345                                 _("Current sysstat version cannot read the format of this file (%#x)\n"),
346                                 fmt_magic);
347                         if (fmt_magic >= FORMAT_MAGIC_2171) {
348                                 fprintf(stderr,
349                                         _("Try to convert it to current format. Enter:\n\n"));
350                                 fprintf(stderr, "sadf -c %s > %s.new\n\n", file, file);
351                                 fprintf(stderr,
352                                         _("You should then be able to read the new file created (%s.new)\n"),
353                                         file);
354                         }
355                 }
356         }
357
358         close (fd);
359         exit(3);
360 }
361
362 /*
363  ***************************************************************************
364  * Display an error message then exit.
365  ***************************************************************************
366  */
367 void print_collect_error(void)
368 {
369         fprintf(stderr, _("Requested activities not available\n"));
370         exit(1);
371 }
372
373 /*
374  ***************************************************************************
375  * Fill system activity file magic header.
376  *
377  * IN:
378  * @file_magic  System activity file magic header.
379  ***************************************************************************
380  */
381 void enum_version_nr(struct file_magic *fm)
382 {
383         char *v;
384         char version[16];
385
386         fm->sysstat_extraversion = 0;
387
388         strcpy(version, VERSION);
389
390         /* Get version number */
391         if ((v = strtok(version, ".")) == NULL)
392                 return;
393         fm->sysstat_version = atoi(v) & 0xff;
394
395         /* Get patchlevel number */
396         if ((v = strtok(NULL, ".")) == NULL)
397                 return;
398         fm->sysstat_patchlevel = atoi(v) & 0xff;
399
400         /* Get sublevel number */
401         if ((v = strtok(NULL, ".")) == NULL)
402                 return;
403         fm->sysstat_sublevel = atoi(v) & 0xff;
404
405         /* Get extraversion number. Don't necessarily exist */
406         if ((v = strtok(NULL, ".")) == NULL)
407                 return;
408         fm->sysstat_extraversion = atoi(v) & 0xff;
409 }
410
411 /*
412  ***************************************************************************
413  * Write data to file. If the write() call was interrupted by a signal, try
414  * again so that the whole buffer can be written.
415  *
416  * IN:
417  * @fd          Output file descriptor.
418  * @buf         Data buffer.
419  * @nr_bytes    Number of bytes to write.
420  *
421  * RETURNS:
422  * Number of bytes written to file, or -1 on error.
423  ***************************************************************************
424  */
425 int write_all(int fd, const void *buf, int nr_bytes)
426 {
427         int block, offset = 0;
428         char *buffer = (char *) buf;
429
430         while (nr_bytes > 0) {
431                 block = write(fd, &buffer[offset], nr_bytes);
432
433                 if (block < 0) {
434                         if (errno == EINTR)
435                                 continue;
436                         return block;
437                 }
438                 if (block == 0)
439                         return offset;
440
441                 offset += block;
442                 nr_bytes -= block;
443         }
444
445         return offset;
446 }
447
448 #ifndef SOURCE_SADC
449 /*
450  ***************************************************************************
451  * Allocate structures.
452  *
453  * IN:
454  * @act Array of activities.
455  ***************************************************************************
456  */
457 void allocate_structures(struct activity *act[])
458 {
459         int i, j;
460
461         for (i = 0; i < NR_ACT; i++) {
462                 if (act[i]->nr_ini > 0) {
463                         for (j = 0; j < 3; j++) {
464                                 SREALLOC(act[i]->buf[j], void,
465                                                 (size_t) act[i]->msize * (size_t) act[i]->nr_ini * (size_t) act[i]->nr2);
466                         }
467                         act[i]->nr_allocated = act[i]->nr_ini;
468                 }
469         }
470 }
471
472 /*
473  ***************************************************************************
474  * Free structures.
475  *
476  * IN:
477  * @act Array of activities.
478  ***************************************************************************
479  */
480 void free_structures(struct activity *act[])
481 {
482         int i, j;
483
484         for (i = 0; i < NR_ACT; i++) {
485                 if (act[i]->nr_allocated > 0) {
486                         for (j = 0; j < 3; j++) {
487                                 if (act[i]->buf[j]) {
488                                         free(act[i]->buf[j]);
489                                         act[i]->buf[j] = NULL;
490                                 }
491                         }
492                         act[i]->nr_allocated = 0;
493                 }
494         }
495 }
496
497 /*
498  ***************************************************************************
499  * Reallocate all the buffers for a given activity.
500  *
501  * IN:
502  * @a           Activity whose buffers need to be reallocated.
503  * @nr_min      Minimum number of items that the new buffers should be able
504  *              to receive.
505  ***************************************************************************
506  */
507 void reallocate_all_buffers(struct activity *a, __nr_t nr_min)
508 {
509         int j;
510         size_t nr_realloc;
511
512         if (nr_min <= 0) {
513                 nr_min = 1;
514         }
515         if (!a->nr_allocated) {
516                 nr_realloc = nr_min;
517         }
518         else {
519                 nr_realloc = a->nr_allocated;
520                 do {
521                         nr_realloc = nr_realloc * 2;
522                 }
523                 while (nr_realloc < nr_min);
524         }
525
526         for (j = 0; j < 3; j++) {
527                 SREALLOC(a->buf[j], void,
528                         (size_t) a->msize * nr_realloc * (size_t) a->nr2);
529                 /* Init additional space which has been allocated */
530                 if (a->nr_allocated) {
531                         memset(a->buf[j] + a->msize * a->nr_allocated * a->nr2, 0,
532                                (size_t) a->msize * (size_t) (nr_realloc - a->nr_allocated) * (size_t) a->nr2);
533                 }
534         }
535
536         a->nr_allocated = nr_realloc;
537 }
538
539 /*
540  ***************************************************************************
541  * Check if we are close enough to desired interval.
542  *
543  * IN:
544  * @uptime_ref  Uptime used as reference. This is the system uptime for the
545  *              first sample statistics, or the first system uptime after a
546  *              LINUX RESTART (in 1/100th of a second).
547  * @uptime      Current system uptime (in 1/100th of a second).
548  * @reset       TRUE if @last_uptime should be reset with @uptime_ref.
549  * @interval    Interval of time.
550  *
551  * RETURNS:
552  * TRUE if we are actually close enough to desired interval, FALSE otherwise.
553  ***************************************************************************
554 */
555 int next_slice(unsigned long long uptime_ref, unsigned long long uptime,
556                int reset, long interval)
557 {
558         unsigned long file_interval, entry;
559         static unsigned long long last_uptime = 0;
560         int min, max, pt1, pt2;
561         double f;
562
563         /* uptime is expressed in 1/100th of a second */
564         if (!last_uptime || reset) {
565                 last_uptime = uptime_ref;
566         }
567
568         /* Interval cannot be greater than 0xffffffff here */
569         f = ((double) ((uptime - last_uptime) & 0xffffffff)) / 100;
570         file_interval = (unsigned long) f;
571         if ((f * 10) - (file_interval * 10) >= 5) {
572                 file_interval++; /* Rounding to correct value */
573         }
574
575         last_uptime = uptime;
576
577         if (interval == 1)
578                 /* Smallest time interval: Always close enough to desired interval */
579                 return TRUE;
580
581         /*
582          * A few notes about the "algorithm" used here to display selected entries
583          * from the system activity file (option -f with -i flag):
584          * Let Iu be the interval value given by the user on the command line,
585          *     In the interval between current and previous sample,
586          * and En the current sample (identified by its time stamp) in the file.
587          * En will ne displayed if there is an integer p so that:
588          * p * Iu belongs to [En - In/2, En + In/2[.
589          */
590         f = ((double) ((uptime - uptime_ref) & 0xffffffff)) / 100;
591         entry = (unsigned long) f;
592         if ((f * 10) - (entry * 10) >= 5) {
593                 entry++;
594         }
595
596         min = entry - (file_interval / 2);
597         max = entry + (file_interval / 2) + (file_interval & 0x1);
598         pt1 = (entry / interval) * interval;
599         pt2 = ((entry / interval) + 1) * interval;
600
601         return (((pt1 >= min) && (pt1 < max)) || ((pt2 >= min) && (pt2 < max)));
602 }
603
604 /*
605  ***************************************************************************
606  * Use time stamp to fill tstamp structure.
607  *
608  * IN:
609  * @timestamp   Timestamp to decode (format: HH:MM:SS).
610  *
611  * OUT:
612  * @tse         Structure containing the decoded timestamp.
613  *
614  * RETURNS:
615  * 0 if the timestamp has been successfully decoded, 1 otherwise.
616  ***************************************************************************
617  */
618 int decode_timestamp(char timestamp[], struct tstamp *tse)
619 {
620         timestamp[2] = timestamp[5] = '\0';
621         tse->tm_sec  = atoi(&timestamp[6]);
622         tse->tm_min  = atoi(&timestamp[3]);
623         tse->tm_hour = atoi(timestamp);
624
625         if ((tse->tm_sec < 0) || (tse->tm_sec > 59) ||
626             (tse->tm_min < 0) || (tse->tm_min > 59) ||
627             (tse->tm_hour < 0) || (tse->tm_hour > 23))
628                 return 1;
629
630         tse->use = TRUE;
631
632         return 0;
633 }
634
635 /*
636  ***************************************************************************
637  * Compare two timestamps.
638  *
639  * IN:
640  * @rectime     Date and time for current sample.
641  * @tse         Timestamp used as reference.
642  * @cross_day   TRUE if a new day has been started.
643  *
644  * RETURNS:
645  * A positive value if @rectime is greater than @tse,
646  * a negative one otherwise.
647  ***************************************************************************
648  */
649 int datecmp(struct tm *rectime, struct tstamp *tse, int cross_day)
650 {
651         int tm_hour = rectime->tm_hour;
652
653         if (cross_day) {
654                 /*
655                  * This is necessary if we want to properly handle something like:
656                  * sar -s time_start -e time_end with
657                  * time_start(day D) > time_end(day D+1)
658                  */
659                 tm_hour += 24;
660         }
661
662         if (tm_hour == tse->tm_hour) {
663                 if (rectime->tm_min == tse->tm_min)
664                         return (rectime->tm_sec - tse->tm_sec);
665                 else
666                         return (rectime->tm_min - tse->tm_min);
667         }
668         else
669                 return (tm_hour - tse->tm_hour);
670 }
671
672 /*
673  ***************************************************************************
674  * Parse a timestamp entered on the command line (hh:mm[:ss]) and decode it.
675  *
676  * IN:
677  * @argv                Arguments list.
678  * @opt                 Index in the arguments list.
679  * @def_timestamp       Default timestamp to use.
680  *
681  * OUT:
682  * @tse                 Structure containing the decoded timestamp.
683  *
684  * RETURNS:
685  * 0 if the timestamp has been successfully decoded, 1 otherwise.
686  ***************************************************************************
687  */
688 int parse_timestamp(char *argv[], int *opt, struct tstamp *tse,
689                     const char *def_timestamp)
690 {
691         char timestamp[9];
692
693         if (argv[++(*opt)]) {
694                 switch (strlen(argv[*opt])) {
695
696                         case 5:
697                                 strncpy(timestamp, argv[(*opt)++], 5);
698                                 timestamp[5] = '\0';
699                                 strcat(timestamp, ":00");
700                                 break;
701
702                         case 8:
703                                 strncpy(timestamp, argv[(*opt)++], 8);
704                                 break;
705
706                         default:
707                                 strncpy(timestamp, def_timestamp, 8);
708                                 break;
709                 }
710         } else {
711                 strncpy(timestamp, def_timestamp, 8);
712         }
713         timestamp[8] = '\0';
714
715         return decode_timestamp(timestamp, tse);
716 }
717
718 /*
719  ***************************************************************************
720  * Set interval value.
721  *
722  * IN:
723  * @record_hdr_curr     Record with current sample statistics.
724  * @record_hdr_prev     Record with previous sample statistics.
725  *
726  * OUT:
727  * @itv                 Interval of time in 1/100th of a second.
728  ***************************************************************************
729  */
730 void get_itv_value(struct record_header *record_hdr_curr,
731                    struct record_header *record_hdr_prev,
732                    unsigned long long *itv)
733 {
734         /* Interval value in jiffies */
735         *itv = get_interval(record_hdr_prev->uptime_cs,
736                             record_hdr_curr->uptime_cs);
737 }
738
739 /*
740  ***************************************************************************
741  * Fill the rectime structure with the file's creation date, based on file's
742  * time data saved in file header.
743  * The resulting timestamp is expressed in the locale of the file creator or
744  * in the user's own locale, depending on whether option -t has been used
745  * or not.
746  *
747  * IN:
748  * @flags       Flags for common options and system state.
749  * @file_hdr    System activity file standard header.
750  *
751  * OUT:
752  * @rectime     Date (and possibly time) from file header. Only the date,
753  *              not the time, should be used by the caller.
754  ***************************************************************************
755  */
756 void get_file_timestamp_struct(uint64_t flags, struct tm *rectime,
757                                struct file_header *file_hdr)
758 {
759         if (PRINT_TRUE_TIME(flags)) {
760                 /* Get local time. This is just to fill fields with a default value. */
761                 get_time(rectime, 0);
762
763                 rectime->tm_mday = file_hdr->sa_day;
764                 rectime->tm_mon  = file_hdr->sa_month;
765                 rectime->tm_year = file_hdr->sa_year;
766                 /*
767                  * Call mktime() to set DST (Daylight Saving Time) flag.
768                  * Has anyone a better way to do it?
769                  */
770                 rectime->tm_hour = rectime->tm_min = rectime->tm_sec = 0;
771                 mktime(rectime);
772         }
773         else {
774                 localtime_r((const time_t *) &file_hdr->sa_ust_time, rectime);
775         }
776 }
777
778 /*
779  ***************************************************************************
780  * Print report header.
781  *
782  * IN:
783  * @flags       Flags for common options and system state.
784  * @file_hdr    System activity file standard header.
785  *
786  * OUT:
787  * @rectime     Date and time from file header.
788  ***************************************************************************
789  */
790 void print_report_hdr(uint64_t flags, struct tm *rectime,
791                       struct file_header *file_hdr)
792 {
793
794         /* Get date of file creation */
795         get_file_timestamp_struct(flags, rectime, file_hdr);
796
797         /*
798          * Display the header.
799          * NB: Number of CPU (value in [1, NR_CPUS + 1]).
800          *      1 means that there is only one proc and non SMP kernel.
801          *      2 means one proc and SMP kernel. Etc.
802          */
803         print_gal_header(rectime, file_hdr->sa_sysname, file_hdr->sa_release,
804                          file_hdr->sa_nodename, file_hdr->sa_machine,
805                          file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
806                          PLAIN_OUTPUT);
807 }
808
809 /*
810  ***************************************************************************
811  * Network interfaces may now be registered (and unregistered) dynamically.
812  * This is what we try to guess here.
813  *
814  * IN:
815  * @a           Activity structure with statistics.
816  * @curr        Index in array for current sample statistics.
817  * @ref         Index in array for sample statistics used as reference.
818  * @pos         Index on current network interface.
819  *
820  * RETURNS:
821  * Position of current network interface in array of sample statistics used
822  * as reference.
823  * -1 if it is a new interface (it was not present in array of stats used
824  * as reference).
825  * -2 if it is a known interface but which has been unregistered then
826  * registered again on the interval.
827  ***************************************************************************
828  */
829 int check_net_dev_reg(struct activity *a, int curr, int ref, int pos)
830 {
831         struct stats_net_dev *sndc, *sndp;
832         int j0, j = pos;
833
834         if (!a->nr[ref])
835                 /*
836                  * No items found in previous iteration:
837                  * Current interface is necessarily new.
838                  */
839                 return -1;
840
841         if (j >= a->nr[ref]) {
842                 j = a->nr[ref] - 1;
843         }
844         j0 = j;
845
846         sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + pos * a->msize);
847
848         do {
849                 sndp = (struct stats_net_dev *) ((char *) a->buf[ref] + j * a->msize);
850
851                 if (!strcmp(sndc->interface, sndp->interface)) {
852                         /*
853                          * Network interface found.
854                          * If a counter has decreased, then we may assume that the
855                          * corresponding interface was unregistered, then registered again.
856                          */
857                         if ((sndc->rx_packets    < sndp->rx_packets)    ||
858                             (sndc->tx_packets    < sndp->tx_packets)    ||
859                             (sndc->rx_bytes      < sndp->rx_bytes)      ||
860                             (sndc->tx_bytes      < sndp->tx_bytes)      ||
861                             (sndc->rx_compressed < sndp->rx_compressed) ||
862                             (sndc->tx_compressed < sndp->tx_compressed) ||
863                             (sndc->multicast     < sndp->multicast)) {
864
865                                 /*
866                                  * Special processing for rx_bytes (_packets) and
867                                  * tx_bytes (_packets) counters: If the number of
868                                  * bytes (packets) has decreased, whereas the number of
869                                  * packets (bytes) has increased, then assume that the
870                                  * relevant counter has met an overflow condition, and that
871                                  * the interface was not unregistered, which is all the
872                                  * more plausible that the previous value for the counter
873                                  * was > ULLONG_MAX/2.
874                                  * NB: the average value displayed will be wrong in this case...
875                                  *
876                                  * If such an overflow is detected, just set the flag. There is no
877                                  * need to handle this in a special way: the difference is still
878                                  * properly calculated if the result is of the same type (i.e.
879                                  * unsigned long) as the two values.
880                                  */
881                                 int ovfw = FALSE;
882
883                                 if ((sndc->rx_bytes   < sndp->rx_bytes)   &&
884                                     (sndc->rx_packets > sndp->rx_packets) &&
885                                     (sndp->rx_bytes   > (~0ULL >> 1))) {
886                                         ovfw = TRUE;
887                                 }
888                                 if ((sndc->tx_bytes   < sndp->tx_bytes)   &&
889                                     (sndc->tx_packets > sndp->tx_packets) &&
890                                     (sndp->tx_bytes   > (~0ULL >> 1))) {
891                                         ovfw = TRUE;
892                                 }
893                                 if ((sndc->rx_packets < sndp->rx_packets) &&
894                                     (sndc->rx_bytes   > sndp->rx_bytes)   &&
895                                     (sndp->rx_packets > (~0ULL >> 1))) {
896                                         ovfw = TRUE;
897                                 }
898                                 if ((sndc->tx_packets < sndp->tx_packets) &&
899                                     (sndc->tx_bytes   > sndp->tx_bytes)   &&
900                                     (sndp->tx_packets > (~0ULL >> 1))) {
901                                         ovfw = TRUE;
902                                 }
903
904                                 if (!ovfw)
905                                         /*
906                                          * OK: Assume here that the device was
907                                          * actually unregistered.
908                                          */
909                                         return -2;
910                         }
911                         return j;
912                 }
913                 if (++j >= a->nr[ref]) {
914                         j = 0;
915                 }
916         }
917         while (j != j0);
918
919         /* This is a newly registered interface */
920         return -1;
921 }
922
923 /*
924  ***************************************************************************
925  * Network interfaces may now be registered (and unregistered) dynamically.
926  * This is what we try to guess here.
927  *
928  * IN:
929  * @a           Activity structure with statistics.
930  * @curr        Index in array for current sample statistics.
931  * @ref         Index in array for sample statistics used as reference.
932  * @pos         Index on current network interface.
933  *
934  * RETURNS:
935  * Position of current network interface in array of sample statistics used
936  * as reference.
937  * -1 if it is a newly registered interface.
938  * -2 if it is a known interface but which has been unregistered then
939  * registered again on the interval.
940  ***************************************************************************
941  */
942 int check_net_edev_reg(struct activity *a, int curr, int ref, int pos)
943 {
944         struct stats_net_edev *snedc, *snedp;
945         int j0, j = pos;
946
947         if (!a->nr[ref])
948                 /*
949                  * No items found in previous iteration:
950                  * Current interface is necessarily new.
951                  */
952                 return -1;
953
954         if (j >= a->nr[ref]) {
955                 j = a->nr[ref] - 1;
956         }
957         j0 = j;
958
959         snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + pos * a->msize);
960
961         do {
962                 snedp = (struct stats_net_edev *) ((char *) a->buf[ref] + j * a->msize);
963
964                 if (!strcmp(snedc->interface, snedp->interface)) {
965                         /*
966                          * Network interface found.
967                          * If a counter has decreased, then we may assume that the
968                          * corresponding interface was unregistered, then registered again.
969                          */
970                         if ((snedc->tx_errors         < snedp->tx_errors)         ||
971                             (snedc->collisions        < snedp->collisions)        ||
972                             (snedc->rx_dropped        < snedp->rx_dropped)        ||
973                             (snedc->tx_dropped        < snedp->tx_dropped)        ||
974                             (snedc->tx_carrier_errors < snedp->tx_carrier_errors) ||
975                             (snedc->rx_frame_errors   < snedp->rx_frame_errors)   ||
976                             (snedc->rx_fifo_errors    < snedp->rx_fifo_errors)    ||
977                             (snedc->tx_fifo_errors    < snedp->tx_fifo_errors))
978                                 /*
979                                  * OK: assume here that the device was
980                                  * actually unregistered.
981                                  */
982                                 return -2;
983
984                         return j;
985                 }
986                 if (++j >= a->nr[ref]) {
987                         j = 0;
988                 }
989         }
990         while (j != j0);
991
992         /* This is a newly registered interface */
993         return -1;
994 }
995
996 /*
997  ***************************************************************************
998  * Disks may be registered dynamically (true in /proc/diskstats file).
999  * This is what we try to guess here.
1000  *
1001  * IN:
1002  * @a           Activity structure with statistics.
1003  * @curr        Index in array for current sample statistics.
1004  * @ref         Index in array for sample statistics used as reference.
1005  * @pos         Index on current disk.
1006  *
1007  * RETURNS:
1008  * Position of current disk in array of sample statistics used as reference
1009  * -1 if it is a newly registered device.
1010  * -2 if it is a known device but which has been unregistered then registered
1011  * again on the interval.
1012  ***************************************************************************
1013  */
1014 int check_disk_reg(struct activity *a, int curr, int ref, int pos)
1015 {
1016         struct stats_disk *sdc, *sdp;
1017         int j0, j = pos;
1018
1019         if (!a->nr[ref])
1020                 /*
1021                  * No items found in previous iteration:
1022                  * Current interface is necessarily new.
1023                  */
1024                 return -1;
1025
1026         if (j >= a->nr[ref]) {
1027                 j = a->nr[ref] - 1;
1028         }
1029         j0 = j;
1030
1031         sdc = (struct stats_disk *) ((char *) a->buf[curr] + pos * a->msize);
1032
1033         do {
1034                 sdp = (struct stats_disk *) ((char *) a->buf[ref] + j * a->msize);
1035
1036                 if ((sdc->major == sdp->major) &&
1037                     (sdc->minor == sdp->minor)) {
1038                         /*
1039                          * Disk found.
1040                          * If all the counters have decreased then the likelyhood
1041                          * is that the disk has been unregistered and a new disk inserted.
1042                          * If only one or two have decreased then the likelyhood
1043                          * is that the counter has simply wrapped.
1044                          * Don't take into account a counter if its previous value was 0
1045                          * (this may be a read-only device, or a kernel that doesn't
1046                          * support discard stats yet...)
1047                          */
1048                         if ((sdc->nr_ios < sdp->nr_ios) &&
1049                             (!sdp->rd_sect || (sdc->rd_sect < sdp->rd_sect)) &&
1050                             (!sdp->wr_sect || (sdc->wr_sect < sdp->wr_sect)) &&
1051                             (!sdp->dc_sect || (sdc->dc_sect < sdp->dc_sect)))
1052                                 /* Same device registered again */
1053                                 return -2;
1054
1055                         return j;
1056                 }
1057                 if (++j >= a->nr[ref]) {
1058                         j = 0;
1059                 }
1060         }
1061         while (j != j0);
1062
1063         /* This is a newly registered device */
1064         return -1;
1065 }
1066
1067 /*
1068  ***************************************************************************
1069  * Allocate bitmaps for activities that have one.
1070  *
1071  * IN:
1072  * @act         Array of activities.
1073  ***************************************************************************
1074  */
1075 void allocate_bitmaps(struct activity *act[])
1076 {
1077         int i;
1078
1079         for (i = 0; i < NR_ACT; i++) {
1080                 /*
1081                  * If current activity has a bitmap which has not already
1082                  * been allocated, then allocate it.
1083                  * Note that a same bitmap may be used by several activities.
1084                  */
1085                 if (act[i]->bitmap && !act[i]->bitmap->b_array) {
1086                         SREALLOC(act[i]->bitmap->b_array, unsigned char,
1087                                  BITMAP_SIZE(act[i]->bitmap->b_size));
1088                 }
1089         }
1090 }
1091
1092 /*
1093  ***************************************************************************
1094  * Free bitmaps for activities that have one.
1095  *
1096  * IN:
1097  * @act         Array of activities.
1098  ***************************************************************************
1099  */
1100 void free_bitmaps(struct activity *act[])
1101 {
1102         int i;
1103
1104         for (i = 0; i < NR_ACT; i++) {
1105                 if (act[i]->bitmap && act[i]->bitmap->b_array) {
1106                         free(act[i]->bitmap->b_array);
1107                         /* Set pointer to NULL to prevent it from being freed again */
1108                         act[i]->bitmap->b_array = NULL;
1109                 }
1110         }
1111 }
1112
1113 /*
1114  ***************************************************************************
1115  * Select all activities, even if they have no associated items.
1116  *
1117  * IN:
1118  * @act         Array of activities.
1119  *
1120  * OUT:
1121  * @act         Array of activities, all of the being selected.
1122  ***************************************************************************
1123  */
1124 void select_all_activities(struct activity *act[])
1125 {
1126         int i;
1127
1128         for (i = 0; i < NR_ACT; i++) {
1129                 act[i]->options |= AO_SELECTED;
1130         }
1131 }
1132
1133 /*
1134  ***************************************************************************
1135  * Select CPU activity if no other activities have been explicitly selected.
1136  * Also select CPU "all" if no other CPU has been selected.
1137  *
1138  * IN:
1139  * @act         Array of activities.
1140  *
1141  * OUT:
1142  * @act         Array of activities with CPU activity selected if needed.
1143  ***************************************************************************
1144  */
1145 void select_default_activity(struct activity *act[])
1146 {
1147         int p;
1148
1149         p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
1150
1151         /* Default is CPU activity... */
1152         if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
1153                 /*
1154                  * Yet A_CPU activity may not be available in file
1155                  * since the user can choose not to collect it.
1156                  */
1157                 act[p]->options |= AO_SELECTED;
1158         }
1159
1160         /*
1161          * If no CPU's have been selected then select CPU "all".
1162          * cpu_bitmap bitmap may be used by several activities (A_CPU, A_PWR_CPU...)
1163          */
1164         if (!count_bits(cpu_bitmap.b_array, BITMAP_SIZE(cpu_bitmap.b_size))) {
1165                 cpu_bitmap.b_array[0] |= 0x01;
1166         }
1167 }
1168
1169 /*
1170  ***************************************************************************
1171  * Swap bytes for every numerical field in structure. Used to convert from
1172  * one endianness type (big-endian or little-endian) to the other.
1173  *
1174  * IN:
1175  * @types_nr    Number of fields in structure for each following types:
1176  *              unsigned long long, unsigned long and int.
1177  * @ps          Pointer on structure.
1178  * @is64bit     TRUE if data come from a 64-bit machine.
1179  ***************************************************************************
1180  */
1181 void swap_struct(unsigned int types_nr[], void *ps, int is64bit)
1182 {
1183         int i;
1184         uint64_t *x;
1185         uint32_t *y;
1186
1187         x = (uint64_t *) ps;
1188         /* For each field of type long long (or double) */
1189         for (i = 0; i < types_nr[0]; i++) {
1190                 *x = __builtin_bswap64(*x);
1191                 x = (uint64_t *) ((char *) x + ULL_ALIGNMENT_WIDTH);
1192         }
1193
1194         y = (uint32_t *) x;
1195         /* For each field of type long */
1196         for (i = 0; i < types_nr[1]; i++) {
1197                 if (is64bit) {
1198                         *x = __builtin_bswap64(*x);
1199                         x = (uint64_t *) ((char *) x + UL_ALIGNMENT_WIDTH);
1200                 }
1201                 else {
1202                         *y = __builtin_bswap32(*y);
1203                         y = (uint32_t *) ((char *) y + UL_ALIGNMENT_WIDTH);
1204                 }
1205         }
1206
1207         if (is64bit) {
1208                 y = (uint32_t *) x;
1209         }
1210         /* For each field of type int */
1211         for (i = 0; i < types_nr[2]; i++) {
1212                 *y = __builtin_bswap32(*y);
1213                 y = (uint32_t *) ((char *) y + U_ALIGNMENT_WIDTH);
1214         }
1215 }
1216
1217 /*
1218  ***************************************************************************
1219  * Map the fields of a structure containing statistics read from a file to
1220  * those of the structure known by current sysstat version.
1221  * Each structure (either read from file or from current sysstat version)
1222  * is described by 3 values: The number of [unsigned] long long integers,
1223  * the number of [unsigned] long integers following in the structure, and
1224  * last the number of [unsigned] integers.
1225  * We assume that those numbers will *never* decrease with newer sysstat
1226  * versions.
1227  *
1228  * IN:
1229  * @gtypes_nr   Structure description as expected for current sysstat version.
1230  * @ftypes_nr   Structure description as read from file.
1231  * @ps          Pointer on structure containing statistics.
1232  * @f_size      Size of the structure containing statistics. This is the
1233  *              size of the structure *read from file*.
1234  * @g_size      Size of the structure expected by current sysstat version.
1235  * @b_size      Size of the buffer pointed by @ps.
1236  *
1237  * RETURNS:
1238  * -1 if an error has been encountered, or 0 otherwise.
1239  ***************************************************************************
1240  */
1241 int remap_struct(unsigned int gtypes_nr[], unsigned int ftypes_nr[],
1242                  void *ps, unsigned int f_size, unsigned int g_size, size_t b_size)
1243 {
1244         int d;
1245         size_t n;
1246
1247         /* Sanity check */
1248         if (MAP_SIZE(ftypes_nr) > f_size)
1249                 return -1;
1250
1251         /* Remap [unsigned] long fields */
1252         d = gtypes_nr[0] - ftypes_nr[0];
1253         if (d) {
1254                 if (ftypes_nr[0] * ULL_ALIGNMENT_WIDTH < ftypes_nr[0])
1255                         /* Overflow */
1256                         return -1;
1257
1258                 n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH,
1259                             g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH);
1260                 if ((ftypes_nr[0] * ULL_ALIGNMENT_WIDTH >= b_size) ||
1261                     (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH + n > b_size) ||
1262                     (ftypes_nr[0] * ULL_ALIGNMENT_WIDTH + n > b_size))
1263                         return -1;
1264
1265                 memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH,
1266                         ((char *) ps) + ftypes_nr[0] * ULL_ALIGNMENT_WIDTH, n);
1267                 if (d > 0) {
1268                         memset(((char *) ps) + ftypes_nr[0] * ULL_ALIGNMENT_WIDTH,
1269                                0, d * ULL_ALIGNMENT_WIDTH);
1270                 }
1271         }
1272         /* Remap [unsigned] int fields */
1273         d = gtypes_nr[1] - ftypes_nr[1];
1274         if (d) {
1275                 if (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1276                     ftypes_nr[1] * UL_ALIGNMENT_WIDTH < ftypes_nr[1])
1277                         /* Overflow */
1278                         return -1;
1279
1280                 n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH
1281                                    - ftypes_nr[1] * UL_ALIGNMENT_WIDTH,
1282                             g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1283                                    - gtypes_nr[1] * UL_ALIGNMENT_WIDTH);
1284                 if ((gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1285                      ftypes_nr[1] * UL_ALIGNMENT_WIDTH >= b_size) ||
1286                     (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1287                      gtypes_nr[1] * UL_ALIGNMENT_WIDTH + n > b_size) ||
1288                     (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1289                      ftypes_nr[1] * UL_ALIGNMENT_WIDTH + n > b_size))
1290                         return -1;
1291
1292                 memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1293                                       + gtypes_nr[1] * UL_ALIGNMENT_WIDTH,
1294                         ((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1295                                       + ftypes_nr[1] * UL_ALIGNMENT_WIDTH, n);
1296                 if (d > 0) {
1297                         memset(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1298                                              + ftypes_nr[1] * UL_ALIGNMENT_WIDTH,
1299                                0, d * UL_ALIGNMENT_WIDTH);
1300                 }
1301         }
1302         /* Remap possible fields (like strings of chars) following int fields */
1303         d = gtypes_nr[2] - ftypes_nr[2];
1304         if (d) {
1305                 if (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1306                     gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
1307                     ftypes_nr[2] * U_ALIGNMENT_WIDTH < ftypes_nr[2])
1308                         /* Overflow */
1309                         return -1;
1310
1311                 n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH
1312                                    - ftypes_nr[1] * UL_ALIGNMENT_WIDTH
1313                                    - ftypes_nr[2] * U_ALIGNMENT_WIDTH,
1314                             g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1315                                    - gtypes_nr[1] * UL_ALIGNMENT_WIDTH
1316                                    - gtypes_nr[2] * U_ALIGNMENT_WIDTH);
1317                 if ((gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1318                      gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
1319                      ftypes_nr[2] * U_ALIGNMENT_WIDTH >= b_size) ||
1320                     (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1321                      gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
1322                      gtypes_nr[2] * U_ALIGNMENT_WIDTH + n > b_size) ||
1323                     (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
1324                      gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
1325                      ftypes_nr[2] * U_ALIGNMENT_WIDTH + n > b_size))
1326                         return -1;
1327
1328                 memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1329                                       + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
1330                                       + gtypes_nr[2] * U_ALIGNMENT_WIDTH,
1331                         ((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1332                                       + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
1333                                       + ftypes_nr[2] * U_ALIGNMENT_WIDTH, n);
1334                 if (d > 0) {
1335                         memset(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
1336                                              + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
1337                                              + ftypes_nr[2] * U_ALIGNMENT_WIDTH,
1338                                0, d * U_ALIGNMENT_WIDTH);
1339                 }
1340         }
1341         return 0;
1342 }
1343
1344 /*
1345  ***************************************************************************
1346  * Read data from a system activity data file.
1347  *
1348  * IN:
1349  * @ifd         Input file descriptor.
1350  * @buffer      Buffer where data are read.
1351  * @size        Number of bytes to read.
1352  * @mode        If set to HARD_SIZE, indicate that an EOF should be considered
1353  *              as an error.
1354  * @oneof       Set to UEOF_CONT if an unexpected end of file should not make
1355  *              sadf stop. Default behavior is to stop on unexpected EOF.
1356  *
1357  * RETURNS:
1358  * 1 if EOF has been reached,
1359  * 2 if an unexpected EOF has been reached (and sadf was told to continue),
1360  * 0 otherwise.
1361  ***************************************************************************
1362  */
1363 int sa_fread(int ifd, void *buffer, size_t size, int mode, int oneof)
1364 {
1365         ssize_t n;
1366
1367         if ((n = read(ifd, buffer, size)) < 0) {
1368                 fprintf(stderr, _("Error while reading system activity file: %s\n"),
1369                         strerror(errno));
1370                 close(ifd);
1371                 exit(2);
1372         }
1373
1374         if (!n && (mode == SOFT_SIZE))
1375                 return 1;       /* EOF */
1376
1377         if (n < size) {
1378                 fprintf(stderr, _("End of system activity file unexpected\n"));
1379                 if (oneof == UEOF_CONT)
1380                         return 2;
1381                 close(ifd);
1382                 exit(2);
1383         }
1384
1385         return 0;
1386 }
1387
1388 /*
1389  ***************************************************************************
1390  * Skip unknown extra structures present in file.
1391  *
1392  * IN:
1393  * @ifd         System activity data file descriptor.
1394  * @endian_mismatch
1395  *              TRUE if file's data don't match current machine's endianness.
1396  * @arch_64     TRUE if file's data come from a 64 bit machine.
1397  *
1398  * RETURNS:
1399  * -1 on error, 0 otherwise.
1400  ***************************************************************************
1401  */
1402 int skip_extra_struct(int ifd, int endian_mismatch, int arch_64)
1403 {
1404         int i;
1405         struct extra_desc xtra_d;
1406
1407         do {
1408                 /* Read extra structure description */
1409                 sa_fread(ifd, &xtra_d, EXTRA_DESC_SIZE, HARD_SIZE, UEOF_STOP);
1410
1411                 /*
1412                  * We don't need to remap as the extra_desc structure won't change,
1413                  * but we may need to normalize endianness anyway.
1414                  */
1415                 if (endian_mismatch) {
1416                         swap_struct(extra_desc_types_nr, &xtra_d, arch_64);
1417                 }
1418
1419                 /* Check values consistency */
1420                 if (MAP_SIZE(xtra_d.extra_types_nr) > xtra_d.extra_size) {
1421 #ifdef DEBUG
1422                         fprintf(stderr, "%s: extra_size=%u types=%d,%d,%d\n",
1423                                 __FUNCTION__, xtra_d.extra_size,
1424                                 xtra_d.extra_types_nr[0], xtra_d.extra_types_nr[1], xtra_d.extra_types_nr[2]);
1425 #endif
1426                         return -1;
1427                 }
1428
1429                 if ((xtra_d.extra_nr > MAX_EXTRA_NR) || (xtra_d.extra_size > MAX_EXTRA_SIZE)) {
1430 #ifdef DEBUG
1431                         fprintf(stderr, "%s: extra_size=%u extra_nr=%u\n",
1432                                 __FUNCTION__, xtra_d.extra_size, xtra_d.extra_size);
1433 #endif
1434                         return -1;
1435                 }
1436
1437                 /* Ignore current unknown extra structures */
1438                 for (i = 0; i < xtra_d.extra_nr; i++) {
1439                         if (lseek(ifd, xtra_d.extra_size, SEEK_CUR) < xtra_d.extra_size)
1440                                 return -1;
1441                 }
1442         }
1443         while (xtra_d.extra_next);
1444
1445         return 0;
1446 }
1447
1448 /*
1449  ***************************************************************************
1450  * Read the record header of current sample and process it.
1451  *
1452  * IN:
1453  * @ifd         Input file descriptor.
1454  * @buffer      Buffer where data will be read.
1455  * @record_hdr  Structure where record header will be saved.
1456  * @file_hdr    file_hdr structure containing data read from file standard
1457  *              header.
1458  * @arch_64     TRUE if file's data come from a 64-bit machine.
1459  * @endian_mismatch
1460  *              TRUE if data read from file don't match current machine's
1461  *              endianness.
1462  * @oneof       Set to EOF_CONT if an unexpected end of file should not make
1463  *              sadf stop. Default behavior is to stop on unexpected EOF.
1464  * @b_size      @buffer size.
1465  * @flags       Flags for common options and system state.
1466  * @ofmt        Pointer on report output format structure.
1467  *
1468  * OUT:
1469  * @record_hdr  Record header for current sample.
1470  *
1471  * RETURNS:
1472  * 1 if EOF has been reached,
1473  * 2 if an error has been encountered (e.g. unexpected EOF),
1474  * 0 otherwise.
1475  ***************************************************************************
1476  */
1477 int read_record_hdr(int ifd, void *buffer, struct record_header *record_hdr,
1478                     struct file_header *file_hdr, int arch_64, int endian_mismatch,
1479                     int oneof, size_t b_size, uint64_t flags, struct report_format *ofmt)
1480 {
1481         int rc;
1482
1483         do {
1484                 if ((rc = sa_fread(ifd, buffer, (size_t) file_hdr->rec_size, SOFT_SIZE, oneof)) != 0)
1485                         /* End of sa data file */
1486                         return rc;
1487
1488                 /* Remap record header structure to that expected by current version */
1489                 if (remap_struct(rec_types_nr, file_hdr->rec_types_nr, buffer,
1490                                  file_hdr->rec_size, RECORD_HEADER_SIZE, b_size) < 0)
1491                         return 2;
1492                 memcpy(record_hdr, buffer, RECORD_HEADER_SIZE);
1493
1494                 /* Normalize endianness */
1495                 if (endian_mismatch) {
1496                         swap_struct(rec_types_nr, record_hdr, arch_64);
1497                 }
1498
1499                 /* Raw output in debug mode */
1500                 if (DISPLAY_DEBUG_MODE(flags) && (ofmt->id == F_RAW_OUTPUT)) {
1501                         printf("# uptime_cs; %llu; ust_time; %llu; extra_next; %u; record_type; %d; HH:MM:SS; %02d:%02d:%02d\n",
1502                                record_hdr->uptime_cs, record_hdr->ust_time,
1503                                record_hdr->extra_next, record_hdr->record_type,
1504                                record_hdr->hour, record_hdr->minute, record_hdr->second);
1505                 }
1506
1507                 /* Sanity checks */
1508                 if ((record_hdr->record_type <= 0) || (record_hdr->record_type > R_EXTRA_MAX) ||
1509                     (record_hdr->hour > 23) || (record_hdr->minute > 59) || (record_hdr->second > 60)) {
1510 #ifdef DEBUG
1511                         fprintf(stderr, "%s: record_type=%d HH:MM:SS=%02d:%02d:%02d\n",
1512                                 __FUNCTION__, record_hdr->record_type,
1513                                 record_hdr->hour, record_hdr->minute, record_hdr->second);
1514 #endif
1515                         return 2;
1516                 }
1517
1518                 /*
1519                  * Skip unknown extra structures if present.
1520                  * This will be done later for R_COMMENT and R_RESTART records, as extra structures
1521                  * are saved after the comment or the number of CPU.
1522                  */
1523                 if ((record_hdr->record_type != R_COMMENT) && (record_hdr->record_type != R_RESTART) &&
1524                     record_hdr->extra_next && (skip_extra_struct(ifd, endian_mismatch, arch_64) < 0))
1525                         return 2;
1526         }
1527         while ((record_hdr->record_type >= R_EXTRA_MIN) && (record_hdr->record_type <= R_EXTRA_MAX)) ;
1528
1529         return 0;
1530 }
1531
1532 /*
1533  ***************************************************************************
1534  * Move structures data.
1535  *
1536  * IN:
1537  * @act         Array of activities.
1538  * @id_seq      Activity sequence in file.
1539  * @record_hdr  Current record header.
1540  * @dest        Index in array where stats have to be copied to.
1541  * @src         Index in array where stats to copy are.
1542  ***************************************************************************
1543  */
1544 void copy_structures(struct activity *act[], unsigned int id_seq[],
1545                      struct record_header record_hdr[], int dest, int src)
1546 {
1547         int i, p;
1548
1549         memcpy(&record_hdr[dest], &record_hdr[src], RECORD_HEADER_SIZE);
1550
1551         for (i = 0; i < NR_ACT; i++) {
1552
1553                 if (!id_seq[i])
1554                         continue;
1555
1556                 p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
1557
1558                 memcpy(act[p]->buf[dest], act[p]->buf[src],
1559                        (size_t) act[p]->msize * (size_t) act[p]->nr[src] * (size_t) act[p]->nr2);
1560                 act[p]->nr[dest] = act[p]->nr[src];
1561         }
1562 }
1563
1564 /*
1565  ***************************************************************************
1566  * Read an __nr_t value from file.
1567  * Such a value can be the new number of CPU saved after a RESTART record,
1568  * or the number of structures to read saved before the structures containing
1569  * statistics for an activity with a varying number of items in file.
1570  *
1571  * IN:
1572  * @ifd         Input file descriptor.
1573  * @file        Name of file being read.
1574  * @file_magic  file_magic structure filled with file magic header data.
1575  * @endian_mismatch
1576  *              TRUE if file's data don't match current machine's endianness.
1577  * @arch_64     TRUE if file's data come from a 64 bit machine.
1578  * @non_zero    TRUE if value should not be zero.
1579  *
1580  * RETURNS:
1581  * __nr_t value, as read from file.
1582  ***************************************************************************
1583  */
1584 __nr_t read_nr_value(int ifd, char *file, struct file_magic *file_magic,
1585                      int endian_mismatch, int arch_64, int non_zero)
1586 {
1587         __nr_t value;
1588
1589         sa_fread(ifd, &value, sizeof(__nr_t), HARD_SIZE, UEOF_STOP);
1590
1591         /* Normalize endianness for file_activity structures */
1592         if (endian_mismatch) {
1593                 nr_types_nr[2] = 1;
1594                 swap_struct(nr_types_nr, &value, arch_64);
1595         }
1596
1597         if ((non_zero && !value) || (value < 0)) {
1598 #ifdef DEBUG
1599                 fprintf(stderr, "%s: Value=%d\n",
1600                         __FUNCTION__, value);
1601 #endif
1602                 /* Value number cannot be zero or negative */
1603                 handle_invalid_sa_file(ifd, file_magic, file, 0);
1604         }
1605
1606         return value;
1607 }
1608
1609 /*
1610  ***************************************************************************
1611  * Read varying part of the statistics from a daily data file.
1612  *
1613  * IN:
1614  * @act         Array of activities.
1615  * @curr        Index in array for current sample statistics.
1616  * @ifd         Input file descriptor.
1617  * @act_nr      Number of activities in file.
1618  * @file_actlst Activity list in file.
1619  * @endian_mismatch
1620  *              TRUE if file's data don't match current machine's endianness.
1621  * @arch_64     TRUE if file's data come from a 64 bit machine.
1622  * @dfile       Name of system activity data file.
1623  * @file_magic  file_magic structure containing data read from file magic
1624  *              header.
1625  * @oneof       Set to UEOF_CONT if an unexpected end of file should not make
1626  *              sadf stop. Default behavior is to stop on unexpected EOF.
1627  *
1628  * RETURNS:
1629  * 2 if an error has been encountered (e.g. unexpected EOF),
1630  * 0 otherwise.
1631  ***************************************************************************
1632  */
1633 int read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr,
1634                          struct file_activity *file_actlst, int endian_mismatch,
1635                          int arch_64, char *dfile, struct file_magic *file_magic,
1636                          int oneof)
1637 {
1638         int i, j, p;
1639         struct file_activity *fal = file_actlst;
1640         off_t offset;
1641         __nr_t nr_value;
1642
1643         for (i = 0; i < act_nr; i++, fal++) {
1644
1645                 /* Read __nr_t value preceding statistics structures if it exists */
1646                 if (fal->has_nr) {
1647                         nr_value = read_nr_value(ifd, dfile, file_magic,
1648                                                  endian_mismatch, arch_64, FALSE);
1649                 }
1650                 else {
1651                         nr_value = fal->nr;
1652                 }
1653
1654                 if (nr_value > NR_MAX) {
1655 #ifdef DEBUG
1656                         fprintf(stderr, "%s: Value=%d Max=%d\n", __FUNCTION__, nr_value, NR_MAX);
1657 #endif
1658                         handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1659                 }
1660
1661                 if (((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0) ||
1662                     (act[p]->magic != fal->magic)) {
1663                         /*
1664                          * Ignore current activity in file, which is unknown to
1665                          * current sysstat version or has an unknown format.
1666                          */
1667                         if (nr_value) {
1668                                 offset = (off_t) fal->size * (off_t) nr_value * (off_t) fal->nr2;
1669                                 if (lseek(ifd, offset, SEEK_CUR) < offset) {
1670                                         close(ifd);
1671                                         perror("lseek");
1672                                         if (oneof == UEOF_CONT)
1673                                                 return 2;
1674                                         exit(2);
1675                                 }
1676                         }
1677                         continue;
1678                 }
1679
1680                 if (nr_value > act[p]->nr_max) {
1681 #ifdef DEBUG
1682                         fprintf(stderr, "%s: %s: Value=%d Max=%d\n",
1683                                 __FUNCTION__, act[p]->name, nr_value, act[p]->nr_max);
1684 #endif
1685                         handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1686                 }
1687                 act[p]->nr[curr] = nr_value;
1688
1689                 /* Reallocate buffers if needed */
1690                 if (nr_value > act[p]->nr_allocated) {
1691                         reallocate_all_buffers(act[p], nr_value);
1692                 }
1693
1694                 /*
1695                  * For persistent activities, we must make sure that no statistics
1696                  * from a previous iteration remain, especially if the number
1697                  * of structures read is smaller than @nr_ini.
1698                  */
1699                 if (HAS_PERSISTENT_VALUES(act[p]->options)) {
1700                     memset(act[p]->buf[curr], 0,
1701                            (size_t) act[p]->msize * (size_t) act[p]->nr_ini * (size_t) act[p]->nr2);
1702                 }
1703
1704                 /* OK, this is a known activity: Read the stats structures */
1705                 if ((nr_value > 0) &&
1706                     ((nr_value > 1) || (act[p]->nr2 > 1)) &&
1707                     (act[p]->msize > act[p]->fsize)) {
1708
1709                         for (j = 0; j < (nr_value * act[p]->nr2); j++) {
1710                                 if (sa_fread(ifd, (char *) act[p]->buf[curr] + j * act[p]->msize,
1711                                          (size_t) act[p]->fsize, HARD_SIZE, oneof) > 0)
1712                                         /* Unexpected EOF */
1713                                         return 2;
1714                         }
1715                 }
1716                 else if (nr_value > 0) {
1717                         /*
1718                          * Note: If msize was smaller than fsize,
1719                          * then it has been set to fsize in check_file_actlst().
1720                          */
1721                         if (sa_fread(ifd, act[p]->buf[curr],
1722                                  (size_t) act[p]->fsize * (size_t) nr_value * (size_t) act[p]->nr2,
1723                                  HARD_SIZE, oneof) > 0)
1724                                 /* Unexpected EOF */
1725                                 return 2;
1726                 }
1727                 else {
1728                         /* nr_value == 0: Nothing to read */
1729                         continue;
1730                 }
1731
1732                 /* Normalize endianness for current activity's structures */
1733                 if (endian_mismatch) {
1734                         for (j = 0; j < (nr_value * act[p]->nr2); j++) {
1735                                 swap_struct(act[p]->ftypes_nr, (char *) act[p]->buf[curr] + j * act[p]->msize,
1736                                             arch_64);
1737                         }
1738                 }
1739
1740                 /* Remap structure's fields to those known by current sysstat version */
1741                 for (j = 0; j < (nr_value * act[p]->nr2); j++) {
1742                         if (remap_struct(act[p]->gtypes_nr, act[p]->ftypes_nr,
1743                                          (char *) act[p]->buf[curr] + j * act[p]->msize,
1744                                          act[p]->fsize, act[p]->msize, act[p]->msize) < 0)
1745                                 return 2;
1746                 }
1747         }
1748
1749         return 0;
1750 }
1751
1752 /*
1753  ***************************************************************************
1754  * Open a sysstat activity data file and read its magic structure.
1755  *
1756  * IN:
1757  * @dfile       Name of system activity data file.
1758  * @ignore      Set to 1 if a true sysstat activity file but with a bad
1759  *              format should not yield an error message. Useful with
1760  *              sadf -H and sadf -c.
1761  *
1762  * OUT:
1763  * @fd          System activity data file descriptor.
1764  * @file_magic  file_magic structure containing data read from file magic
1765  *              header.
1766  * @endian_mismatch
1767  *              TRUE if file's data don't match current machine's endianness.
1768  * @do_swap     TRUE if endianness should be normalized for sysstat_magic
1769  *              and format_magic numbers.
1770  *
1771  * RETURNS:
1772  * -1 if data file is a sysstat file with an old format (which we cannot
1773  * read), 0 otherwise.
1774  ***************************************************************************
1775  */
1776 int sa_open_read_magic(int *fd, char *dfile, struct file_magic *file_magic,
1777                        int ignore, int *endian_mismatch, int do_swap)
1778 {
1779         int n;
1780         unsigned int fm_types_nr[] = {FILE_MAGIC_ULL_NR, FILE_MAGIC_UL_NR, FILE_MAGIC_U_NR};
1781
1782         /* Open sa data file */
1783         if ((*fd = open(dfile, O_RDONLY)) < 0) {
1784                 int saved_errno = errno;
1785
1786                 fprintf(stderr, _("Cannot open %s: %s\n"), dfile, strerror(errno));
1787
1788                 if ((saved_errno == ENOENT) && default_file_used) {
1789                         fprintf(stderr, _("Please check if data collecting is enabled\n"));
1790                 }
1791                 exit(2);
1792         }
1793
1794         /* Read file magic data */
1795         n = read(*fd, file_magic, FILE_MAGIC_SIZE);
1796
1797         if ((n != FILE_MAGIC_SIZE) ||
1798             ((file_magic->sysstat_magic != SYSSTAT_MAGIC) && (file_magic->sysstat_magic != SYSSTAT_MAGIC_SWAPPED)) ||
1799             ((file_magic->format_magic != FORMAT_MAGIC) && (file_magic->format_magic != FORMAT_MAGIC_SWAPPED) && !ignore)) {
1800 #ifdef DEBUG
1801                 fprintf(stderr, "%s: Bytes read=%d sysstat_magic=%x format_magic=%x\n",
1802                         __FUNCTION__, n, file_magic->sysstat_magic, file_magic->format_magic);
1803 #endif
1804                 /* Display error message and exit */
1805                 handle_invalid_sa_file(*fd, file_magic, dfile, n);
1806         }
1807
1808         *endian_mismatch = (file_magic->sysstat_magic != SYSSTAT_MAGIC);
1809         if (*endian_mismatch) {
1810                 if (do_swap) {
1811                         /* Swap bytes for file_magic fields */
1812                         file_magic->sysstat_magic = SYSSTAT_MAGIC;
1813                         file_magic->format_magic  = __builtin_bswap16(file_magic->format_magic);
1814                 }
1815                 /*
1816                  * Start swapping at field "header_size" position.
1817                  * May not exist for older versions but in this case, it won't be used.
1818                  */
1819                 swap_struct(fm_types_nr, &file_magic->header_size, 0);
1820         }
1821
1822         if ((file_magic->sysstat_version > 10) ||
1823             ((file_magic->sysstat_version == 10) && (file_magic->sysstat_patchlevel >= 3))) {
1824                 /* header_size field exists only for sysstat versions 10.3.1 and later */
1825                 if ((file_magic->header_size <= MIN_FILE_HEADER_SIZE) ||
1826                     (file_magic->header_size > MAX_FILE_HEADER_SIZE)) {
1827 #ifdef DEBUG
1828                         fprintf(stderr, "%s: header_size=%u\n",
1829                                 __FUNCTION__, file_magic->header_size);
1830 #endif
1831                         /* Display error message and exit */
1832                         handle_invalid_sa_file(*fd, file_magic, dfile, n);
1833                 }
1834         }
1835         if ((file_magic->sysstat_version > 11) ||
1836             ((file_magic->sysstat_version == 11) && (file_magic->sysstat_patchlevel >= 7))) {
1837                 /* hdr_types_nr field exists only for sysstat versions 11.7.1 and later */
1838                 if (MAP_SIZE(file_magic->hdr_types_nr) > file_magic->header_size) {
1839 #ifdef DEBUG
1840                         fprintf(stderr, "%s: map_size=%u header_size=%u\n",
1841                                 __FUNCTION__, MAP_SIZE(file_magic->hdr_types_nr), file_magic->header_size);
1842 #endif
1843                         handle_invalid_sa_file(*fd, file_magic, dfile, n);
1844                 }
1845         }
1846
1847         if ((file_magic->format_magic != FORMAT_MAGIC) &&
1848             (file_magic->format_magic != FORMAT_MAGIC_SWAPPED))
1849                 /*
1850                  * This is an old (or new) sa datafile format to
1851                  * be read by sadf (since @ignore was set to TRUE).
1852                  */
1853                 return -1;
1854
1855         return 0;
1856 }
1857
1858 /*
1859  ***************************************************************************
1860  * Open a data file, and perform various checks before reading.
1861  * NB: This is called only when reading a datafile (sar and sadf), never
1862  * when writing or appending data to a datafile.
1863  *
1864  * IN:
1865  * @dfile       Name of system activity data file.
1866  * @act         Array of activities.
1867  * @flags       Flags for common options and system state.
1868  *
1869  * OUT:
1870  * @ifd         System activity data file descriptor.
1871  * @file_magic  file_magic structure containing data read from file magic
1872  *              header.
1873  * @file_hdr    file_hdr structure containing data read from file standard
1874  *              header.
1875  * @file_actlst Acvtivity list in file.
1876  * @id_seq      Activity sequence.
1877  * @endian_mismatch
1878  *              TRUE if file's data don't match current machine's endianness.
1879  * @arch_64     TRUE if file's data come from a 64 bit machine.
1880  ***************************************************************************
1881  */
1882 void check_file_actlst(int *ifd, char *dfile, struct activity *act[], uint64_t flags,
1883                        struct file_magic *file_magic, struct file_header *file_hdr,
1884                        struct file_activity **file_actlst, unsigned int id_seq[],
1885                        int *endian_mismatch, int *arch_64)
1886 {
1887         int i, j, k, p, skip;
1888         struct file_activity *fal;
1889         void *buffer = NULL;
1890         size_t bh_size = FILE_HEADER_SIZE;
1891         size_t ba_size = FILE_ACTIVITY_SIZE;
1892
1893         /* Open sa data file and read its magic structure */
1894         if (sa_open_read_magic(ifd, dfile, file_magic,
1895                                DISPLAY_HDR_ONLY(flags), endian_mismatch, TRUE) < 0)
1896                 /*
1897                  * Not current sysstat's format.
1898                  * Return now so that sadf -H can display at least
1899                  * file's version and magic number.
1900                  */
1901                 return;
1902
1903         /*
1904          * We know now that we have a *compatible* sysstat datafile format
1905          * (correct FORMAT_MAGIC value), and in this case, we should have
1906          * checked header_size value. Anyway, with a corrupted datafile,
1907          * this may not be the case. So check again.
1908          */
1909         if ((file_magic->header_size <= MIN_FILE_HEADER_SIZE) ||
1910             (file_magic->header_size > MAX_FILE_HEADER_SIZE)) {
1911 #ifdef DEBUG
1912                 fprintf(stderr, "%s: header_size=%u\n",
1913                         __FUNCTION__, file_magic->header_size);
1914 #endif
1915                 goto format_error;
1916         }
1917
1918         /* Allocate buffer for file_header structure */
1919         if (file_magic->header_size > FILE_HEADER_SIZE) {
1920                 bh_size = file_magic->header_size;
1921         }
1922         SREALLOC(buffer, char, bh_size);
1923
1924         /* Read sa data file standard header and allocate activity list */
1925         sa_fread(*ifd, buffer, (size_t) file_magic->header_size, HARD_SIZE, UEOF_STOP);
1926         /*
1927          * Data file header size (file_magic->header_size) may be greater or
1928          * smaller than FILE_HEADER_SIZE. Remap the fields of the file header
1929          * then copy its contents to the expected structure.
1930          */
1931         if (remap_struct(hdr_types_nr, file_magic->hdr_types_nr, buffer,
1932                          file_magic->header_size, FILE_HEADER_SIZE, bh_size) < 0)
1933                 goto format_error;
1934
1935         memcpy(file_hdr, buffer, FILE_HEADER_SIZE);
1936         free(buffer);
1937         buffer = NULL;
1938
1939         /* Tell that data come from a 64 bit machine */
1940         *arch_64 = (file_hdr->sa_sizeof_long == SIZEOF_LONG_64BIT);
1941
1942         /* Normalize endianness for file_hdr structure */
1943         if (*endian_mismatch) {
1944                 swap_struct(hdr_types_nr, file_hdr, *arch_64);
1945         }
1946
1947         /*
1948          * Sanity checks.
1949          * NB: Compare against MAX_NR_ACT and not NR_ACT because
1950          * we are maybe reading a datafile from a future sysstat version
1951          * with more activities than known today.
1952          */
1953         if ((file_hdr->sa_act_nr > MAX_NR_ACT) ||
1954             (file_hdr->act_size > MAX_FILE_ACTIVITY_SIZE) ||
1955             (file_hdr->rec_size > MAX_RECORD_HEADER_SIZE) ||
1956             (MAP_SIZE(file_hdr->act_types_nr) > file_hdr->act_size) ||
1957             (MAP_SIZE(file_hdr->rec_types_nr) > file_hdr->rec_size)) {
1958 #ifdef DEBUG
1959                 fprintf(stderr, "%s: sa_act_nr=%d act_size=%u rec_size=%u map_size(act)=%u map_size(rec)=%u\n",
1960                         __FUNCTION__, file_hdr->sa_act_nr, file_hdr->act_size, file_hdr->rec_size,
1961                         MAP_SIZE(file_hdr->act_types_nr), MAP_SIZE(file_hdr->rec_types_nr));
1962 #endif
1963                 /* Maybe a "false positive" sysstat datafile? */
1964                 goto format_error;
1965         }
1966
1967         /* Allocate buffer for file_activity structures */
1968         if (file_hdr->act_size > FILE_ACTIVITY_SIZE) {
1969                 ba_size = file_hdr->act_size;
1970         }
1971         SREALLOC(buffer, char, ba_size);
1972         SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_act_nr);
1973         fal = *file_actlst;
1974
1975         /* Read activity list */
1976         j = 0;
1977         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
1978
1979                 /* Read current file_activity structure from file */
1980                 sa_fread(*ifd, buffer, (size_t) file_hdr->act_size, HARD_SIZE, UEOF_STOP);
1981
1982                 /*
1983                  * Data file_activity size (file_hdr->act_size) may be greater or
1984                  * smaller than FILE_ACTIVITY_SIZE. Remap the fields of the file's structure
1985                  * then copy its contents to the expected structure.
1986                  */
1987                 if (remap_struct(act_types_nr, file_hdr->act_types_nr, buffer,
1988                              file_hdr->act_size, FILE_ACTIVITY_SIZE, ba_size) < 0)
1989                         goto format_error;
1990                 memcpy(fal, buffer, FILE_ACTIVITY_SIZE);
1991
1992                 /* Normalize endianness for file_activity structures */
1993                 if (*endian_mismatch) {
1994                         swap_struct(act_types_nr, fal, *arch_64);
1995                 }
1996
1997                 /*
1998                  * Every activity, known or unknown, should have
1999                  * at least one item and sub-item, and a size value in
2000                  * a defined range.
2001                  * Also check that the number of items and sub-items
2002                  * doesn't exceed a max value. This is necessary
2003                  * because we will use @nr and @nr2 to
2004                  * allocate memory to read the file contents. So we
2005                  * must make sure the file is not corrupted.
2006                  * NB: Another check will be made below for known
2007                  * activities which have each a specific max value.
2008                  */
2009                 if ((fal->nr < 1) || (fal->nr2 < 1) ||
2010                     (fal->nr > NR_MAX) || (fal->nr2 > NR2_MAX) ||
2011                     (fal->size <= 0) || (fal->size > MAX_ITEM_STRUCT_SIZE)) {
2012 #ifdef DEBUG
2013                         fprintf(stderr, "%s: id=%d nr=%d nr2=%d size=%d\n",
2014                                 __FUNCTION__, fal->id, fal->nr, fal->nr2, fal->size);
2015 #endif
2016                         goto format_error;
2017                 }
2018
2019                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0)
2020                         /* Unknown activity */
2021                         continue;
2022
2023                 if ((fal->magic != act[p]->magic) && !DISPLAY_HDR_ONLY(flags)) {
2024                         skip = TRUE;
2025                 }
2026                 else {
2027                         skip = FALSE;
2028                 }
2029
2030                 /* Check max value for known activities */
2031                 if (fal->nr > act[p]->nr_max) {
2032 #ifdef DEBUG
2033                         fprintf(stderr, "%s: id=%d nr=%d nr_max=%d\n",
2034                                 __FUNCTION__, fal->id, fal->nr, act[p]->nr_max);
2035 #endif
2036                         goto format_error;
2037                 }
2038
2039                 /*
2040                  * Number of fields of each type ("long long", or "long"
2041                  * or "int") composing the structure with statistics may
2042                  * only increase with new sysstat versions, unless we change
2043                  * the activity's magic number. Here, we may
2044                  * be reading a file created by current sysstat version,
2045                  * or by an older or a newer version.
2046                  */
2047                 if (!(((fal->types_nr[0] >= act[p]->gtypes_nr[0]) &&
2048                      (fal->types_nr[1] >= act[p]->gtypes_nr[1]) &&
2049                      (fal->types_nr[2] >= act[p]->gtypes_nr[2]))
2050                      ||
2051                      ((fal->types_nr[0] <= act[p]->gtypes_nr[0]) &&
2052                      (fal->types_nr[1] <= act[p]->gtypes_nr[1]) &&
2053                      (fal->types_nr[2] <= act[p]->gtypes_nr[2]))) &&
2054                      (fal->magic == act[p]->magic) && !DISPLAY_HDR_ONLY(flags)) {
2055 #ifdef DEBUG
2056                         fprintf(stderr, "%s: id=%d file=%d,%d,%d activity=%d,%d,%d\n",
2057                                 __FUNCTION__, fal->id, fal->types_nr[0], fal->types_nr[1], fal->types_nr[2],
2058                                 act[p]->gtypes_nr[0], act[p]->gtypes_nr[1], act[p]->gtypes_nr[2]);
2059 #endif
2060                         goto format_error;
2061                 }
2062
2063                 if (MAP_SIZE(fal->types_nr) > fal->size) {
2064 #ifdef DEBUG
2065                 fprintf(stderr, "%s: id=%d size=%u map_size=%u\n",
2066                         __FUNCTION__, fal->id, fal->size, MAP_SIZE(fal->types_nr));
2067 #endif
2068                         goto format_error;
2069                 }
2070
2071                 for (k = 0; k < 3; k++) {
2072                         act[p]->ftypes_nr[k] = fal->types_nr[k];
2073                 }
2074
2075                 if (fal->size > act[p]->msize) {
2076                         act[p]->msize = fal->size;
2077                 }
2078
2079                 act[p]->nr_ini = fal->nr;
2080                 act[p]->nr2    = fal->nr2;
2081                 act[p]->fsize  = fal->size;
2082
2083                 /*
2084                  * This is a known activity with a known format
2085                  * (magical number). Only such activities will be displayed.
2086                  * (Well, this may also be an unknown format if we have entered sadf -H.)
2087                  */
2088                 if (!skip) {
2089                         id_seq[j++] = fal->id;
2090                 }
2091         }
2092
2093         while (j < NR_ACT) {
2094                 id_seq[j++] = 0;
2095         }
2096
2097         free(buffer);
2098         buffer = NULL;
2099
2100         /* Check that at least one activity selected by the user is available in file */
2101         for (i = 0; i < NR_ACT; i++) {
2102
2103                 if (!IS_SELECTED(act[i]->options))
2104                         continue;
2105
2106                 /* Here is a selected activity: Does it exist in file? */
2107                 fal = *file_actlst;
2108                 for (j = 0; j < file_hdr->sa_act_nr; j++, fal++) {
2109                         if (act[i]->id == fal->id)
2110                                 break;
2111                 }
2112                 if (j == file_hdr->sa_act_nr) {
2113                         /* No: Unselect it */
2114                         act[i]->options &= ~AO_SELECTED;
2115                 }
2116         }
2117
2118         /*
2119          * None of selected activities exist in file: Abort.
2120          * NB: Error is ignored if we only want to display
2121          * datafile header (sadf -H).
2122          */
2123         if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES) && !DISPLAY_HDR_ONLY(flags)) {
2124                 fprintf(stderr, _("Requested activities not available in file %s\n"),
2125                         dfile);
2126                 close(*ifd);
2127                 exit(1);
2128         }
2129
2130         /*
2131          * Check if there are some extra structures.
2132          * We will just skip them as they are unknown for now.
2133          */
2134         if (file_hdr->extra_next && (skip_extra_struct(*ifd, *endian_mismatch, *arch_64) < 0))
2135                 goto format_error;
2136
2137         return;
2138
2139 format_error:
2140         if (buffer) {
2141                 free(buffer);
2142         }
2143         handle_invalid_sa_file(*ifd, file_magic, dfile, 0);
2144 }
2145
2146 /*
2147  ***************************************************************************
2148  * Parse sar activities options (also used by sadf).
2149  *
2150  * IN:
2151  * @argv        Arguments list.
2152  * @opt         Index in list of arguments.
2153  * @caller      Indicate whether it's sar or sadf that called this function.
2154  *
2155  * OUT:
2156  * @act         Array of selected activities.
2157  * @flags       Common flags and system state.
2158  *
2159  * RETURNS:
2160  * 0 on success.
2161  ***************************************************************************
2162  */
2163 int parse_sar_opt(char *argv[], int *opt, struct activity *act[],
2164                   uint64_t *flags, int caller)
2165 {
2166         int i, p;
2167
2168         for (i = 1; *(argv[*opt] + i); i++) {
2169                 /*
2170                  * Note: argv[*opt] contains something like "-BruW"
2171                  *     *(argv[*opt] + i) will contain 'B', 'r', etc.
2172                  */
2173
2174                 switch (*(argv[*opt] + i)) {
2175
2176                 case 'A':
2177                         select_all_activities(act);
2178                         *flags |= S_F_OPTION_A;
2179
2180                         /*
2181                          * Force '-r ALL -u ALL -F'.
2182                          * Setting -F is compulsory because corresponding activity
2183                          * has AO_MULTIPLE_OUTPUTS flag set.
2184                          * -P ALL will be set only if corresponding option has
2185                          * not been exlicitly entered on the command line.
2186                          */
2187                         p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
2188                         act[p]->opt_flags |= AO_F_MEMORY + AO_F_SWAP + AO_F_MEM_ALL;
2189
2190                         p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
2191                         act[p]->opt_flags = AO_F_CPU_ALL;
2192
2193                         p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
2194                         act[p]->opt_flags = AO_F_FILESYSTEM;
2195                         break;
2196
2197                 case 'B':
2198                         SELECT_ACTIVITY(A_PAGE);
2199                         break;
2200
2201                 case 'b':
2202                         SELECT_ACTIVITY(A_IO);
2203                         break;
2204
2205                 case 'C':
2206                         *flags |= S_F_COMMENT;
2207                         break;
2208
2209                 case 'd':
2210                         SELECT_ACTIVITY(A_DISK);
2211                         break;
2212
2213                 case 'F':
2214                         p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
2215                         act[p]->options |= AO_SELECTED;
2216                         if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_MOUNT)) {
2217                                 (*opt)++;
2218                                 act[p]->opt_flags |= AO_F_MOUNT;
2219                                 return 0;
2220                         }
2221                         else {
2222                                 act[p]->opt_flags |= AO_F_FILESYSTEM;
2223                         }
2224                         break;
2225
2226                 case 'H':
2227                         SELECT_ACTIVITY(A_HUGE);
2228                         break;
2229
2230                 case 'h':
2231                         /* Option -h is equivalent to --pretty --human */
2232                         *flags |= S_F_PRETTY + S_F_UNIT;
2233                         break;
2234
2235                 case 'I':
2236                         p = get_activity_position(act, A_IRQ, EXIT_IF_NOT_FOUND);
2237                         act[p]->options |= AO_SELECTED;
2238
2239                         if (!*(argv[*opt] + i + 1) && argv[*opt + 1] &&
2240                             (!strcmp(argv[*opt + 1], K_ALL) || !strcmp(argv[*opt + 1], K_SUM))) {
2241                                 (*opt)++;
2242                                 /* Select int "sum". Keyword ALL is ignored */
2243                                 if (!strcmp(argv[*opt], K_SUM)) {
2244                                         act[p]->item_list_sz += add_list_item(&(act[p]->item_list), K_LOWERSUM, MAX_SA_IRQ_LEN);
2245                                         act[p]->options |= AO_LIST_ON_CMDLINE;
2246                                 }
2247                                 return 0;
2248                         }
2249                         break;
2250
2251                 case 'j':
2252                         if (!argv[*opt + 1]) {
2253                                 return 1;
2254                         }
2255                         (*opt)++;
2256                         if (!strcmp(argv[*opt], K_SID)) {
2257                                 *flags |= S_F_DEV_SID + S_F_PRETTY;
2258                                 return 0;
2259                         }
2260
2261                         if (strnlen(argv[*opt], sizeof(persistent_name_type)) >= sizeof(persistent_name_type) - 1)
2262                                 return 1;
2263
2264                         strncpy(persistent_name_type, argv[*opt], sizeof(persistent_name_type) - 1);
2265                         persistent_name_type[sizeof(persistent_name_type) - 1] = '\0';
2266                         strtolower(persistent_name_type);
2267                         if (!get_persistent_type_dir(persistent_name_type)) {
2268                                 fprintf(stderr, _("Invalid type of persistent device name\n"));
2269                                 return 2;
2270                         }
2271                         /* Pretty print report (option -j implies option -p) */
2272                         *flags |= S_F_PERSIST_NAME + S_F_PRETTY;
2273                         return 0;
2274                         break;
2275
2276                 case 'p':
2277                         *flags |= S_F_PRETTY;
2278                         break;
2279
2280                 case 'q':
2281                         /* Option -q grouped with other ones */
2282                         SELECT_ACTIVITY(A_QUEUE);
2283                         break;
2284
2285                 case 'r':
2286                         p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
2287                         act[p]->options   |= AO_SELECTED;
2288                         act[p]->opt_flags |= AO_F_MEMORY;
2289                         if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
2290                                 (*opt)++;
2291                                 act[p]->opt_flags |= AO_F_MEM_ALL;
2292                                 return 0;
2293                         }
2294                         break;
2295
2296                 case 'S':
2297                         p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
2298                         act[p]->options   |= AO_SELECTED;
2299                         act[p]->opt_flags |= AO_F_SWAP;
2300                         break;
2301
2302                 case 't':
2303                         /*
2304                          * Check sar option -t here (as it can be combined
2305                          * with other ones, eg. "sar -rtu ..."
2306                          * But sadf option -t is checked in sadf.c as it won't
2307                          * be entered as a sar option after "--".
2308                          */
2309                         if (caller != C_SAR) {
2310                                 return 1;
2311                         }
2312                         *flags |= S_F_TRUE_TIME;
2313                         break;
2314
2315                 case 'u':
2316                         p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
2317                         act[p]->options |= AO_SELECTED;
2318                         if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
2319                                 (*opt)++;
2320                                 act[p]->opt_flags = AO_F_CPU_ALL;
2321                                 return 0;
2322                         }
2323                         else {
2324                                 act[p]->opt_flags = AO_F_CPU_DEF;
2325                         }
2326                         break;
2327
2328                 case 'v':
2329                         SELECT_ACTIVITY(A_KTABLES);
2330                         break;
2331
2332                 case 'w':
2333                         SELECT_ACTIVITY(A_PCSW);
2334                         break;
2335
2336                 case 'W':
2337                         SELECT_ACTIVITY(A_SWAP);
2338                         break;
2339
2340                 case 'y':
2341                         SELECT_ACTIVITY(A_SERIAL);
2342                         break;
2343
2344                 case 'z':
2345                         *flags |= S_F_ZERO_OMIT;
2346                         break;
2347
2348                 case 'V':
2349                         print_version();
2350                         break;
2351
2352                 default:
2353                         return 1;
2354                 }
2355         }
2356         return 0;
2357 }
2358
2359 /*
2360  ***************************************************************************
2361  * Parse sar "-m" option.
2362  *
2363  * IN:
2364  * @argv        Arguments list.
2365  * @opt         Index in list of arguments.
2366  *
2367  * OUT:
2368  * @act         Array of selected activities.
2369  *
2370  * RETURNS:
2371  * 0 on success, 1 otherwise.
2372  ***************************************************************************
2373  */
2374 int parse_sar_m_opt(char *argv[], int *opt, struct activity *act[])
2375 {
2376         char *t;
2377
2378         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
2379                 if (!strcmp(t, K_CPU)) {
2380                         SELECT_ACTIVITY(A_PWR_CPU);
2381                 }
2382                 else if (!strcmp(t, K_FAN)) {
2383                         SELECT_ACTIVITY(A_PWR_FAN);
2384                 }
2385                 else if (!strcmp(t, K_IN)) {
2386                         SELECT_ACTIVITY(A_PWR_IN);
2387                 }
2388                 else if (!strcmp(t, K_TEMP)) {
2389                         SELECT_ACTIVITY(A_PWR_TEMP);
2390                 }
2391                 else if (!strcmp(t, K_FREQ)) {
2392                         SELECT_ACTIVITY(A_PWR_FREQ);
2393                 }
2394                 else if (!strcmp(t, K_USB)) {
2395                         SELECT_ACTIVITY(A_PWR_USB);
2396                 }
2397                 else if (!strcmp(t, K_ALL)) {
2398                         SELECT_ACTIVITY(A_PWR_CPU);
2399                         SELECT_ACTIVITY(A_PWR_FAN);
2400                         SELECT_ACTIVITY(A_PWR_IN);
2401                         SELECT_ACTIVITY(A_PWR_TEMP);
2402                         SELECT_ACTIVITY(A_PWR_FREQ);
2403                         SELECT_ACTIVITY(A_PWR_USB);
2404                 }
2405                 else
2406                         return 1;
2407         }
2408
2409         (*opt)++;
2410         return 0;
2411 }
2412
2413 /*
2414  ***************************************************************************
2415  * Parse sar "-n" option.
2416  *
2417  * IN:
2418  * @argv        Arguments list.
2419  * @opt         Index in list of arguments.
2420  *
2421  * OUT:
2422  * @act         Array of selected activities.
2423  *
2424  * RETURNS:
2425  * 0 on success, 1 otherwise.
2426  ***************************************************************************
2427  */
2428 int parse_sar_n_opt(char *argv[], int *opt, struct activity *act[])
2429 {
2430         char *t;
2431
2432         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
2433                 if (!strcmp(t, K_DEV)) {
2434                         SELECT_ACTIVITY(A_NET_DEV);
2435                 }
2436                 else if (!strcmp(t, K_EDEV)) {
2437                         SELECT_ACTIVITY(A_NET_EDEV);
2438                 }
2439                 else if (!strcmp(t, K_SOCK)) {
2440                         SELECT_ACTIVITY(A_NET_SOCK);
2441                 }
2442                 else if (!strcmp(t, K_NFS)) {
2443                         SELECT_ACTIVITY(A_NET_NFS);
2444                 }
2445                 else if (!strcmp(t, K_NFSD)) {
2446                         SELECT_ACTIVITY(A_NET_NFSD);
2447                 }
2448                 else if (!strcmp(t, K_IP)) {
2449                         SELECT_ACTIVITY(A_NET_IP);
2450                 }
2451                 else if (!strcmp(t, K_EIP)) {
2452                         SELECT_ACTIVITY(A_NET_EIP);
2453                 }
2454                 else if (!strcmp(t, K_ICMP)) {
2455                         SELECT_ACTIVITY(A_NET_ICMP);
2456                 }
2457                 else if (!strcmp(t, K_EICMP)) {
2458                         SELECT_ACTIVITY(A_NET_EICMP);
2459                 }
2460                 else if (!strcmp(t, K_TCP)) {
2461                         SELECT_ACTIVITY(A_NET_TCP);
2462                 }
2463                 else if (!strcmp(t, K_ETCP)) {
2464                         SELECT_ACTIVITY(A_NET_ETCP);
2465                 }
2466                 else if (!strcmp(t, K_UDP)) {
2467                         SELECT_ACTIVITY(A_NET_UDP);
2468                 }
2469                 else if (!strcmp(t, K_SOCK6)) {
2470                         SELECT_ACTIVITY(A_NET_SOCK6);
2471                 }
2472                 else if (!strcmp(t, K_IP6)) {
2473                         SELECT_ACTIVITY(A_NET_IP6);
2474                 }
2475                 else if (!strcmp(t, K_EIP6)) {
2476                         SELECT_ACTIVITY(A_NET_EIP6);
2477                 }
2478                 else if (!strcmp(t, K_ICMP6)) {
2479                         SELECT_ACTIVITY(A_NET_ICMP6);
2480                 }
2481                 else if (!strcmp(t, K_EICMP6)) {
2482                         SELECT_ACTIVITY(A_NET_EICMP6);
2483                 }
2484                 else if (!strcmp(t, K_UDP6)) {
2485                         SELECT_ACTIVITY(A_NET_UDP6);
2486                 }
2487                 else if (!strcmp(t, K_FC)) {
2488                         SELECT_ACTIVITY(A_NET_FC);
2489                 }
2490                 else if (!strcmp(t, K_SOFT)) {
2491                         SELECT_ACTIVITY(A_NET_SOFT);
2492                 }
2493                 else if (!strcmp(t, K_ALL)) {
2494                         SELECT_ACTIVITY(A_NET_DEV);
2495                         SELECT_ACTIVITY(A_NET_EDEV);
2496                         SELECT_ACTIVITY(A_NET_SOCK);
2497                         SELECT_ACTIVITY(A_NET_NFS);
2498                         SELECT_ACTIVITY(A_NET_NFSD);
2499                         SELECT_ACTIVITY(A_NET_IP);
2500                         SELECT_ACTIVITY(A_NET_EIP);
2501                         SELECT_ACTIVITY(A_NET_ICMP);
2502                         SELECT_ACTIVITY(A_NET_EICMP);
2503                         SELECT_ACTIVITY(A_NET_TCP);
2504                         SELECT_ACTIVITY(A_NET_ETCP);
2505                         SELECT_ACTIVITY(A_NET_UDP);
2506                         SELECT_ACTIVITY(A_NET_SOCK6);
2507                         SELECT_ACTIVITY(A_NET_IP6);
2508                         SELECT_ACTIVITY(A_NET_EIP6);
2509                         SELECT_ACTIVITY(A_NET_ICMP6);
2510                         SELECT_ACTIVITY(A_NET_EICMP6);
2511                         SELECT_ACTIVITY(A_NET_UDP6);
2512                         SELECT_ACTIVITY(A_NET_FC);
2513                         SELECT_ACTIVITY(A_NET_SOFT);
2514                 }
2515                 else
2516                         return 1;
2517         }
2518
2519         (*opt)++;
2520         return 0;
2521 }
2522
2523 /*
2524  ***************************************************************************
2525  * Parse sar "-q" option.
2526  *
2527  * IN:
2528  * @argv        Arguments list.
2529  * @opt         Index in list of arguments.
2530  *
2531  * OUT:
2532  * @act         Array of selected activities.
2533  *
2534  * RETURNS:
2535  * 0 on success, 1 otherwise.
2536  ***************************************************************************
2537  */
2538 int parse_sar_q_opt(char *argv[], int *opt, struct activity *act[])
2539 {
2540         char *t;
2541
2542         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
2543                 if (!strcmp(t, K_LOAD)) {
2544                         SELECT_ACTIVITY(A_QUEUE);
2545                 }
2546                 else if (!strcmp(t, K_PSI_CPU)) {
2547                         SELECT_ACTIVITY(A_PSI_CPU);
2548                 }
2549                 else if (!strcmp(t, K_PSI_IO)) {
2550                         SELECT_ACTIVITY(A_PSI_IO);
2551                 }
2552                 else if (!strcmp(t, K_PSI_MEM)) {
2553                         SELECT_ACTIVITY(A_PSI_MEM);
2554                 }
2555                 else if (!strcmp(t, K_PSI)) {
2556                         SELECT_ACTIVITY(A_PSI_CPU);
2557                         SELECT_ACTIVITY(A_PSI_IO);
2558                         SELECT_ACTIVITY(A_PSI_MEM);
2559                 }
2560                 else if (!strcmp(t, K_ALL)) {
2561                         SELECT_ACTIVITY(A_QUEUE);
2562                         SELECT_ACTIVITY(A_PSI_CPU);
2563                         SELECT_ACTIVITY(A_PSI_IO);
2564                         SELECT_ACTIVITY(A_PSI_MEM);
2565                 }
2566                 else
2567                         return 1;
2568         }
2569
2570         (*opt)++;
2571         return 0;
2572 }
2573
2574 /*
2575  ***************************************************************************
2576  * Parse sar and sadf "-P" option.
2577  *
2578  * IN:
2579  * @argv        Arguments list.
2580  * @opt         Index in list of arguments.
2581  * @act         Array of activities.
2582  *
2583  * OUT:
2584  * @flags       Common flags and system state.
2585  * @act         Array of activities, with CPUs selected.
2586  *
2587  * RETURNS:
2588  * 0 on success, 1 otherwise.
2589  ***************************************************************************
2590  */
2591 int parse_sa_P_opt(char *argv[], int *opt, uint64_t *flags, struct activity *act[])
2592 {
2593         int p;
2594
2595         p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
2596
2597         if (argv[++(*opt)]) {
2598                 if (parse_values(argv[*opt], act[p]->bitmap->b_array,
2599                              act[p]->bitmap->b_size, K_LOWERALL))
2600                         return 1;
2601                 (*opt)++;
2602                 *flags |= S_F_OPTION_P;
2603                 return 0;
2604         }
2605
2606         return 1;
2607 }
2608
2609 /*
2610  ***************************************************************************
2611  * If option -A has been used, force -P ALL only if corresponding
2612  * option has not been explicitly entered on the command line.
2613  *
2614  * IN:
2615  * @flags       Common flags and system state.
2616  *
2617  * OUT:
2618  * @act         Array of selected activities.
2619  ***************************************************************************
2620  */
2621 void set_bitmaps(struct activity *act[], uint64_t *flags)
2622 {
2623         int p;
2624
2625         if (!USE_OPTION_P(*flags)) {
2626                 /* Force -P ALL */
2627                 p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
2628                 memset(act[p]->bitmap->b_array, ~0,
2629                        BITMAP_SIZE(act[p]->bitmap->b_size));
2630         }
2631 }
2632
2633 /*
2634  ***************************************************************************
2635  * Look for item in list.
2636  *
2637  * IN:
2638  * @list        Pointer on the start of the linked list.
2639  * @item_name   Item name to look for.
2640  *
2641  * RETURNS:
2642  * 1 if item found in list, 0 otherwise.
2643  ***************************************************************************
2644  */
2645 int search_list_item(struct sa_item *list, char *item_name)
2646 {
2647         while (list != NULL) {
2648                 if (!strcmp(list->item_name, item_name))
2649                         return 1;       /* Item found in list */
2650                 list = list->next;
2651         }
2652
2653         /* Item not found */
2654         return 0;
2655 }
2656
2657 /*
2658  ***************************************************************************
2659  * Add item to the list.
2660  *
2661  * IN:
2662  * @list        Address of pointer on the start of the linked list.
2663  * @item_name   Name of the item.
2664  * @max_len     Max length of an item.
2665  *
2666  * RETURNS:
2667  * 1 if item has been added to the list (since it was not previously there),
2668  * and 0 otherwise (item already in list or item name too long).
2669  ***************************************************************************
2670  */
2671 int add_list_item(struct sa_item **list, char *item_name, int max_len)
2672 {
2673         struct sa_item *e;
2674         int len;
2675
2676         if ((len = strnlen(item_name, max_len)) == max_len)
2677                 /* Item too long */
2678                 return 0;
2679
2680         while (*list != NULL) {
2681                 e = *list;
2682                 if (!strcmp(e->item_name, item_name))
2683                         return 0;       /* Item found in list */
2684                 list = &(e->next);
2685         }
2686
2687         /* Item not found: Add it to the list */
2688         SREALLOC(*list, struct sa_item, sizeof(struct sa_item));
2689         e = *list;
2690         if ((e->item_name = (char *) malloc(len + 1)) == NULL) {
2691                 perror("malloc");
2692                 exit(4);
2693         }
2694         strcpy(e->item_name, item_name);
2695
2696         return 1;
2697 }
2698
2699 /*
2700  ***************************************************************************
2701  * Parse devices entered on the command line and save them in activity's
2702  * list.
2703  *
2704  * IN:
2705  * @argv        Argument with list of devices.
2706  * @a           Activity for which devices are entered on the command line.
2707  * @max_len     Max length of a device name.
2708  * @opt         Index in list of arguments.
2709  * @pos         Position is string where is located the first device.
2710  * @max_val     If > 0 then ranges of values are allowed (e.g. 3-5,9-, etc.)
2711  *              Values are in range [0..@max_val].
2712  *
2713  * OUT:
2714  * @opt         Index on next argument.
2715  ***************************************************************************
2716  */
2717 void parse_sa_devices(char *argv, struct activity *a, int max_len, int *opt, int pos,
2718                       int max_val)
2719 {
2720         int i, val_low, val;
2721         char *t;
2722         char svalue[9];
2723
2724         for (t = strtok(argv + pos, ","); t; t = strtok(NULL, ",")) {
2725
2726                 /* Test ranges of values, if allowed */
2727                 if ((max_val > 0) && (strlen(t) <= 16) && (strspn(t, XDIGITS) == strlen(t))) {
2728                         if (parse_range_values(t, max_val, &val_low, &val) == 0) {
2729                                 /* This is a real range of values: Save each if its values */
2730                                 for (i = val_low; i <= val; i++) {
2731                                         snprintf(svalue, sizeof(svalue), "%d", i);
2732                                         svalue[sizeof(svalue) - 1] = '\0';
2733                                         a->item_list_sz += add_list_item(&(a->item_list), svalue, max_len);
2734                                 }
2735                                 continue;
2736                         }
2737                 }
2738                 a->item_list_sz += add_list_item(&(a->item_list), t, max_len);
2739         }
2740         if (a->item_list_sz) {
2741                 a->options |= AO_LIST_ON_CMDLINE;
2742         }
2743         (*opt)++;
2744 }
2745
2746 /*
2747  ***************************************************************************
2748  * Compute network interface utilization.
2749  *
2750  * IN:
2751  * @st_net_dev  Structure with network interface stats.
2752  * @rx          Number of bytes received per second.
2753  * @tx          Number of bytes transmitted per second.
2754  *
2755  * RETURNS:
2756  * NIC utilization (0-100%).
2757  ***************************************************************************
2758  */
2759 double compute_ifutil(struct stats_net_dev *st_net_dev, double rx, double tx)
2760 {
2761         unsigned long long speed;
2762
2763         if (st_net_dev->speed) {
2764
2765                 speed = (unsigned long long) st_net_dev->speed * 1000000;
2766
2767                 if (st_net_dev->duplex == C_DUPLEX_FULL) {
2768                         /* Full duplex */
2769                         if (rx > tx) {
2770                                 return (rx * 800 / speed);
2771                         }
2772                         else {
2773                                 return (tx * 800 / speed);
2774                         }
2775                 }
2776                 else {
2777                         /* Half duplex */
2778                         return ((rx + tx) * 800 / speed);
2779                 }
2780         }
2781
2782         return 0;
2783 }
2784
2785 /*
2786  ***************************************************************************
2787  * Read and replace unprintable characters in comment with ".".
2788  *
2789  * IN:
2790  * @ifd         Input file descriptor.
2791  * @comment     Comment.
2792  ***************************************************************************
2793  */
2794 void replace_nonprintable_char(int ifd, char *comment)
2795 {
2796         int i;
2797
2798         /* Read comment */
2799         sa_fread(ifd, comment, MAX_COMMENT_LEN, HARD_SIZE, UEOF_STOP);
2800         comment[MAX_COMMENT_LEN - 1] = '\0';
2801
2802         /* Replace non printable chars */
2803         for (i = 0; i < strlen(comment); i++) {
2804                 if (!isprint(comment[i]))
2805                         comment[i] = '.';
2806         }
2807 }
2808
2809 /*
2810  ***************************************************************************
2811  * Fill the rectime and loctime structures with current record's date and
2812  * time, based on current record's "number of seconds since the epoch" saved
2813  * in file.
2814  * For loctime (if given): The timestamp is expressed in local time.
2815  * For rectime: The timestamp is expressed in UTC, in local time, or in the
2816  * time of the file's creator depending on options entered by the user on the
2817  * command line.
2818  *
2819  * IN:
2820  * @l_flags     Flags indicating the type of time expected by the user.
2821  *              S_F_LOCAL_TIME means time should be expressed in local time.
2822  *              S_F_TRUE_TIME means time should be expressed in time of
2823  *              file's creator.
2824  *              Default is time expressed in UTC (except for sar, where it
2825  *              is local time).
2826  * @record_hdr  Record header containing the number of seconds since the
2827  *              epoch, and the HH:MM:SS of the file's creator.
2828  *
2829  * OUT:
2830  * @rectime     Structure where timestamp for current record has been saved
2831  *              (in local time, in UTC or in time of file's creator
2832  *              depending on options used).
2833  *
2834  * RETURNS:
2835  * 1 if an error was detected, or 0 otherwise.
2836  ***************************************************************************
2837 */
2838 int sa_get_record_timestamp_struct(uint64_t l_flags, struct record_header *record_hdr,
2839                                    struct tm *rectime)
2840 {
2841         struct tm *ltm;
2842         int rc = 0;
2843
2844         /*
2845          * Fill generic rectime structure in local time.
2846          * Done so that we have some default values.
2847          */
2848         ltm = localtime_r((const time_t *) &(record_hdr->ust_time), rectime);
2849
2850         if (!PRINT_LOCAL_TIME(l_flags) && !PRINT_TRUE_TIME(l_flags)) {
2851                 /*
2852                  * Get time in UTC
2853                  * (the user doesn't want local time nor time of file's creator).
2854                  */
2855                 ltm = gmtime_r((const time_t *) &(record_hdr->ust_time), rectime);
2856         }
2857
2858         if (!ltm) {
2859                 rc = 1;
2860         }
2861
2862         if (PRINT_TRUE_TIME(l_flags)) {
2863                 /* Time of file's creator */
2864                 rectime->tm_hour = record_hdr->hour;
2865                 rectime->tm_min  = record_hdr->minute;
2866                 rectime->tm_sec  = record_hdr->second;
2867         }
2868
2869         return rc;
2870 }
2871
2872 /*
2873  ***************************************************************************
2874  * Set current record's timestamp strings (date and time) using the time
2875  * data saved in @rectime structure. The string may be the number of seconds
2876  * since the epoch if flag S_F_SEC_EPOCH has been set.
2877  *
2878  * IN:
2879  * @l_flags     Flags indicating the type of time expected by the user.
2880  *              S_F_SEC_EPOCH means the time should be expressed in seconds
2881  *              since the epoch (01/01/1970).
2882  * @record_hdr  Record header containing the number of seconds since the
2883  *              epoch.
2884  * @cur_date    String where timestamp's date will be saved. May be NULL.
2885  * @cur_time    String where timestamp's time will be saved.
2886  * @len         Maximum length of timestamp strings.
2887  * @rectime     Structure with current timestamp (expressed in local time or
2888  *              in UTC depending on whether options -T or -t have been used
2889  *              or not) that should be broken down in date and time strings.
2890  *
2891  * OUT:
2892  * @cur_date    Timestamp's date string (if expected).
2893  * @cur_time    Timestamp's time string. May contain the number of seconds
2894  *              since the epoch (01-01-1970) if corresponding option has
2895  *              been used.
2896  ***************************************************************************
2897 */
2898 void set_record_timestamp_string(uint64_t l_flags, struct record_header *record_hdr,
2899                                  char *cur_date, char *cur_time, int len, struct tm *rectime)
2900 {
2901         /* Set cur_time date value */
2902         if (PRINT_SEC_EPOCH(l_flags) && cur_date) {
2903                 sprintf(cur_time, "%llu", record_hdr->ust_time);
2904                 strcpy(cur_date, "");
2905         }
2906         else {
2907                 /*
2908                  * If options -T or -t have been used then cur_time is
2909                  * expressed in local time. Else it is expressed in UTC.
2910                  */
2911                 if (cur_date) {
2912                         strftime(cur_date, len, "%Y-%m-%d", rectime);
2913                 }
2914                 if (USE_PREFD_TIME_OUTPUT(l_flags)) {
2915                         strftime(cur_time, len, "%X", rectime);
2916                 }
2917                 else {
2918                         strftime(cur_time, len, "%H:%M:%S", rectime);
2919                 }
2920         }
2921 }
2922
2923 /*
2924  ***************************************************************************
2925  * Print contents of a special (RESTART or COMMENT) record.
2926  * Note: This function is called only when reading a file.
2927  *
2928  * IN:
2929  * @record_hdr  Current record header.
2930  * @l_flags     Flags for common options.
2931  * @tm_start    Structure filled when option -s has been used.
2932  * @tm_end      Structure filled when option -e has been used.
2933  * @rtype       Record type (R_RESTART or R_COMMENT).
2934  * @ifd         Input file descriptor.
2935  * @rectime     Structure where timestamp (expressed in local time or in UTC
2936  *              depending on whether options -T/-t have been used or not) can
2937  *              be saved for current record.
2938  * @file        Name of file being read.
2939  * @tab         Number of tabulations to print.
2940  * @file_magic  file_magic structure filled with file magic header data.
2941  * @file_hdr    System activity file standard header.
2942  * @act         Array of activities.
2943  * @ofmt        Pointer on report output format structure.
2944  * @endian_mismatch
2945  *              TRUE if file's data don't match current machine's endianness.
2946  * @arch_64     TRUE if file's data come from a 64 bit machine.
2947  *
2948  * OUT:
2949  * @rectime     Structure where timestamp (expressed in local time or in UTC)
2950  *              has been saved.
2951  *
2952  * RETURNS:
2953  * 1 if the record has been successfully displayed, and 0 otherwise.
2954  ***************************************************************************
2955  */
2956 int print_special_record(struct record_header *record_hdr, uint64_t l_flags,
2957                          struct tstamp *tm_start, struct tstamp *tm_end, int rtype, int ifd,
2958                          struct tm *rectime, char *file, int tab,
2959                          struct file_magic *file_magic, struct file_header *file_hdr,
2960                          struct activity *act[], struct report_format *ofmt,
2961                          int endian_mismatch, int arch_64)
2962 {
2963         char cur_date[TIMESTAMP_LEN], cur_time[TIMESTAMP_LEN];
2964         int dp = 1;
2965         int p;
2966
2967         /* Fill timestamp structure (rectime) for current record */
2968         if (sa_get_record_timestamp_struct(l_flags, record_hdr, rectime))
2969                 return 0;
2970
2971         /* The record must be in the interval specified by -s/-e options */
2972         if ((tm_start->use && (datecmp(rectime, tm_start, FALSE) < 0)) ||
2973             (tm_end->use && (datecmp(rectime, tm_end, FALSE) > 0))) {
2974                 /* Will not display the special record */
2975                 dp = 0;
2976         }
2977         else {
2978                 /* Set date and time strings to be displayed for current record */
2979                 set_record_timestamp_string(l_flags, record_hdr,
2980                                             cur_date, cur_time, TIMESTAMP_LEN, rectime);
2981         }
2982
2983         if (rtype == R_RESTART) {
2984                 /* Read new cpu number following RESTART record */
2985                 file_hdr->sa_cpu_nr = read_nr_value(ifd, file, file_magic,
2986                                                     endian_mismatch, arch_64, TRUE);
2987
2988                 /*
2989                  * We don't know if CPU related activities will be displayed or not.
2990                  * But if it is the case, @nr_ini will be used in the loop
2991                  * to process all CPUs. So update their value here and
2992                  * reallocate buffers if needed.
2993                  * NB: We may have nr_allocated=0 here if the activity has
2994                  * not been collected in file (or if it has an unknown format).
2995                  */
2996                 for (p = 0; p < NR_ACT; p++) {
2997                         if (HAS_PERSISTENT_VALUES(act[p]->options)) {
2998                                 act[p]->nr_ini = file_hdr->sa_cpu_nr;
2999                                 if (act[p]->nr_ini > act[p]->nr_allocated) {
3000                                         reallocate_all_buffers(act[p], act[p]->nr_ini);
3001                                 }
3002                         }
3003                 }
3004
3005                 /* Ignore unknown extra structures if present */
3006                 if (record_hdr->extra_next && (skip_extra_struct(ifd, endian_mismatch, arch_64) < 0))
3007                         return 0;
3008
3009                 if (!dp)
3010                         return 0;
3011
3012                 if (*ofmt->f_restart) {
3013                         (*ofmt->f_restart)(&tab, F_MAIN, cur_date, cur_time,
3014                                            !PRINT_LOCAL_TIME(l_flags) &&
3015                                            !PRINT_TRUE_TIME(l_flags), file_hdr, record_hdr);
3016                 }
3017         }
3018         else if (rtype == R_COMMENT) {
3019                 char file_comment[MAX_COMMENT_LEN];
3020
3021                 /* Read and replace non printable chars in comment */
3022                 replace_nonprintable_char(ifd, file_comment);
3023
3024                 /* Ignore unknown extra structures if present */
3025                 if (record_hdr->extra_next && (skip_extra_struct(ifd, endian_mismatch, arch_64) < 0))
3026                         return 0;
3027
3028                 if (!dp || !DISPLAY_COMMENT(l_flags))
3029                         return 0;
3030
3031                 if (*ofmt->f_comment) {
3032                         (*ofmt->f_comment)(&tab, F_MAIN, cur_date, cur_time,
3033                                            !PRINT_LOCAL_TIME(l_flags) &&
3034                                            !PRINT_TRUE_TIME(l_flags), file_comment,
3035                                            file_hdr, record_hdr);
3036                 }
3037         }
3038
3039         return 1;
3040 }
3041
3042 /*
3043  ***************************************************************************
3044  * Compute global CPU statistics as the sum of individual CPU ones, and
3045  * calculate interval for global CPU.
3046  * Also identify offline CPU.
3047  *
3048  * IN:
3049  * @a           Activity structure with statistics.
3050  * @prev        Index in array where stats used as reference are.
3051  * @curr        Index in array for current sample statistics.
3052  * @flags       Flags for common options and system state.
3053  * @offline_cpu_bitmap
3054  *              CPU bitmap for offline CPU.
3055  *
3056  * OUT:
3057  * @a           Activity structure with updated statistics (those for global
3058  *              CPU, and also those for offline CPU).
3059  * @offline_cpu_bitmap
3060  *              CPU bitmap with offline CPU.
3061  *
3062  * RETURNS:
3063  * Interval for global CPU.
3064  ***************************************************************************
3065  */
3066 unsigned long long get_global_cpu_statistics(struct activity *a, int prev, int curr,
3067                                              uint64_t flags, unsigned char offline_cpu_bitmap[])
3068 {
3069         int i;
3070         unsigned long long tot_jiffies_c, tot_jiffies_p;
3071         unsigned long long deltot_jiffies = 0;
3072         struct stats_cpu *scc, *scp;
3073         struct stats_cpu *scc_all = (struct stats_cpu *) ((char *) a->buf[curr]);
3074         struct stats_cpu *scp_all = (struct stats_cpu *) ((char *) a->buf[prev]);
3075
3076         /*
3077          * Initial processing.
3078          * Compute CPU "all" as sum of all individual CPU. Done only on SMP machines (a->nr_ini > 1).
3079          * For UP machines we keep the values read from global CPU line in /proc/stat.
3080          * Also look for offline CPU: They won't be displayed, and some of their values may
3081          * have to be modified.
3082          */
3083         if (a->nr_ini > 1) {
3084                 memset(scc_all, 0, sizeof(struct stats_cpu));
3085                 memset(scp_all, 0, sizeof(struct stats_cpu));
3086         }
3087
3088         for (i = 1; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
3089
3090                 /*
3091                  * The size of a->buf[...] CPU structure may be different from the default
3092                  * sizeof(struct stats_cpu) value if data have been read from a file!
3093                  * That's why we don't use a syntax like:
3094                  * scc = (struct stats_cpu *) a->buf[...] + i;
3095                  */
3096                 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
3097                 scp = (struct stats_cpu *) ((char *) a->buf[prev] + i * a->msize);
3098
3099                 /*
3100                  * Compute the total number of jiffies spent by current processor.
3101                  * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
3102                  * already include them.
3103                  */
3104                 tot_jiffies_c = scc->cpu_user + scc->cpu_nice +
3105                                 scc->cpu_sys + scc->cpu_idle +
3106                                 scc->cpu_iowait + scc->cpu_hardirq +
3107                                 scc->cpu_steal + scc->cpu_softirq;
3108                 tot_jiffies_p = scp->cpu_user + scp->cpu_nice +
3109                                 scp->cpu_sys + scp->cpu_idle +
3110                                 scp->cpu_iowait + scp->cpu_hardirq +
3111                                 scp->cpu_steal + scp->cpu_softirq;
3112
3113                 /*
3114                  * If the CPU is offline then it is omited from /proc/stat:
3115                  * All the fields couldn't have been read and the sum of them is zero.
3116                  */
3117                 if (tot_jiffies_c == 0) {
3118                         /*
3119                          * CPU is currently offline.
3120                          * Set current struct fields (which have been set to zero)
3121                          * to values from previous iteration. Hence their values won't
3122                          * jump from zero when the CPU comes back online.
3123                          * Note that this workaround no longer fully applies with recent kernels,
3124                          * as I have noticed that when a CPU comes back online, some fields
3125                          * restart from their previous value (e.g. user, nice, system)
3126                          * whereas others restart from zero (idle, iowait)! To deal with this,
3127                          * the get_per_cpu_interval() function will set these previous values
3128                          * to zero if necessary.
3129                          */
3130                         *scc = *scp;
3131
3132                         /*
3133                          * Mark CPU as offline to not display it
3134                          * (and thus it will not be confused with a tickless CPU).
3135                          */
3136                         offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3137                 }
3138
3139                 if ((tot_jiffies_p == 0) && !WANT_SINCE_BOOT(flags)) {
3140                         /*
3141                          * CPU has just come back online.
3142                          * Unfortunately, no reference values are available
3143                          * from a previous iteration, probably because it was
3144                          * already offline when the first sample has been taken.
3145                          * So don't display that CPU to prevent "jump-from-zero"
3146                          * output syndrome, and don't take it into account for CPU "all".
3147                          */
3148                         offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3149                         continue;
3150                 }
3151
3152                 /*
3153                  * Get interval for current CPU and add it to global CPU.
3154                  * Note: Previous idle and iowait values (saved in scp) may be modified here.
3155                  */
3156                 deltot_jiffies += get_per_cpu_interval(scc, scp);
3157
3158                 scc_all->cpu_user += scc->cpu_user;
3159                 scp_all->cpu_user += scp->cpu_user;
3160
3161                 scc_all->cpu_nice += scc->cpu_nice;
3162                 scp_all->cpu_nice += scp->cpu_nice;
3163
3164                 scc_all->cpu_sys += scc->cpu_sys;
3165                 scp_all->cpu_sys += scp->cpu_sys;
3166
3167                 scc_all->cpu_idle += scc->cpu_idle;
3168                 scp_all->cpu_idle += scp->cpu_idle;
3169
3170                 scc_all->cpu_iowait += scc->cpu_iowait;
3171                 scp_all->cpu_iowait += scp->cpu_iowait;
3172
3173                 scc_all->cpu_hardirq += scc->cpu_hardirq;
3174                 scp_all->cpu_hardirq += scp->cpu_hardirq;
3175
3176                 scc_all->cpu_steal += scc->cpu_steal;
3177                 scp_all->cpu_steal += scp->cpu_steal;
3178
3179                 scc_all->cpu_softirq += scc->cpu_softirq;
3180                 scp_all->cpu_softirq += scp->cpu_softirq;
3181
3182                 scc_all->cpu_guest += scc->cpu_guest;
3183                 scp_all->cpu_guest += scp->cpu_guest;
3184
3185                 scc_all->cpu_guest_nice += scc->cpu_guest_nice;
3186                 scp_all->cpu_guest_nice += scp->cpu_guest_nice;
3187         }
3188
3189         return deltot_jiffies;
3190 }
3191
3192 /*
3193  ***************************************************************************
3194  * Compute softnet statistics for CPU "all" as the sum of individual CPU
3195  * ones.
3196  * Also identify offline CPU.
3197  *
3198  * IN:
3199  * @a           Activity structure with statistics.
3200  * @prev        Index in array where stats used as reference are.
3201  * @curr        Index in array for current sample statistics.
3202  * @flags       Flags for common options and system state.
3203  * @offline_cpu_bitmap
3204  *              CPU bitmap for offline CPU.
3205  *
3206  * OUT:
3207  * @a           Activity structure with updated statistics (those for global
3208  *              CPU, and also those for offline CPU).
3209  * @offline_cpu_bitmap
3210  *              CPU bitmap with offline CPU.
3211  ***************************************************************************
3212  */
3213 void get_global_soft_statistics(struct activity *a, int prev, int curr,
3214                                 uint64_t flags, unsigned char offline_cpu_bitmap[])
3215 {
3216         int i;
3217         struct stats_softnet *ssnc, *ssnp;
3218         struct stats_softnet *ssnc_all = (struct stats_softnet *) ((char *) a->buf[curr]);
3219         struct stats_softnet *ssnp_all = (struct stats_softnet *) ((char *) a->buf[prev]);
3220
3221         /*
3222          * Init structures that will contain values for CPU "all".
3223          * CPU "all" doesn't exist in /proc/net/softnet_stat file, so
3224          * we compute its values as the sum of the values of each CPU.
3225          */
3226         memset(ssnc_all, 0, sizeof(struct stats_softnet));
3227         memset(ssnp_all, 0, sizeof(struct stats_softnet));
3228
3229         for (i = 1; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
3230
3231                 /*
3232                  * The size of a->buf[...] CPU structure may be different from the default
3233                  * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
3234                  * That's why we don't use a syntax like:
3235                  * ssnc = (struct stats_softnet *) a->buf[...] + i;
3236                  */
3237                 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
3238                 ssnp = (struct stats_softnet *) ((char *) a->buf[prev] + i * a->msize);
3239
3240                 if (ssnc->processed + ssnc->dropped + ssnc->time_squeeze +
3241                     ssnc->received_rps + ssnc->flow_limit == 0) {
3242                         /* Assume current CPU is offline */
3243                         *ssnc = *ssnp;
3244                         offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3245                 }
3246
3247                 if ((ssnp->processed + ssnp->dropped + ssnp->time_squeeze +
3248                     ssnp->received_rps + ssnp->flow_limit == 0) && !WANT_SINCE_BOOT(flags)) {
3249                         /* Current CPU back online but no previous sample for it */
3250                         offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3251                         continue;
3252                 }
3253
3254                 ssnc_all->processed += ssnc->processed;
3255                 ssnc_all->dropped += ssnc->dropped;
3256                 ssnc_all->time_squeeze += ssnc->time_squeeze;
3257                 ssnc_all->received_rps += ssnc->received_rps;
3258                 ssnc_all->flow_limit += ssnc->flow_limit;
3259
3260                 ssnp_all->processed += ssnp->processed;
3261                 ssnp_all->dropped += ssnp->dropped;
3262                 ssnp_all->time_squeeze += ssnp->time_squeeze;
3263                 ssnp_all->received_rps += ssnp->received_rps;
3264                 ssnp_all->flow_limit += ssnp->flow_limit;
3265         }
3266 }
3267
3268 /*
3269  ***************************************************************************
3270  * Identify offline CPU (those for which all interrupts are 0) and keep
3271  * interrupts statistics (their values are persistent). Include also CPU
3272  * which have not been selected (this is necessary so that the header of the
3273  * interrupts statistics report can be displayed).
3274  *
3275  * IN:
3276  * @a           Activity structure with statistics.
3277  * @prev        Index in array where stats used as reference are.
3278  * @curr        Index in array for current sample statistics.
3279  * @flags       Flags for common options and system state.
3280  * @masked_cpu_bitmap
3281  *              CPU bitmap for offline and unselected CPU.
3282  *
3283  * OUT:
3284  * @a           Activity structure with updated statistics (those for global
3285  *              CPU, and also those for offline CPU).
3286  * @masked_cpu_bitmap
3287  *              CPU bitmap with offline and unselected CPU.
3288  ***************************************************************************
3289  */
3290 void get_global_int_statistics(struct activity *a, int prev, int curr,
3291                                uint64_t flags, unsigned char masked_cpu_bitmap[])
3292 {
3293         int i;
3294         struct stats_irq *stc_cpu_sum, *stp_cpu_sum;
3295
3296         for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
3297
3298                 /*
3299                  * The size of a->buf[...] CPU structure may be different from the default
3300                  * sizeof(struct stats_irq) value if data have been read from a file!
3301                  * That's why we don't use a syntax like:
3302                  * stc_cpu_sum = (struct stats_irq *) a->buf[...] + i;
3303                  */
3304                 stc_cpu_sum = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize * a->nr2);
3305                 stp_cpu_sum = (struct stats_irq *) ((char *) a->buf[prev] + i * a->msize * a->nr2);
3306
3307                 if (stc_cpu_sum->irq_nr == 0) {
3308                         /* Assume current CPU is offline */
3309                         masked_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3310                         memcpy(stc_cpu_sum, stp_cpu_sum, a->msize * a->nr2);
3311                         continue;
3312                 }
3313
3314                 /*
3315                  * Check if current CPU is back online but with no previous sample for it,
3316                  * or if it has not been selected.
3317                  */
3318                 if (((stp_cpu_sum->irq_nr == 0) && !WANT_SINCE_BOOT(flags)) ||
3319                     (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))) {
3320                         /* CPU should not be displayed */
3321                         masked_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
3322                 }
3323         }
3324 }
3325
3326 /*
3327  ***************************************************************************
3328  * Get filesystem name to display. This may be either the persistent name
3329  * if requested by the user, the standard filesystem name (e.g. /dev/sda1,
3330  * /dev/sdb3, etc.) or the mount point. This is used when displaying
3331  * filesystem statistics: sar -F or sadf -- -F).
3332  *
3333  * IN:
3334  * @a           Activity structure.
3335  * @flags       Flags for common options and system state.
3336  * @st_fs       Statistics for current filesystem.
3337  *
3338  * RETURNS:
3339  * Filesystem name to display.
3340  ***************************************************************************
3341  */
3342 char *get_fs_name_to_display(struct activity *a, uint64_t flags, struct stats_filesystem *st_fs)
3343 {
3344         char *pname = NULL, *persist_dev_name;
3345         char fname[MAX_FS_LEN];
3346
3347         if (DISPLAY_PERSIST_NAME_S(flags) && !DISPLAY_MOUNT(a->opt_flags)) {
3348                 strncpy(fname, st_fs->fs_name, sizeof(fname));
3349                 fname[sizeof(fname) - 1] = '\0';
3350                 if ((persist_dev_name = get_persistent_name_from_pretty(basename(fname))) != NULL) {
3351                         pname = persist_dev_name;
3352                 }
3353         }
3354         if (!pname) {
3355                 pname = DISPLAY_MOUNT(a->opt_flags) ? st_fs->mountp : st_fs->fs_name;
3356         }
3357         return pname;
3358 }
3359 #endif /* SOURCE_SADC undefined */