]> granicus.if.org Git - sysstat/blob - rd_stats.c
Changed IPv6 counters (used by sar -n {IP6 | EIP6 }) to
[sysstat] / rd_stats.c
1 /*
2  * rd_stats.c: Read system statistics
3  * (C) 1999-2012 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 <errno.h>
26 #include <dirent.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include "common.h"
33 #include "rd_stats.h"
34 #include "ioconf.h"
35
36 #ifdef USE_NLS
37 #include <locale.h>
38 #include <libintl.h>
39 #define _(string) gettext(string)
40 #else
41 #define _(string) (string)
42 #endif
43
44 /*
45  ***************************************************************************
46  * Read CPU statistics and machine uptime.
47  *
48  * IN:
49  * @st_cpu      Structure where stats will be saved.
50  * @nbr         Total number of CPU (including cpu "all").
51  *
52  * OUT:
53  * @st_cpu      Structure with statistics.
54  * @uptime      Machine uptime multiplied by the number of processors.
55  * @uptime0     Machine uptime. Filled only if previously set to zero.
56  ***************************************************************************
57  */
58 void read_stat_cpu(struct stats_cpu *st_cpu, int nbr,
59                    unsigned long long *uptime, unsigned long long *uptime0)
60 {
61         FILE *fp;
62         struct stats_cpu *st_cpu_i;
63         struct stats_cpu sc;
64         char line[8192];
65         int proc_nb;
66
67         if ((fp = fopen(STAT, "r")) == NULL) {
68                 fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
69                 exit(2);
70         }
71
72         while (fgets(line, 8192, fp) != NULL) {
73
74                 if (!strncmp(line, "cpu ", 4)) {
75
76                         /*
77                          * All the fields don't necessarily exist,
78                          * depending on the kernel version used.
79                          */
80                         memset(st_cpu, 0, STATS_CPU_SIZE);
81
82                         /*
83                          * Read the number of jiffies spent in the different modes
84                          * (user, nice, etc.) among all proc. CPU usage is not reduced
85                          * to one processor to avoid rounding problems.
86                          */
87                         sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
88                                &st_cpu->cpu_user,
89                                &st_cpu->cpu_nice,
90                                &st_cpu->cpu_sys,
91                                &st_cpu->cpu_idle,
92                                &st_cpu->cpu_iowait,
93                                &st_cpu->cpu_hardirq,
94                                &st_cpu->cpu_softirq,
95                                &st_cpu->cpu_steal,
96                                &st_cpu->cpu_guest,
97                                &st_cpu->cpu_guest_nice);
98
99                         /*
100                          * Compute the uptime of the system in jiffies (1/100ths of a second
101                          * if HZ=100).
102                          * Machine uptime is multiplied by the number of processors here.
103                          *
104                          * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
105                          * already include them.
106                          */
107                         *uptime = st_cpu->cpu_user + st_cpu->cpu_nice    +
108                                 st_cpu->cpu_sys    + st_cpu->cpu_idle    +
109                                 st_cpu->cpu_iowait + st_cpu->cpu_hardirq +
110                                 st_cpu->cpu_steal  + st_cpu->cpu_softirq;
111                 }
112
113                 else if (!strncmp(line, "cpu", 3)) {
114                         if (nbr > 1) {
115                                 /* All the fields don't necessarily exist */
116                                 memset(&sc, 0, STATS_CPU_SIZE);
117                                 /*
118                                  * Read the number of jiffies spent in the different modes
119                                  * (user, nice, etc) for current proc.
120                                  * This is done only on SMP machines.
121                                  */
122                                 sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
123                                        &proc_nb,
124                                        &sc.cpu_user,
125                                        &sc.cpu_nice,
126                                        &sc.cpu_sys,
127                                        &sc.cpu_idle,
128                                        &sc.cpu_iowait,
129                                        &sc.cpu_hardirq,
130                                        &sc.cpu_softirq,
131                                        &sc.cpu_steal,
132                                        &sc.cpu_guest,
133                                        &sc.cpu_guest_nice);
134
135                                 if (proc_nb < (nbr - 1)) {
136                                         st_cpu_i = st_cpu + proc_nb + 1;
137                                         *st_cpu_i = sc;
138                                 }
139                                 /*
140                                  * else additional CPUs have been dynamically registered
141                                  * in /proc/stat.
142                                  */
143
144                                 if (!proc_nb && !*uptime0) {
145                                         /*
146                                          * Compute uptime reduced to one proc using proc#0.
147                                          * Done if /proc/uptime was unavailable.
148                                          *
149                                          * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
150                                          * already include them.
151                                          */
152                                         *uptime0 = sc.cpu_user + sc.cpu_nice  +
153                                                 sc.cpu_sys     + sc.cpu_idle  +
154                                                 sc.cpu_iowait  + sc.cpu_steal +
155                                                 sc.cpu_hardirq + sc.cpu_softirq;
156                                 }
157                         }
158                 }
159         }
160
161         fclose(fp);
162 }
163
164 /*
165  ***************************************************************************
166  * Read processes (tasks) creation and context switches statistics
167  * from /proc/stat.
168  *
169  * IN:
170  * @st_pcsw     Structure where stats will be saved.
171  *
172  * OUT:
173  * @st_pcsw     Structure with statistics.
174  ***************************************************************************
175  */
176 void read_stat_pcsw(struct stats_pcsw *st_pcsw)
177 {
178         FILE *fp;
179         char line[8192];
180
181         if ((fp = fopen(STAT, "r")) == NULL)
182                 return;
183
184         while (fgets(line, 8192, fp) != NULL) {
185
186                 if (!strncmp(line, "ctxt ", 5)) {
187                         /* Read number of context switches */
188                         sscanf(line + 5, "%llu", &st_pcsw->context_switch);
189                 }
190
191                 else if (!strncmp(line, "processes ", 10)) {
192                         /* Read number of processes created since system boot */
193                         sscanf(line + 10, "%lu", &st_pcsw->processes);
194                 }
195         }
196
197         fclose(fp);
198 }
199
200 /*
201  ***************************************************************************
202  * Read interrupts statistics from /proc/stat.
203  *
204  * IN:
205  * @st_irq      Structure where stats will be saved.
206  * @nbr         Number of interrupts to read, including the total number
207  *              of interrupts.
208  *
209  * OUT:
210  * @st_irq      Structure with statistics.
211  ***************************************************************************
212  */
213 void read_stat_irq(struct stats_irq *st_irq, int nbr)
214 {
215         FILE *fp;
216         struct stats_irq *st_irq_i;
217         char line[8192];
218         int i, pos;
219
220         if ((fp = fopen(STAT, "r")) == NULL)
221                 return;
222         
223         while (fgets(line, 8192, fp) != NULL) {
224
225                 if (!strncmp(line, "intr ", 5)) {
226                         /* Read total number of interrupts received since system boot */
227                         sscanf(line + 5, "%llu", &st_irq->irq_nr);
228                         pos = strcspn(line + 5, " ") + 5;
229
230                         for (i = 1; i < nbr; i++) {
231                                 st_irq_i = st_irq + i;
232                                 sscanf(line + pos, " %llu", &st_irq_i->irq_nr);
233                                 pos += strcspn(line + pos + 1, " ") + 1;
234                         }
235                 }
236         }
237
238         fclose(fp);
239 }
240
241 /*
242  ***************************************************************************
243  * Read queue and load statistics from /proc/loadavg and /proc/stat.
244  *
245  * IN:
246  * @st_queue    Structure where stats will be saved.
247  *
248  * OUT:
249  * @st_queue    Structure with statistics.
250  ***************************************************************************
251  */
252 void read_loadavg(struct stats_queue *st_queue)
253 {
254         FILE *fp;
255         char line[8192];
256         int load_tmp[3];
257
258         if ((fp = fopen(LOADAVG, "r")) == NULL)
259                 return;
260         
261         /* Read load averages and queue length */
262         fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n",
263                &load_tmp[0], &st_queue->load_avg_1,
264                &load_tmp[1], &st_queue->load_avg_5,
265                &load_tmp[2], &st_queue->load_avg_15,
266                &st_queue->nr_running,
267                &st_queue->nr_threads);
268
269         fclose(fp);
270
271         st_queue->load_avg_1  += load_tmp[0] * 100;
272         st_queue->load_avg_5  += load_tmp[1] * 100;
273         st_queue->load_avg_15 += load_tmp[2] * 100;
274
275         if (st_queue->nr_running) {
276                 /* Do not take current process into account */
277                 st_queue->nr_running--;
278         }
279
280         /* Read nr of tasks blocked from /proc/stat */
281         if ((fp = fopen(STAT, "r")) == NULL)
282                 return;
283
284         while (fgets(line, 8192, fp) != NULL) {
285
286                 if (!strncmp(line, "procs_blocked ", 14)) {
287                         /* Read number of processes blocked */
288                         sscanf(line + 14, "%lu", &st_queue->procs_blocked);
289                         break;
290                 }
291         }
292
293         fclose(fp);
294 }
295
296 /*
297  ***************************************************************************
298  * Read memory statistics from /proc/meminfo.
299  *
300  * IN:
301  * @st_memory   Structure where stats will be saved.
302  *
303  * OUT:
304  * @st_memory   Structure with statistics.
305  ***************************************************************************
306  */
307 void read_meminfo(struct stats_memory *st_memory)
308 {
309         FILE *fp;
310         char line[128];
311         
312         if ((fp = fopen(MEMINFO, "r")) == NULL)
313                 return;
314
315         while (fgets(line, 128, fp) != NULL) {
316
317                 if (!strncmp(line, "MemTotal:", 9)) {
318                         /* Read the total amount of memory in kB */
319                         sscanf(line + 9, "%lu", &st_memory->tlmkb);
320                 }
321                 else if (!strncmp(line, "MemFree:", 8)) {
322                         /* Read the amount of free memory in kB */
323                         sscanf(line + 8, "%lu", &st_memory->frmkb);
324                 }
325                 else if (!strncmp(line, "Buffers:", 8)) {
326                         /* Read the amount of buffered memory in kB */
327                         sscanf(line + 8, "%lu", &st_memory->bufkb);
328                 }
329                 else if (!strncmp(line, "Cached:", 7)) {
330                         /* Read the amount of cached memory in kB */
331                         sscanf(line + 7, "%lu", &st_memory->camkb);
332                 }
333                 else if (!strncmp(line, "SwapCached:", 11)) {
334                         /* Read the amount of cached swap in kB */
335                         sscanf(line + 11, "%lu", &st_memory->caskb);
336                 }
337                 else if (!strncmp(line, "Active:", 7)) {
338                         /* Read the amount of active memory in kB */
339                         sscanf(line + 7, "%lu", &st_memory->activekb);
340                 }
341                 else if (!strncmp(line, "Inactive:", 9)) {
342                         /* Read the amount of inactive memory in kB */
343                         sscanf(line + 9, "%lu", &st_memory->inactkb);
344                 }
345                 else if (!strncmp(line, "SwapTotal:", 10)) {
346                         /* Read the total amount of swap memory in kB */
347                         sscanf(line + 10, "%lu", &st_memory->tlskb);
348                 }
349                 else if (!strncmp(line, "SwapFree:", 9)) {
350                         /* Read the amount of free swap memory in kB */
351                         sscanf(line + 9, "%lu", &st_memory->frskb);
352                 }
353                 else if (!strncmp(line, "Dirty:", 6)) {
354                         /* Read the amount of dirty memory in kB */
355                         sscanf(line + 6, "%lu", &st_memory->dirtykb);
356                 }
357                 else if (!strncmp(line, "Committed_AS:", 13)) {
358                         /* Read the amount of commited memory in kB */
359                         sscanf(line + 13, "%lu", &st_memory->comkb);
360                 }
361         }
362
363         fclose(fp);
364 }
365
366 /*
367  ***************************************************************************
368  * Read swapping statistics from /proc/vmstat.
369  *
370  * IN:
371  * @st_swap     Structure where stats will be saved.
372  *
373  * OUT:
374  * @st_swap     Structure with statistics.
375  ***************************************************************************
376  */
377 void read_vmstat_swap(struct stats_swap *st_swap)
378 {
379         FILE *fp;
380         char line[128];
381
382         if ((fp = fopen(VMSTAT, "r")) == NULL)
383                 return;
384
385         while (fgets(line, 128, fp) != NULL) {
386
387                 if (!strncmp(line, "pswpin ", 7)) {
388                         /* Read number of swap pages brought in */
389                         sscanf(line + 7, "%lu", &st_swap->pswpin);
390                 }
391                 else if (!strncmp(line, "pswpout ", 8)) {
392                         /* Read number of swap pages brought out */
393                         sscanf(line + 8, "%lu", &st_swap->pswpout);
394                 }
395         }
396         
397         fclose(fp);
398 }
399
400 /*
401  ***************************************************************************
402  * Read paging statistics from /proc/vmstat.
403  *
404  * IN:
405  * @st_paging   Structure where stats will be saved.
406  *
407  * OUT:
408  * @st_paging   Structure with statistics.
409  ***************************************************************************
410  */
411 void read_vmstat_paging(struct stats_paging *st_paging)
412 {
413         FILE *fp;
414         char line[128];
415         unsigned long pgtmp;
416
417         if ((fp = fopen(VMSTAT, "r")) == NULL)
418                 return;
419
420         st_paging->pgsteal = 0;
421         st_paging->pgscan_kswapd = st_paging->pgscan_direct = 0;
422
423         while (fgets(line, 128, fp) != NULL) {
424
425                 if (!strncmp(line, "pgpgin ", 7)) {
426                         /* Read number of pages the system paged in */
427                         sscanf(line + 7, "%lu", &st_paging->pgpgin);
428                 }
429                 else if (!strncmp(line, "pgpgout ", 8)) {
430                         /* Read number of pages the system paged out */
431                         sscanf(line + 8, "%lu", &st_paging->pgpgout);
432                 }
433                 else if (!strncmp(line, "pgfault ", 8)) {
434                         /* Read number of faults (major+minor) made by the system */
435                         sscanf(line + 8, "%lu", &st_paging->pgfault);
436                 }
437                 else if (!strncmp(line, "pgmajfault ", 11)) {
438                         /* Read number of faults (major only) made by the system */
439                         sscanf(line + 11, "%lu", &st_paging->pgmajfault);
440                 }
441                 else if (!strncmp(line, "pgfree ", 7)) {
442                         /* Read number of pages freed by the system */
443                         sscanf(line + 7, "%lu", &st_paging->pgfree);
444                 }
445                 else if (!strncmp(line, "pgsteal_", 8)) {
446                         /* Read number of pages stolen by the system */
447                         sscanf(strchr(line, ' '), "%lu", &pgtmp);
448                         st_paging->pgsteal += pgtmp;
449                 }
450                 else if (!strncmp(line, "pgscan_kswapd_", 14)) {
451                         /* Read number of pages scanned by the kswapd daemon */
452                         sscanf(strchr(line, ' '), "%lu", &pgtmp);
453                         st_paging->pgscan_kswapd += pgtmp;
454                 }
455                 else if (!strncmp(line, "pgscan_direct_", 14)) {
456                         /* Read number of pages scanned directly */
457                         sscanf(strchr(line, ' '), "%lu", &pgtmp);
458                         st_paging->pgscan_direct += pgtmp;
459                 }
460         }
461         
462         fclose(fp);
463 }
464
465 /*
466  ***************************************************************************
467  * Read I/O and transfer rates statistics from /proc/diskstats.
468  *
469  * IN:
470  * @st_io       Structure where stats will be saved.
471  *
472  * OUT:
473  * @st_io       Structure with statistics.
474  ***************************************************************************
475  */
476 void read_diskstats_io(struct stats_io *st_io)
477 {
478         FILE *fp;
479         char line[256];
480         char dev_name[MAX_NAME_LEN];
481         unsigned int major, minor;
482         unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
483
484         if ((fp = fopen(DISKSTATS, "r")) == NULL)
485                 return;
486
487         while (fgets(line, 256, fp) != NULL) {
488
489                 if (sscanf(line, "%u %u %s %lu %*u %lu %*u %lu %*u %lu",
490                            &major, &minor, dev_name,
491                            &rd_ios, &rd_sec, &wr_ios, &wr_sec) == 7) {
492                         
493                         if (is_device(dev_name, IGNORE_VIRTUAL_DEVICES)) {
494                                 /*
495                                  * OK: It's a (real) device and not a partition.
496                                  * Note: Structure should have been initialized first!
497                                  */
498                                 st_io->dk_drive      += rd_ios + wr_ios;
499                                 st_io->dk_drive_rio  += rd_ios;
500                                 st_io->dk_drive_rblk += rd_sec;
501                                 st_io->dk_drive_wio  += wr_ios;
502                                 st_io->dk_drive_wblk += wr_sec;
503                         }
504                 }
505         }
506         
507         fclose(fp);
508 }
509
510 /*
511  ***************************************************************************
512  * Read block devices statistics from /proc/diskstats.
513  *
514  * IN:
515  * @st_disk     Structure where stats will be saved.
516  * @nbr         Maximum number of block devices.
517  * @read_part   True if disks *and* partitions should be read; False if only
518  *              disks are read.
519  *
520  * OUT:
521  * @st_disk     Structure with statistics.
522  ***************************************************************************
523  */
524 void read_diskstats_disk(struct stats_disk *st_disk, int nbr, int read_part)
525 {
526         FILE *fp;
527         char line[256];
528         char dev_name[MAX_NAME_LEN];
529         int dsk = 0;
530         struct stats_disk *st_disk_i;
531         unsigned int major, minor, rd_ticks, wr_ticks, tot_ticks, rq_ticks;
532         unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
533
534         if ((fp = fopen(DISKSTATS, "r")) == NULL)
535                 return;
536
537         while ((fgets(line, 256, fp) != NULL) && (dsk < nbr)) {
538
539                 if (sscanf(line, "%u %u %s %lu %*u %lu %u %lu %*u %lu"
540                            " %u %*u %u %u",
541                            &major, &minor, dev_name,
542                            &rd_ios, &rd_sec, &rd_ticks, &wr_ios, &wr_sec, &wr_ticks,
543                            &tot_ticks, &rq_ticks) == 11) {
544                         
545                         if (!rd_ios && !wr_ios)
546                                 /* Unused device: Ignore it */
547                                 continue;
548                         if (read_part || is_device(dev_name, ACCEPT_VIRTUAL_DEVICES)) {
549                                 st_disk_i = st_disk + dsk++;
550                                 st_disk_i->major     = major;
551                                 st_disk_i->minor     = minor;
552                                 st_disk_i->nr_ios    = rd_ios + wr_ios;
553                                 st_disk_i->rd_sect   = rd_sec;
554                                 st_disk_i->wr_sect   = wr_sec;
555                                 st_disk_i->rd_ticks  = rd_ticks;
556                                 st_disk_i->wr_ticks  = wr_ticks;
557                                 st_disk_i->tot_ticks = tot_ticks;
558                                 st_disk_i->rq_ticks  = rq_ticks;
559                         }
560                 }
561         }
562
563         fclose(fp);
564 }
565
566 /*
567  ***************************************************************************
568  * Read serial lines statistics from /proc/tty/driver/serial.
569  *
570  * IN:
571  * @st_serial   Structure where stats will be saved.
572  * @nbr         Maximum number of serial lines.
573  *
574  * OUT:
575  * @st_serial   Structure with statistics.
576  ***************************************************************************
577  */
578 void read_tty_driver_serial(struct stats_serial *st_serial, int nbr)
579 {
580         FILE *fp;
581         struct stats_serial *st_serial_i;
582         int sl = 0;
583         char line[256];
584         char *p;
585
586         if ((fp = fopen(SERIAL, "r")) == NULL)
587                 return;
588
589         while ((fgets(line, 256, fp) != NULL) && (sl < nbr)) {
590
591                 if ((p = strstr(line, "tx:")) != NULL) {
592                         st_serial_i = st_serial + sl;
593                         sscanf(line, "%u", &st_serial_i->line);
594                         /*
595                          * A value of 0 means an unused structure.
596                          * So increment it to make sure it is not null.
597                          */
598                         (st_serial_i->line)++;
599                         /*
600                          * Read the number of chars transmitted and received by
601                          * current serial line.
602                          */
603                         sscanf(p + 3, "%u", &st_serial_i->tx);
604                         if ((p = strstr(line, "rx:")) != NULL) {
605                                 sscanf(p + 3, "%u", &st_serial_i->rx);
606                         }
607                         if ((p = strstr(line, "fe:")) != NULL) {
608                                 sscanf(p + 3, "%u", &st_serial_i->frame);
609                         }
610                         if ((p = strstr(line, "pe:")) != NULL) {
611                                 sscanf(p + 3, "%u", &st_serial_i->parity);
612                         }
613                         if ((p = strstr(line, "brk:")) != NULL) {
614                                 sscanf(p + 4, "%u", &st_serial_i->brk);
615                         }
616                         if ((p = strstr(line, "oe:")) != NULL) {
617                                 sscanf(p + 3, "%u", &st_serial_i->overrun);
618                         }
619                         
620                         sl++;
621                 }
622         }
623
624         fclose(fp);
625 }
626
627 /*
628  ***************************************************************************
629  * Read kernel tables statistics from various system files.
630  *
631  * IN:
632  * @st_ktables  Structure where stats will be saved.
633  *
634  * OUT:
635  * @st_ktables  Structure with statistics.
636  ***************************************************************************
637  */
638 void read_kernel_tables(struct stats_ktables *st_ktables)
639 {
640         FILE *fp;
641         unsigned int parm;
642         
643         /* Open /proc/sys/fs/dentry-state file */
644         if ((fp = fopen(FDENTRY_STATE, "r")) != NULL) {
645                 fscanf(fp, "%*d %u",
646                        &st_ktables->dentry_stat);
647                 fclose(fp);
648         }
649
650         /* Open /proc/sys/fs/file-nr file */
651         if ((fp = fopen(FFILE_NR, "r")) != NULL) {
652                 fscanf(fp, "%u %u",
653                        &st_ktables->file_used, &parm);
654                 fclose(fp);
655                 /*
656                  * The number of used handles is the number of allocated ones
657                  * minus the number of free ones.
658                  */
659                 st_ktables->file_used -= parm;
660         }
661
662         /* Open /proc/sys/fs/inode-state file */
663         if ((fp = fopen(FINODE_STATE, "r")) != NULL) {
664                 fscanf(fp, "%u %u",
665                        &st_ktables->inode_used, &parm);
666                 fclose(fp);
667                 /*
668                  * The number of inuse inodes is the number of allocated ones
669                  * minus the number of free ones.
670                  */
671                 st_ktables->inode_used -= parm;
672         }
673
674         /* Open /proc/sys/kernel/pty/nr file */
675         if ((fp = fopen(PTY_NR, "r")) != NULL) {
676                 fscanf(fp, "%u",
677                        &st_ktables->pty_nr);
678                 fclose(fp);
679         }
680 }
681
682 /*
683  ***************************************************************************
684  * Read network interfaces statistics from /proc/net/dev.
685  *
686  * IN:
687  * @st_net_dev  Structure where stats will be saved.
688  * @nbr         Maximum number of network interfaces.
689  *
690  * OUT:
691  * @st_net_dev  Structure with statistics.
692  ***************************************************************************
693  */
694 void read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
695 {
696         FILE *fp;
697         struct stats_net_dev *st_net_dev_i;
698         char line[256];
699         char iface[MAX_IFACE_LEN];
700         int dev = 0;
701         int pos;
702
703         if ((fp = fopen(NET_DEV, "r")) == NULL)
704                 return;
705         
706         while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
707
708                 pos = strcspn(line, ":");
709                 if (pos < strlen(line)) {
710                         st_net_dev_i = st_net_dev + dev;
711                         strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
712                         iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
713                         sscanf(iface, "%s", st_net_dev_i->interface); /* Skip heading spaces */
714                         sscanf(line + pos + 1, "%llu %llu %*u %*u %*u %*u %llu %llu %llu %llu "
715                                "%*u %*u %*u %*u %*u %llu",
716                                &st_net_dev_i->rx_bytes,
717                                &st_net_dev_i->rx_packets,
718                                &st_net_dev_i->rx_compressed,
719                                &st_net_dev_i->multicast,
720                                &st_net_dev_i->tx_bytes,
721                                &st_net_dev_i->tx_packets,
722                                &st_net_dev_i->tx_compressed);
723                         dev++;
724                 }
725         }
726
727         fclose(fp);
728 }
729
730 /*
731  ***************************************************************************
732  * Read network interfaces errors statistics from /proc/net/dev.
733  *
734  * IN:
735  * @st_net_edev Structure where stats will be saved.
736  * @nbr         Maximum number of network interfaces.
737  *
738  * OUT:
739  * @st_net_edev Structure with statistics.
740  ***************************************************************************
741  */
742 void read_net_edev(struct stats_net_edev *st_net_edev, int nbr)
743 {
744         FILE *fp;
745         struct stats_net_edev *st_net_edev_i;
746         static char line[256];
747         char iface[MAX_IFACE_LEN];
748         int dev = 0;
749         int pos;
750
751         if ((fp = fopen(NET_DEV, "r")) == NULL)
752                 return;
753
754         while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
755
756                 pos = strcspn(line, ":");
757                 if (pos < strlen(line)) {
758                         st_net_edev_i = st_net_edev + dev;
759                         strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
760                         iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
761                         sscanf(iface, "%s", st_net_edev_i->interface); /* Skip heading spaces */
762                         sscanf(line + pos + 1, "%*u %*u %llu %llu %llu %llu %*u %*u %*u %*u "
763                                "%llu %llu %llu %llu %llu",
764                                &st_net_edev_i->rx_errors,
765                                &st_net_edev_i->rx_dropped,
766                                &st_net_edev_i->rx_fifo_errors,
767                                &st_net_edev_i->rx_frame_errors,
768                                &st_net_edev_i->tx_errors,
769                                &st_net_edev_i->tx_dropped,
770                                &st_net_edev_i->tx_fifo_errors,
771                                &st_net_edev_i->collisions,
772                                &st_net_edev_i->tx_carrier_errors);
773                         dev++;
774                 }
775         }
776
777         fclose(fp);
778 }
779
780 /*
781  ***************************************************************************
782  * Read NFS client statistics from /proc/net/rpc/nfs.
783  *
784  * IN:
785  * @st_net_nfs  Structure where stats will be saved.
786  *
787  * OUT:
788  * @st_net_nfs  Structure with statistics.
789  ***************************************************************************
790  */
791 void read_net_nfs(struct stats_net_nfs *st_net_nfs)
792 {
793         FILE *fp;
794         char line[256];
795         unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
796
797         if ((fp = fopen(NET_RPC_NFS, "r")) == NULL)
798                 return;
799
800         memset(st_net_nfs, 0, STATS_NET_NFS_SIZE);
801         
802         while (fgets(line, 256, fp) != NULL) {
803
804                 if (!strncmp(line, "rpc ", 4)) {
805                         sscanf(line + 4, "%u %u",
806                                &st_net_nfs->nfs_rpccnt, &st_net_nfs->nfs_rpcretrans);
807                 }
808                 else if (!strncmp(line, "proc3 ", 6)) {
809                         sscanf(line + 6, "%*u %*u %u %*u %*u %u %*u %u %u",
810                                &getattcnt, &accesscnt, &readcnt, &writecnt);
811                         
812                         st_net_nfs->nfs_getattcnt += getattcnt;
813                         st_net_nfs->nfs_accesscnt += accesscnt;
814                         st_net_nfs->nfs_readcnt   += readcnt;
815                         st_net_nfs->nfs_writecnt  += writecnt;
816                 }
817                 else if (!strncmp(line, "proc4 ", 6)) {
818                         sscanf(line + 6, "%*u %*u %u %u "
819                                "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u %u",
820                                &readcnt, &writecnt, &accesscnt, &getattcnt);
821                         
822                         st_net_nfs->nfs_getattcnt += getattcnt;
823                         st_net_nfs->nfs_accesscnt += accesscnt;
824                         st_net_nfs->nfs_readcnt   += readcnt;
825                         st_net_nfs->nfs_writecnt  += writecnt;
826                 }
827         }
828
829         fclose(fp);
830 }
831
832 /*
833  ***************************************************************************
834  * Read NFS server statistics from /proc/net/rpc/nfsd.
835  *
836  * IN:
837  * @st_net_nfsd Structure where stats will be saved.
838  *
839  * OUT:
840  * @st_net_nfsd Structure with statistics.
841  ***************************************************************************
842  */
843 void read_net_nfsd(struct stats_net_nfsd *st_net_nfsd)
844 {
845         FILE *fp;
846         char line[256];
847         unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
848
849         if ((fp = fopen(NET_RPC_NFSD, "r")) == NULL)
850                 return;
851         
852         memset(st_net_nfsd, 0, STATS_NET_NFSD_SIZE);
853
854         while (fgets(line, 256, fp) != NULL) {
855
856                 if (!strncmp(line, "rc ", 3)) {
857                         sscanf(line + 3, "%u %u",
858                                &st_net_nfsd->nfsd_rchits, &st_net_nfsd->nfsd_rcmisses);
859                 }
860                 else if (!strncmp(line, "net ", 4)) {
861                         sscanf(line + 4, "%u %u %u",
862                                &st_net_nfsd->nfsd_netcnt, &st_net_nfsd->nfsd_netudpcnt,
863                                &st_net_nfsd->nfsd_nettcpcnt);
864                 }
865                 else if (!strncmp(line, "rpc ", 4)) {
866                         sscanf(line + 4, "%u %u",
867                                &st_net_nfsd->nfsd_rpccnt, &st_net_nfsd->nfsd_rpcbad);
868                 }
869                 else if (!strncmp(line, "proc3 ", 6)) {
870                         sscanf(line + 6, "%*u %*u %u %*u %*u %u %*u %u %u",
871                                &getattcnt, &accesscnt, &readcnt, &writecnt);
872
873                         st_net_nfsd->nfsd_getattcnt += getattcnt;
874                         st_net_nfsd->nfsd_accesscnt += accesscnt;
875                         st_net_nfsd->nfsd_readcnt   += readcnt;
876                         st_net_nfsd->nfsd_writecnt  += writecnt;
877                         
878                 }
879                 else if (!strncmp(line, "proc4ops ", 9)) {
880                         sscanf(line + 9, "%*u %*u %*u %*u %u "
881                                "%*u %*u %*u %*u %*u %u "
882                                "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u "
883                                "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u",
884                                &accesscnt, &getattcnt, &readcnt, &writecnt);
885                         
886                         st_net_nfsd->nfsd_getattcnt += getattcnt;
887                         st_net_nfsd->nfsd_accesscnt += accesscnt;
888                         st_net_nfsd->nfsd_readcnt   += readcnt;
889                         st_net_nfsd->nfsd_writecnt  += writecnt;
890                 }
891         }
892
893         fclose(fp);
894 }
895
896 /*
897  ***************************************************************************
898  * Read network sockets statistics from /proc/net/sockstat.
899  *
900  * IN:
901  * @st_net_sock Structure where stats will be saved.
902  *
903  * OUT:
904  * @st_net_sock Structure with statistics.
905  ***************************************************************************
906  */
907 void read_net_sock(struct stats_net_sock *st_net_sock)
908 {
909         FILE *fp;
910         char line[96];
911         char *p;
912
913         if ((fp = fopen(NET_SOCKSTAT, "r")) == NULL)
914                 return;
915         
916         while (fgets(line, 96, fp) != NULL) {
917
918                 if (!strncmp(line, "sockets:", 8)) {
919                         /* Sockets */
920                         sscanf(line + 14, "%u", &st_net_sock->sock_inuse);
921                 }
922                 else if (!strncmp(line, "TCP:", 4)) {
923                         /* TCP sockets */
924                         sscanf(line + 11, "%u", &st_net_sock->tcp_inuse);
925                         if ((p = strstr(line, "tw")) != NULL) {
926                                 sscanf(p + 2, "%u", &st_net_sock->tcp_tw);
927                         }
928                 }
929                 else if (!strncmp(line, "UDP:", 4)) {
930                         /* UDP sockets */
931                         sscanf(line + 11, "%u", &st_net_sock->udp_inuse);
932                 }
933                 else if (!strncmp(line, "RAW:", 4)) {
934                         /* RAW sockets */
935                         sscanf(line + 11, "%u", &st_net_sock->raw_inuse);
936                 }
937                 else if (!strncmp(line, "FRAG:", 5)) {
938                         /* FRAGments */
939                         sscanf(line + 12, "%u", &st_net_sock->frag_inuse);
940                 }
941         }
942
943         fclose(fp);
944 }
945
946 /*
947  ***************************************************************************
948  * Read IP network traffic statistics from /proc/net/snmp.
949  *
950  * IN:
951  * @st_net_ip   Structure where stats will be saved.
952  *
953  * OUT:
954  * @st_net_ip   Structure with statistics.
955  ***************************************************************************
956  */
957 void read_net_ip(struct stats_net_ip *st_net_ip)
958 {
959         FILE *fp;
960         char line[1024];
961         int sw = FALSE;
962
963         if ((fp = fopen(NET_SNMP, "r")) == NULL)
964                 return;
965         
966         while (fgets(line, 1024, fp) != NULL) {
967
968                 if (!strncmp(line, "Ip:", 3)) {
969                         if (sw) {
970                                 sscanf(line + 3, "%*u %*u %llu %*u %*u %llu %*u %*u "
971                                        "%llu %llu %*u %*u %*u %llu %llu %*u %llu %*u %llu",
972                                        &st_net_ip->InReceives,
973                                        &st_net_ip->ForwDatagrams,
974                                        &st_net_ip->InDelivers,
975                                        &st_net_ip->OutRequests,
976                                        &st_net_ip->ReasmReqds,
977                                        &st_net_ip->ReasmOKs,
978                                        &st_net_ip->FragOKs,
979                                        &st_net_ip->FragCreates);
980                                 
981                                 break;
982                         }
983                         else {
984                                 sw = TRUE;
985                         }
986                 }
987         }
988
989         fclose(fp);
990 }
991
992 /*
993  ***************************************************************************
994  * Read IP network error statistics from /proc/net/snmp.
995  *
996  * IN:
997  * @st_net_eip  Structure where stats will be saved.
998  *
999  * OUT:
1000  * @st_net_eip  Structure with statistics.
1001  ***************************************************************************
1002  */
1003 void read_net_eip(struct stats_net_eip *st_net_eip)
1004 {
1005         FILE *fp;
1006         char line[1024];
1007         int sw = FALSE;
1008
1009         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1010                 return;
1011         
1012         while (fgets(line, 1024, fp) != NULL) {
1013
1014                 if (!strncmp(line, "Ip:", 3)) {
1015                         if (sw) {
1016                                 sscanf(line + 3, "%*u %*u %*u %llu %llu %*u %llu %llu "
1017                                        "%*u %*u %llu %llu %*u %*u %*u %llu %*u %llu",
1018                                        &st_net_eip->InHdrErrors,
1019                                        &st_net_eip->InAddrErrors,
1020                                        &st_net_eip->InUnknownProtos,
1021                                        &st_net_eip->InDiscards,
1022                                        &st_net_eip->OutDiscards,
1023                                        &st_net_eip->OutNoRoutes,
1024                                        &st_net_eip->ReasmFails,
1025                                        &st_net_eip->FragFails);
1026                                 
1027                                 break;
1028                         }
1029                         else {
1030                                 sw = TRUE;
1031                         }
1032                 }
1033         }
1034
1035         fclose(fp);
1036 }
1037
1038 /*
1039  ***************************************************************************
1040  * Read ICMP network traffic statistics from /proc/net/snmp.
1041  *
1042  * IN:
1043  * @st_net_icmp Structure where stats will be saved.
1044  *
1045  * OUT:
1046  * @st_net_icmp Structure with statistics.
1047  ***************************************************************************
1048  */
1049 void read_net_icmp(struct stats_net_icmp *st_net_icmp)
1050 {
1051         FILE *fp;
1052         char line[1024];
1053         int sw = FALSE;
1054
1055         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1056                 return;
1057         
1058         while (fgets(line, 1024, fp) != NULL) {
1059
1060                 if (!strncmp(line, "Icmp:", 5)) {
1061                         if (sw) {
1062                                 sscanf(line + 5, "%lu %*u %*u %*u %*u %*u %*u "
1063                                        "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
1064                                        "%*u %*u %lu %lu %lu %lu %lu %lu",
1065                                        &st_net_icmp->InMsgs,
1066                                        &st_net_icmp->InEchos,
1067                                        &st_net_icmp->InEchoReps,
1068                                        &st_net_icmp->InTimestamps,
1069                                        &st_net_icmp->InTimestampReps,
1070                                        &st_net_icmp->InAddrMasks,
1071                                        &st_net_icmp->InAddrMaskReps,
1072                                        &st_net_icmp->OutMsgs,
1073                                        &st_net_icmp->OutEchos,
1074                                        &st_net_icmp->OutEchoReps,
1075                                        &st_net_icmp->OutTimestamps,
1076                                        &st_net_icmp->OutTimestampReps,
1077                                        &st_net_icmp->OutAddrMasks,
1078                                        &st_net_icmp->OutAddrMaskReps);
1079
1080                                 break;
1081                         }
1082                         else {
1083                                 sw = TRUE;
1084                         }
1085                 }
1086         }
1087
1088         fclose(fp);
1089 }
1090
1091 /*
1092  ***************************************************************************
1093  * Read ICMP network error statistics from /proc/net/snmp.
1094  *
1095  * IN:
1096  * @st_net_eicmp        Structure where stats will be saved.
1097  *
1098  * OUT:
1099  * @st_net_eicmp        Structure with statistics.
1100  ***************************************************************************
1101  */
1102 void read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
1103 {
1104         FILE *fp;
1105         char line[1024];
1106         int sw = FALSE;
1107
1108         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1109                 return;
1110         
1111         while (fgets(line, 1024, fp) != NULL) {
1112
1113                 if (!strncmp(line, "Icmp:", 5)) {
1114                         if (sw) {
1115                                 sscanf(line + 5, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
1116                                        "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu",
1117                                        &st_net_eicmp->InErrors,
1118                                        &st_net_eicmp->InDestUnreachs,
1119                                        &st_net_eicmp->InTimeExcds,
1120                                        &st_net_eicmp->InParmProbs,
1121                                        &st_net_eicmp->InSrcQuenchs,
1122                                        &st_net_eicmp->InRedirects,
1123                                        &st_net_eicmp->OutErrors,
1124                                        &st_net_eicmp->OutDestUnreachs,
1125                                        &st_net_eicmp->OutTimeExcds,
1126                                        &st_net_eicmp->OutParmProbs,
1127                                        &st_net_eicmp->OutSrcQuenchs,
1128                                        &st_net_eicmp->OutRedirects);
1129
1130                                 break;
1131                         }
1132                         else {
1133                                 sw = TRUE;
1134                         }
1135                 }
1136         }
1137
1138         fclose(fp);
1139 }
1140
1141 /*
1142  ***************************************************************************
1143  * Read TCP network traffic statistics from /proc/net/snmp.
1144  *
1145  * IN:
1146  * @st_net_tcp  Structure where stats will be saved.
1147  *
1148  * OUT:
1149  * @st_net_tcp  Structure with statistics.
1150  ***************************************************************************
1151  */
1152 void read_net_tcp(struct stats_net_tcp *st_net_tcp)
1153 {
1154         FILE *fp;
1155         char line[1024];
1156         int sw = FALSE;
1157
1158         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1159                 return;
1160         
1161         while (fgets(line, 1024, fp) != NULL) {
1162
1163                 if (!strncmp(line, "Tcp:", 4)) {
1164                         if (sw) {
1165                                 sscanf(line + 4, "%*u %*u %*u %*d %lu %lu "
1166                                        "%*u %*u %*u %lu %lu",
1167                                        &st_net_tcp->ActiveOpens,
1168                                        &st_net_tcp->PassiveOpens,
1169                                        &st_net_tcp->InSegs,
1170                                        &st_net_tcp->OutSegs);
1171
1172                                 break;
1173                         }
1174                         else {
1175                                 sw = TRUE;
1176                         }
1177                 }
1178         }
1179
1180         fclose(fp);
1181 }
1182
1183 /*
1184  ***************************************************************************
1185  * Read TCP network error statistics from /proc/net/snmp.
1186  *
1187  * IN:
1188  * @st_net_etcp Structure where stats will be saved.
1189  *
1190  * OUT:
1191  * @st_net_etcp Structure with statistics.
1192  ***************************************************************************
1193  */
1194 void read_net_etcp(struct stats_net_etcp *st_net_etcp)
1195 {
1196         FILE *fp;
1197         char line[1024];
1198         int sw = FALSE;
1199
1200         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1201                 return;
1202         
1203         while (fgets(line, 1024, fp) != NULL) {
1204
1205                 if (!strncmp(line, "Tcp:", 4)) {
1206                         if (sw) {
1207                                 sscanf(line + 4, "%*u %*u %*u %*d %*u %*u "
1208                                        "%lu %lu %*u %*u %*u %lu %lu %lu",
1209                                        &st_net_etcp->AttemptFails,
1210                                        &st_net_etcp->EstabResets,
1211                                        &st_net_etcp->RetransSegs,
1212                                        &st_net_etcp->InErrs,
1213                                        &st_net_etcp->OutRsts);
1214
1215                                 break;
1216                         }
1217                         else {
1218                                 sw = TRUE;
1219                         }
1220                 }
1221         }
1222
1223         fclose(fp);
1224 }
1225
1226 /*
1227  ***************************************************************************
1228  * Read UDP network traffic statistics from /proc/net/snmp.
1229  *
1230  * IN:
1231  * @st_net_udp  Structure where stats will be saved.
1232  *
1233  * OUT:
1234  * @st_net_udp  Structure with statistics.
1235  ***************************************************************************
1236  */
1237 void read_net_udp(struct stats_net_udp *st_net_udp)
1238 {
1239         FILE *fp;
1240         char line[1024];
1241         int sw = FALSE;
1242
1243         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1244                 return;
1245         
1246         while (fgets(line, 1024, fp) != NULL) {
1247
1248                 if (!strncmp(line, "Udp:", 4)) {
1249                         if (sw) {
1250                                 sscanf(line + 4, "%lu %lu %lu %lu",
1251                                        &st_net_udp->InDatagrams,
1252                                        &st_net_udp->NoPorts,
1253                                        &st_net_udp->InErrors,
1254                                        &st_net_udp->OutDatagrams);
1255
1256                                 break;
1257                         }
1258                         else {
1259                                 sw = TRUE;
1260                         }
1261                 }
1262         }
1263
1264         fclose(fp);
1265 }
1266
1267 /*
1268  ***************************************************************************
1269  * Read IPv6 network sockets statistics from /proc/net/sockstat6.
1270  *
1271  * IN:
1272  * @st_net_sock6        Structure where stats will be saved.
1273  *
1274  * OUT:
1275  * @st_net_sock6        Structure with statistics.
1276  ***************************************************************************
1277  */
1278 void read_net_sock6(struct stats_net_sock6 *st_net_sock6)
1279 {
1280         FILE *fp;
1281         char line[96];
1282
1283         if ((fp = fopen(NET_SOCKSTAT6, "r")) == NULL)
1284                 return;
1285         
1286         while (fgets(line, 96, fp) != NULL) {
1287
1288                 if (!strncmp(line, "TCP6:", 5)) {
1289                         /* TCPv6 sockets */
1290                         sscanf(line + 12, "%u", &st_net_sock6->tcp6_inuse);
1291                 }
1292                 else if (!strncmp(line, "UDP6:", 5)) {
1293                         /* UDPv6 sockets */
1294                         sscanf(line + 12, "%u", &st_net_sock6->udp6_inuse);
1295                 }
1296                 else if (!strncmp(line, "RAW6:", 5)) {
1297                         /* IPv6 RAW sockets */
1298                         sscanf(line + 12, "%u", &st_net_sock6->raw6_inuse);
1299                 }
1300                 else if (!strncmp(line, "FRAG6:", 6)) {
1301                         /* IPv6 FRAGments */
1302                         sscanf(line + 13, "%u", &st_net_sock6->frag6_inuse);
1303                 }
1304         }
1305
1306         fclose(fp);
1307 }
1308
1309 /*
1310  ***************************************************************************
1311  * Read IPv6 network traffic statistics from /proc/net/snmp6.
1312  *
1313  * IN:
1314  * @st_net_ip6  Structure where stats will be saved.
1315  *
1316  * OUT:
1317  * @st_net_ip6  Structure with statistics.
1318  ***************************************************************************
1319  */
1320 void read_net_ip6(struct stats_net_ip6 *st_net_ip6)
1321 {
1322         FILE *fp;
1323         char line[128];
1324
1325         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1326                 return;
1327
1328         while (fgets(line, 128, fp) != NULL) {
1329
1330                 if (!strncmp(line, "Ip6InReceives ", 14)) {
1331                         sscanf(line + 14, "%llu", &st_net_ip6->InReceives6);
1332                 }
1333                 else if (!strncmp(line, "Ip6OutForwDatagrams ", 20)) {
1334                         sscanf(line + 20, "%llu", &st_net_ip6->OutForwDatagrams6);
1335                 }
1336                 else if (!strncmp(line, "Ip6InDelivers ", 14)) {
1337                         sscanf(line + 14, "%llu", &st_net_ip6->InDelivers6);
1338                 }
1339                 else if (!strncmp(line, "Ip6OutRequests ", 15)) {
1340                         sscanf(line + 15, "%llu", &st_net_ip6->OutRequests6);
1341                 }
1342                 else if (!strncmp(line, "Ip6ReasmReqds ", 14)) {
1343                         sscanf(line + 14, "%llu", &st_net_ip6->ReasmReqds6);
1344                 }
1345                 else if (!strncmp(line, "Ip6ReasmOKs ", 12)) {
1346                         sscanf(line + 12, "%llu", &st_net_ip6->ReasmOKs6);
1347                 }
1348                 else if (!strncmp(line, "Ip6InMcastPkts ", 15)) {
1349                         sscanf(line + 15, "%llu", &st_net_ip6->InMcastPkts6);
1350                 }
1351                 else if (!strncmp(line, "Ip6OutMcastPkts ", 16)) {
1352                         sscanf(line + 16, "%llu", &st_net_ip6->OutMcastPkts6);
1353                 }
1354                 else if (!strncmp(line, "Ip6FragOKs ", 11)) {
1355                         sscanf(line + 11, "%llu", &st_net_ip6->FragOKs6);
1356                 }
1357                 else if (!strncmp(line, "Ip6FragCreates ", 15)) {
1358                         sscanf(line + 15, "%llu", &st_net_ip6->FragCreates6);
1359                 }
1360         }
1361         
1362         fclose(fp);
1363 }
1364
1365 /*
1366  ***************************************************************************
1367  * Read IPv6 network error statistics from /proc/net/snmp6.
1368  *
1369  * IN:
1370  * @st_net_eip6 Structure where stats will be saved.
1371  *
1372  * OUT:
1373  * @st_net_eip6 Structure with statistics.
1374  ***************************************************************************
1375  */
1376 void read_net_eip6(struct stats_net_eip6 *st_net_eip6)
1377 {
1378         FILE *fp;
1379         char line[128];
1380
1381         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1382                 return;
1383
1384         while (fgets(line, 128, fp) != NULL) {
1385
1386                 if (!strncmp(line, "Ip6InHdrErrors ", 15)) {
1387                         sscanf(line + 15, "%llu", &st_net_eip6->InHdrErrors6);
1388                 }
1389                 else if (!strncmp(line, "Ip6InAddrErrors ", 16)) {
1390                         sscanf(line + 16, "%llu", &st_net_eip6->InAddrErrors6);
1391                 }
1392                 else if (!strncmp(line, "Ip6InUnknownProtos ", 19)) {
1393                         sscanf(line + 19, "%llu", &st_net_eip6->InUnknownProtos6);
1394                 }
1395                 else if (!strncmp(line, "Ip6InTooBigErrors ", 18)) {
1396                         sscanf(line + 18, "%llu", &st_net_eip6->InTooBigErrors6);
1397                 }
1398                 else if (!strncmp(line, "Ip6InDiscards ", 14)) {
1399                         sscanf(line + 14, "%llu", &st_net_eip6->InDiscards6);
1400                 }
1401                 else if (!strncmp(line, "Ip6OutDiscards ", 15)) {
1402                         sscanf(line + 15, "%llu", &st_net_eip6->OutDiscards6);
1403                 }
1404                 else if (!strncmp(line, "Ip6InNoRoutes ", 14)) {
1405                         sscanf(line + 14, "%llu", &st_net_eip6->InNoRoutes6);
1406                 }
1407                 else if (!strncmp(line, "Ip6OutNoRoutes ", 15)) {
1408                         sscanf(line + 15, "%llu", &st_net_eip6->OutNoRoutes6);
1409                 }
1410                 else if (!strncmp(line, "Ip6ReasmFails ", 14)) {
1411                         sscanf(line + 14, "%llu", &st_net_eip6->ReasmFails6);
1412                 }
1413                 else if (!strncmp(line, "Ip6FragFails ", 13)) {
1414                         sscanf(line + 13, "%llu", &st_net_eip6->FragFails6);
1415                 }
1416                 else if (!strncmp(line, "Ip6InTruncatedPkts ", 19)) {
1417                         sscanf(line + 19, "%llu", &st_net_eip6->InTruncatedPkts6);
1418                 }
1419         }
1420         
1421         fclose(fp);
1422 }
1423
1424 /*
1425  ***************************************************************************
1426  * Read ICMPv6 network traffic statistics from /proc/net/snmp6.
1427  *
1428  * IN:
1429  * @st_net_icmp6        Structure where stats will be saved.
1430  *
1431  * OUT:
1432  * @st_net_icmp6        Structure with statistics.
1433  ***************************************************************************
1434  */
1435 void read_net_icmp6(struct stats_net_icmp6 *st_net_icmp6)
1436 {
1437         FILE *fp;
1438         char line[128];
1439
1440         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1441                 return;
1442
1443         while (fgets(line, 128, fp) != NULL) {
1444
1445                 if (!strncmp(line, "Icmp6InMsgs ", 12)) {
1446                         sscanf(line + 12, "%lu", &st_net_icmp6->InMsgs6);
1447                 }
1448                 else if (!strncmp(line, "Icmp6OutMsgs ", 13)) {
1449                         sscanf(line + 13, "%lu", &st_net_icmp6->OutMsgs6);
1450                 }
1451                 else if (!strncmp(line, "Icmp6InEchos ", 13)) {
1452                         sscanf(line + 13, "%lu", &st_net_icmp6->InEchos6);
1453                 }
1454                 else if (!strncmp(line, "Icmp6InEchoReplies ", 19)) {
1455                         sscanf(line + 19, "%lu", &st_net_icmp6->InEchoReplies6);
1456                 }
1457                 else if (!strncmp(line, "Icmp6OutEchoReplies ", 20)) {
1458                         sscanf(line + 20, "%lu", &st_net_icmp6->OutEchoReplies6);
1459                 }
1460                 else if (!strncmp(line, "Icmp6InGroupMembQueries ", 24)) {
1461                         sscanf(line + 24, "%lu", &st_net_icmp6->InGroupMembQueries6);
1462                 }
1463                 else if (!strncmp(line, "Icmp6InGroupMembResponses ", 26)) {
1464                         sscanf(line + 26, "%lu", &st_net_icmp6->InGroupMembResponses6);
1465                 }
1466                 else if (!strncmp(line, "Icmp6OutGroupMembResponses ", 27)) {
1467                         sscanf(line + 27, "%lu", &st_net_icmp6->OutGroupMembResponses6);
1468                 }
1469                 else if (!strncmp(line, "Icmp6InGroupMembReductions ", 27)) {
1470                         sscanf(line + 27, "%lu", &st_net_icmp6->InGroupMembReductions6);
1471                 }
1472                 else if (!strncmp(line, "Icmp6OutGroupMembReductions ", 28)) {
1473                         sscanf(line + 28, "%lu", &st_net_icmp6->OutGroupMembReductions6);
1474                 }
1475                 else if (!strncmp(line, "Icmp6InRouterSolicits ", 22)) {
1476                         sscanf(line + 22, "%lu", &st_net_icmp6->InRouterSolicits6);
1477                 }
1478                 else if (!strncmp(line, "Icmp6OutRouterSolicits ", 23)) {
1479                         sscanf(line + 23, "%lu", &st_net_icmp6->OutRouterSolicits6);
1480                 }
1481                 else if (!strncmp(line, "Icmp6InRouterAdvertisements ", 28)) {
1482                         sscanf(line + 28, "%lu", &st_net_icmp6->InRouterAdvertisements6);
1483                 }
1484                 else if (!strncmp(line, "Icmp6InNeighborSolicits ", 24)) {
1485                         sscanf(line + 24, "%lu", &st_net_icmp6->InNeighborSolicits6);
1486                 }
1487                 else if (!strncmp(line, "Icmp6OutNeighborSolicits ", 25)) {
1488                         sscanf(line + 25, "%lu", &st_net_icmp6->OutNeighborSolicits6);
1489                 }
1490                 else if (!strncmp(line, "Icmp6InNeighborAdvertisements ", 30)) {
1491                         sscanf(line + 30, "%lu", &st_net_icmp6->InNeighborAdvertisements6);
1492                 }
1493                 else if (!strncmp(line, "Icmp6OutNeighborAdvertisements ", 31)) {
1494                         sscanf(line + 31, "%lu", &st_net_icmp6->OutNeighborAdvertisements6);
1495                 }
1496         }
1497         
1498         fclose(fp);
1499 }
1500
1501 /*
1502  ***************************************************************************
1503  * Read ICMPv6 network error statistics from /proc/net/snmp6.
1504  *
1505  * IN:
1506  * @st_net_eicmp6       Structure where stats will be saved.
1507  *
1508  * OUT:
1509  * @st_net_eicmp6       Structure with statistics.
1510  ***************************************************************************
1511  */
1512 void read_net_eicmp6(struct stats_net_eicmp6 *st_net_eicmp6)
1513 {
1514         FILE *fp;
1515         char line[128];
1516
1517         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1518                 return;
1519
1520         while (fgets(line, 128, fp) != NULL) {
1521
1522                 if (!strncmp(line, "Icmp6InErrors ", 14)) {
1523                         sscanf(line + 14, "%lu", &st_net_eicmp6->InErrors6);
1524                 }
1525                 else if (!strncmp(line, "Icmp6InDestUnreachs ", 20)) {
1526                         sscanf(line + 20, "%lu", &st_net_eicmp6->InDestUnreachs6);
1527                 }
1528                 else if (!strncmp(line, "Icmp6OutDestUnreachs ", 21)) {
1529                         sscanf(line + 21, "%lu", &st_net_eicmp6->OutDestUnreachs6);
1530                 }
1531                 else if (!strncmp(line, "Icmp6InTimeExcds ", 17)) {
1532                         sscanf(line + 17, "%lu", &st_net_eicmp6->InTimeExcds6);
1533                 }
1534                 else if (!strncmp(line, "Icmp6OutTimeExcds ", 18)) {
1535                         sscanf(line + 18, "%lu", &st_net_eicmp6->OutTimeExcds6);
1536                 }
1537                 else if (!strncmp(line, "Icmp6InParmProblems ", 20)) {
1538                         sscanf(line + 20, "%lu", &st_net_eicmp6->InParmProblems6);
1539                 }
1540                 else if (!strncmp(line, "Icmp6OutParmProblems ", 21)) {
1541                         sscanf(line + 21, "%lu", &st_net_eicmp6->OutParmProblems6);
1542                 }
1543                 else if (!strncmp(line, "Icmp6InRedirects ", 17)) {
1544                         sscanf(line + 17, "%lu", &st_net_eicmp6->InRedirects6);
1545                 }
1546                 else if (!strncmp(line, "Icmp6OutRedirects ", 18)) {
1547                         sscanf(line + 18, "%lu", &st_net_eicmp6->OutRedirects6);
1548                 }
1549                 else if (!strncmp(line, "Icmp6InPktTooBigs ", 18)) {
1550                         sscanf(line + 18, "%lu", &st_net_eicmp6->InPktTooBigs6);
1551                 }
1552                 else if (!strncmp(line, "Icmp6OutPktTooBigs ", 19)) {
1553                         sscanf(line + 19, "%lu", &st_net_eicmp6->OutPktTooBigs6);
1554                 }
1555         }
1556         
1557         fclose(fp);
1558 }
1559
1560 /*
1561  ***************************************************************************
1562  * Read UDPv6 network traffic statistics from /proc/net/snmp6.
1563  *
1564  * IN:
1565  * @st_net_udp6 Structure where stats will be saved.
1566  *
1567  * OUT:
1568  * @st_net_udp6 Structure with statistics.
1569  ***************************************************************************
1570  */
1571 void read_net_udp6(struct stats_net_udp6 *st_net_udp6)
1572 {
1573         FILE *fp;
1574         char line[128];
1575
1576         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1577                 return;
1578
1579         while (fgets(line, 128, fp) != NULL) {
1580
1581                 if (!strncmp(line, "Udp6InDatagrams ", 16)) {
1582                         sscanf(line + 16, "%lu", &st_net_udp6->InDatagrams6);
1583                 }
1584                 else if (!strncmp(line, "Udp6OutDatagrams ", 17)) {
1585                         sscanf(line + 17, "%lu", &st_net_udp6->OutDatagrams6);
1586                 }
1587                 else if (!strncmp(line, "Udp6NoPorts ", 12)) {
1588                         sscanf(line + 12, "%lu", &st_net_udp6->NoPorts6);
1589                 }
1590                 else if (!strncmp(line, "Udp6InErrors ", 13)) {
1591                         sscanf(line + 13, "%lu", &st_net_udp6->InErrors6);
1592                 }
1593         }
1594         
1595         fclose(fp);
1596 }
1597
1598 /*
1599  ***************************************************************************
1600  * Read CPU frequency statistics.
1601  *
1602  * IN:
1603  * @st_pwr_cpufreq      Structure where stats will be saved.
1604  * @nbr                 Total number of CPU (including cpu "all").
1605  *
1606  * OUT:
1607  * @st_pwr_cpufreq      Structure with statistics.
1608  ***************************************************************************
1609  */
1610 void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
1611 {
1612         FILE *fp;
1613         struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
1614         char line[1024];
1615         int proc_nb = 0, nr = 0;
1616         unsigned int ifreq, dfreq;
1617         
1618         if ((fp = fopen(CPUINFO, "r")) == NULL)
1619                 return;
1620         
1621         st_pwr_cpufreq->cpufreq = 0;
1622         
1623         while (fgets(line, 1024, fp) != NULL) {
1624                 
1625                 if (!strncmp(line, "processor\t", 10)) {
1626                         sscanf(strchr(line, ':') + 1, "%d", &proc_nb);
1627                 }
1628                 
1629                 else if (!strncmp(line, "cpu MHz\t", 8)) {
1630                         sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
1631                         
1632                         if (proc_nb < (nbr - 1)) {
1633                                 /* Save current CPU frequency */
1634                                 st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
1635                                 st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
1636                                 
1637                                 /* Also save it to compute an average CPU frequency */
1638                                 st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
1639                                 nr++;
1640                         }
1641                         else if (!proc_nb && (nbr == 1)) {
1642                                 /*
1643                                  * We are reading freq for "Processor 0" and we have a machine
1644                                  * with only one processor and not an SMP kernel, with /sys not mounted
1645                                  * (the nr of proc has been counted using /proc/stat and there was
1646                                  * only one line with global CPU stats here).
1647                                  * This is a very specific case, I must admit...
1648                                  */
1649                                 st_pwr_cpufreq->cpufreq = ifreq * 100 + dfreq / 10;
1650                         }
1651                 }
1652         }
1653         
1654         fclose(fp);
1655         
1656         if (nr) {
1657                 /* Compute average CPU frequency for this machine */
1658                 st_pwr_cpufreq->cpufreq /= nr;
1659         }
1660 }
1661
1662 /*
1663  ***************************************************************************
1664  * Read hugepages statistics from /proc/meminfo.
1665  *
1666  * IN:
1667  * @st_huge     Structure where stats will be saved.
1668  *
1669  * OUT:
1670  * @st_huge     Structure with statistics.
1671  ***************************************************************************
1672  */
1673 void read_meminfo_huge(struct stats_huge *st_huge)
1674 {
1675         FILE *fp;
1676         char line[128];
1677         unsigned long szhkb = 0;
1678
1679         if ((fp = fopen(MEMINFO, "r")) == NULL)
1680                 return;
1681
1682         while (fgets(line, 128, fp) != NULL) {
1683
1684                 if (!strncmp(line, "HugePages_Total:", 16)) {
1685                         /* Read the total number of huge pages */
1686                         sscanf(line + 16, "%lu", &st_huge->tlhkb);
1687                 }
1688                 else if (!strncmp(line, "HugePages_Free:", 15)) {
1689                         /* Read the number of free huge pages */
1690                         sscanf(line + 15, "%lu", &st_huge->frhkb);
1691                 }
1692                 else if (!strncmp(line, "Hugepagesize:", 13)) {
1693                         /* Read the default size of a huge page in kB */
1694                         sscanf(line + 13, "%lu", &szhkb);
1695                 }
1696         }
1697
1698         fclose(fp);
1699
1700         /* We want huge pages stats in kB and not expressed in a number of pages */
1701         st_huge->tlhkb *= szhkb;
1702         st_huge->frhkb *= szhkb;
1703 }
1704
1705 /*
1706  ***************************************************************************
1707  * Read CPU average frequencies statistics.
1708  *
1709  * IN:
1710  * @st_pwr_wghfreq      Structure where stats will be saved.
1711  * @cpu_nr              CPU number for which time_in_state date will be read.
1712  * @nbr                 Total number of states (frequencies).
1713  *
1714  * OUT:
1715  * @st_pwr_wghfreq      Structure with statistics.
1716  ***************************************************************************
1717  */
1718 void read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
1719 {
1720         FILE *fp;
1721         struct stats_pwr_wghfreq *st_pwr_wghfreq_j;
1722         char filename[MAX_PF_NAME];
1723         char line[128];
1724         int j = 0;
1725         unsigned long freq;
1726         unsigned long long time_in_state;
1727
1728         snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s",
1729                  SYSFS_DEVCPU, cpu_nr, SYSFS_TIME_IN_STATE);
1730         if ((fp = fopen(filename, "r")) == NULL)
1731                 return;
1732
1733         while (fgets(line, 128, fp) != NULL) {
1734
1735                 sscanf(line, "%lu %llu", &freq, &time_in_state);
1736
1737                 if (j < nbr) {
1738                         /* Save current frequency and time */
1739                         st_pwr_wghfreq_j = st_pwr_wghfreq + j;
1740                         st_pwr_wghfreq_j->freq = freq;
1741                         st_pwr_wghfreq_j->time_in_state = time_in_state;
1742                         j++;
1743                 }
1744         }
1745
1746         fclose(fp);
1747 }
1748
1749 /*
1750  ***************************************************************************
1751  * Read current USB device data.
1752  *
1753  * IN:
1754  * @st_pwr_usb          Structure where stats will be saved.
1755  * @usb_device          File name for current USB device.
1756  *
1757  * OUT:
1758  * @st_pwr_usb          Structure with statistics.
1759  ***************************************************************************
1760  */
1761 void read_usb_stats(struct stats_pwr_usb *st_pwr_usb, char *usb_device)
1762 {
1763         int l;
1764         FILE *fp;
1765         char filename[MAX_PF_NAME];
1766
1767         /* Get USB device bus number */
1768         sscanf(usb_device, "%u", &st_pwr_usb->bus_nr);
1769
1770         /* Read USB device vendor ID */
1771         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1772                  SYSFS_USBDEV, usb_device, SYSFS_IDVENDOR);
1773         if ((fp = fopen(filename, "r")) != NULL) {
1774                 fscanf(fp, "%x",
1775                        &st_pwr_usb->vendor_id);
1776                 fclose(fp);
1777         }
1778
1779         /* Read USB device product ID */
1780         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1781                  SYSFS_USBDEV, usb_device, SYSFS_IDPRODUCT);
1782         if ((fp = fopen(filename, "r")) != NULL) {
1783                 fscanf(fp, "%x",
1784                        &st_pwr_usb->product_id);
1785                 fclose(fp);
1786         }
1787         
1788         /* Read USB device max power consumption */
1789         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1790                  SYSFS_USBDEV, usb_device, SYSFS_BMAXPOWER);
1791         if ((fp = fopen(filename, "r")) != NULL) {
1792                 fscanf(fp, "%u",
1793                        &st_pwr_usb->bmaxpower);
1794                 fclose(fp);
1795         }
1796
1797         /* Read USB device manufacturer */
1798         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1799                  SYSFS_USBDEV, usb_device, SYSFS_MANUFACTURER);
1800         if ((fp = fopen(filename, "r")) != NULL) {
1801                 fgets(st_pwr_usb->manufacturer, MAX_MANUF_LEN - 1, fp);
1802                 fclose(fp);
1803                 if ((l = strlen(st_pwr_usb->manufacturer)) > 0) {
1804                         /* Remove trailing CR */
1805                         st_pwr_usb->manufacturer[l - 1] = '\0';
1806                 }
1807         }
1808
1809         /* Read USB device product */
1810         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1811                  SYSFS_USBDEV, usb_device, SYSFS_PRODUCT);
1812         if ((fp = fopen(filename, "r")) != NULL) {
1813                 fgets(st_pwr_usb->product, MAX_PROD_LEN - 1, fp);
1814                 fclose(fp);
1815                 if ((l = strlen(st_pwr_usb->product)) > 0) {
1816                         /* Remove trailing CR */
1817                         st_pwr_usb->product[l - 1] = '\0';
1818                 }
1819         }
1820 }
1821
1822 /*
1823  ***************************************************************************
1824  * Read USB devices statistics.
1825  *
1826  * IN:
1827  * @st_pwr_usb          Structure where stats will be saved.
1828  * @nbr                 Total number of USB devices.
1829  *
1830  * OUT:
1831  * @st_pwr_usb          Structure with statistics.
1832  ***************************************************************************
1833  */
1834 void read_bus_usb_dev(struct stats_pwr_usb *st_pwr_usb, int nbr)
1835 {
1836         DIR *dir;
1837         struct dirent *drd;
1838         struct stats_pwr_usb *st_pwr_usb_j;
1839         int j = 0;
1840
1841         /* Open relevant /sys directory */
1842         if ((dir = opendir(SYSFS_USBDEV)) == NULL)
1843                 return;
1844
1845         /* Get current file entry */
1846         while ((drd = readdir(dir)) != NULL) {
1847
1848                 if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
1849                         if (j < nbr) {
1850                                 /* Read current USB device data */
1851                                 st_pwr_usb_j = st_pwr_usb + j;
1852                                 read_usb_stats(st_pwr_usb_j, drd->d_name);
1853                                 j++;
1854                         }
1855                         else
1856                                 break;
1857                 }
1858         }
1859
1860         /* Close directory */
1861         closedir(dir);
1862 }
1863
1864 /*
1865  ***************************************************************************
1866  * Read machine uptime, independently of the number of processors.
1867  *
1868  * OUT:
1869  * @uptime      Uptime value in jiffies.
1870  ***************************************************************************
1871  */
1872 void read_uptime(unsigned long long *uptime)
1873 {
1874         FILE *fp;
1875         char line[128];
1876         unsigned long up_sec, up_cent;
1877
1878         if ((fp = fopen(UPTIME, "r")) == NULL)
1879                 return;
1880
1881         if (fgets(line, 128, fp) == NULL) {
1882                 fclose(fp);
1883                 return;
1884         }
1885
1886         sscanf(line, "%lu.%lu", &up_sec, &up_cent);
1887         *uptime = (unsigned long long) up_sec * HZ +
1888                   (unsigned long long) up_cent * HZ / 100;
1889
1890         fclose(fp);
1891
1892 }
1893
1894 /*
1895  ***************************************************************************
1896  * Count number of interrupts that are in /proc/stat file.
1897  *
1898  * RETURNS:
1899  * Number of interrupts, including total number of interrupts.
1900  ***************************************************************************
1901  */
1902 int get_irq_nr(void)
1903 {
1904         FILE *fp;
1905         char line[8192];
1906         int in = 0;
1907         int pos = 4;
1908
1909         if ((fp = fopen(STAT, "r")) == NULL)
1910                 return 0;
1911
1912         while (fgets(line, 8192, fp) != NULL) {
1913
1914                 if (!strncmp(line, "intr ", 5)) {
1915
1916                         while (pos < strlen(line)) {
1917                                 in++;
1918                                 pos += strcspn(line + pos + 1, " ") + 1;
1919                         }
1920                 }
1921         }
1922
1923         fclose(fp);
1924
1925         return in;
1926 }
1927
1928 /*
1929  ***************************************************************************
1930  * Find number of serial lines that support tx/rx accounting
1931  * in /proc/tty/driver/serial file.
1932  *
1933  * RETURNS:
1934  * Number of serial lines supporting tx/rx accouting.
1935  ***************************************************************************
1936  */
1937 int get_serial_nr(void)
1938 {
1939         FILE *fp;
1940         char line[256];
1941         int sl = 0;
1942
1943         if ((fp = fopen(SERIAL, "r")) == NULL)
1944                 return 0;       /* No SERIAL file */
1945
1946         while (fgets(line, 256, fp) != NULL) {
1947                 /*
1948                  * tx/rx statistics are always present,
1949                  * except when serial line is unknown.
1950                  */
1951                 if (strstr(line, "tx:") != NULL) {
1952                         sl++;
1953                 }
1954         }
1955
1956         fclose(fp);
1957
1958         return sl;
1959 }
1960
1961 /*
1962  ***************************************************************************
1963  * Find number of interfaces (network devices) that are in /proc/net/dev
1964  * file.
1965  *
1966  * RETURNS:
1967  * Number of network interfaces.
1968  ***************************************************************************
1969  */
1970 int get_iface_nr(void)
1971 {
1972         FILE *fp;
1973         char line[128];
1974         int iface = 0;
1975
1976         if ((fp = fopen(NET_DEV, "r")) == NULL)
1977                 return 0;       /* No network device file */
1978
1979         while (fgets(line, 128, fp) != NULL) {
1980                 if (strchr(line, ':')) {
1981                         iface++;
1982                 }
1983         }
1984
1985         fclose(fp);
1986
1987         return iface;
1988 }
1989
1990 /*
1991  ***************************************************************************
1992  * Find number of devices and partitions available in /proc/diskstats.
1993  *
1994  * IN:
1995  * @count_part          Set to TRUE if devices _and_ partitions are to be
1996  *                      counted.
1997  * @only_used_dev       When counting devices, set to TRUE if only devices
1998  *                      with non zero stats must be counted.
1999  *
2000  * RETURNS:
2001  * Number of devices (and partitions).
2002  ***************************************************************************
2003  */
2004 int get_diskstats_dev_nr(int count_part, int only_used_dev)
2005 {
2006         FILE *fp;
2007         char line[256];
2008         char dev_name[MAX_NAME_LEN];
2009         int dev = 0, i;
2010         unsigned long rd_ios, wr_ios;
2011
2012         if ((fp = fopen(DISKSTATS, "r")) == NULL)
2013                 /* File non-existent */
2014                 return 0;
2015
2016         /*
2017          * Counting devices and partitions is simply a matter of counting
2018          * the number of lines...
2019          */
2020         while (fgets(line, 256, fp) != NULL) {
2021                 if (!count_part) {
2022                         i = sscanf(line, "%*d %*d %s %lu %*u %*u %*u %lu",
2023                                    dev_name, &rd_ios, &wr_ios);
2024                         if ((i == 2) || !is_device(dev_name, ACCEPT_VIRTUAL_DEVICES))
2025                                 /* It was a partition and not a device */
2026                                 continue;
2027                         if (only_used_dev && !rd_ios && !wr_ios)
2028                                 /* Unused device */
2029                                 continue;
2030                 }
2031                 dev++;
2032         }
2033
2034         fclose(fp);
2035
2036         return dev;
2037 }
2038
2039 /*
2040  ***************************************************************************
2041  * Get number of devices in /proc/diskstats.
2042  *
2043  * IN:
2044  * @f   Non zero (true) if disks *and* partitions should be counted, and
2045  *      zero (false) if only disks must be counted.
2046  *
2047  * RETURNS:
2048  * Number of devices.
2049  ***************************************************************************
2050  */
2051 int get_disk_nr(unsigned int f)
2052 {
2053         int disk_nr;
2054
2055         /*
2056          * Partitions are taken into account by sar -d only with
2057          * kernels 2.6.25 and later.
2058          */
2059         disk_nr = get_diskstats_dev_nr(f, CNT_USED_DEV);
2060
2061         return disk_nr;
2062 }
2063
2064 /*
2065  ***************************************************************************
2066  * Count number of processors in /sys.
2067  *
2068  * RETURNS:
2069  * Number of processors (online and offline).
2070  * A value of 0 means that /sys was not mounted.
2071  * A value of N (!=0) means N processor(s) (cpu0 .. cpu(N-1)).
2072  ***************************************************************************
2073  */
2074 int get_sys_cpu_nr(void)
2075 {
2076         DIR *dir;
2077         struct dirent *drd;
2078         struct stat buf;
2079         char line[MAX_PF_NAME];
2080         int proc_nr = 0;
2081
2082         /* Open relevant /sys directory */
2083         if ((dir = opendir(SYSFS_DEVCPU)) == NULL)
2084                 return 0;
2085
2086         /* Get current file entry */
2087         while ((drd = readdir(dir)) != NULL) {
2088
2089                 if (!strncmp(drd->d_name, "cpu", 3) && isdigit(drd->d_name[3])) {
2090                         snprintf(line, MAX_PF_NAME, "%s/%s", SYSFS_DEVCPU, drd->d_name);
2091                         line[MAX_PF_NAME - 1] = '\0';
2092                         if (stat(line, &buf) < 0)
2093                                 continue;
2094                         if (S_ISDIR(buf.st_mode)) {
2095                                 proc_nr++;
2096                         }
2097                 }
2098         }
2099
2100         /* Close directory */
2101         closedir(dir);
2102
2103         return proc_nr;
2104 }
2105
2106 /*
2107  ***************************************************************************
2108  * Count number of processors in /proc/stat.
2109  *
2110  * RETURNS:
2111  * Number of processors. The returned value is greater than or equal to the
2112  * number of online processors.
2113  * A value of 0 means one processor and non SMP kernel.
2114  * A value of N (!=0) means N processor(s) (0 .. N-1) with SMP kernel.
2115  ***************************************************************************
2116  */
2117 int get_proc_cpu_nr(void)
2118 {
2119         FILE *fp;
2120         char line[16];
2121         int num_proc, proc_nr = -1;
2122
2123         if ((fp = fopen(STAT, "r")) == NULL) {
2124                 fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
2125                 exit(1);
2126         }
2127
2128         while (fgets(line, 16, fp) != NULL) {
2129
2130                 if (strncmp(line, "cpu ", 4) && !strncmp(line, "cpu", 3)) {
2131                         sscanf(line + 3, "%d", &num_proc);
2132                         if (num_proc > proc_nr) {
2133                                 proc_nr = num_proc;
2134                         }
2135                 }
2136         }
2137
2138         fclose(fp);
2139
2140         return (proc_nr + 1);
2141 }
2142
2143 /*
2144  ***************************************************************************
2145  * Count the number of processors on the machine.
2146  * Try to use /sys for that, or /proc/stat if /sys doesn't exist.
2147  *
2148  * IN:
2149  * @max_nr_cpus Maximum number of proc that sysstat can handle.
2150  *
2151  * RETURNS:
2152  * Number of processors.
2153  * 0: one proc and non SMP kernel.
2154  * 1: one proc and SMP kernel (NB: On SMP machines where all the CPUs but
2155  *    one have been disabled, we get the total number of proc since we use
2156  *    /sys to count them).
2157  * 2: two proc...
2158  ***************************************************************************
2159  */
2160 int get_cpu_nr(unsigned int max_nr_cpus)
2161 {
2162         int cpu_nr;
2163
2164         if ((cpu_nr = get_sys_cpu_nr()) == 0) {
2165                 /* /sys may be not mounted. Use /proc/stat instead */
2166                 cpu_nr = get_proc_cpu_nr();
2167         }
2168
2169         if (cpu_nr > max_nr_cpus) {
2170                 fprintf(stderr, _("Cannot handle so many processors!\n"));
2171                 exit(1);
2172         }
2173
2174         return cpu_nr;
2175 }
2176
2177 /*
2178  ***************************************************************************
2179  * Find number of interrupts available per processor (use
2180  * /proc/interrupts file or /proc/softirqs).
2181  *
2182  * IN:
2183  * @file                /proc file to read (interrupts or softirqs).
2184  * @max_nr_irqcpu       Maximum number of interrupts per processor that
2185  *                      sadc can handle.
2186  * @cpu_nr              Number of processors.
2187  *
2188  * RETURNS:
2189  * Number of interrupts per processor + a pre-allocation constant.
2190  ***************************************************************************
2191  */
2192 int get_irqcpu_nr(char *file, int max_nr_irqcpu, int cpu_nr)
2193 {
2194         FILE *fp;
2195         char *line = NULL;
2196         unsigned int irq = 0;
2197         int p;
2198
2199         if ((fp = fopen(file, "r")) == NULL)
2200                 return 0;       /* No interrupts file */
2201
2202         SREALLOC(line, char, INTERRUPTS_LINE + 11 * cpu_nr);
2203
2204         while ((fgets(line, INTERRUPTS_LINE + 11 * cpu_nr , fp) != NULL) &&
2205                (irq < max_nr_irqcpu)) {
2206                 p = strcspn(line, ":");
2207                 if ((p > 0) && (p < 16)) {
2208                         irq++;
2209                 }
2210         }
2211
2212         fclose(fp);
2213
2214         if (line) {
2215                 free(line);
2216         }
2217
2218         return irq;
2219 }
2220
2221 /*
2222  ***************************************************************************
2223  * Count number of possible frequencies for CPU#0.
2224  *
2225  * RETURNS:
2226  * Number of frequencies.
2227  ***************************************************************************
2228  */
2229 int get_freq_nr(void)
2230 {
2231         FILE *fp;
2232         char filename[MAX_PF_NAME];
2233         char line[128];
2234         int freq = 0;
2235
2236         snprintf(filename, MAX_PF_NAME, "%s/cpu0/%s",
2237                  SYSFS_DEVCPU, SYSFS_TIME_IN_STATE);
2238         if ((fp = fopen(filename, "r")) == NULL)
2239                 return 0;       /* No time_in_state file for CPU#0 */
2240
2241         while (fgets(line, 128, fp) != NULL) {
2242                 freq++;
2243         }
2244
2245         fclose(fp);
2246
2247         return freq;
2248 }
2249
2250 /*
2251  ***************************************************************************
2252  * Count number of USB devices in /sys/bus/usb/devices.
2253  *
2254  * RETURNS:
2255  * Number of USB devices plugged into the system.
2256  * Don't count USB root hubs.
2257  * Return -1 if directory doesn't exist in sysfs.
2258  ***************************************************************************
2259  */
2260 int get_usb_nr(void)
2261 {
2262         DIR *dir;
2263         struct dirent *drd;
2264         int usb = 0;
2265
2266         /* Open relevant /sys directory */
2267         if ((dir = opendir(SYSFS_USBDEV)) == NULL)
2268                 return -1;
2269
2270         /* Get current file entry */
2271         while ((drd = readdir(dir)) != NULL) {
2272
2273                 if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
2274                         usb++;
2275                 }
2276         }
2277
2278         /* Close directory */
2279         closedir(dir);
2280
2281         return usb;
2282 }