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
getdtablesize(void)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
__sysconf_beos(int name)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
__sysconf(int name)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
fstype(const char * fsh_name)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
__pathconf_common(struct statvfs * fs,struct stat * st,int name)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
fpathconf(int fd,int name)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
pathconf(const char * path,int name)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
confstr(int name,char * buffer,size_t length)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