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