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