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
38int
39getdtablesize(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
49long
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
61long
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
400enum {
401	FS_BFS,
402	FS_FAT,
403	FS_EXT,
404	FS_UNKNOWN
405};
406
407
408static int
409fstype(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
426static 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
537long
538fpathconf(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
557long
558pathconf(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
577size_t
578confstr(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
599DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf_beos", "sysconf@", "BASE");
600
601DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf", "sysconf@@", "1_ALPHA4");
602