]> granicus.if.org Git - sysstat/blob - sa_common.c
sadc now overwrites its daily data file when it is from a previous month.
[sysstat] / sa_common.c
1 /*
2  * sar and sadf common routines.
3  * (C) 1999-2011 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  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                   *
19  ***************************************************************************
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <errno.h>
27 #include <unistd.h>     /* For STDOUT_FILENO, among others */
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32
33 #include "sa.h"
34 #include "common.h"
35 #include "ioconf.h"
36 #include "rd_stats.h"
37
38 #ifdef USE_NLS
39 #include <locale.h>
40 #include <libintl.h>
41 #define _(string) gettext(string)
42 #else
43 #define _(string) (string)
44 #endif
45
46 extern struct act_bitmap cpu_bitmap;
47
48 /*
49  ***************************************************************************
50  * Init a bitmap (CPU, IRQ, etc.).
51  *
52  * IN:
53  * @value       Value used to init bitmap.
54  * @sz          Size of the bitmap in bytes.
55  *
56  * OUT:
57  * @bitmap      Bitmap initialized.
58  ***************************************************************************
59  */
60 void set_bitmap(unsigned char bitmap[], unsigned char value, unsigned int sz)
61 {
62         register int i;
63
64         for (i = 0; i < sz; i++) {
65                 bitmap[i] = value;
66         }
67 }
68
69 /*
70  ***************************************************************************
71  * Allocate structures.
72  *
73  * IN:
74  * @act Array of activities.
75  ***************************************************************************
76  */
77 void allocate_structures(struct activity *act[])
78 {
79         int i, j;
80
81         for (i = 0; i < NR_ACT; i++) {
82                 if (act[i]->nr > 0) {
83                         for (j = 0; j < 3; j++) {
84                                 SREALLOC(act[i]->buf[j], void, act[i]->msize * act[i]->nr * act[i]->nr2);
85                         }
86                 }
87         }
88 }
89
90 /*
91  ***************************************************************************
92  * Free structures.
93  *
94  * IN:
95  * @act Array of activities.
96  ***************************************************************************
97  */
98 void free_structures(struct activity *act[])
99 {
100         int i, j;
101
102         for (i = 0; i < NR_ACT; i++) {
103                 if (act[i]->nr > 0) {
104                         for (j = 0; j < 3; j++) {
105                                 if (act[i]->buf[j]) {
106                                         free(act[i]->buf[j]);
107                                         act[i]->buf[j] = NULL;
108                                 }
109                         }
110                 }
111         }
112 }
113
114 /*
115  ***************************************************************************
116  * Get device real name if possible.
117  * Warning: This routine may return a bad name on 2.4 kernels where
118  * disk activities are read from /proc/stat.
119  *
120  * IN:
121  * @major       Major number of the device.
122  * @minor       Minor number of the device.
123  * @pretty      TRUE if the real name of the device (as it appears in /dev)
124  *              should be returned.
125  *
126  * RETURNS:
127  * The name of the device, which may be the real name (as it appears in /dev)
128  * or a string with the following format devM-n.
129  ***************************************************************************
130  */
131 char *get_devname(unsigned int major, unsigned int minor, int pretty)
132 {
133         static char buf[32];
134         char *name;
135
136         snprintf(buf, 32, "dev%d-%d", major, minor);
137
138         if (!pretty)
139                 return (buf);
140
141         name = ioc_name(major, minor);
142         if ((name == NULL) || !strcmp(name, K_NODEV))
143                 return (buf);
144
145         return (name);
146 }
147
148 /*
149  ***************************************************************************
150  * Check if we are close enough to desired interval.
151  *
152  * IN:
153  * @uptime_ref  Uptime used as reference. This is the system uptime for the
154  *              first sample statistics, or the first system uptime after a
155  *              LINUX RESTART.
156  * @uptime      Current system uptime.
157  * @reset       TRUE if @last_uptime should be reset with @uptime_ref.
158  * @interval    Interval of time.
159  *
160  * RETURNS:
161  * 1 if we are actually close enough to desired interval, 0 otherwise.
162  ***************************************************************************
163 */
164 int next_slice(unsigned long long uptime_ref, unsigned long long uptime,
165                int reset, long interval)
166 {
167         unsigned long file_interval, entry;
168         static unsigned long long last_uptime = 0;
169         int min, max, pt1, pt2;
170         double f;
171
172         /* uptime is expressed in jiffies (basis of 1 processor) */
173         if (!last_uptime || reset) {
174                 last_uptime = uptime_ref;
175         }
176
177         /* Interval cannot be greater than 0xffffffff here */
178         f = ((double) ((uptime - last_uptime) & 0xffffffff)) / HZ;
179         file_interval = (unsigned long) f;
180         if ((f * 10) - (file_interval * 10) >= 5) {
181                 file_interval++; /* Rounding to correct value */
182         }
183
184         last_uptime = uptime;
185
186         /*
187          * A few notes about the "algorithm" used here to display selected entries
188          * from the system activity file (option -f with -i flag):
189          * Let 'Iu' be the interval value given by the user on the command line,
190          *     'If' the interval between current and previous line in the system
191          * activity file,
192          * and 'En' the nth entry (identified by its time stamp) of the file.
193          * We choose In = [ En - If/2, En + If/2 [ if If is even,
194          *        or In = [ En - If/2, En + If/2 ] if not.
195          * En will be displayed if
196          *       (Pn * Iu) or (P'n * Iu) belongs to In
197          * with  Pn = En / Iu and P'n = En / Iu + 1
198          */
199         f = ((double) ((uptime - uptime_ref) & 0xffffffff)) / HZ;
200         entry = (unsigned long) f;
201         if ((f * 10) - (entry * 10) >= 5) {
202                 entry++;
203         }
204
205         min = entry - (file_interval / 2);
206         max = entry + (file_interval / 2) + (file_interval & 0x1);
207         pt1 = (entry / interval) * interval;
208         pt2 = ((entry / interval) + 1) * interval;
209
210         return (((pt1 >= min) && (pt1 < max)) || ((pt2 >= min) && (pt2 < max)));
211 }
212
213 /*
214  ***************************************************************************
215  * Use time stamp to fill tstamp structure.
216  *
217  * IN:
218  * @timestamp   Timestamp to decode (format: HH:MM:SS).
219  *
220  * OUT:
221  * @tse         Structure containing the decoded timestamp.
222  *
223  * RETURNS:
224  * 0 if the timestamp has been successfully decoded, 1 otherwise.
225  ***************************************************************************
226  */
227 int decode_timestamp(char timestamp[], struct tstamp *tse)
228 {
229         timestamp[2] = timestamp[5] = '\0';
230         tse->tm_sec  = atoi(&timestamp[6]);
231         tse->tm_min  = atoi(&timestamp[3]);
232         tse->tm_hour = atoi(timestamp);
233
234         if ((tse->tm_sec < 0) || (tse->tm_sec > 59) ||
235             (tse->tm_min < 0) || (tse->tm_min > 59) ||
236             (tse->tm_hour < 0) || (tse->tm_hour > 23))
237                 return 1;
238
239         tse->use = TRUE;
240
241         return 0;
242 }
243
244 /*
245  ***************************************************************************
246  * Compare two timestamps.
247  *
248  * IN:
249  * @rectime     Date and time for current sample.
250  * @tse         Timestamp used as reference.
251  *
252  * RETURNS:
253  * A positive value if @rectime is greater than @tse,
254  * a negative one otherwise.
255  ***************************************************************************
256  */
257 int datecmp(struct tm *rectime, struct tstamp *tse)
258 {
259         if (rectime->tm_hour == tse->tm_hour) {
260                 if (rectime->tm_min == tse->tm_min)
261                         return (rectime->tm_sec - tse->tm_sec);
262                 else
263                         return (rectime->tm_min - tse->tm_min);
264         }
265         else
266                 return (rectime->tm_hour - tse->tm_hour);
267 }
268
269 /*
270  ***************************************************************************
271  * Parse a time stamp entered on the command line (hh:mm:ss) and decode it.
272  *
273  * IN:
274  * @argv                Arguments list.
275  * @opt                 Index in the arguments list.
276  * @def_timestamp       Default timestamp to use.
277  *
278  * OUT:
279  * @tse                 Structure containing the decoded timestamp.
280  *
281  * RETURNS:
282  * 0 if the timestamp has been successfully decoded, 1 otherwise.
283  ***************************************************************************
284  */
285 int parse_timestamp(char *argv[], int *opt, struct tstamp *tse,
286                     const char *def_timestamp)
287 {
288         char timestamp[9];
289
290         if ((argv[++(*opt)]) && (strlen(argv[*opt]) == 8)) {
291                 strcpy(timestamp, argv[(*opt)++]);
292         }
293         else {
294                 strcpy(timestamp, def_timestamp);
295         }
296
297         return decode_timestamp(timestamp, tse);
298 }
299
300 /*
301  ***************************************************************************
302  * Set current daily data file name.
303  *
304  * OUT:
305  * @rectime     Current date and time.
306  * @datafile    Name of daily data file.
307  ***************************************************************************
308  */
309 void set_default_file(struct tm *rectime, char *datafile)
310 {
311         get_time(rectime);
312         snprintf(datafile, MAX_FILE_LEN,
313                  "%s/sa%02d", SA_DIR, rectime->tm_mday);
314         datafile[MAX_FILE_LEN - 1] = '\0';
315 }
316
317 /*
318  ***************************************************************************
319  * Set interval value.
320  *
321  * IN:
322  * @record_hdr_curr     Record with current sample statistics.
323  * @record_hdr_prev     Record with previous sample statistics.
324  * @nr_proc             Number of CPU, including CPU "all".
325  *
326  * OUT:
327  * @itv                 Interval in jiffies.
328  * @g_itv               Interval in jiffies multiplied by the # of proc.
329  ***************************************************************************
330  */
331 void get_itv_value(struct record_header *record_hdr_curr,
332                    struct record_header *record_hdr_prev,
333                    unsigned int nr_proc,
334                    unsigned long long *itv, unsigned long long *g_itv)
335 {
336         /* Interval value in jiffies */
337         *g_itv = get_interval(record_hdr_prev->uptime,
338                               record_hdr_curr->uptime);
339
340         if (nr_proc > 2) {
341                 *itv = get_interval(record_hdr_prev->uptime0,
342                                     record_hdr_curr->uptime0);
343         }
344         else {
345                 *itv = *g_itv;
346         }
347 }
348
349 /*
350  ***************************************************************************
351  * Fill the rectime structure with the file's creation date, based on file's
352  * time data saved in file header.
353  * The resulting timestamp is expressed in the locale of the file creator or
354  * in the user's own locale, depending on whether option -t has been used
355  * or not.
356  *
357  * IN:
358  * @flags       Flags for common options and system state.
359  * @file_hdr    System activity file standard header.
360  *
361  * OUT:
362  * @rectime     Date and time from file header.
363  ***************************************************************************
364  */
365 void get_file_timestamp_struct(unsigned int flags, struct tm *rectime,
366                                struct file_header *file_hdr)
367 {
368         struct tm *loc_t;
369
370         if (PRINT_TRUE_TIME(flags)) {
371                 /* Get local time. This is just to fill HH:MM:SS fields */
372                 get_time(rectime);
373
374                 rectime->tm_mday = file_hdr->sa_day;
375                 rectime->tm_mon  = file_hdr->sa_month;
376                 rectime->tm_year = file_hdr->sa_year;
377                 /*
378                  * Call mktime() to set DST (Daylight Saving Time) flag.
379                  * Has anyone a better way to do it?
380                  */
381                 rectime->tm_hour = rectime->tm_min = rectime->tm_sec = 0;
382                 mktime(rectime);
383         }
384         else {
385                 if ((loc_t = localtime((const time_t *) &file_hdr->sa_ust_time)) != NULL) {
386                         *rectime = *loc_t;
387                 }
388         }
389 }
390
391 /*
392  ***************************************************************************
393  * Print report header.
394  *
395  * IN:
396  * @flags       Flags for common options and system state.
397  * @file_hdr    System activity file standard header.
398  * @cpu_nr      Number of CPU (value in [1, NR_CPUS + 1]).
399  *              1 means that there is only one proc and non SMP kernel.
400  *              2 means one proc and SMP kernel.
401  *              Etc.
402  *
403  * OUT:
404  * @rectime     Date and time from file header.
405  ***************************************************************************
406  */
407 void print_report_hdr(unsigned int flags, struct tm *rectime,
408                       struct file_header *file_hdr, int cpu_nr)
409 {
410
411         /* Get date of file creation */
412         get_file_timestamp_struct(flags, rectime, file_hdr);
413
414         /* Display the header */
415         print_gal_header(rectime, file_hdr->sa_sysname, file_hdr->sa_release,
416                          file_hdr->sa_nodename, file_hdr->sa_machine,
417                          cpu_nr > 1 ? cpu_nr - 1 : 1);
418 }
419
420 /*
421  ***************************************************************************
422  * Network interfaces may now be registered (and unregistered) dynamically.
423  * This is what we try to guess here.
424  *
425  * IN:
426  * @a           Activity structure with statistics.
427  * @curr        Index in array for current sample statistics.
428  * @ref         Index in array for sample statistics used as reference.
429  * @pos         Index on current network interface.
430  *
431  * RETURNS:
432  * Position of current network interface in array of sample statistics used
433  * as reference.
434  ***************************************************************************
435  */
436 unsigned int check_net_dev_reg(struct activity *a, int curr, int ref,
437                                unsigned int pos)
438 {
439         struct stats_net_dev *sndc, *sndp;
440         unsigned int index = 0;
441
442         sndc = (struct stats_net_dev *) a->buf[curr] + pos;
443
444         while (index < a->nr) {
445                 sndp = (struct stats_net_dev *) a->buf[ref] + index;
446                 if (!strcmp(sndc->interface, sndp->interface)) {
447                         /*
448                          * Network interface found.
449                          * If a counter has decreased, then we may assume that the
450                          * corresponding interface was unregistered, then registered again.
451                          */
452                         if ((sndc->rx_packets    < sndp->rx_packets)    ||
453                             (sndc->tx_packets    < sndp->tx_packets)    ||
454                             (sndc->rx_bytes      < sndp->rx_bytes)      ||
455                             (sndc->tx_bytes      < sndp->tx_bytes)      ||
456                             (sndc->rx_compressed < sndp->rx_compressed) ||
457                             (sndc->tx_compressed < sndp->tx_compressed) ||
458                             (sndc->multicast     < sndp->multicast)) {
459
460                                 /*
461                                  * Special processing for rx_bytes (_packets) and
462                                  * tx_bytes (_packets) counters: If the number of
463                                  * bytes (packets) has decreased, whereas the number of
464                                  * packets (bytes) has increased, then assume that the
465                                  * relevant counter has met an overflow condition, and that
466                                  * the interface was not unregistered, which is all the
467                                  * more plausible that the previous value for the counter
468                                  * was > ULONG_MAX/2.
469                                  * NB: the average value displayed will be wrong in this case...
470                                  *
471                                  * If such an overflow is detected, just set the flag. There is no
472                                  * need to handle this in a special way: the difference is still
473                                  * properly calculated if the result is of the same type (i.e.
474                                  * unsigned long) as the two values.
475                                  */
476                                 int ovfw = FALSE;
477
478                                 if ((sndc->rx_bytes   < sndp->rx_bytes)   &&
479                                     (sndc->rx_packets > sndp->rx_packets) &&
480                                     (sndp->rx_bytes   > (~0UL >> 1))) {
481                                         ovfw = TRUE;
482                                 }
483                                 if ((sndc->tx_bytes   < sndp->tx_bytes)   &&
484                                     (sndc->tx_packets > sndp->tx_packets) &&
485                                     (sndp->tx_bytes   > (~0UL >> 1))) {
486                                         ovfw = TRUE;
487                                 }
488                                 if ((sndc->rx_packets < sndp->rx_packets) &&
489                                     (sndc->rx_bytes   > sndp->rx_bytes)   &&
490                                     (sndp->rx_packets > (~0UL >> 1))) {
491                                         ovfw = TRUE;
492                                 }
493                                 if ((sndc->tx_packets < sndp->tx_packets) &&
494                                     (sndc->tx_bytes   > sndp->tx_bytes)   &&
495                                     (sndp->tx_packets > (~0UL >> 1))) {
496                                         ovfw = TRUE;
497                                 }
498
499                                 if (!ovfw) {
500                                         /*
501                                          * OK: assume here that the device was
502                                          * actually unregistered.
503                                          */
504                                         memset(sndp, 0, STATS_NET_DEV_SIZE);
505                                         strcpy(sndp->interface, sndc->interface);
506                                 }
507                         }
508                         return index;
509                 }
510                 index++;
511         }
512
513         /* Network interface not found: Look for the first free structure */
514         for (index = 0; index < a->nr; index++) {
515                 sndp = (struct stats_net_dev *) a->buf[ref] + index;
516                 if (!strcmp(sndp->interface, "?")) {
517                         memset(sndp, 0, STATS_NET_DEV_SIZE);
518                         strcpy(sndp->interface, sndc->interface);
519                         break;
520                 }
521         }
522         if (index >= a->nr) {
523                 /* No free structure: Default is structure of same rank */
524                 index = pos;
525         }
526
527         sndp = (struct stats_net_dev *) a->buf[ref] + index;
528         /* Since the name is not the same, reset all the structure */
529         memset(sndp, 0, STATS_NET_DEV_SIZE);
530         strcpy(sndp->interface, sndc->interface);
531
532         return  index;
533 }
534
535 /*
536  ***************************************************************************
537  * Network interfaces may now be registered (and unregistered) dynamically.
538  * This is what we try to guess here.
539  *
540  * IN:
541  * @a           Activity structure with statistics.
542  * @curr        Index in array for current sample statistics.
543  * @ref         Index in array for sample statistics used as reference.
544  * @pos         Index on current network interface.
545  *
546  * RETURNS:
547  * Position of current network interface in array of sample statistics used
548  * as reference.
549  ***************************************************************************
550  */
551 unsigned int check_net_edev_reg(struct activity *a, int curr, int ref,
552                                 unsigned int pos)
553 {
554         struct stats_net_edev *snedc, *snedp;
555         unsigned int index = 0;
556
557         snedc = (struct stats_net_edev *) a->buf[curr] + pos;
558
559         while (index < a->nr) {
560                 snedp = (struct stats_net_edev *) a->buf[ref] + index;
561                 if (!strcmp(snedc->interface, snedp->interface)) {
562                         /*
563                          * Network interface found.
564                          * If a counter has decreased, then we may assume that the
565                          * corresponding interface was unregistered, then registered again.
566                          */
567                         if ((snedc->tx_errors         < snedp->tx_errors)         ||
568                             (snedc->collisions        < snedp->collisions)        ||
569                             (snedc->rx_dropped        < snedp->rx_dropped)        ||
570                             (snedc->tx_dropped        < snedp->tx_dropped)        ||
571                             (snedc->tx_carrier_errors < snedp->tx_carrier_errors) ||
572                             (snedc->rx_frame_errors   < snedp->rx_frame_errors)   ||
573                             (snedc->rx_fifo_errors    < snedp->rx_fifo_errors)    ||
574                             (snedc->tx_fifo_errors    < snedp->tx_fifo_errors)) {
575
576                                 /*
577                                  * OK: assume here that the device was
578                                  * actually unregistered.
579                                  */
580                                 memset(snedp, 0, STATS_NET_EDEV_SIZE);
581                                 strcpy(snedp->interface, snedc->interface);
582                         }
583                         return index;
584                 }
585                 index++;
586         }
587
588         /* Network interface not found: Look for the first free structure */
589         for (index = 0; index < a->nr; index++) {
590                 snedp = (struct stats_net_edev *) a->buf[ref] + index;
591                 if (!strcmp(snedp->interface, "?")) {
592                         memset(snedp, 0, STATS_NET_EDEV_SIZE);
593                         strcpy(snedp->interface, snedc->interface);
594                         break;
595                 }
596         }
597         if (index >= a->nr) {
598                 /* No free structure: Default is structure of same rank */
599                 index = pos;
600         }
601
602         snedp = (struct stats_net_edev *) a->buf[ref] + index;
603         /* Since the name is not the same, reset all the structure */
604         memset(snedp, 0, STATS_NET_EDEV_SIZE);
605         strcpy(snedp->interface, snedc->interface);
606
607         return  index;
608 }
609
610 /*
611  ***************************************************************************
612  * Disks may be registered dynamically (true in /proc/stat file).
613  * This is what we try to guess here.
614  *
615  * IN:
616  * @a           Activity structure with statistics.
617  * @curr        Index in array for current sample statistics.
618  * @ref         Index in array for sample statistics used as reference.
619  * @pos         Index on current disk.
620  *
621  * RETURNS:
622  * Position of current disk in array of sample statistics used as reference.
623  ***************************************************************************
624  */
625 int check_disk_reg(struct activity *a, int curr, int ref, int pos)
626 {
627         struct stats_disk *sdc, *sdp;
628         int index = 0;
629
630         sdc = (struct stats_disk *) a->buf[curr] + pos;
631
632         while (index < a->nr) {
633                 sdp = (struct stats_disk *) a->buf[ref] + index;
634                 if ((sdc->major == sdp->major) &&
635                     (sdc->minor == sdp->minor)) {
636                         /*
637                          * Disk found.
638                          * If all the counters have decreased then the likelyhood
639                          * is that the disk has been unregistered and a new disk inserted.
640                          * If only one or two have decreased then the likelyhood
641                          * is that the counter has simply wrapped.
642                          */
643                         if ((sdc->nr_ios < sdp->nr_ios) &&
644                             (sdc->rd_sect < sdp->rd_sect) &&
645                             (sdc->wr_sect < sdp->wr_sect)) {
646
647                                 memset(sdp, 0, STATS_DISK_SIZE);
648                                 sdp->major = sdc->major;
649                                 sdp->minor = sdc->minor;
650                         }
651                         return index;
652                 }
653                 index++;
654         }
655
656         /* Disk not found: Look for the first free structure */
657         for (index = 0; index < a->nr; index++) {
658                 sdp = (struct stats_disk *) a->buf[ref] + index;
659                 if (!(sdp->major + sdp->minor)) {
660                         memset(sdp, 0, STATS_DISK_SIZE);
661                         sdp->major = sdc->major;
662                         sdp->minor = sdc->minor;
663                         break;
664                 }
665         }
666         if (index >= a->nr) {
667                 /* No free structure found: Default is structure of same rank */
668                 index = pos;
669         }
670
671         sdp = (struct stats_disk *) a->buf[ref] + index;
672         /* Since the device is not the same, reset all the structure */
673         memset(sdp, 0, STATS_DISK_SIZE);
674         sdp->major = sdc->major;
675         sdp->minor = sdc->minor;
676
677         return index;
678 }
679
680 /*
681  ***************************************************************************
682  * Allocate bitmaps for activities that have one.
683  *
684  * IN:
685  * @act         Array of activities.
686  ***************************************************************************
687  */
688 void allocate_bitmaps(struct activity *act[])
689 {
690         int i;
691
692         for (i = 0; i < NR_ACT; i++) {
693                 /*
694                  * If current activity has a bitmap which has not already
695                  * been allocated, then allocate it.
696                  * Note that a same bitmap may be used by several activities.
697                  */
698                 if (act[i]->bitmap && !act[i]->bitmap->b_array) {
699                         SREALLOC(act[i]->bitmap->b_array, unsigned char,
700                                  BITMAP_SIZE(act[i]->bitmap->b_size));
701                 }
702         }
703 }
704
705 /*
706  ***************************************************************************
707  * Free bitmaps for activities that have one.
708  *
709  * IN:
710  * @act         Array of activities.
711  ***************************************************************************
712  */
713 void free_bitmaps(struct activity *act[])
714 {
715         int i;
716
717         for (i = 0; i < NR_ACT; i++) {
718                 if (act[i]->bitmap && act[i]->bitmap->b_array) {
719                         free(act[i]->bitmap->b_array);
720                         /* Set pointer to NULL to prevent it from being freed again */
721                         act[i]->bitmap->b_array = NULL;
722                 }
723         }
724 }
725
726 /*
727  ***************************************************************************
728  * Look for activity in array.
729  *
730  * IN:
731  * @act         Array of activities.
732  * @act_flag    Activity flag to look for.
733  *
734  * RETURNS:
735  * Position of activity in array, or -1 if not found (this may happen when
736  * reading data from a system activity file created by another version of
737  * sysstat).
738  ***************************************************************************
739  */
740 int get_activity_position(struct activity *act[], unsigned int act_flag)
741 {
742         int i;
743
744         for (i = 0; i < NR_ACT; i++) {
745                 if (act[i]->id == act_flag)
746                         break;
747         }
748
749         if (i == NR_ACT)
750                 return -1;
751
752         return i;
753 }
754
755 /*
756  ***************************************************************************
757  * Count number of activities with given option.
758  *
759  * IN:
760  * @act                 Array of activities.
761  * @option              Option that activities should have to be counted
762  *                      (eg. AO_COLLECTED...)
763  * @count_outputs       TRUE if each output should be counted for activities with
764  *                      multiple outputs.
765  *
766  * RETURNS:
767  * Number of selected activities
768  ***************************************************************************
769  */
770 int get_activity_nr(struct activity *act[], unsigned int option, int count_outputs)
771 {
772         int i, n = 0;
773         unsigned int msk;
774
775         for (i = 0; i < NR_ACT; i++) {
776                 if ((act[i]->options & option) == option) {
777
778                         if (HAS_MULTIPLE_OUTPUTS(act[i]->options) && count_outputs) {
779                                 for (msk = 1; msk < 0x10; msk <<= 1) {
780                                         if (act[i]->opt_flags & msk) {
781                                                 n++;
782                                         }
783                                 }
784                         }
785                         else {
786                                 n++;
787                         }
788                 }
789         }
790
791         return n;
792 }
793
794 /*
795  ***************************************************************************
796  * Select all activities, even if they have no associated items.
797  *
798  * IN:
799  * @act         Array of activities.
800  *
801  * OUT:
802  * @act         Array of activities, all of the being selected.
803  ***************************************************************************
804  */
805 void select_all_activities(struct activity *act[])
806 {
807         int i;
808
809         for (i = 0; i < NR_ACT; i++) {
810                 act[i]->options |= AO_SELECTED;
811         }
812 }
813
814 /*
815  ***************************************************************************
816  * Select CPU activity if no other activities have been explicitly selected.
817  * Also select CPU "all" if no other CPU has been selected.
818  *
819  * IN:
820  * @act         Array of activities.
821  *
822  * OUT:
823  * @act         Array of activities with CPU activity selected if needed.
824  ***************************************************************************
825  */
826 void select_default_activity(struct activity *act[])
827 {
828         int p;
829
830         p = get_activity_position(act, A_CPU);
831
832         /* Default is CPU activity... */
833         if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
834                 /*
835                  * Still OK even when reading stats from a file
836                  * since A_CPU activity is always recorded.
837                  */
838                 act[p]->options |= AO_SELECTED;
839         }
840
841         /*
842          * If no CPU's have been selected then select CPU "all".
843          * cpu_bitmap bitmap may be used by several activities (A_CPU, A_PWR_CPUFREQ...)
844          */
845         if (!count_bits(cpu_bitmap.b_array, BITMAP_SIZE(cpu_bitmap.b_size))) {
846                 cpu_bitmap.b_array[0] |= 0x01;
847         }
848 }
849
850 /*
851  ***************************************************************************
852  * Read data from a system activity data file.
853  *
854  * IN:
855  * @ifd         Input file descriptor.
856  * @buffer      Buffer where data are read.
857  * @size        Number of bytes to read.
858  * @mode        If set to HARD_SIZE, indicate that an EOF should be considered
859  *              as an error.
860  *
861  * RETURNS:
862  * 1 if EOF has been reached, 0 otherwise.
863  ***************************************************************************
864  */
865 int sa_fread(int ifd, void *buffer, int size, int mode)
866 {
867         int n;
868
869         if ((n = read(ifd, buffer, size)) < 0) {
870                 fprintf(stderr, _("Error while reading system activity file: %s\n"),
871                         strerror(errno));
872                 close(ifd);
873                 exit(2);
874         }
875
876         if (!n && (mode == SOFT_SIZE))
877                 return 1;       /* EOF */
878
879         if (n < size) {
880                 fprintf(stderr, _("End of system activity file unexpected\n"));
881                 close(ifd);
882                 exit(2);
883         }
884
885         return 0;
886 }
887
888 /*
889  ***************************************************************************
890  * Display sysstat version used to create system activity data file.
891  *
892  * IN:
893  * @file_magic  File magic header
894  ***************************************************************************
895  */
896 void display_sa_file_version(struct file_magic *file_magic)
897 {
898         fprintf(stderr, _("File created using sar/sadc from sysstat version %d.%d.%d"),
899                 file_magic->sysstat_version,
900                 file_magic->sysstat_patchlevel,
901                 file_magic->sysstat_sublevel);
902
903         if (file_magic->sysstat_extraversion) {
904                 fprintf(stderr, ".%d", file_magic->sysstat_extraversion);
905         }
906         fprintf(stderr, "\n");
907 }
908
909 /*
910  ***************************************************************************
911  * An invalid system activity file has been opened for reading.
912  * If this file was created by an old version of sysstat, tell it to the
913  * user...
914  *
915  * IN:
916  * @fd          Descriptor of the file that has been opened.
917  * @file_magic  file_magic structure filled with file magic header data.
918  *              May contain invalid data.
919  * @file        Name of the file being read.
920  * @n           Number of bytes read while reading file magic header.
921  *              This function may also be called after failing to read file
922  *              standard header, or if CPU activity has not been found in
923  *              file. In this case, n is set to 0.
924  ***************************************************************************
925  */
926 void handle_invalid_sa_file(int *fd, struct file_magic *file_magic, char *file,
927                             int n)
928 {
929         fprintf(stderr, _("Invalid system activity file: %s\n"), file);
930
931         if ((n == FILE_MAGIC_SIZE) && (file_magic->sysstat_magic == SYSSTAT_MAGIC)) {
932                 /* This is a sysstat file, but this file has an old format */
933                 display_sa_file_version(file_magic);
934
935                 fprintf(stderr,
936                         _("Current sysstat version can no longer read the format of this file (%#x)\n"),
937                         file_magic->format_magic);
938         }
939
940         close (*fd);
941         exit(3);
942 }
943
944 /*
945  ***************************************************************************
946  * Move structures data.
947  *
948  * IN:
949  * @act         Array of activities.
950  * @id_seq      Activity sequence in file.
951  * @record_hdr  Current record header.
952  * @dest        Index in array where stats have to be copied to.
953  * @src         Index in array where stats to copy are.
954  ***************************************************************************
955  */
956 void copy_structures(struct activity *act[], unsigned int id_seq[],
957                      struct record_header record_hdr[], int dest, int src)
958 {
959         int i, p;
960
961         memcpy(&record_hdr[dest], &record_hdr[src], RECORD_HEADER_SIZE);
962
963         for (i = 0; i < NR_ACT; i++) {
964
965                 if (!id_seq[i])
966                         continue;
967
968                 if (((p = get_activity_position(act, id_seq[i])) < 0) ||
969                     (act[p]->nr < 1) || (act[p]->nr2 < 1)) {
970                         PANIC(1);
971                 }
972                 
973                 memcpy(act[p]->buf[dest], act[p]->buf[src], act[p]->msize * act[p]->nr * act[p]->nr2);
974         }
975 }
976
977 /*
978  ***************************************************************************
979  * Read varying part of the statistics from a daily data file.
980  *
981  * IN:
982  * @act         Array of activities.
983  * @curr        Index in array for current sample statistics.
984  * @ifd         Input file descriptor.
985  * @act_nr      Number of activities in file.
986  * @file_actlst Activity list in file.
987  ***************************************************************************
988  */
989 void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr,
990                           struct file_activity *file_actlst)
991 {
992         int i, j, k, p;
993         struct file_activity *fal = file_actlst;
994
995         for (i = 0; i < act_nr; i++, fal++) {
996
997                 if (((p = get_activity_position(act, fal->id)) < 0) ||
998                     (act[p]->magic != fal->magic)) {
999                         /*
1000                          * Ignore current activity in file, which is unknown to
1001                          * current sysstat version or has an unknown format.
1002                          */
1003                         if (lseek(ifd, fal->size * fal->nr * fal->nr2, SEEK_CUR) < (fal->size * fal->nr * fal->nr2)) {
1004                                 close(ifd);
1005                                 perror("lseek");
1006                                 exit(2);
1007                         }
1008                 }
1009                 else if ((act[p]->nr > 0) &&
1010                          ((act[p]->nr > 1) || (act[p]->nr2 > 1)) &&
1011                          (act[p]->msize > act[p]->fsize)) {
1012                         for (j = 0; j < act[p]->nr; j++) {
1013                                 for (k = 0; k < act[p]->nr2; k++) {
1014                                         sa_fread(ifd,
1015                                                  (char *) act[p]->buf[curr] + (j * act[p]->nr2 + k) * act[p]->msize,
1016                                                  act[p]->fsize, HARD_SIZE);
1017                                 }
1018                         }
1019                 }
1020                 else if (act[p]->nr > 0) {
1021                         sa_fread(ifd, act[p]->buf[curr], act[p]->fsize * act[p]->nr * act[p]->nr2, HARD_SIZE);
1022                 }
1023                 else {
1024                         PANIC(act[p]->nr);
1025                 }
1026         }
1027 }
1028
1029 /*
1030  ***************************************************************************
1031  * Open a data file, and perform various checks before reading.
1032  *
1033  * IN:
1034  * @dfile       Name of system activity data file
1035  * @act         Array of activities.
1036  * @ignore      Set to 1 if a true sysstat activity file but with a bad
1037  *              format should not yield an error message. Useful with
1038  *              sadf -H.
1039  *
1040  * OUT:
1041  * @ifd         System activity data file descriptor
1042  * @file_magic  file_magic structure containing data read from file magic
1043  *              header
1044  * @file_hdr    file_hdr structure containing data read from file standard
1045  *              header
1046  * @file_actlst Acvtivity list in file.
1047  * @id_seq      Activity sequence.
1048  ***************************************************************************
1049  */
1050 void check_file_actlst(int *ifd, char *dfile, struct activity *act[],
1051                        struct file_magic *file_magic, struct file_header *file_hdr,
1052                        struct file_activity **file_actlst, unsigned int id_seq[],
1053                        int ignore)
1054 {
1055         int i, j, n, p;
1056         unsigned int a_cpu = FALSE;
1057         struct file_activity *fal;
1058
1059         /* Open sa data file */
1060         if ((*ifd = open(dfile, O_RDONLY)) < 0) {
1061                 fprintf(stderr, _("Cannot open %s: %s\n"), dfile, strerror(errno));
1062                 exit(2);
1063         }
1064
1065         /* Read file magic data */
1066         n = read(*ifd, file_magic, FILE_MAGIC_SIZE);
1067
1068         if ((n != FILE_MAGIC_SIZE) ||
1069             (file_magic->sysstat_magic != SYSSTAT_MAGIC) ||
1070             (file_magic->format_magic != FORMAT_MAGIC)) {
1071
1072                 if (ignore &&
1073                     (n == FILE_MAGIC_SIZE) &&
1074                     (file_magic->sysstat_magic == SYSSTAT_MAGIC))
1075                         /* Don't display error message. This is for sadf -H */
1076                         return;
1077                 else {
1078                         /* Display error message and exit */
1079                         handle_invalid_sa_file(ifd, file_magic, dfile, n);
1080                 }
1081         }
1082
1083         /* Read sa data file standard header and allocate activity list */
1084         sa_fread(*ifd, file_hdr, FILE_HEADER_SIZE, HARD_SIZE);
1085
1086         SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_nr_act);
1087         fal = *file_actlst;
1088
1089         /* Read activity list */
1090         j = 0;
1091         for (i = 0; i < file_hdr->sa_nr_act; i++, fal++) {
1092
1093                 sa_fread(*ifd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE);
1094
1095                 if ((fal->nr < 1) || (fal->nr2 < 1)) {
1096                         /*
1097                          * Every activity, known or unknown,
1098                          * should have at least one item and sub-item.
1099                          */
1100                         handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1101                 }
1102
1103                 if ((p = get_activity_position(act, fal->id)) < 0)
1104                         /* Unknown activity */
1105                         continue;
1106                 
1107                 if (act[p]->magic != fal->magic) {
1108                         /* Bad magical number */
1109                         if (ignore) {
1110                                 /*
1111                                  * This is how sadf -H knows that this
1112                                  * activity has an unknown format.
1113                                  */
1114                                 act[p]->magic = ACTIVITY_MAGIC_UNKNOWN;
1115                         }
1116                         else
1117                                 continue;
1118                 }
1119
1120                 if (fal->id == A_CPU) {
1121                         a_cpu = TRUE;
1122                 }
1123
1124                 if (fal->size > act[p]->msize) {
1125                         act[p]->msize = fal->size;
1126                 }
1127                 act[p]->fsize = fal->size;
1128                 act[p]->nr    = fal->nr;
1129                 act[p]->nr2   = fal->nr2;
1130                 /*
1131                  * This is a known activity with a known format
1132                  * (magical number). Only such activities will be displayed.
1133                  * (Well, this may also be an unknown format if we have entered sadf -H.)
1134                  */
1135                 id_seq[j++] = fal->id;
1136         }
1137
1138         if (!a_cpu) {
1139                 /*
1140                  * CPU activity should always be in file
1141                  * and have a known format (expected magical number).
1142                  */
1143                 handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1144         }
1145
1146         while (j < NR_ACT) {
1147                 id_seq[j++] = 0;
1148         }
1149
1150         /* Check that at least one selected activity is available in file */
1151         for (i = 0; i < NR_ACT; i++) {
1152
1153                 if (!IS_SELECTED(act[i]->options))
1154                         continue;
1155
1156                 /* Here is a selected activity: Does it exist in file? */
1157                 fal = *file_actlst;
1158                 for (j = 0; j < file_hdr->sa_nr_act; j++, fal++) {
1159                         if (act[i]->id == fal->id)
1160                                 break;
1161                 }
1162                 if (j == file_hdr->sa_nr_act) {
1163                         /* No: Unselect it */
1164                         act[i]->options &= ~AO_SELECTED;
1165                 }
1166         }
1167         if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
1168                 fprintf(stderr, _("Requested activities not available in file %s\n"),
1169                         dfile);
1170                 close(*ifd);
1171                 exit(1);
1172         }
1173 }
1174
1175 /*
1176  ***************************************************************************
1177  * Parse sar activities options (also used by sadf).
1178  *
1179  * IN:
1180  * @argv        Arguments list.
1181  * @opt         Index in list of arguments.
1182  * @caller      Indicate whether it's sar or sadf that called this function.
1183  *
1184  * OUT:
1185  * @act         Array of selected activities.
1186  * @flags       Common flags and system state.
1187  *
1188  * RETURNS:
1189  * 0 on success, 1 otherwise.
1190  ***************************************************************************
1191  */
1192 int parse_sar_opt(char *argv[], int *opt, struct activity *act[],
1193                   unsigned int *flags, int caller)
1194 {
1195         int i, p;
1196
1197         for (i = 1; *(argv[*opt] + i); i++) {
1198
1199                 switch (*(argv[*opt] + i)) {
1200
1201                 case 'A':
1202                         select_all_activities(act);
1203
1204                         /* Force '-P ALL -I XALL' */
1205                         *flags |= S_F_PER_PROC;
1206
1207                         p = get_activity_position(act, A_MEMORY);
1208                         act[p]->opt_flags |= AO_F_MEM_AMT + AO_F_MEM_DIA +
1209                                              AO_F_MEM_SWAP;
1210
1211                         p = get_activity_position(act, A_IRQ);
1212                         set_bitmap(act[p]->bitmap->b_array, ~0,
1213                                    BITMAP_SIZE(act[p]->bitmap->b_size));
1214
1215                         p = get_activity_position(act, A_CPU);
1216                         set_bitmap(act[p]->bitmap->b_array, ~0,
1217                                    BITMAP_SIZE(act[p]->bitmap->b_size));
1218                         act[p]->opt_flags = AO_F_CPU_ALL;
1219                         break;
1220
1221                 case 'B':
1222                         SELECT_ACTIVITY(A_PAGE);
1223                         break;
1224
1225                 case 'b':
1226                         SELECT_ACTIVITY(A_IO);
1227                         break;
1228
1229                 case 'C':
1230                         *flags |= S_F_COMMENT;
1231                         break;
1232
1233                 case 'd':
1234                         SELECT_ACTIVITY(A_DISK);
1235                         break;
1236
1237                 case 'H':
1238                         p = get_activity_position(act, A_HUGE);
1239                         act[p]->options   |= AO_SELECTED;
1240                         break;
1241                         
1242                 case 'p':
1243                         *flags |= S_F_DEV_PRETTY;
1244                         break;
1245
1246                 case 'q':
1247                         SELECT_ACTIVITY(A_QUEUE);
1248                         break;
1249
1250                 case 'r':
1251                         p = get_activity_position(act, A_MEMORY);
1252                         act[p]->options   |= AO_SELECTED;
1253                         act[p]->opt_flags |= AO_F_MEM_AMT;
1254                         break;
1255
1256                 case 'R':
1257                         p = get_activity_position(act, A_MEMORY);
1258                         act[p]->options   |= AO_SELECTED;
1259                         act[p]->opt_flags |= AO_F_MEM_DIA;
1260                         break;
1261
1262                 case 'S':
1263                         p = get_activity_position(act, A_MEMORY);
1264                         act[p]->options   |= AO_SELECTED;
1265                         act[p]->opt_flags |= AO_F_MEM_SWAP;
1266                         break;
1267
1268                 case 't':
1269                         if (caller == C_SAR) {
1270                                 *flags |= S_F_TRUE_TIME;
1271                         }
1272                         else
1273                                 return 1;
1274                         break;
1275
1276                 case 'u':
1277                         p = get_activity_position(act, A_CPU);
1278                         act[p]->options |= AO_SELECTED;
1279                         if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
1280                                 (*opt)++;
1281                                 act[p]->opt_flags = AO_F_CPU_ALL;
1282                                 return 0;
1283                         }
1284                         else {
1285                                 act[p]->opt_flags = AO_F_CPU_DEF;
1286                         }
1287                         break;
1288
1289                 case 'v':
1290                         SELECT_ACTIVITY(A_KTABLES);
1291                         break;
1292
1293                 case 'w':
1294                         SELECT_ACTIVITY(A_PCSW);
1295                         break;
1296
1297                 case 'W':
1298                         SELECT_ACTIVITY(A_SWAP);
1299                         break;
1300
1301                 case 'y':
1302                         SELECT_ACTIVITY(A_SERIAL);
1303                         break;
1304
1305                 case 'V':
1306                         print_version();
1307                         break;
1308
1309                 default:
1310                         return 1;
1311                 }
1312         }
1313         return 0;
1314 }
1315
1316 /*
1317  ***************************************************************************
1318  * Parse sar "-m" option.
1319  *
1320  * IN:
1321  * @argv        Arguments list.
1322  * @opt         Index in list of arguments.
1323  *
1324  * OUT:
1325  * @act         Array of selected activities.
1326  *
1327  * RETURNS:
1328  * 0 on success, 1 otherwise.
1329  ***************************************************************************
1330  */
1331 int parse_sar_m_opt(char *argv[], int *opt, struct activity *act[])
1332 {
1333         char *t;
1334
1335         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1336                 if (!strcmp(t, K_CPU)) {
1337                         SELECT_ACTIVITY(A_PWR_CPUFREQ);
1338                 }
1339                 else if (!strcmp(t, K_FAN)) {
1340                         SELECT_ACTIVITY(A_PWR_FAN);
1341                 }
1342                 else if (!strcmp(t, K_IN)) {
1343                         SELECT_ACTIVITY(A_PWR_IN);
1344                 }
1345                 else if (!strcmp(t, K_TEMP)) {
1346                         SELECT_ACTIVITY(A_PWR_TEMP);
1347                 }
1348                 else if (!strcmp(t, K_FREQ)) {
1349                         SELECT_ACTIVITY(A_PWR_WGHFREQ);
1350                 }
1351                 else if (!strcmp(t, K_USB)) {
1352                         SELECT_ACTIVITY(A_PWR_USB);
1353                 }
1354                 else if (!strcmp(t, K_ALL)) {
1355                         SELECT_ACTIVITY(A_PWR_CPUFREQ);
1356                         SELECT_ACTIVITY(A_PWR_FAN);
1357                         SELECT_ACTIVITY(A_PWR_IN);
1358                         SELECT_ACTIVITY(A_PWR_TEMP);
1359                         SELECT_ACTIVITY(A_PWR_WGHFREQ);
1360                         SELECT_ACTIVITY(A_PWR_USB);
1361                 }
1362                 else
1363                         return 1;
1364         }
1365
1366         (*opt)++;
1367         return 0;
1368 }
1369
1370 /*
1371  ***************************************************************************
1372  * Parse sar "-n" option.
1373  *
1374  * IN:
1375  * @argv        Arguments list.
1376  * @opt         Index in list of arguments.
1377  *
1378  * OUT:
1379  * @act         Array of selected activities.
1380  *
1381  * RETURNS:
1382  * 0 on success, 1 otherwise.
1383  ***************************************************************************
1384  */
1385 int parse_sar_n_opt(char *argv[], int *opt, struct activity *act[])
1386 {
1387         char *t;
1388
1389         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1390                 if (!strcmp(t, K_DEV)) {
1391                         SELECT_ACTIVITY(A_NET_DEV);
1392                 }
1393                 else if (!strcmp(t, K_EDEV)) {
1394                         SELECT_ACTIVITY(A_NET_EDEV);
1395                 }
1396                 else if (!strcmp(t, K_SOCK)) {
1397                         SELECT_ACTIVITY(A_NET_SOCK);
1398                 }
1399                 else if (!strcmp(t, K_NFS)) {
1400                         SELECT_ACTIVITY(A_NET_NFS);
1401                 }
1402                 else if (!strcmp(t, K_NFSD)) {
1403                         SELECT_ACTIVITY(A_NET_NFSD);
1404                 }
1405                 else if (!strcmp(t, K_IP)) {
1406                         SELECT_ACTIVITY(A_NET_IP);
1407                 }
1408                 else if (!strcmp(t, K_EIP)) {
1409                         SELECT_ACTIVITY(A_NET_EIP);
1410                 }
1411                 else if (!strcmp(t, K_ICMP)) {
1412                         SELECT_ACTIVITY(A_NET_ICMP);
1413                 }
1414                 else if (!strcmp(t, K_EICMP)) {
1415                         SELECT_ACTIVITY(A_NET_EICMP);
1416                 }
1417                 else if (!strcmp(t, K_TCP)) {
1418                         SELECT_ACTIVITY(A_NET_TCP);
1419                 }
1420                 else if (!strcmp(t, K_ETCP)) {
1421                         SELECT_ACTIVITY(A_NET_ETCP);
1422                 }
1423                 else if (!strcmp(t, K_UDP)) {
1424                         SELECT_ACTIVITY(A_NET_UDP);
1425                 }
1426                 else if (!strcmp(t, K_SOCK6)) {
1427                         SELECT_ACTIVITY(A_NET_SOCK6);
1428                 }
1429                 else if (!strcmp(t, K_IP6)) {
1430                         SELECT_ACTIVITY(A_NET_IP6);
1431                 }
1432                 else if (!strcmp(t, K_EIP6)) {
1433                         SELECT_ACTIVITY(A_NET_EIP6);
1434                 }
1435                 else if (!strcmp(t, K_ICMP6)) {
1436                         SELECT_ACTIVITY(A_NET_ICMP6);
1437                 }
1438                 else if (!strcmp(t, K_EICMP6)) {
1439                         SELECT_ACTIVITY(A_NET_EICMP6);
1440                 }
1441                 else if (!strcmp(t, K_UDP6)) {
1442                         SELECT_ACTIVITY(A_NET_UDP6);
1443                 }
1444                 else if (!strcmp(t, K_ALL)) {
1445                         SELECT_ACTIVITY(A_NET_DEV);
1446                         SELECT_ACTIVITY(A_NET_EDEV);
1447                         SELECT_ACTIVITY(A_NET_SOCK);
1448                         SELECT_ACTIVITY(A_NET_NFS);
1449                         SELECT_ACTIVITY(A_NET_NFSD);
1450                         SELECT_ACTIVITY(A_NET_IP);
1451                         SELECT_ACTIVITY(A_NET_EIP);
1452                         SELECT_ACTIVITY(A_NET_ICMP);
1453                         SELECT_ACTIVITY(A_NET_EICMP);
1454                         SELECT_ACTIVITY(A_NET_TCP);
1455                         SELECT_ACTIVITY(A_NET_ETCP);
1456                         SELECT_ACTIVITY(A_NET_UDP);
1457                         SELECT_ACTIVITY(A_NET_SOCK6);
1458                         SELECT_ACTIVITY(A_NET_IP6);
1459                         SELECT_ACTIVITY(A_NET_EIP6);
1460                         SELECT_ACTIVITY(A_NET_ICMP6);
1461                         SELECT_ACTIVITY(A_NET_EICMP6);
1462                         SELECT_ACTIVITY(A_NET_UDP6);
1463                 }
1464                 else
1465                         return 1;
1466         }
1467
1468         (*opt)++;
1469         return 0;
1470 }
1471
1472 /*
1473  ***************************************************************************
1474  * Parse sar "-I" option.
1475  *
1476  * IN:
1477  * @argv        Arguments list.
1478  * @opt         Index in list of arguments.
1479  * @act         Array of activities.
1480  *
1481  * OUT:
1482  * @act         Array of activities, with interrupts activity selected.
1483  *
1484  * RETURNS:
1485  * 0 on success, 1 otherwise.
1486  ***************************************************************************
1487  */
1488 int parse_sar_I_opt(char *argv[], int *opt, struct activity *act[])
1489 {
1490         int i, p;
1491         unsigned char c;
1492         char *t;
1493
1494         /* Select interrupt activity */
1495         p = get_activity_position(act, A_IRQ);
1496         act[p]->options |= AO_SELECTED;
1497
1498         for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1499                 if (!strcmp(t, K_SUM)) {
1500                         /* Select total number of interrupts */
1501                         act[p]->bitmap->b_array[0] |= 0x01;
1502                 }
1503                 else if (!strcmp(t, K_ALL)) {
1504                         /* Set bit for the first 16 individual interrupts */
1505                         act[p]->bitmap->b_array[0] |= 0xfe;
1506                         act[p]->bitmap->b_array[1] |= 0xff;
1507                         act[p]->bitmap->b_array[2] |= 0x01;
1508                 }
1509                 else if (!strcmp(t, K_XALL)) {
1510                         /* Set every bit except for total number of interrupts */
1511                         c = act[p]->bitmap->b_array[0];
1512                         set_bitmap(act[p]->bitmap->b_array, ~0,
1513                                    BITMAP_SIZE(act[p]->bitmap->b_size));
1514                         act[p]->bitmap->b_array[0] = 0xfe | c;
1515                 }
1516                 else {
1517                         /* Get irq number */
1518                         if (strspn(t, DIGITS) != strlen(t))
1519                                 return 1;
1520                         i = atoi(t);
1521                         if ((i < 0) || (i >= act[p]->bitmap->b_size))
1522                                 return 1;
1523                         act[p]->bitmap->b_array[(i + 1) >> 3] |= 1 << ((i + 1) & 0x07);
1524                 }
1525         }
1526
1527         (*opt)++;
1528         return 0;
1529 }
1530
1531 /*
1532  ***************************************************************************
1533  * Parse sar and sadf "-P" option.
1534  *
1535  * IN:
1536  * @argv        Arguments list.
1537  * @opt         Index in list of arguments.
1538  * @act         Array of activities.
1539  *
1540  * OUT:
1541  * @flags       Common flags and system state.
1542  * @act         Array of activities, with CPUs selected.
1543  *
1544  * RETURNS:
1545  * 0 on success, 1 otherwise.
1546  ***************************************************************************
1547  */
1548 int parse_sa_P_opt(char *argv[], int *opt, unsigned int *flags, struct activity *act[])
1549 {
1550         int i, p;
1551         char *t;
1552
1553         p = get_activity_position(act, A_CPU);
1554
1555         if (argv[++(*opt)]) {
1556                 *flags |= S_F_PER_PROC;
1557
1558                 for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1559                         if (!strcmp(t, K_ALL)) {
1560                                 /*
1561                                  * Set bit for every processor.
1562                                  * We still don't know if we are going to read stats
1563                                  * from a file or not...
1564                                  */
1565                                 set_bitmap(act[p]->bitmap->b_array, ~0,
1566                                            BITMAP_SIZE(act[p]->bitmap->b_size));
1567                         }
1568                         else {
1569                                 /* Get cpu number */
1570                                 if (strspn(t, DIGITS) != strlen(t))
1571                                         return 1;
1572                                 i = atoi(t);
1573                                 if ((i < 0) || (i >= act[p]->bitmap->b_size))
1574                                         return 1;
1575                                 act[p]->bitmap->b_array[(i + 1) >> 3] |= 1 << ((i + 1) & 0x07);
1576                         }
1577                 }
1578                 (*opt)++;
1579         }
1580         else
1581                 return 1;
1582
1583         return 0;
1584 }
1585