2 * count.c: Count items for which statistics will be collected.
3 * (C) 1999-2013 by Sebastien GODARD (sysstat <at> orange.fr)
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. *
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 *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19 ***************************************************************************
28 #include <sys/types.h>
39 #define _(string) gettext(string)
41 #define _(string) (string)
46 ***************************************************************************
47 * Count number of interrupts that are in /proc/stat file.
50 * Number of interrupts, including total number of interrupts.
51 ***************************************************************************
60 if ((fp = fopen(STAT, "r")) == NULL)
63 while (fgets(line, 8192, fp) != NULL) {
65 if (!strncmp(line, "intr ", 5)) {
67 while (pos < strlen(line)) {
69 pos += strcspn(line + pos + 1, " ") + 1;
80 ***************************************************************************
81 * Find number of serial lines that support tx/rx accounting
82 * in /proc/tty/driver/serial file.
85 * Number of serial lines supporting tx/rx accouting.
86 ***************************************************************************
88 int get_serial_nr(void)
94 if ((fp = fopen(SERIAL, "r")) == NULL)
95 return 0; /* No SERIAL file */
97 while (fgets(line, 256, fp) != NULL) {
99 * tx/rx statistics are always present,
100 * except when serial line is unknown.
102 if (strstr(line, "tx:") != NULL) {
113 ***************************************************************************
114 * Find number of interfaces (network devices) that are in /proc/net/dev
118 * Number of network interfaces.
119 ***************************************************************************
121 int get_iface_nr(void)
127 if ((fp = fopen(NET_DEV, "r")) == NULL)
128 return 0; /* No network device file */
130 while (fgets(line, 128, fp) != NULL) {
131 if (strchr(line, ':')) {
142 ***************************************************************************
143 * Find number of devices and partitions available in /proc/diskstats.
146 * @count_part Set to TRUE if devices _and_ partitions are to be
148 * @only_used_dev When counting devices, set to TRUE if only devices
149 * with non zero stats must be counted.
152 * Number of devices (and partitions).
153 ***************************************************************************
155 int get_diskstats_dev_nr(int count_part, int only_used_dev)
159 char dev_name[MAX_NAME_LEN];
161 unsigned long rd_ios, wr_ios;
163 if ((fp = fopen(DISKSTATS, "r")) == NULL)
164 /* File non-existent */
168 * Counting devices and partitions is simply a matter of counting
169 * the number of lines...
171 while (fgets(line, 256, fp) != NULL) {
173 i = sscanf(line, "%*d %*d %s %lu %*u %*u %*u %lu",
174 dev_name, &rd_ios, &wr_ios);
175 if ((i == 2) || !is_device(dev_name, ACCEPT_VIRTUAL_DEVICES))
176 /* It was a partition and not a device */
178 if (only_used_dev && !rd_ios && !wr_ios)
191 ***************************************************************************
192 * Get number of devices in /proc/diskstats.
195 * @f Non zero (true) if disks *and* partitions should be counted, and
196 * zero (false) if only disks must be counted.
200 ***************************************************************************
202 int get_disk_nr(unsigned int f)
207 * Partitions are taken into account by sar -d only with
208 * kernels 2.6.25 and later.
210 disk_nr = get_diskstats_dev_nr(f, CNT_USED_DEV);
216 ***************************************************************************
217 * Count number of processors in /sys.
220 * Number of processors (online and offline).
221 * A value of 0 means that /sys was not mounted.
222 * A value of N (!=0) means N processor(s) (cpu0 .. cpu(N-1)).
223 ***************************************************************************
225 int get_sys_cpu_nr(void)
230 char line[MAX_PF_NAME];
233 /* Open relevant /sys directory */
234 if ((dir = opendir(SYSFS_DEVCPU)) == NULL)
237 /* Get current file entry */
238 while ((drd = readdir(dir)) != NULL) {
240 if (!strncmp(drd->d_name, "cpu", 3) && isdigit(drd->d_name[3])) {
241 snprintf(line, MAX_PF_NAME, "%s/%s", SYSFS_DEVCPU, drd->d_name);
242 line[MAX_PF_NAME - 1] = '\0';
243 if (stat(line, &buf) < 0)
245 if (S_ISDIR(buf.st_mode)) {
251 /* Close directory */
258 ***************************************************************************
259 * Count number of processors in /proc/stat.
262 * Number of processors. The returned value is greater than or equal to the
263 * number of online processors.
264 * A value of 0 means one processor and non SMP kernel.
265 * A value of N (!=0) means N processor(s) (0 .. N-1) with SMP kernel.
266 ***************************************************************************
268 int get_proc_cpu_nr(void)
272 int num_proc, proc_nr = -1;
274 if ((fp = fopen(STAT, "r")) == NULL) {
275 fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
279 while (fgets(line, 16, fp) != NULL) {
281 if (strncmp(line, "cpu ", 4) && !strncmp(line, "cpu", 3)) {
282 sscanf(line + 3, "%d", &num_proc);
283 if (num_proc > proc_nr) {
291 return (proc_nr + 1);
295 ***************************************************************************
296 * Count the number of processors on the machine.
297 * Try to use /sys for that, or /proc/stat if /sys doesn't exist.
300 * @max_nr_cpus Maximum number of proc that sysstat can handle.
303 * Number of processors.
304 * 0: one proc and non SMP kernel.
305 * 1: one proc and SMP kernel (NB: On SMP machines where all the CPUs but
306 * one have been disabled, we get the total number of proc since we use
307 * /sys to count them).
309 ***************************************************************************
311 int get_cpu_nr(unsigned int max_nr_cpus)
315 if ((cpu_nr = get_sys_cpu_nr()) == 0) {
316 /* /sys may be not mounted. Use /proc/stat instead */
317 cpu_nr = get_proc_cpu_nr();
320 if (cpu_nr > max_nr_cpus) {
321 fprintf(stderr, _("Cannot handle so many processors!\n"));
329 ***************************************************************************
330 * Find number of interrupts available per processor (use
331 * /proc/interrupts file or /proc/softirqs).
334 * @file /proc file to read (interrupts or softirqs).
335 * @max_nr_irqcpu Maximum number of interrupts per processor that
337 * @cpu_nr Number of processors.
340 * Number of interrupts per processor + a pre-allocation constant.
341 ***************************************************************************
343 int get_irqcpu_nr(char *file, int max_nr_irqcpu, int cpu_nr)
347 unsigned int irq = 0;
350 if ((fp = fopen(file, "r")) == NULL)
351 return 0; /* No interrupts file */
353 SREALLOC(line, char, INTERRUPTS_LINE + 11 * cpu_nr);
355 while ((fgets(line, INTERRUPTS_LINE + 11 * cpu_nr , fp) != NULL) &&
356 (irq < max_nr_irqcpu)) {
357 p = strcspn(line, ":");
358 if ((p > 0) && (p < 16)) {
371 ***************************************************************************
372 * Count number of possible frequencies for CPU#0.
375 * Number of frequencies.
376 ***************************************************************************
378 int get_freq_nr(void)
381 char filename[MAX_PF_NAME];
385 snprintf(filename, MAX_PF_NAME, "%s/cpu0/%s",
386 SYSFS_DEVCPU, SYSFS_TIME_IN_STATE);
387 if ((fp = fopen(filename, "r")) == NULL)
388 return 0; /* No time_in_state file for CPU#0 */
390 while (fgets(line, 128, fp) != NULL) {
400 ***************************************************************************
401 * Count number of USB devices in /sys/bus/usb/devices.
404 * Number of USB devices plugged into the system.
405 * Don't count USB root hubs.
406 * Return -1 if directory doesn't exist in sysfs.
407 ***************************************************************************
415 /* Open relevant /sys directory */
416 if ((dir = opendir(SYSFS_USBDEV)) == NULL)
419 /* Get current file entry */
420 while ((drd = readdir(dir)) != NULL) {
422 if (isdigit(drd->d_name[0]) && !strchr(drd->d_name, ':')) {
427 /* Close directory */
434 ***************************************************************************
435 * Find number of filesystems in /etc/mtab. Pseudo-filesystems are ignored.
438 * Number of filesystems.
439 ***************************************************************************
441 int get_filesystem_nr(void)
444 char line[256], fs_name[MAX_FS_LEN], mountp[128];
448 if ((fp = fopen(MTAB, "r")) == NULL)
449 /* File non-existent */
452 /* Get current filesystem */
453 while (fgets(line, 256, fp) != NULL) {
454 if (line[0] == '/') {
456 /* Read filesystem name and mount point */
457 sscanf(line, "%71s %127s", fs_name, mountp);
459 /* Replace octal codes */
462 /* Check that total size is not null */
463 if (statfs(mountp, &buf) < 0)