chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / sysdeps / unix / sysv / linux / sysconf.c
1 /* Get file-specific information about a file.  Linux version.
2    Copyright (C) 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <sysdep.h>
24 #include <time.h>
25 #include <unistd.h>
26 #include <sys/resource.h>
27 #include <not-cancel.h>
28 #include <ldsodefs.h>
29
30 /* Legacy value of ARG_MAX.  The macro is now not defined since the
31    actual value varies based on the stack size.  */
32 #define legacy_ARG_MAX 131072
33
34
35 static long int posix_sysconf (int name);
36
37
38 /* Get the value of the system variable NAME.  */
39 long int
40 __sysconf (int name)
41 {
42   const char *procfname = NULL;
43
44   switch (name)
45     {
46       struct rlimit rlimit;
47 #ifdef __NR_clock_getres
48     case _SC_MONOTONIC_CLOCK:
49       /* Check using the clock_getres system call.  */
50       {
51         struct timespec ts;
52         INTERNAL_SYSCALL_DECL (err);
53         int r;
54         r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts);
55         return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION;
56       }
57 #endif
58
59 #if defined __NR_clock_getres || HP_TIMING_AVAIL
60     case _SC_CPUTIME:
61     case _SC_THREAD_CPUTIME:
62       {
63         /* If we have HP_TIMING, we will fall back on that if the system
64            call does not work, so we support it either way.  */
65 # if !HP_TIMING_AVAIL
66         /* Check using the clock_getres system call.  */
67         struct timespec ts;
68         INTERNAL_SYSCALL_DECL (err);
69         int r = INTERNAL_SYSCALL (clock_getres, err, 2,
70                                   (name == _SC_CPUTIME
71                                    ? CLOCK_PROCESS_CPUTIME_ID
72                                    : CLOCK_THREAD_CPUTIME_ID),
73                                   &ts);
74         if (INTERNAL_SYSCALL_ERROR_P (r, err))
75           return -1;
76 # endif
77         return _POSIX_VERSION;
78       }
79 #endif
80
81     case _SC_ARG_MAX:
82 #if __LINUX_KERNEL_VERSION < 0x020617
83       /* Determine whether this is a kernel 2.6.23 or later.  Only
84          then do we have an argument limit determined by the stack
85          size.  */
86       if (GLRO(dl_discover_osversion) () >= 0x020617)
87 #endif
88         /* Use getrlimit to get the stack limit.  */
89         if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
90           return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);
91
92       return legacy_ARG_MAX;
93
94     case _SC_NGROUPS_MAX:
95       /* Try to read the information from the /proc/sys/kernel/ngroups_max
96          file.  */
97       procfname = "/proc/sys/kernel/ngroups_max";
98       break;
99
100     case _SC_SIGQUEUE_MAX:
101       if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0)
102         return rlimit.rlim_cur;
103
104       /* The /proc/sys/kernel/rtsig-max file contains the answer.  */
105       procfname = "/proc/sys/kernel/rtsig-max";
106       break;
107
108     default:
109       break;
110     }
111
112   if (procfname != NULL)
113     {
114       int fd = open_not_cancel_2 (procfname, O_RDONLY);
115       if (fd != -1)
116         {
117           /* This is more than enough, the file contains a single integer.  */
118           char buf[32];
119           ssize_t n;
120           n = TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, sizeof (buf) - 1));
121           close_not_cancel_no_status (fd);
122
123           if (n > 0)
124             {
125               /* Terminate the string.  */
126               buf[n] = '\0';
127
128               char *endp;
129               long int res = strtol (buf, &endp, 10);
130               if (endp != buf && (*endp == '\0' || *endp == '\n'))
131                 return res;
132             }
133         }
134     }
135
136   return posix_sysconf (name);
137 }
138
139 /* Now the POSIX version.  */
140 #undef __sysconf
141 #define __sysconf static posix_sysconf
142 #include <sysdeps/posix/sysconf.c>