]> granicus.if.org Git - sysstat/blob - rd_stats.c
sysstat 11.1.4
[sysstat] / rd_stats.c
1 /*
2  * rd_stats.c: Read system statistics
3  * (C) 1999-2015 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/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 null.
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 error 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         int sw = FALSE;
1235
1236         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1237                 return;
1238
1239         while (fgets(line, sizeof(line), fp) != NULL) {
1240
1241                 if (!strncmp(line, "Icmp:", 5)) {
1242                         if (sw) {
1243                                 sscanf(line + 5, "%lu %*u %*u %*u %*u %*u %*u "
1244                                        "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
1245                                        "%*u %*u %lu %lu %lu %lu %lu %lu",
1246                                        &st_net_icmp->InMsgs,
1247                                        &st_net_icmp->InEchos,
1248                                        &st_net_icmp->InEchoReps,
1249                                        &st_net_icmp->InTimestamps,
1250                                        &st_net_icmp->InTimestampReps,
1251                                        &st_net_icmp->InAddrMasks,
1252                                        &st_net_icmp->InAddrMaskReps,
1253                                        &st_net_icmp->OutMsgs,
1254                                        &st_net_icmp->OutEchos,
1255                                        &st_net_icmp->OutEchoReps,
1256                                        &st_net_icmp->OutTimestamps,
1257                                        &st_net_icmp->OutTimestampReps,
1258                                        &st_net_icmp->OutAddrMasks,
1259                                        &st_net_icmp->OutAddrMaskReps);
1260
1261                                 break;
1262                         }
1263                         else {
1264                                 sw = TRUE;
1265                         }
1266                 }
1267         }
1268
1269         fclose(fp);
1270 }
1271
1272 /*
1273  ***************************************************************************
1274  * Read ICMP network error statistics from /proc/net/snmp.
1275  *
1276  * IN:
1277  * @st_net_eicmp        Structure where stats will be saved.
1278  *
1279  * OUT:
1280  * @st_net_eicmp        Structure with statistics.
1281  ***************************************************************************
1282  */
1283 void read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
1284 {
1285         FILE *fp;
1286         char line[1024];
1287         int sw = FALSE;
1288
1289         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1290                 return;
1291
1292         while (fgets(line, sizeof(line), fp) != NULL) {
1293
1294                 if (!strncmp(line, "Icmp:", 5)) {
1295                         if (sw) {
1296                                 sscanf(line + 5, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
1297                                        "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu",
1298                                        &st_net_eicmp->InErrors,
1299                                        &st_net_eicmp->InDestUnreachs,
1300                                        &st_net_eicmp->InTimeExcds,
1301                                        &st_net_eicmp->InParmProbs,
1302                                        &st_net_eicmp->InSrcQuenchs,
1303                                        &st_net_eicmp->InRedirects,
1304                                        &st_net_eicmp->OutErrors,
1305                                        &st_net_eicmp->OutDestUnreachs,
1306                                        &st_net_eicmp->OutTimeExcds,
1307                                        &st_net_eicmp->OutParmProbs,
1308                                        &st_net_eicmp->OutSrcQuenchs,
1309                                        &st_net_eicmp->OutRedirects);
1310
1311                                 break;
1312                         }
1313                         else {
1314                                 sw = TRUE;
1315                         }
1316                 }
1317         }
1318
1319         fclose(fp);
1320 }
1321
1322 /*
1323  ***************************************************************************
1324  * Read TCP network traffic statistics from /proc/net/snmp.
1325  *
1326  * IN:
1327  * @st_net_tcp  Structure where stats will be saved.
1328  *
1329  * OUT:
1330  * @st_net_tcp  Structure with statistics.
1331  ***************************************************************************
1332  */
1333 void read_net_tcp(struct stats_net_tcp *st_net_tcp)
1334 {
1335         FILE *fp;
1336         char line[1024];
1337         int sw = FALSE;
1338
1339         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1340                 return;
1341
1342         while (fgets(line, sizeof(line), fp) != NULL) {
1343
1344                 if (!strncmp(line, "Tcp:", 4)) {
1345                         if (sw) {
1346                                 sscanf(line + 4, "%*u %*u %*u %*d %lu %lu "
1347                                        "%*u %*u %*u %lu %lu",
1348                                        &st_net_tcp->ActiveOpens,
1349                                        &st_net_tcp->PassiveOpens,
1350                                        &st_net_tcp->InSegs,
1351                                        &st_net_tcp->OutSegs);
1352
1353                                 break;
1354                         }
1355                         else {
1356                                 sw = TRUE;
1357                         }
1358                 }
1359         }
1360
1361         fclose(fp);
1362 }
1363
1364 /*
1365  ***************************************************************************
1366  * Read TCP network error statistics from /proc/net/snmp.
1367  *
1368  * IN:
1369  * @st_net_etcp Structure where stats will be saved.
1370  *
1371  * OUT:
1372  * @st_net_etcp Structure with statistics.
1373  ***************************************************************************
1374  */
1375 void read_net_etcp(struct stats_net_etcp *st_net_etcp)
1376 {
1377         FILE *fp;
1378         char line[1024];
1379         int sw = FALSE;
1380
1381         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1382                 return;
1383
1384         while (fgets(line, sizeof(line), fp) != NULL) {
1385
1386                 if (!strncmp(line, "Tcp:", 4)) {
1387                         if (sw) {
1388                                 sscanf(line + 4, "%*u %*u %*u %*d %*u %*u "
1389                                        "%lu %lu %*u %*u %*u %lu %lu %lu",
1390                                        &st_net_etcp->AttemptFails,
1391                                        &st_net_etcp->EstabResets,
1392                                        &st_net_etcp->RetransSegs,
1393                                        &st_net_etcp->InErrs,
1394                                        &st_net_etcp->OutRsts);
1395
1396                                 break;
1397                         }
1398                         else {
1399                                 sw = TRUE;
1400                         }
1401                 }
1402         }
1403
1404         fclose(fp);
1405 }
1406
1407 /*
1408  ***************************************************************************
1409  * Read UDP network traffic statistics from /proc/net/snmp.
1410  *
1411  * IN:
1412  * @st_net_udp  Structure where stats will be saved.
1413  *
1414  * OUT:
1415  * @st_net_udp  Structure with statistics.
1416  ***************************************************************************
1417  */
1418 void read_net_udp(struct stats_net_udp *st_net_udp)
1419 {
1420         FILE *fp;
1421         char line[1024];
1422         int sw = FALSE;
1423
1424         if ((fp = fopen(NET_SNMP, "r")) == NULL)
1425                 return;
1426
1427         while (fgets(line, sizeof(line), fp) != NULL) {
1428
1429                 if (!strncmp(line, "Udp:", 4)) {
1430                         if (sw) {
1431                                 sscanf(line + 4, "%lu %lu %lu %lu",
1432                                        &st_net_udp->InDatagrams,
1433                                        &st_net_udp->NoPorts,
1434                                        &st_net_udp->InErrors,
1435                                        &st_net_udp->OutDatagrams);
1436
1437                                 break;
1438                         }
1439                         else {
1440                                 sw = TRUE;
1441                         }
1442                 }
1443         }
1444
1445         fclose(fp);
1446 }
1447
1448 /*
1449  ***************************************************************************
1450  * Read IPv6 network sockets statistics from /proc/net/sockstat6.
1451  *
1452  * IN:
1453  * @st_net_sock6        Structure where stats will be saved.
1454  *
1455  * OUT:
1456  * @st_net_sock6        Structure with statistics.
1457  ***************************************************************************
1458  */
1459 void read_net_sock6(struct stats_net_sock6 *st_net_sock6)
1460 {
1461         FILE *fp;
1462         char line[96];
1463
1464         if ((fp = fopen(NET_SOCKSTAT6, "r")) == NULL)
1465                 return;
1466
1467         while (fgets(line, sizeof(line), fp) != NULL) {
1468
1469                 if (!strncmp(line, "TCP6:", 5)) {
1470                         /* TCPv6 sockets */
1471                         sscanf(line + 12, "%u", &st_net_sock6->tcp6_inuse);
1472                 }
1473                 else if (!strncmp(line, "UDP6:", 5)) {
1474                         /* UDPv6 sockets */
1475                         sscanf(line + 12, "%u", &st_net_sock6->udp6_inuse);
1476                 }
1477                 else if (!strncmp(line, "RAW6:", 5)) {
1478                         /* IPv6 RAW sockets */
1479                         sscanf(line + 12, "%u", &st_net_sock6->raw6_inuse);
1480                 }
1481                 else if (!strncmp(line, "FRAG6:", 6)) {
1482                         /* IPv6 FRAGments */
1483                         sscanf(line + 13, "%u", &st_net_sock6->frag6_inuse);
1484                 }
1485         }
1486
1487         fclose(fp);
1488 }
1489
1490 /*
1491  ***************************************************************************
1492  * Read IPv6 network traffic statistics from /proc/net/snmp6.
1493  *
1494  * IN:
1495  * @st_net_ip6  Structure where stats will be saved.
1496  *
1497  * OUT:
1498  * @st_net_ip6  Structure with statistics.
1499  ***************************************************************************
1500  */
1501 void read_net_ip6(struct stats_net_ip6 *st_net_ip6)
1502 {
1503         FILE *fp;
1504         char line[128];
1505
1506         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1507                 return;
1508
1509         while (fgets(line, sizeof(line), fp) != NULL) {
1510
1511                 if (!strncmp(line, "Ip6InReceives ", 14)) {
1512                         sscanf(line + 14, "%llu", &st_net_ip6->InReceives6);
1513                 }
1514                 else if (!strncmp(line, "Ip6OutForwDatagrams ", 20)) {
1515                         sscanf(line + 20, "%llu", &st_net_ip6->OutForwDatagrams6);
1516                 }
1517                 else if (!strncmp(line, "Ip6InDelivers ", 14)) {
1518                         sscanf(line + 14, "%llu", &st_net_ip6->InDelivers6);
1519                 }
1520                 else if (!strncmp(line, "Ip6OutRequests ", 15)) {
1521                         sscanf(line + 15, "%llu", &st_net_ip6->OutRequests6);
1522                 }
1523                 else if (!strncmp(line, "Ip6ReasmReqds ", 14)) {
1524                         sscanf(line + 14, "%llu", &st_net_ip6->ReasmReqds6);
1525                 }
1526                 else if (!strncmp(line, "Ip6ReasmOKs ", 12)) {
1527                         sscanf(line + 12, "%llu", &st_net_ip6->ReasmOKs6);
1528                 }
1529                 else if (!strncmp(line, "Ip6InMcastPkts ", 15)) {
1530                         sscanf(line + 15, "%llu", &st_net_ip6->InMcastPkts6);
1531                 }
1532                 else if (!strncmp(line, "Ip6OutMcastPkts ", 16)) {
1533                         sscanf(line + 16, "%llu", &st_net_ip6->OutMcastPkts6);
1534                 }
1535                 else if (!strncmp(line, "Ip6FragOKs ", 11)) {
1536                         sscanf(line + 11, "%llu", &st_net_ip6->FragOKs6);
1537                 }
1538                 else if (!strncmp(line, "Ip6FragCreates ", 15)) {
1539                         sscanf(line + 15, "%llu", &st_net_ip6->FragCreates6);
1540                 }
1541         }
1542
1543         fclose(fp);
1544 }
1545
1546 /*
1547  ***************************************************************************
1548  * Read IPv6 network error statistics from /proc/net/snmp6.
1549  *
1550  * IN:
1551  * @st_net_eip6 Structure where stats will be saved.
1552  *
1553  * OUT:
1554  * @st_net_eip6 Structure with statistics.
1555  ***************************************************************************
1556  */
1557 void read_net_eip6(struct stats_net_eip6 *st_net_eip6)
1558 {
1559         FILE *fp;
1560         char line[128];
1561
1562         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1563                 return;
1564
1565         while (fgets(line, sizeof(line), fp) != NULL) {
1566
1567                 if (!strncmp(line, "Ip6InHdrErrors ", 15)) {
1568                         sscanf(line + 15, "%llu", &st_net_eip6->InHdrErrors6);
1569                 }
1570                 else if (!strncmp(line, "Ip6InAddrErrors ", 16)) {
1571                         sscanf(line + 16, "%llu", &st_net_eip6->InAddrErrors6);
1572                 }
1573                 else if (!strncmp(line, "Ip6InUnknownProtos ", 19)) {
1574                         sscanf(line + 19, "%llu", &st_net_eip6->InUnknownProtos6);
1575                 }
1576                 else if (!strncmp(line, "Ip6InTooBigErrors ", 18)) {
1577                         sscanf(line + 18, "%llu", &st_net_eip6->InTooBigErrors6);
1578                 }
1579                 else if (!strncmp(line, "Ip6InDiscards ", 14)) {
1580                         sscanf(line + 14, "%llu", &st_net_eip6->InDiscards6);
1581                 }
1582                 else if (!strncmp(line, "Ip6OutDiscards ", 15)) {
1583                         sscanf(line + 15, "%llu", &st_net_eip6->OutDiscards6);
1584                 }
1585                 else if (!strncmp(line, "Ip6InNoRoutes ", 14)) {
1586                         sscanf(line + 14, "%llu", &st_net_eip6->InNoRoutes6);
1587                 }
1588                 else if (!strncmp(line, "Ip6OutNoRoutes ", 15)) {
1589                         sscanf(line + 15, "%llu", &st_net_eip6->OutNoRoutes6);
1590                 }
1591                 else if (!strncmp(line, "Ip6ReasmFails ", 14)) {
1592                         sscanf(line + 14, "%llu", &st_net_eip6->ReasmFails6);
1593                 }
1594                 else if (!strncmp(line, "Ip6FragFails ", 13)) {
1595                         sscanf(line + 13, "%llu", &st_net_eip6->FragFails6);
1596                 }
1597                 else if (!strncmp(line, "Ip6InTruncatedPkts ", 19)) {
1598                         sscanf(line + 19, "%llu", &st_net_eip6->InTruncatedPkts6);
1599                 }
1600         }
1601
1602         fclose(fp);
1603 }
1604
1605 /*
1606  ***************************************************************************
1607  * Read ICMPv6 network traffic statistics from /proc/net/snmp6.
1608  *
1609  * IN:
1610  * @st_net_icmp6        Structure where stats will be saved.
1611  *
1612  * OUT:
1613  * @st_net_icmp6        Structure with statistics.
1614  ***************************************************************************
1615  */
1616 void read_net_icmp6(struct stats_net_icmp6 *st_net_icmp6)
1617 {
1618         FILE *fp;
1619         char line[128];
1620
1621         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1622                 return;
1623
1624         while (fgets(line, sizeof(line), fp) != NULL) {
1625
1626                 if (!strncmp(line, "Icmp6InMsgs ", 12)) {
1627                         sscanf(line + 12, "%lu", &st_net_icmp6->InMsgs6);
1628                 }
1629                 else if (!strncmp(line, "Icmp6OutMsgs ", 13)) {
1630                         sscanf(line + 13, "%lu", &st_net_icmp6->OutMsgs6);
1631                 }
1632                 else if (!strncmp(line, "Icmp6InEchos ", 13)) {
1633                         sscanf(line + 13, "%lu", &st_net_icmp6->InEchos6);
1634                 }
1635                 else if (!strncmp(line, "Icmp6InEchoReplies ", 19)) {
1636                         sscanf(line + 19, "%lu", &st_net_icmp6->InEchoReplies6);
1637                 }
1638                 else if (!strncmp(line, "Icmp6OutEchoReplies ", 20)) {
1639                         sscanf(line + 20, "%lu", &st_net_icmp6->OutEchoReplies6);
1640                 }
1641                 else if (!strncmp(line, "Icmp6InGroupMembQueries ", 24)) {
1642                         sscanf(line + 24, "%lu", &st_net_icmp6->InGroupMembQueries6);
1643                 }
1644                 else if (!strncmp(line, "Icmp6InGroupMembResponses ", 26)) {
1645                         sscanf(line + 26, "%lu", &st_net_icmp6->InGroupMembResponses6);
1646                 }
1647                 else if (!strncmp(line, "Icmp6OutGroupMembResponses ", 27)) {
1648                         sscanf(line + 27, "%lu", &st_net_icmp6->OutGroupMembResponses6);
1649                 }
1650                 else if (!strncmp(line, "Icmp6InGroupMembReductions ", 27)) {
1651                         sscanf(line + 27, "%lu", &st_net_icmp6->InGroupMembReductions6);
1652                 }
1653                 else if (!strncmp(line, "Icmp6OutGroupMembReductions ", 28)) {
1654                         sscanf(line + 28, "%lu", &st_net_icmp6->OutGroupMembReductions6);
1655                 }
1656                 else if (!strncmp(line, "Icmp6InRouterSolicits ", 22)) {
1657                         sscanf(line + 22, "%lu", &st_net_icmp6->InRouterSolicits6);
1658                 }
1659                 else if (!strncmp(line, "Icmp6OutRouterSolicits ", 23)) {
1660                         sscanf(line + 23, "%lu", &st_net_icmp6->OutRouterSolicits6);
1661                 }
1662                 else if (!strncmp(line, "Icmp6InRouterAdvertisements ", 28)) {
1663                         sscanf(line + 28, "%lu", &st_net_icmp6->InRouterAdvertisements6);
1664                 }
1665                 else if (!strncmp(line, "Icmp6InNeighborSolicits ", 24)) {
1666                         sscanf(line + 24, "%lu", &st_net_icmp6->InNeighborSolicits6);
1667                 }
1668                 else if (!strncmp(line, "Icmp6OutNeighborSolicits ", 25)) {
1669                         sscanf(line + 25, "%lu", &st_net_icmp6->OutNeighborSolicits6);
1670                 }
1671                 else if (!strncmp(line, "Icmp6InNeighborAdvertisements ", 30)) {
1672                         sscanf(line + 30, "%lu", &st_net_icmp6->InNeighborAdvertisements6);
1673                 }
1674                 else if (!strncmp(line, "Icmp6OutNeighborAdvertisements ", 31)) {
1675                         sscanf(line + 31, "%lu", &st_net_icmp6->OutNeighborAdvertisements6);
1676                 }
1677         }
1678
1679         fclose(fp);
1680 }
1681
1682 /*
1683  ***************************************************************************
1684  * Read ICMPv6 network error statistics from /proc/net/snmp6.
1685  *
1686  * IN:
1687  * @st_net_eicmp6       Structure where stats will be saved.
1688  *
1689  * OUT:
1690  * @st_net_eicmp6       Structure with statistics.
1691  ***************************************************************************
1692  */
1693 void read_net_eicmp6(struct stats_net_eicmp6 *st_net_eicmp6)
1694 {
1695         FILE *fp;
1696         char line[128];
1697
1698         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1699                 return;
1700
1701         while (fgets(line, sizeof(line), fp) != NULL) {
1702
1703                 if (!strncmp(line, "Icmp6InErrors ", 14)) {
1704                         sscanf(line + 14, "%lu", &st_net_eicmp6->InErrors6);
1705                 }
1706                 else if (!strncmp(line, "Icmp6InDestUnreachs ", 20)) {
1707                         sscanf(line + 20, "%lu", &st_net_eicmp6->InDestUnreachs6);
1708                 }
1709                 else if (!strncmp(line, "Icmp6OutDestUnreachs ", 21)) {
1710                         sscanf(line + 21, "%lu", &st_net_eicmp6->OutDestUnreachs6);
1711                 }
1712                 else if (!strncmp(line, "Icmp6InTimeExcds ", 17)) {
1713                         sscanf(line + 17, "%lu", &st_net_eicmp6->InTimeExcds6);
1714                 }
1715                 else if (!strncmp(line, "Icmp6OutTimeExcds ", 18)) {
1716                         sscanf(line + 18, "%lu", &st_net_eicmp6->OutTimeExcds6);
1717                 }
1718                 else if (!strncmp(line, "Icmp6InParmProblems ", 20)) {
1719                         sscanf(line + 20, "%lu", &st_net_eicmp6->InParmProblems6);
1720                 }
1721                 else if (!strncmp(line, "Icmp6OutParmProblems ", 21)) {
1722                         sscanf(line + 21, "%lu", &st_net_eicmp6->OutParmProblems6);
1723                 }
1724                 else if (!strncmp(line, "Icmp6InRedirects ", 17)) {
1725                         sscanf(line + 17, "%lu", &st_net_eicmp6->InRedirects6);
1726                 }
1727                 else if (!strncmp(line, "Icmp6OutRedirects ", 18)) {
1728                         sscanf(line + 18, "%lu", &st_net_eicmp6->OutRedirects6);
1729                 }
1730                 else if (!strncmp(line, "Icmp6InPktTooBigs ", 18)) {
1731                         sscanf(line + 18, "%lu", &st_net_eicmp6->InPktTooBigs6);
1732                 }
1733                 else if (!strncmp(line, "Icmp6OutPktTooBigs ", 19)) {
1734                         sscanf(line + 19, "%lu", &st_net_eicmp6->OutPktTooBigs6);
1735                 }
1736         }
1737
1738         fclose(fp);
1739 }
1740
1741 /*
1742  ***************************************************************************
1743  * Read UDPv6 network traffic statistics from /proc/net/snmp6.
1744  *
1745  * IN:
1746  * @st_net_udp6 Structure where stats will be saved.
1747  *
1748  * OUT:
1749  * @st_net_udp6 Structure with statistics.
1750  ***************************************************************************
1751  */
1752 void read_net_udp6(struct stats_net_udp6 *st_net_udp6)
1753 {
1754         FILE *fp;
1755         char line[128];
1756
1757         if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1758                 return;
1759
1760         while (fgets(line, sizeof(line), fp) != NULL) {
1761
1762                 if (!strncmp(line, "Udp6InDatagrams ", 16)) {
1763                         sscanf(line + 16, "%lu", &st_net_udp6->InDatagrams6);
1764                 }
1765                 else if (!strncmp(line, "Udp6OutDatagrams ", 17)) {
1766                         sscanf(line + 17, "%lu", &st_net_udp6->OutDatagrams6);
1767                 }
1768                 else if (!strncmp(line, "Udp6NoPorts ", 12)) {
1769                         sscanf(line + 12, "%lu", &st_net_udp6->NoPorts6);
1770                 }
1771                 else if (!strncmp(line, "Udp6InErrors ", 13)) {
1772                         sscanf(line + 13, "%lu", &st_net_udp6->InErrors6);
1773                 }
1774         }
1775
1776         fclose(fp);
1777 }
1778
1779 /*
1780  ***************************************************************************
1781  * Read CPU frequency statistics.
1782  *
1783  * IN:
1784  * @st_pwr_cpufreq      Structure where stats will be saved.
1785  * @nbr                 Total number of CPU (including cpu "all").
1786  *
1787  * OUT:
1788  * @st_pwr_cpufreq      Structure with statistics.
1789  ***************************************************************************
1790  */
1791 void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
1792 {
1793         FILE *fp;
1794         struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
1795         char line[1024];
1796         int nr = 0;
1797         unsigned int proc_nb = 0, ifreq, dfreq;
1798
1799         if ((fp = fopen(CPUINFO, "r")) == NULL)
1800                 return;
1801
1802         st_pwr_cpufreq->cpufreq = 0;
1803
1804         while (fgets(line, sizeof(line), fp) != NULL) {
1805
1806                 if (!strncmp(line, "processor\t", 10)) {
1807                         sscanf(strchr(line, ':') + 1, "%u", &proc_nb);
1808                 }
1809
1810                 else if (!strncmp(line, "cpu MHz\t", 8)) {
1811                         sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
1812
1813                         if (proc_nb < (nbr - 1)) {
1814                                 /* Save current CPU frequency */
1815                                 st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
1816                                 st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
1817
1818                                 /* Also save it to compute an average CPU frequency */
1819                                 st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
1820                                 nr++;
1821                         }
1822                         else if (!proc_nb && (nbr == 1)) {
1823                                 /*
1824                                  * We are reading freq for "Processor 0" and we have a machine
1825                                  * with only one processor and not an SMP kernel, with /sys not mounted
1826                                  * (the nr of proc has been counted using /proc/stat and there was
1827                                  * only one line with global CPU stats here).
1828                                  * This is a very specific case, I must admit...
1829                                  */
1830                                 st_pwr_cpufreq->cpufreq = ifreq * 100 + dfreq / 10;
1831                         }
1832                 }
1833         }
1834
1835         fclose(fp);
1836
1837         if (nr) {
1838                 /* Compute average CPU frequency for this machine */
1839                 st_pwr_cpufreq->cpufreq /= nr;
1840         }
1841 }
1842
1843 /*
1844  ***************************************************************************
1845  * Read hugepages statistics from /proc/meminfo.
1846  *
1847  * IN:
1848  * @st_huge     Structure where stats will be saved.
1849  *
1850  * OUT:
1851  * @st_huge     Structure with statistics.
1852  ***************************************************************************
1853  */
1854 void read_meminfo_huge(struct stats_huge *st_huge)
1855 {
1856         FILE *fp;
1857         char line[128];
1858         unsigned long szhkb = 0;
1859
1860         if ((fp = fopen(MEMINFO, "r")) == NULL)
1861                 return;
1862
1863         while (fgets(line, sizeof(line), fp) != NULL) {
1864
1865                 if (!strncmp(line, "HugePages_Total:", 16)) {
1866                         /* Read the total number of huge pages */
1867                         sscanf(line + 16, "%lu", &st_huge->tlhkb);
1868                 }
1869                 else if (!strncmp(line, "HugePages_Free:", 15)) {
1870                         /* Read the number of free huge pages */
1871                         sscanf(line + 15, "%lu", &st_huge->frhkb);
1872                 }
1873                 else if (!strncmp(line, "Hugepagesize:", 13)) {
1874                         /* Read the default size of a huge page in kB */
1875                         sscanf(line + 13, "%lu", &szhkb);
1876                 }
1877         }
1878
1879         fclose(fp);
1880
1881         /* We want huge pages stats in kB and not expressed in a number of pages */
1882         st_huge->tlhkb *= szhkb;
1883         st_huge->frhkb *= szhkb;
1884 }
1885
1886 /*
1887  ***************************************************************************
1888  * Read CPU average frequencies statistics.
1889  *
1890  * IN:
1891  * @st_pwr_wghfreq      Structure where stats will be saved.
1892  * @cpu_nr              CPU number for which time_in_state date will be read.
1893  * @nbr                 Total number of states (frequencies).
1894  *
1895  * OUT:
1896  * @st_pwr_wghfreq      Structure with statistics.
1897  ***************************************************************************
1898  */
1899 void read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
1900 {
1901         FILE *fp;
1902         struct stats_pwr_wghfreq *st_pwr_wghfreq_j;
1903         char filename[MAX_PF_NAME];
1904         char line[128];
1905         int j = 0;
1906         unsigned long freq;
1907         unsigned long long time_in_state;
1908
1909         snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s",
1910                  SYSFS_DEVCPU, cpu_nr, SYSFS_TIME_IN_STATE);
1911         if ((fp = fopen(filename, "r")) == NULL)
1912                 return;
1913
1914         while (fgets(line, sizeof(line), fp) != NULL) {
1915
1916                 sscanf(line, "%lu %llu", &freq, &time_in_state);
1917
1918                 if (j < nbr) {
1919                         /* Save current frequency and time */
1920                         st_pwr_wghfreq_j = st_pwr_wghfreq + j;
1921                         st_pwr_wghfreq_j->freq = freq;
1922                         st_pwr_wghfreq_j->time_in_state = time_in_state;
1923                         j++;
1924                 }
1925         }
1926
1927         fclose(fp);
1928 }
1929
1930 /*
1931  ***************************************************************************
1932  * Read current USB device data.
1933  *
1934  * IN:
1935  * @st_pwr_usb          Structure where stats will be saved.
1936  * @usb_device          File name for current USB device.
1937  *
1938  * OUT:
1939  * @st_pwr_usb          Structure with statistics.
1940  ***************************************************************************
1941  */
1942 void read_usb_stats(struct stats_pwr_usb *st_pwr_usb, char *usb_device)
1943 {
1944         int l, rc;
1945         FILE *fp;
1946         char * rs;
1947         char filename[MAX_PF_NAME];
1948
1949         /* Get USB device bus number */
1950         sscanf(usb_device, "%u", &st_pwr_usb->bus_nr);
1951
1952         /* Read USB device vendor ID */
1953         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1954                  SYSFS_USBDEV, usb_device, SYSFS_IDVENDOR);
1955         if ((fp = fopen(filename, "r")) != NULL) {
1956                 rc = fscanf(fp, "%x",
1957                             &st_pwr_usb->vendor_id);
1958                 fclose(fp);
1959                 if (rc == 0) {
1960                         st_pwr_usb->vendor_id = 0;
1961                 }
1962         }
1963
1964         /* Read USB device product ID */
1965         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1966                  SYSFS_USBDEV, usb_device, SYSFS_IDPRODUCT);
1967         if ((fp = fopen(filename, "r")) != NULL) {
1968                 rc = fscanf(fp, "%x",
1969                             &st_pwr_usb->product_id);
1970                 fclose(fp);
1971                 if (rc == 0) {
1972                         st_pwr_usb->product_id = 0;
1973                 }
1974         }
1975
1976         /* Read USB device max power consumption */
1977         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1978                  SYSFS_USBDEV, usb_device, SYSFS_BMAXPOWER);
1979         if ((fp = fopen(filename, "r")) != NULL) {
1980                 rc = fscanf(fp, "%u",
1981                             &st_pwr_usb->bmaxpower);
1982                 fclose(fp);
1983                 if (rc == 0) {
1984                         st_pwr_usb->bmaxpower = 0;
1985                 }
1986         }
1987
1988         /* Read USB device manufacturer */
1989         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
1990                  SYSFS_USBDEV, usb_device, SYSFS_MANUFACTURER);
1991         if ((fp = fopen(filename, "r")) != NULL) {
1992                 rs = fgets(st_pwr_usb->manufacturer,
1993                            MAX_MANUF_LEN - 1, fp);
1994                 fclose(fp);
1995                 if ((rs != NULL) &&
1996                     (l = strlen(st_pwr_usb->manufacturer)) > 0) {
1997                         /* Remove trailing CR */
1998                         st_pwr_usb->manufacturer[l - 1] = '\0';
1999                 }
2000         }
2001
2002         /* Read USB device product */
2003         snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
2004                  SYSFS_USBDEV, usb_device, SYSFS_PRODUCT);
2005         if ((fp = fopen(filename, "r")) != NULL) {
2006                 rs = fgets(st_pwr_usb->product,
2007                            MAX_PROD_LEN - 1, fp);
2008                 fclose(fp);
2009                 if ((rs != NULL) &&
2010                     (l = strlen(st_pwr_usb->product)) > 0) {
2011                         /* Remove trailing CR */
2012                         st_pwr_usb->product[l - 1] = '\0';
2013                 }
2014         }
2015 }
2016
2017 /*
2018  ***************************************************************************
2019  * Read USB devices statistics.
2020  *
2021  * IN:
2022  * @st_pwr_usb          Structure where stats will be saved.
2023  * @nbr                 Total number of USB devices.
2024  *
2025  * OUT:
2026  * @st_pwr_usb          Structure with statistics.
2027  ***************************************************************************
2028  */
2029 void read_bus_usb_dev(struct stats_pwr_usb *st_pwr_usb, int nbr)
2030 {
2031         DIR *dir;
2032         struct dirent *drd;
2033         struct stats_pwr_usb *st_pwr_usb_j;
2034         int j = 0;
2035
2036         /* Open relevant /sys directory */
2037         if ((dir = opendir(SYSFS_USBDEV)) == NULL)
2038                 return;
2039
2040         /* Get current file entry */
2041         while ((drd = readdir(dir)) != NULL) {
2042
2043                 if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
2044                         if (j < nbr) {
2045                                 /* Read current USB device data */
2046                                 st_pwr_usb_j = st_pwr_usb + j;
2047                                 read_usb_stats(st_pwr_usb_j, drd->d_name);
2048                                 j++;
2049                         }
2050                         else
2051                                 break;
2052                 }
2053         }
2054
2055         /* Close directory */
2056         closedir(dir);
2057 }
2058
2059 /*
2060  ***************************************************************************
2061  * Read filesystems statistics.
2062  *
2063  * IN:
2064  * @st_filesystem       Structure where stats will be saved.
2065  * @nbr                 Total number of filesystems.
2066  *
2067  * OUT:
2068  * @st_filesystem       Structure with statistics.
2069  ***************************************************************************
2070  */
2071 void read_filesystem(struct stats_filesystem *st_filesystem, int nbr)
2072 {
2073         FILE *fp;
2074         char line[512], fs_name[MAX_FS_LEN], mountp[256];
2075         int fs = 0;
2076         struct stats_filesystem *st_filesystem_i;
2077         struct statvfs buf;
2078
2079         if ((fp = fopen(MTAB, "r")) == NULL)
2080                 return;
2081
2082         while ((fgets(line, sizeof(line), fp) != NULL) && (fs < nbr)) {
2083                 if (line[0] == '/') {
2084
2085                         /* Read current filesystem name */
2086                         sscanf(line, "%127s", fs_name);
2087                         /*
2088                          * And now read the corresponding mount point.
2089                          * Read fs name and mount point in two distinct operations.
2090                          * Indeed, if fs name length is greater than 127 chars,
2091                          * previous scanf() will read only the first 127 chars, and
2092                          * mount point name will be read using the remaining chars
2093                          * from the fs name. This will result in a bogus name
2094                          * and following statvfs() function will always fail.
2095                          */
2096                         sscanf(strchr(line, ' ') + 1, "%255s", mountp);
2097
2098                         /* Replace octal codes */
2099                         oct2chr(mountp);
2100
2101                         /*
2102                          * It's important to have read the whole mount point name
2103                          * for statvfs() to work properly (see above).
2104                          */
2105                         if ((statvfs(mountp, &buf) < 0) || (!buf.f_blocks))
2106                                 continue;
2107
2108                         st_filesystem_i = st_filesystem + fs++;
2109                         st_filesystem_i->f_blocks = buf.f_blocks * buf.f_frsize;
2110                         st_filesystem_i->f_bfree  = buf.f_bfree * buf.f_frsize;
2111                         st_filesystem_i->f_bavail = buf.f_bavail * buf.f_frsize;
2112                         st_filesystem_i->f_files  = buf.f_files;
2113                         st_filesystem_i->f_ffree  = buf.f_ffree;
2114                         strcpy(st_filesystem_i->fs_name, fs_name);
2115                         strncpy(st_filesystem_i->mountp, mountp, MAX_FS_LEN);
2116                         st_filesystem_i->mountp[MAX_FS_LEN - 1] = '\0';
2117                 }
2118         }
2119
2120         fclose(fp);
2121 }
2122
2123 /*------------------ END: FUNCTIONS USED BY SADC ONLY ---------------------*/
2124 #endif /* SOURCE_SADC */