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