xref: /haiku/src/system/libroot/posix/unistd/conf.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 <limits.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/resource.h>
15 #include <sys/statvfs.h>
16 
17 #include <SupportDefs.h>
18 
19 #include <directories.h>
20 #include <fs_info.h>
21 #include <posix/realtime_sem_defs.h>
22 #include <signal_defs.h>
23 #include <symbol_versioning.h>
24 #include <syscalls.h>
25 #include <thread_defs.h>
26 #include <user_group.h>
27 #include <user_timer_defs.h>
28 #include <vfs_defs.h>
29 
30 #include <errno_private.h>
31 #include <libroot_private.h>
32 #include <time_private.h>
33 #include <unistd_private.h>
34 
35 #include <OS.h>
36 
37 
38 int
39 getdtablesize(void)
40 {
41 	struct rlimit rlimit;
42 	if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0)
43 		return OPEN_MAX;
44 
45 	return rlimit.rlim_cur;
46 }
47 
48 
49 long
50 __sysconf_beos(int name)
51 {
52 	switch (name) {
53 		case _SC_CLK_TCK:
54 			return CLK_TCK_BEOS;
55 	}
56 
57 	return __sysconf(name);
58 }
59 
60 
61 long
62 __sysconf(int name)
63 {
64 	int err;
65 
66 	switch (name) {
67 		case _SC_ARG_MAX:
68 			return ARG_MAX;
69 		case _SC_CHILD_MAX:
70 			return CHILD_MAX;
71 		case _SC_CLK_TCK:
72 			return CLK_TCK;
73 		case _SC_HOST_NAME_MAX:
74 			return _POSIX_HOST_NAME_MAX;
75 		case _SC_NGROUPS_MAX:
76 			return NGROUPS_MAX;
77 		case _SC_OPEN_MAX:
78 			return getdtablesize();
79 		case _SC_STREAM_MAX:
80 			return STREAM_MAX;
81 		case _SC_SYMLOOP_MAX:
82 			return SYMLOOP_MAX;
83 		case _SC_TTY_NAME_MAX:
84 			return TTY_NAME_MAX;
85 		case _SC_TZNAME_MAX:
86 			return TZNAME_MAX;
87 		case _SC_VERSION:
88 			return _POSIX_VERSION;
89 		case _SC_GETGR_R_SIZE_MAX:
90 			return MAX_GROUP_BUFFER_SIZE;
91 		case _SC_GETPW_R_SIZE_MAX:
92 			return MAX_PASSWD_BUFFER_SIZE;
93 		case _SC_PAGE_SIZE:
94 			return B_PAGE_SIZE;
95 		case _SC_SEM_NSEMS_MAX:
96 			// unlimited, instead of _POSIX_SEM_NSEMS_MAX
97 			return -1;
98 		case _SC_SEM_VALUE_MAX:
99 			return _POSIX_SEM_VALUE_MAX;
100 		case _SC_IOV_MAX:
101 			return IOV_MAX;
102 		case _SC_NPROCESSORS_CONF:
103 		{
104 			system_info info;
105 			err = get_system_info(&info);
106 			if (err < B_OK) {
107 				__set_errno(err);
108 				return -1;
109 			}
110 			return info.cpu_count;
111 		}
112 		case _SC_NPROCESSORS_ONLN:
113 		{
114 			system_info info;
115 			unsigned int i;
116 			int count = 0;
117 			err = get_system_info(&info);
118 			if (err < B_OK) {
119 				__set_errno(err);
120 				return -1;
121 			}
122 			for (i = 0; i < info.cpu_count; i++)
123 				if (_kern_cpu_enabled(i))
124 					count++;
125 			return count;
126 		}
127 		case _SC_ATEXIT_MAX:
128 			return ATEXIT_MAX;
129 		case _SC_PASS_MAX:
130 			break;
131 			//XXX:return PASS_MAX;
132 		case _SC_PHYS_PAGES:
133 		{
134 			system_info info;
135 			err = get_system_info(&info);
136 			if (err < B_OK) {
137 				__set_errno(err);
138 				return -1;
139 			}
140 			return info.max_pages;
141 		}
142 		case _SC_AVPHYS_PAGES:
143 		{
144 			system_info info;
145 			err = get_system_info(&info);
146 			if (err < B_OK) {
147 				__set_errno(err);
148 				return -1;
149 			}
150 			return info.max_pages - info.used_pages;
151 		}
152 		case _SC_THREAD_STACK_MIN:
153 			return MIN_USER_STACK_SIZE;
154 		case _SC_SIGQUEUE_MAX:
155 			return MAX_QUEUED_SIGNALS;
156 		case _SC_RTSIG_MAX:
157 			return SIGRTMAX - SIGRTMIN + 1;
158 		case _SC_DELAYTIMER_MAX:
159 			return MAX_USER_TIMER_OVERRUN_COUNT;
160 		case _SC_TIMER_MAX:
161 			return MAX_USER_TIMERS_PER_TEAM;
162 
163 		/* posix options */
164 		case _SC_ADVISORY_INFO:
165 			return _POSIX_ADVISORY_INFO;
166 		case _SC_BARRIERS:
167 			return _POSIX_BARRIERS;
168 		case _SC_CLOCK_SELECTION:
169 			return _POSIX_CLOCK_SELECTION;
170 		case _SC_CPUTIME:
171 			return _POSIX_CPUTIME;
172 		case _SC_FSYNC:
173 			return _POSIX_FSYNC;
174 		case _SC_IPV6:
175 			return _POSIX_IPV6;
176 		case _SC_JOB_CONTROL:
177 			return _POSIX_JOB_CONTROL;
178 		case _SC_MAPPED_FILES:
179 			return _POSIX_MAPPED_FILES;
180 		case _SC_MEMLOCK:
181 			return _POSIX_MEMLOCK;
182 		case _SC_MEMORY_PROTECTION:
183 			return _POSIX_MEMORY_PROTECTION;
184 		case _SC_MESSAGE_PASSING:
185 			return _POSIX_MESSAGE_PASSING;
186 		case _SC_MONOTONIC_CLOCK:
187 			return _POSIX_MONOTONIC_CLOCK;
188 		case _SC_PRIORITIZED_IO:
189 			return _POSIX_PRIORITIZED_IO;
190 		case _SC_PRIORITY_SCHEDULING:
191 			return _POSIX_PRIORITY_SCHEDULING;
192 		case _SC_READER_WRITER_LOCKS:
193 			return _POSIX_READER_WRITER_LOCKS;
194 		case _SC_REALTIME_SIGNALS:
195 			return _POSIX_REALTIME_SIGNALS;
196 		case _SC_REGEXP:
197 			return _POSIX_REGEXP;
198 		case _SC_SAVED_IDS:
199 			return _POSIX_SAVED_IDS;
200 		case _SC_SEMAPHORES:
201 			return _POSIX_SEMAPHORES;
202 		case _SC_SHARED_MEMORY_OBJECTS:
203 			return _POSIX_SHARED_MEMORY_OBJECTS;
204 		case _SC_SHELL:
205 			return _POSIX_SHELL;
206 		case _SC_SPAWN:
207 			return _POSIX_SPAWN;
208 		case _SC_SPIN_LOCKS:
209 			return _POSIX_SPIN_LOCKS;
210 		case _SC_SPORADIC_SERVER:
211 			return _POSIX_SPORADIC_SERVER;
212 		case _SC_SYNCHRONIZED_IO:
213 			return _POSIX_SYNCHRONIZED_IO;
214 		case _SC_THREAD_ATTR_STACKADDR:
215 			return _POSIX_THREAD_ATTR_STACKADDR;
216 		case _SC_THREAD_ATTR_STACKSIZE:
217 			return _POSIX_THREAD_ATTR_STACKSIZE;
218 		case _SC_THREAD_CPUTIME:
219 			return _POSIX_THREAD_CPUTIME;
220 		case _SC_THREAD_PRIO_INHERIT:
221 			return _POSIX_THREAD_PRIO_INHERIT;
222 		case _SC_THREAD_PRIO_PROTECT:
223 			return _POSIX_THREAD_PRIO_PROTECT;
224 		case _SC_THREAD_PRIORITY_SCHEDULING:
225 			return _POSIX_THREAD_PRIORITY_SCHEDULING;
226 		case _SC_THREAD_PROCESS_SHARED:
227 			return _POSIX_THREAD_PROCESS_SHARED;
228 		case _SC_THREAD_ROBUST_PRIO_INHERIT:
229 			return _POSIX_THREAD_ROBUST_PRIO_INHERIT;
230 		case _SC_THREAD_ROBUST_PRIO_PROTECT:
231 			return _POSIX_THREAD_ROBUST_PRIO_PROTECT;
232 		case _SC_THREAD_SAFE_FUNCTIONS:
233 			return _POSIX_THREAD_SAFE_FUNCTIONS;
234 		case _SC_THREADS:
235 			return _POSIX_THREADS;
236 		case _SC_TIMEOUTS:
237 			return _POSIX_TIMEOUTS;
238 		case _SC_TIMERS:
239 			return _POSIX_TIMERS;
240 		case _SC_TRACE:
241 			return _POSIX_TRACE;
242 		case _SC_TRACE_EVENT_FILTER:
243 			return _POSIX_TRACE_EVENT_FILTER;
244 		case _SC_TRACE_INHERIT:
245 			return _POSIX_TRACE_INHERIT;
246 		case _SC_TRACE_LOG:
247 			return _POSIX_TRACE_LOG;
248 		case _SC_TYPED_MEMORY_OBJECTS:
249 			return _POSIX_TYPED_MEMORY_OBJECTS;
250 
251 		case _SC_V6_ILP32_OFF32:
252 		case _SC_V7_ILP32_OFF32:
253 #if _ILP32_OFF32 == 0
254 			if (sizeof(int) * CHAR_BIT == 32 &&
255 			    sizeof(long) * CHAR_BIT == 32 &&
256 				sizeof(void *) * CHAR_BIT == 32 &&
257 				sizeof(off_t) * CHAR_BIT == 32)
258 				return 1;
259 			else
260 				return -1;
261 #else
262 			return _ILP32_OFF32;
263 #endif
264 		case _SC_V6_ILP32_OFFBIG:
265 		case _SC_V7_ILP32_OFFBIG:
266 #if _ILP32_OFFBIG == 0
267 			if (sizeof(int) * CHAR_BIT == 32 &&
268 				sizeof(long) * CHAR_BIT == 32 &&
269 				sizeof(void *) * CHAR_BIT == 32 &&
270 				sizeof(off_t) * CHAR_BIT >= 64)
271 				return 1;
272 			else
273 				return -1;
274 #else
275 			return _ILP32_OFFBIG;
276 #endif
277 		case _SC_V6_LP64_OFF64:
278 		case _SC_V7_LP64_OFF64:
279 #if _LP64_OFF64 == 0
280 			if (sizeof(int) * CHAR_BIT == 64 &&
281 				sizeof(long) * CHAR_BIT == 64 &&
282 				sizeof(void *) * CHAR_BIT == 64 &&
283 				sizeof(off_t) * CHAR_BIT == 64)
284 				return 1;
285 			else
286 				return -1;
287 #else
288 			return _LP64_OFF64;
289 #endif
290 		case _SC_V6_LPBIG_OFFBIG:
291 		case _SC_V7_LPBIG_OFFBIG:
292 #if _LPBIG_OFFBIG == 0
293 			if (sizeof(int) * CHAR_BIT >= 32 &&
294 				sizeof(long) * CHAR_BIT >= 64 &&
295 				sizeof(void *) * CHAR_BIT >= 64 &&
296 				sizeof(off_t) * CHAR_BIT >= 64)
297 				return 1;
298 			else
299 				return -1;
300 #else
301 			return _LPBIG_OFFBIG;
302 #endif
303 		case _SC_2_C_BIND:
304 			return _POSIX2_C_BIND;
305 		case _SC_2_C_DEV:
306 			return _POSIX2_C_DEV;
307 		case _SC_2_CHAR_TERM:
308 			return _POSIX2_CHAR_TERM;
309 		case _SC_2_FORT_DEV:
310 			return _POSIX2_FORT_DEV;
311 		case _SC_2_FORT_RUN:
312 			return _POSIX2_FORT_RUN;
313 		case _SC_2_LOCALEDEF:
314 			return _POSIX2_LOCALEDEF;
315 		case _SC_2_PBS:
316 			return _POSIX2_PBS;
317 		case _SC_2_PBS_ACCOUNTING:
318 			return _POSIX2_PBS_ACCOUNTING;
319 		case _SC_2_PBS_CHECKPOINT:
320 			return _POSIX2_PBS_CHECKPOINT;
321 		case _SC_2_PBS_LOCATE:
322 			return _POSIX2_PBS_LOCATE;
323 		case _SC_2_PBS_MESSAGE:
324 			return _POSIX2_PBS_MESSAGE;
325 		case _SC_2_PBS_TRACK:
326 			return _POSIX2_PBS_TRACK;
327 		case _SC_2_VERSION:
328 			return _POSIX2_VERSION;
329 		case _SC_XOPEN_CRYPT:
330 			return _XOPEN_CRYPT;
331 		case _SC_XOPEN_ENH_I18N:
332 			return _XOPEN_ENH_I18N;
333 		case _SC_XOPEN_REALTIME:
334 			return _XOPEN_REALTIME;
335 		case _SC_XOPEN_REALTIME_THREADS:
336 			return _XOPEN_REALTIME_THREADS;
337 		case _SC_XOPEN_SHM:
338 			return _XOPEN_SHM;
339 		case _SC_XOPEN_STREAMS:
340 			return _XOPEN_STREAMS;
341 		case _SC_XOPEN_UNIX:
342 			return _XOPEN_UNIX;
343 		case _SC_XOPEN_UUCP:
344 			return _XOPEN_UUCP;
345 		case _SC_XOPEN_VERSION:
346 			return _XOPEN_VERSION;
347 
348 #if _POSIX_ASYNCHRONOUS_IO >= 0
349 		case _SC_AIO_LISTIO_MAX:
350 			return AIO_LISTIO_MAX;
351 		case _SC_AIO_MAX:
352 			return AIO_MAX;
353 		case _SC_AIO_PRIO_DELTA_MAX:
354 			return AIO_PRIO_DELTA_MAX;
355 #endif
356 
357 		case _SC_BC_BASE_MAX:
358 			return BC_BASE_MAX;
359 		case _SC_BC_DIM_MAX:
360 			return BC_DIM_MAX;
361 		case _SC_BC_SCALE_MAX:
362 			return BC_SCALE_MAX;
363 		case _SC_BC_STRING_MAX:
364 			return BC_STRING_MAX;
365 
366 		case _SC_COLL_WEIGHTS_MAX:
367 			return COLL_WEIGHTS_MAX;
368 		case _SC_EXPR_NEST_MAX:
369 			return EXPR_NEST_MAX;
370 		case _SC_LINE_MAX:
371 			return LINE_MAX;
372 		case _SC_LOGIN_NAME_MAX:
373 			return LOGIN_NAME_MAX;
374 		case _SC_MQ_OPEN_MAX:
375 			return MQ_OPEN_MAX;
376 		case _SC_MQ_PRIO_MAX:
377 			return  MQ_PRIO_MAX;
378 		case _SC_THREAD_DESTRUCTOR_ITERATIONS:
379 			return PTHREAD_DESTRUCTOR_ITERATIONS;
380 		case _SC_THREAD_KEYS_MAX:
381 			return PTHREAD_KEYS_MAX;
382 		case _SC_THREAD_THREADS_MAX:
383 			system_info info;
384 			get_system_info(&info);
385 			return (int)info.max_threads;
386 		case _SC_RE_DUP_MAX:
387 			return RE_DUP_MAX;
388 
389 		// not POSIX (anymore)
390 		case _SC_PIPE:
391 		case _SC_SELECT:
392 		case _SC_POLL:
393 			return 1;
394 	}
395 
396 	__set_errno(EINVAL);
397 	return -1;
398 }
399 
400 
401 enum {
402 	FS_BFS,
403 	FS_FAT,
404 	FS_EXT,
405 	FS_UNKNOWN
406 };
407 
408 
409 static int
410 fstype(const char *fsh_name)
411 {
412 	if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH))
413 		return FS_BFS;
414 	if (!strncmp(fsh_name, "dos", B_OS_NAME_LENGTH))
415 		return FS_FAT;
416 	if (!strncmp(fsh_name, "fat", B_OS_NAME_LENGTH))
417 		return FS_FAT;
418 	if (!strncmp(fsh_name, "ext2", B_OS_NAME_LENGTH))
419 		return FS_EXT;
420 	if (!strncmp(fsh_name, "ext3", B_OS_NAME_LENGTH))
421 		return FS_EXT;
422 	return FS_UNKNOWN;
423 }
424 
425 
426 
427 static long
428 __pathconf_common(struct statvfs *fs, struct stat *st,
429 	int name)
430 {
431 	fs_info info;
432 	int ret;
433 	ret = fs_stat_dev(fs->f_fsid, &info);
434 	if (ret < 0) {
435 		__set_errno(ret);
436 		return -1;
437 	}
438 
439 	// TODO: many cases should check for file type from st.
440 	switch (name) {
441 		case _PC_CHOWN_RESTRICTED:
442 			return _POSIX_CHOWN_RESTRICTED;
443 
444 		case _PC_MAX_CANON:
445 			return MAX_CANON;
446 
447 		case _PC_MAX_INPUT:
448 			return MAX_INPUT;
449 
450 		case _PC_NAME_MAX:
451 			return fs->f_namemax;
452 			//return NAME_MAX;
453 
454 		case _PC_NO_TRUNC:
455 			return _POSIX_NO_TRUNC;
456 
457 		case _PC_PATH_MAX:
458 			return PATH_MAX;
459 
460 		case _PC_PIPE_BUF:
461 			return VFS_FIFO_ATOMIC_WRITE_SIZE;
462 
463 		case _PC_LINK_MAX:
464 			return LINK_MAX;
465 
466 		case _PC_VDISABLE:
467 			return _POSIX_VDISABLE;
468 
469 		case _PC_FILESIZEBITS:
470 		{
471 			int type = fstype(info.fsh_name);
472 			switch (type) {
473 				case FS_BFS:
474 				case FS_EXT:
475 					return 64;
476 				case FS_FAT:
477 					return 32;
478 			}
479 			// XXX: add fs ? add to statvfs/fs_info ?
480 			return FILESIZEBITS;
481 		}
482 
483 		case _PC_SYMLINK_MAX:
484 			return SYMLINK_MAX;
485 
486 		case _PC_2_SYMLINKS:
487 		{
488 			int type = fstype(info.fsh_name);
489 			switch (type) {
490 				case FS_BFS:
491 				case FS_EXT:
492 					return 1;
493 				case FS_FAT:
494 					return 0;
495 			}
496 			// XXX: there should be an HAS_SYMLINKS flag
497 			// to fs_info...
498 			return 1;
499 		}
500 
501 		case _PC_XATTR_EXISTS:
502 		case _PC_XATTR_ENABLED:
503 		{
504 #if 0
505 			/* those seem to be Solaris specific,
506 			 * else we should return 1 I suppose.
507 			 * we don't yet map POSIX xattrs
508 			 * to BFS ones anyway.
509 			 */
510 			if (info.flags & B_FS_HAS_ATTR)
511 				return 1;
512 			return -1;
513 #endif
514 			__set_errno(EINVAL);
515 			return -1;
516 		}
517 
518 		case _PC_SYNC_IO:
519 		case _PC_ASYNC_IO:
520 		case _PC_PRIO_IO:
521 		case _PC_SOCK_MAXBUF:
522 		case _PC_REC_INCR_XFER_SIZE:
523 		case _PC_REC_MAX_XFER_SIZE:
524 		case _PC_REC_MIN_XFER_SIZE:
525 		case _PC_REC_XFER_ALIGN:
526 		case _PC_ALLOC_SIZE_MIN:
527 			/* not yet supported */
528 			__set_errno(EINVAL);
529 			return -1;
530 
531 	}
532 
533 	__set_errno(EINVAL);
534 	return -1;
535 }
536 
537 
538 long
539 fpathconf(int fd, int name)
540 {
541 	struct statvfs fs;
542 	struct stat st;
543 	int ret;
544 	if (fd < 0) {
545 		__set_errno(EBADF);
546 		return -1;
547 	}
548 	ret = fstat(fd, &st);
549 	if (ret < 0)
550 		return ret;
551 	ret = fstatvfs(fd, &fs);
552 	if (ret < 0)
553 		return ret;
554 	return __pathconf_common(&fs, &st, name);
555 }
556 
557 
558 long
559 pathconf(const char *path, int name)
560 {
561 	struct statvfs fs;
562 	struct stat st;
563 	int ret;
564 	if (path == NULL) {
565 		__set_errno(EFAULT);
566 		return -1;
567 	}
568 	ret = lstat(path, &st);
569 	if (ret < 0)
570 		return ret;
571 	ret = statvfs(path, &fs);
572 	if (ret < 0)
573 		return ret;
574 	return __pathconf_common(&fs, &st, name);
575 }
576 
577 
578 size_t
579 confstr(int name, char *buffer, size_t length)
580 {
581 	const char *string = "";
582 
583 	switch (name) {
584 		case _CS_PATH:
585 			string = kSystemNonpackagedBinDirectory ":" kGlobalBinDirectory ":"
586 				kSystemAppsDirectory ":" kSystemPreferencesDirectory;
587 			break;
588 		default:
589 			__set_errno(EINVAL);
590 			return 0;
591 	}
592 
593 	if (buffer != NULL)
594 		strlcpy(buffer, string, length);
595 
596 	return strlen(string) + 1;
597 }
598 
599 
600 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf_beos", "sysconf@", "BASE");
601 
602 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf", "sysconf@@", "1_ALPHA4");
603