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