xref: /haiku/src/system/libroot/posix/unistd/conf.cpp (revision 837b16251d4b2b6249ebcaa19bb319cbe82c6126)
1 /*
2  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <unistd.h>
8 
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/resource.h>
14 #include <sys/statvfs.h>
15 
16 #include <SupportDefs.h>
17 
18 #include <fs_info.h>
19 #include <posix/realtime_sem_defs.h>
20 #include <signal_defs.h>
21 #include <symbol_versioning.h>
22 #include <syscalls.h>
23 #include <thread_defs.h>
24 #include <user_group.h>
25 #include <user_timer_defs.h>
26 
27 #include <libroot_private.h>
28 #include <time_private.h>
29 #include <unistd_private.h>
30 
31 
32 int
33 getdtablesize(void)
34 {
35 	struct rlimit rlimit;
36 	if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0)
37 		return 0;
38 
39 	return rlimit.rlim_cur;
40 }
41 
42 
43 long
44 __sysconf_beos(int name)
45 {
46 	switch (name) {
47 		case _SC_CLK_TCK:
48 			return CLK_TCK_BEOS;
49 	}
50 
51 	return __sysconf(name);
52 }
53 
54 
55 long
56 __sysconf(int name)
57 {
58 	int err;
59 	// TODO: This is about what BeOS does, better POSIX conformance would be
60 	// nice, though
61 
62 	switch (name) {
63 		case _SC_ARG_MAX:
64 			return ARG_MAX;
65 		case _SC_CHILD_MAX:
66 			return CHILD_MAX;
67 		case _SC_CLK_TCK:
68 			return CLK_TCK;
69 		case _SC_JOB_CONTROL:
70 			return 1;
71 		case _SC_NGROUPS_MAX:
72 			return NGROUPS_MAX;
73 		case _SC_OPEN_MAX:
74 			return OPEN_MAX;
75 		case _SC_SAVED_IDS:
76 			return 1;
77 		case _SC_STREAM_MAX:
78 			return STREAM_MAX;
79 		case _SC_TZNAME_MAX:
80 			return TZNAME_MAX;
81 		case _SC_VERSION:
82 			return _POSIX_VERSION;
83 		case _SC_GETGR_R_SIZE_MAX:
84 			return MAX_GROUP_BUFFER_SIZE;
85 		case _SC_GETPW_R_SIZE_MAX:
86 			return MAX_PASSWD_BUFFER_SIZE;
87 		case _SC_PAGE_SIZE:
88 			return B_PAGE_SIZE;
89 		case _SC_SEM_NSEMS_MAX:
90 			return MAX_POSIX_SEMS;
91 		case _SC_SEM_VALUE_MAX:
92 			return _POSIX_SEM_VALUE_MAX;
93 		case _SC_SEMAPHORES:
94 			return _POSIX_SEMAPHORES;
95 		case _SC_THREADS:
96 			return _POSIX_THREADS;
97 		case _SC_IOV_MAX:
98 			return IOV_MAX;
99 		case _SC_NPROCESSORS_MAX:
100 			return B_MAX_CPU_COUNT;
101 		case _SC_NPROCESSORS_CONF:
102 		{
103 			system_info info;
104 			err = get_system_info(&info);
105 			if (err < B_OK) {
106 				errno = err;
107 				return -1;
108 			}
109 			return info.cpu_count;
110 		}
111 		case _SC_NPROCESSORS_ONLN:
112 		{
113 			system_info info;
114 			int i;
115 			int count = 0;
116 			err = get_system_info(&info);
117 			if (err < B_OK) {
118 				errno = err;
119 				return -1;
120 			}
121 			for (i = 0; i < info.cpu_count; i++)
122 				if (_kern_cpu_enabled(i))
123 					count++;
124 			return count;
125 		}
126 		case _SC_CPUID_MAX:
127 			return B_MAX_CPU_COUNT - 1;
128 		case _SC_ATEXIT_MAX:
129 			return ATEXIT_MAX;
130 		case _SC_PASS_MAX:
131 			break;
132 			//XXX:return PASS_MAX;
133 		case _SC_PHYS_PAGES:
134 		{
135 			system_info info;
136 			err = get_system_info(&info);
137 			if (err < B_OK) {
138 				errno = err;
139 				return -1;
140 			}
141 			return info.max_pages;
142 		}
143 		case _SC_AVPHYS_PAGES:
144 		{
145 			system_info info;
146 			err = get_system_info(&info);
147 			if (err < B_OK) {
148 				errno = err;
149 				return -1;
150 			}
151 			return info.max_pages - info.used_pages;
152 		}
153 		case _SC_MAPPED_FILES:
154 			return _POSIX_MAPPED_FILES;
155 		case _SC_THREAD_PROCESS_SHARED:
156 			return _POSIX_THREAD_PROCESS_SHARED;
157 		case _SC_THREAD_STACK_MIN:
158 			return MIN_USER_STACK_SIZE;
159 		case _SC_THREAD_ATTR_STACKADDR:
160 			return _POSIX_THREAD_ATTR_STACKADDR;
161 		case _SC_THREAD_ATTR_STACKSIZE:
162 			return _POSIX_THREAD_ATTR_STACKSIZE;
163 		case _SC_THREAD_PRIORITY_SCHEDULING:
164 			return _POSIX_THREAD_PRIORITY_SCHEDULING;
165 		case _SC_REALTIME_SIGNALS:
166 			return _POSIX_REALTIME_SIGNALS;
167 		case _SC_MEMORY_PROTECTION:
168 			return _POSIX_MEMORY_PROTECTION;
169 		case _SC_SIGQUEUE_MAX:
170 			return MAX_QUEUED_SIGNALS;
171 		case _SC_RTSIG_MAX:
172 			return SIGRTMAX - SIGRTMIN + 1;
173 		case _SC_MONOTONIC_CLOCK:
174 			return _POSIX_MONOTONIC_CLOCK;
175 		case _SC_DELAYTIMER_MAX:
176 			return MAX_USER_TIMER_OVERRUN_COUNT;
177 		case _SC_TIMER_MAX:
178 			return MAX_USER_TIMERS_PER_TEAM;
179 		case _SC_TIMERS:
180 			return _POSIX_TIMERS;
181 		case _SC_CPUTIME:
182 			return _POSIX_CPUTIME;
183 		case _SC_THREAD_CPUTIME:
184 			return _POSIX_THREAD_CPUTIME;
185 
186 		// not POSIX (anymore)
187 		case _SC_PIPE:
188 		case _SC_SELECT:
189 		case _SC_POLL:
190 			return 1;
191 	}
192 
193 	errno = EINVAL;
194 	return -1;
195 }
196 
197 
198 enum {
199 	FS_BFS,
200 	FS_FAT,
201 	FS_EXT,
202 	FS_UNKNOWN
203 };
204 
205 
206 static int
207 fstype(const char *fsh_name)
208 {
209 	if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH))
210 		return FS_BFS;
211 	if (!strncmp(fsh_name, "dos", B_OS_NAME_LENGTH))
212 		return FS_FAT;
213 	if (!strncmp(fsh_name, "fat", B_OS_NAME_LENGTH))
214 		return FS_FAT;
215 	if (!strncmp(fsh_name, "ext2", B_OS_NAME_LENGTH))
216 		return FS_EXT;
217 	if (!strncmp(fsh_name, "ext3", B_OS_NAME_LENGTH))
218 		return FS_EXT;
219 	return FS_UNKNOWN;
220 }
221 
222 
223 
224 static long
225 __pathconf_common(struct statvfs *fs, struct stat *st,
226 	int name)
227 {
228 	fs_info info;
229 	int ret;
230 	ret = fs_stat_dev(fs->f_fsid, &info);
231 	if (ret < 0) {
232 		errno = ret;
233 		return -1;
234 	}
235 
236 	// TODO: many cases should check for file type from st.
237 	switch (name) {
238 		case _PC_CHOWN_RESTRICTED:
239 			return _POSIX_CHOWN_RESTRICTED;
240 
241 		case _PC_MAX_CANON:
242 			return MAX_CANON;
243 
244 		case _PC_MAX_INPUT:
245 			return MAX_INPUT;
246 
247 		case _PC_NAME_MAX:
248 			return fs->f_namemax;
249 			//return NAME_MAX;
250 
251 		case _PC_NO_TRUNC:
252 			return _POSIX_NO_TRUNC;
253 
254 		case _PC_PATH_MAX:
255 			return PATH_MAX;
256 
257 		case _PC_PIPE_BUF:
258 			return 4096;
259 
260 		case _PC_LINK_MAX:
261 			return LINK_MAX;
262 
263 		case _PC_VDISABLE:
264 			return _POSIX_VDISABLE;
265 
266 		case _PC_FILESIZEBITS:
267 		{
268 			int type = fstype(info.fsh_name);
269 			switch (type) {
270 				case FS_BFS:
271 				case FS_EXT:
272 					return 64;
273 				case FS_FAT:
274 					return 32;
275 			}
276 			// XXX: add fs ? add to statvfs/fs_info ?
277 			return FILESIZEBITS;
278 		}
279 
280 		case _PC_SYMLINK_MAX:
281 			return SYMLINK_MAX;
282 
283 		case _PC_2_SYMLINKS:
284 		{
285 			int type = fstype(info.fsh_name);
286 			switch (type) {
287 				case FS_BFS:
288 				case FS_EXT:
289 					return 1;
290 				case FS_FAT:
291 					return 0;
292 			}
293 			// XXX: there should be an HAS_SYMLINKS flag
294 			// to fs_info...
295 			return 1;
296 		}
297 
298 		case _PC_XATTR_EXISTS:
299 		case _PC_XATTR_ENABLED:
300 		{
301 #if 0
302 			/* those seem to be Solaris specific,
303 			 * else we should return 1 I suppose.
304 			 * we don't yet map POSIX xattrs
305 			 * to BFS ones anyway.
306 			 */
307 			if (info.flags & B_FS_HAS_ATTR)
308 				return 1;
309 			return -1;
310 #endif
311 			errno = EINVAL;
312 			return -1;
313 		}
314 
315 		case _PC_SYNC_IO:
316 		case _PC_ASYNC_IO:
317 		case _PC_PRIO_IO:
318 		case _PC_SOCK_MAXBUF:
319 		case _PC_REC_INCR_XFER_SIZE:
320 		case _PC_REC_MAX_XFER_SIZE:
321 		case _PC_REC_MIN_XFER_SIZE:
322 		case _PC_REC_XFER_ALIGN:
323 		case _PC_ALLOC_SIZE_MIN:
324 			/* not yet supported */
325 			errno = EINVAL;
326 			return -1;
327 
328 	}
329 
330 	errno = EINVAL;
331 	return -1;
332 }
333 
334 
335 long
336 fpathconf(int fd, int name)
337 {
338 	struct statvfs fs;
339 	struct stat st;
340 	int ret;
341 	if (fd < 0) {
342 		errno = EBADF;
343 		return -1;
344 	}
345 	ret = fstat(fd, &st);
346 	if (ret < 0)
347 		return ret;
348 	ret = fstatvfs(fd, &fs);
349 	if (ret < 0)
350 		return ret;
351 	return __pathconf_common(&fs, &st, name);
352 }
353 
354 
355 long
356 pathconf(const char *path, int name)
357 {
358 	struct statvfs fs;
359 	struct stat st;
360 	int ret;
361 	if (path == NULL) {
362 		errno = EFAULT;
363 		return -1;
364 	}
365 	ret = lstat(path, &st);
366 	if (ret < 0)
367 		return ret;
368 	ret = statvfs(path, &fs);
369 	if (ret < 0)
370 		return ret;
371 	return __pathconf_common(&fs, &st, name);
372 }
373 
374 
375 size_t
376 confstr(int name, char *buffer, size_t length)
377 {
378 	size_t stringLength = 0;
379 	char *string = "";
380 
381 	if (!length || !buffer) {
382 		errno = EINVAL;
383 		return 0;
384 	}
385 
386 	switch (name) {
387 		case _CS_PATH:
388 			string = "/bin:/boot/system/apps:" \
389 				"/boot/common/bin:/boot/develop/bin";
390 			break;
391 		default:
392 			errno = EINVAL;
393 			return 0;
394 	}
395 
396 	if (buffer != NULL) {
397 		stringLength = strlen(string) + 1;
398 		strlcpy(buffer, string,
399 			min_c(length - 1, stringLength));
400 	}
401 
402 	return stringLength;
403 }
404 
405 
406 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf_beos", "sysconf@", "BASE");
407 
408 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf", "sysconf@@", "1_ALPHA4");
409