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