Back to index

glibc  2.9
sysconf.c
Go to the documentation of this file.
00001 /* Get file-specific information about a file.  Linux version.
00002    Copyright (C) 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <stdlib.h>
00023 #include <sysdep.h>
00024 #include <time.h>
00025 #include <unistd.h>
00026 #include <sys/resource.h>
00027 #include <not-cancel.h>
00028 #include <ldsodefs.h>
00029 
00030 /* Legacy value of ARG_MAX.  The macro is now not defined since the
00031    actual value varies based on the stack size.  */
00032 #define legacy_ARG_MAX 131072
00033 
00034 
00035 static long int posix_sysconf (int name);
00036 
00037 
00038 /* Get the value of the system variable NAME.  */
00039 long int
00040 __sysconf (int name)
00041 {
00042   const char *procfname = NULL;
00043 
00044   switch (name)
00045     {
00046 #ifdef __NR_clock_getres
00047     case _SC_MONOTONIC_CLOCK:
00048       /* Check using the clock_getres system call.  */
00049       {
00050        struct timespec ts;
00051        INTERNAL_SYSCALL_DECL (err);
00052        int r;
00053        r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts);
00054        return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION;
00055       }
00056 #endif
00057 
00058 #if defined __NR_clock_getres || HP_TIMING_AVAIL
00059     case _SC_CPUTIME:
00060     case _SC_THREAD_CPUTIME:
00061       {
00062        /* If we have HP_TIMING, we will fall back on that if the system
00063           call does not work, so we support it either way.  */
00064 # if !HP_TIMING_AVAIL
00065        /* Check using the clock_getres system call.  */
00066        struct timespec ts;
00067        INTERNAL_SYSCALL_DECL (err);
00068        int r = INTERNAL_SYSCALL (clock_getres, err, 2,
00069                               (name == _SC_CPUTIME
00070                                ? CLOCK_PROCESS_CPUTIME_ID
00071                                : CLOCK_THREAD_CPUTIME_ID),
00072                               &ts);
00073        if (INTERNAL_SYSCALL_ERROR_P (r, err))
00074          return -1;
00075 # endif
00076        return _POSIX_VERSION;
00077       }
00078 #endif
00079 
00080     case _SC_ARG_MAX:
00081 #if __LINUX_KERNEL_VERSION < 0x020617
00082       /* Determine whether this is a kernel 2.6.23 or later.  Only
00083         then do we have an argument limit determined by the stack
00084         size.  */
00085       if (GLRO(dl_discover_osversion) () >= 0x020617)
00086 #endif
00087        {
00088          /* Use getrlimit to get the stack limit.  */
00089          struct rlimit rlimit;
00090          if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
00091            return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);
00092        }
00093 
00094       return legacy_ARG_MAX;
00095 
00096     case _SC_NGROUPS_MAX:
00097       /* Try to read the information from the /proc/sys/kernel/ngroups_max
00098         file.  */
00099       procfname = "/proc/sys/kernel/ngroups_max";
00100       break;
00101 
00102     case _SC_SIGQUEUE_MAX:
00103       /* The /proc/sys/kernel/rtsig-max file contains the answer.  */
00104       procfname = "/proc/sys/kernel/rtsig-max";
00105       break;
00106 
00107     default:
00108       break;
00109     }
00110 
00111   if (procfname != NULL)
00112     {
00113       int fd = open_not_cancel_2 (procfname, O_RDONLY);
00114       if (fd != -1)
00115        {
00116          /* This is more than enough, the file contains a single integer.  */
00117          char buf[32];
00118          ssize_t n;
00119          n = TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, sizeof (buf) - 1));
00120          close_not_cancel_no_status (fd);
00121 
00122          if (n > 0)
00123            {
00124              /* Terminate the string.  */
00125              buf[n] = '\0';
00126 
00127              char *endp;
00128              long int res = strtol (buf, &endp, 10);
00129              if (endp != buf && (*endp == '\0' || *endp == '\n'))
00130               return res;
00131            }
00132        }
00133     }
00134 
00135   return posix_sysconf (name);
00136 }
00137 
00138 /* Now the POSIX version.  */
00139 #undef __sysconf
00140 #define __sysconf static posix_sysconf
00141 #include <sysdeps/posix/sysconf.c>