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