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