manual/llio.texi: update manual to document file-private locks
[jlayton/glibc.git] / posix / confstr.c
1 /* Copyright (C) 1991-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <stddef.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <confstr.h>
23 #include "../version.h"
24
25 /* If BUF is not NULL and LEN > 0, fill in at most LEN - 1 bytes
26    of BUF with the value corresponding to NAME and zero-terminate BUF.
27    Return the number of bytes required to hold NAME's entire value.  */
28 size_t
29 confstr (name, buf, len)
30      int name;
31      char *buf;
32      size_t len;
33 {
34   const char *string = "";
35   size_t string_len = 1;
36
37   /* Note that this buffer must be large enough for the longest strings
38      used below.  */
39   char restenvs[4 * sizeof "POSIX_V7_LPBIG_OFFBIG"];
40
41   switch (name)
42     {
43     case _CS_PATH:
44       {
45         static const char cs_path[] = CS_PATH;
46         string = cs_path;
47         string_len = sizeof (cs_path);
48       }
49       break;
50
51       /* For _CS_V7_WIDTH_RESTRICTED_ENVS, _CS_V6_WIDTH_RESTRICTED_ENVS
52          and _CS_V5_WIDTH_RESTRICTED_ENVS:
53
54          We have to return a newline-separated list of names of
55          programming environments in which the widths of blksize_t,
56          cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
57          ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
58          wint_t types are no greater than the width of type long.
59
60          Currently this means all environments that the system allows.  */
61
62 #define START_ENV_GROUP(VERSION)                \
63     case _CS_##VERSION##_WIDTH_RESTRICTED_ENVS: \
64       string_len = 0;
65
66 #define END_ENV_GROUP(VERSION)                  \
67       restenvs[string_len++] = '\0';            \
68       string = restenvs;                        \
69       break;
70
71 #define KNOWN_ABSENT_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX) \
72       /* Empty.  */
73
74 #define KNOWN_PRESENT_ENV_STRING(STR)           \
75       if (string_len > 0)                       \
76         restenvs[string_len++] = '\n';          \
77       memcpy (restenvs + string_len, STR,       \
78               sizeof STR - 1);                  \
79       string_len += sizeof STR - 1;
80
81 #define KNOWN_PRESENT_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX)        \
82       KNOWN_PRESENT_ENV_STRING (#ENV_PREFIX "_" #SUFFIX)
83
84 #define UNKNOWN_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX)              \
85       if (__sysconf (_SC_##SC_PREFIX##_##SUFFIX) > 0)                   \
86         {                                                               \
87           KNOWN_PRESENT_ENVIRONMENT (SC_PREFIX, ENV_PREFIX, SUFFIX)     \
88         }
89
90 #include "posix-envs.def"
91
92 #undef START_ENV_GROUP
93 #undef END_ENV_GROUP
94 #undef KNOWN_ABSENT_ENVIRONMENT
95 #undef KNOWN_PRESENT_ENV_STRING
96 #undef KNOWN_PRESENT_ENVIRONMENT
97 #undef UNKNOWN_ENVIRONMENT
98
99     case _CS_XBS5_ILP32_OFF32_CFLAGS:
100     case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
101     case _CS_POSIX_V7_ILP32_OFF32_CFLAGS:
102 #ifdef __ILP32_OFF32_CFLAGS
103 # if _POSIX_V7_ILP32_OFF32 == -1
104 #  error "__ILP32_OFF32_CFLAGS should not be defined"
105 # elif !defined _POSIX_V7_ILP32_OFF32
106       if (__sysconf (_SC_V7_ILP32_OFF32) < 0)
107         break;
108 # endif
109       string = __ILP32_OFF32_CFLAGS;
110       string_len = sizeof (__ILP32_OFF32_CFLAGS);
111 #endif
112       break;
113
114     case _CS_XBS5_ILP32_OFFBIG_CFLAGS:
115     case _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS:
116     case _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS:
117 #ifdef __ILP32_OFFBIG_CFLAGS
118 # if _POSIX_V7_ILP32_OFFBIG == -1
119 #  error "__ILP32_OFFBIG_CFLAGS should not be defined"
120 # elif !defined _POSIX_V7_ILP32_OFFBIG
121       if (__sysconf (_SC_V7_ILP32_OFFBIG) < 0)
122         break;
123 # endif
124       string = __ILP32_OFFBIG_CFLAGS;
125       string_len = sizeof (__ILP32_OFFBIG_CFLAGS);
126 #endif
127       break;
128
129     case _CS_XBS5_LP64_OFF64_CFLAGS:
130     case _CS_POSIX_V6_LP64_OFF64_CFLAGS:
131     case _CS_POSIX_V7_LP64_OFF64_CFLAGS:
132 #ifdef __LP64_OFF64_CFLAGS
133 # if _POSIX_V7_LP64_OFF64 == -1
134 #  error "__LP64_OFF64_CFLAGS should not be defined"
135 # elif !defined _POSIX_V7_LP64_OFF64
136       if (__sysconf (_SC_V7_LP64_OFF64) < 0)
137         break;
138 # endif
139       string = __LP64_OFF64_CFLAGS;
140       string_len = sizeof (__LP64_OFF64_CFLAGS);
141 #endif
142       break;
143
144     case _CS_XBS5_ILP32_OFF32_LDFLAGS:
145     case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS:
146     case _CS_POSIX_V7_ILP32_OFF32_LDFLAGS:
147 #ifdef __ILP32_OFF32_LDFLAGS
148 # if _POSIX_V7_ILP32_OFF32 == -1
149 #  error "__ILP32_OFF32_LDFLAGS should not be defined"
150 # elif !defined _POSIX_V7_ILP32_OFF32
151       if (__sysconf (_SC_V7_ILP32_OFF32) < 0)
152         break;
153 # endif
154       string = __ILP32_OFF32_LDFLAGS;
155       string_len = sizeof (__ILP32_OFF32_LDFLAGS);
156 #endif
157       break;
158
159     case _CS_XBS5_ILP32_OFFBIG_LDFLAGS:
160     case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS:
161     case _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS:
162 #ifdef __ILP32_OFFBIG_LDFLAGS
163 # if _POSIX_V7_ILP32_OFFBIG == -1
164 #  error "__ILP32_OFFBIG_LDFLAGS should not be defined"
165 # elif !defined _POSIX_V7_ILP32_OFFBIG
166       if (__sysconf (_SC_V7_ILP32_OFFBIG) < 0)
167         break;
168 # endif
169       string = __ILP32_OFFBIG_LDFLAGS;
170       string_len = sizeof (__ILP32_OFFBIG_LDFLAGS);
171 #endif
172       break;
173
174     case _CS_XBS5_LP64_OFF64_LDFLAGS:
175     case _CS_POSIX_V6_LP64_OFF64_LDFLAGS:
176     case _CS_POSIX_V7_LP64_OFF64_LDFLAGS:
177 #ifdef __LP64_OFF64_LDFLAGS
178 # if _POSIX_V7_LP64_OFF64 == -1
179 #  error "__LP64_OFF64_LDFLAGS should not be defined"
180 # elif !defined _POSIX_V7_LP64_OFF64
181       if (__sysconf (_SC_V7_LP64_OFF64) < 0)
182         break;
183 # endif
184       string = __LP64_OFF64_LDFLAGS;
185       string_len = sizeof (__LP64_OFF64_LDFLAGS);
186 #endif
187       break;
188
189     case _CS_LFS_CFLAGS:
190     case _CS_LFS_LINTFLAGS:
191 #if _POSIX_V6_ILP32_OFF32 == 1 && _POSIX_V6_ILP32_OFFBIG == 1
192 # define __LFS_CFLAGS "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
193       /* Signal that we want the new ABI.  */
194       string = __LFS_CFLAGS;
195       string_len = sizeof (__LFS_CFLAGS);
196 #endif
197       break;
198
199     case _CS_LFS_LDFLAGS:
200     case _CS_LFS_LIBS:
201       /* No special libraries or linker flags needed.  */
202       break;
203
204     case _CS_LFS64_CFLAGS:
205     case _CS_LFS64_LINTFLAGS:
206 #define __LFS64_CFLAGS "-D_LARGEFILE64_SOURCE"
207       string = __LFS64_CFLAGS;
208       string_len = sizeof (__LFS64_CFLAGS);
209       break;
210
211     case _CS_LFS64_LDFLAGS:
212     case _CS_LFS64_LIBS:
213       /* No special libraries or linker flags needed.  */
214       break;
215
216     case _CS_XBS5_ILP32_OFF32_LIBS:
217     case _CS_XBS5_ILP32_OFF32_LINTFLAGS:
218     case _CS_XBS5_ILP32_OFFBIG_LIBS:
219     case _CS_XBS5_ILP32_OFFBIG_LINTFLAGS:
220     case _CS_XBS5_LP64_OFF64_LIBS:
221     case _CS_XBS5_LP64_OFF64_LINTFLAGS:
222     case _CS_XBS5_LPBIG_OFFBIG_CFLAGS:
223     case _CS_XBS5_LPBIG_OFFBIG_LDFLAGS:
224     case _CS_XBS5_LPBIG_OFFBIG_LIBS:
225     case _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS:
226
227     case _CS_POSIX_V6_ILP32_OFF32_LIBS:
228     case _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS:
229     case _CS_POSIX_V6_ILP32_OFFBIG_LIBS:
230     case _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS:
231     case _CS_POSIX_V6_LP64_OFF64_LIBS:
232     case _CS_POSIX_V6_LP64_OFF64_LINTFLAGS:
233     case _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS:
234     case _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS:
235     case _CS_POSIX_V6_LPBIG_OFFBIG_LIBS:
236     case _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS:
237
238     case _CS_POSIX_V7_ILP32_OFF32_LIBS:
239     case _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS:
240     case _CS_POSIX_V7_ILP32_OFFBIG_LIBS:
241     case _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS:
242     case _CS_POSIX_V7_LP64_OFF64_LIBS:
243     case _CS_POSIX_V7_LP64_OFF64_LINTFLAGS:
244     case _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS:
245     case _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS:
246     case _CS_POSIX_V7_LPBIG_OFFBIG_LIBS:
247     case _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS:
248       /* GNU libc does not require special actions to use LFS functions.  */
249       break;
250
251     case _CS_GNU_LIBC_VERSION:
252       string = "glibc " VERSION;
253       string_len = sizeof ("glibc " VERSION);
254       break;
255
256     case _CS_GNU_LIBPTHREAD_VERSION:
257 #ifdef LIBPTHREAD_VERSION
258       string = LIBPTHREAD_VERSION;
259       string_len = sizeof LIBPTHREAD_VERSION;
260       break;
261 #else
262       /* No thread library.  */
263       __set_errno (EINVAL);
264       return 0;
265 #endif
266
267     case _CS_V6_ENV:
268     case _CS_V7_ENV:
269       /* Maybe something else is needed in future.  */
270       string = "POSIXLY_CORRECT=1";
271       string_len = sizeof ("POSIXLY_CORRECT=1");
272       break;
273
274     default:
275       __set_errno (EINVAL);
276       return 0;
277     }
278
279   if (len > 0 && buf != NULL)
280     {
281       if (string_len <= len)
282         memcpy (buf, string, string_len);
283       else
284         {
285           memcpy (buf, string, len - 1);
286           buf[len - 1] = '\0';
287         }
288     }
289   return string_len;
290 }
291 libc_hidden_def (confstr)