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