update from main archive 960927
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / getsysstats.c
1 /* getsysstats - Determine various system internal values, Linux version.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB.  If
18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include <errno.h>
22 #include <mntent.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/sysinfo.h>
27
28
29 /* Determine the path to the /proc filesystem if available.  */
30 static char *
31 get_proc_path (char *buffer, size_t bufsize)
32 {
33   FILE *fp;
34   struct mntent mount_point;
35   struct mntent *entry;
36   char *result = NULL;
37
38   /* First find the mount point of the proc filesystem.  */
39   fp = __setmntent (_PATH_MNTTAB, "r");
40   if (fp != NULL)
41     {
42       while ((entry = __getmntent_r (fp, &mount_point, buffer, bufsize))
43              != NULL)
44         if (strcmp (mount_point.mnt_type, "proc") == 0)
45           {
46             result = mount_point.mnt_dir;
47             break;
48           }
49       __endmntent (fp);
50     }
51
52   return result;
53 }
54
55
56 /* How we can determine the number of available processors depends on
57    the configuration.  There is currently (as of version 2.0.21) no
58    system call to determine the number.  It is planned for the 2.1.x
59    series to add this, though.
60
61    One possibility to implement it for systems using Linux 2.0 is to
62    examine the pseudo file /proc/meminfo.  Here we have one entry for
63    each processor.
64
65    But not all systems have support for the /proc filesystem.  If it
66    is not available we simply return 1 since there is no way.  */
67 int
68 __get_nprocs ()
69 {
70   FILE *fp;
71   char buffer[8192];
72   char *proc_path;
73   int result = 1;
74
75   /* XXX Here will come a test for the new system call.  */
76
77   /* Get mount point of proc filesystem.  */
78   proc_path = get_proc_path (buffer, sizeof buffer);
79
80   /* If we haven't found an appropriate entry return 1.  */
81   if (proc_path != NULL)
82     {
83       char *proc_cpuinfo = alloca (strlen (proc_path) + sizeof ("/cpuinfo"));
84       __stpcpy (__stpcpy (proc_cpuinfo, proc_path), "/cpuinfo");
85
86       fp = fopen (proc_cpuinfo, "r");
87       if (fp != NULL)
88         {
89           result = 0;
90           /* Read all lines and count the lines starting with the
91              string "processor".  We don't have to fear extremely long
92              lines since the kernel will not generate them.  8192
93              bytes are really enough.  */
94           while (fgets (buffer, sizeof buffer, fp) != NULL)
95             if (strncmp (buffer, "processor", 9) == 0)
96               ++result;
97
98           fclose (fp);
99         }
100     }
101
102   return result;
103 }
104 weak_alias (__get_nprocs, get_nprocs)
105
106 /* As far as I know Linux has no separate numbers for configured and
107    available processors.  So make the `get_nprocs_conf' function an
108    alias.  */
109 strong_alias (__get_nprocs, __get_nprocs_conf)
110 weak_alias (__get_nprocs, get_nprocs_conf)
111
112
113 /* General function to get information about memory status from proc
114    filesystem.  */
115 static int
116 phys_pages_info (const char *format)
117 {
118   FILE *fp;
119   char buffer[8192];
120   char *proc_path;
121   int result = -1;
122
123   /* Get mount point of proc filesystem.  */
124   proc_path = get_proc_path (buffer, sizeof buffer);
125
126   /* If we haven't found an appropriate entry return 1.  */
127   if (proc_path != NULL)
128     {
129       char *proc_meminfo = alloca (strlen (proc_path) + sizeof ("/meminfo"));
130       __stpcpy (__stpcpy (proc_meminfo, proc_path), "/meminfo");
131
132       fp = fopen (proc_meminfo, "r");
133       if (fp != NULL)
134         {
135           result = 0;
136           /* Read all lines and count the lines starting with the
137              string "processor".  We don't have to fear extremely long
138              lines since the kernel will not generate them.  8192
139              bytes are really enough.  */
140           while (fgets (buffer, sizeof buffer, fp) != NULL)
141             if (sscanf (buffer, format, &result) == 1)
142               {
143                 result /= (__getpagesize () / 1024);
144                 break;
145               }
146
147           fclose (fp);
148         }
149     }
150
151   if (result == -1)
152     /* We cannot get the needed value: signal an error.  */
153     __set_errno (ENOSYS);
154
155   return result;
156 }
157
158
159 /* Return the number of pages of physical memory in the system.  There
160    is currently (as of version 2.0.21) no system call to determine the
161    number.  It is planned for the 2.1.x series to add this, though.
162
163    One possibility to implement it for systems using Linux 2.0 is to
164    examine the pseudo file /proc/cpuinfo.  Here we have one entry for
165    each processor.
166
167    But not all systems have support for the /proc filesystem.  If it
168    is not available we return -1 as an error signal.  */
169 int
170 __get_phys_pages ()
171 {
172   /* XXX Here will come a test for the new system call.  */
173
174   return phys_pages_info ("MemTotal: %d kB");
175 }
176 weak_alias (__get_phys_pages, get_phys_pages)
177
178
179 /* Return the number of available pages of physical memory in the
180    system.  There is currently (as of version 2.0.21) no system call
181    to determine the number.  It is planned for the 2.1.x series to add
182    this, though.
183
184    One possibility to implement it for systems using Linux 2.0 is to
185    examine the pseudo file /proc/cpuinfo.  Here we have one entry for
186    each processor.
187
188    But not all systems have support for the /proc filesystem.  If it
189    is not available we return -1 as an error signal.  */
190 int
191 __get_avphys_pages ()
192 {
193   /* XXX Here will come a test for the new system call.  */
194
195   return phys_pages_info ("MemFree: %d kB");
196 }
197 weak_alias (__get_avphys_pages, get_avphys_pages)