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