"Fossies" - the Fresh Open Source Software Archive

Member "sysstat-12.1.5/rd_stats.c" (31 May 2019, 72636 Bytes) of package /linux/misc/sysstat-12.1.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rd_stats.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 12.1.4_vs_12.1.5.

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