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 <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/resource.h> 14 #include <sys/statvfs.h> 15 16 #include <SupportDefs.h> 17 18 #include <directories.h> 19 #include <fs_info.h> 20 #include <posix/realtime_sem_defs.h> 21 #include <signal_defs.h> 22 #include <symbol_versioning.h> 23 #include <syscalls.h> 24 #include <thread_defs.h> 25 #include <user_group.h> 26 #include <user_timer_defs.h> 27 28 #include <errno_private.h> 29 #include <libroot_private.h> 30 #include <time_private.h> 31 #include <unistd_private.h> 32 33 34 int 35 getdtablesize(void) 36 { 37 struct rlimit rlimit; 38 if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0) 39 return 0; 40 41 return rlimit.rlim_cur; 42 } 43 44 45 long 46 __sysconf_beos(int name) 47 { 48 switch (name) { 49 case _SC_CLK_TCK: 50 return CLK_TCK_BEOS; 51 } 52 53 return __sysconf(name); 54 } 55 56 57 long 58 __sysconf(int name) 59 { 60 int err; 61 // TODO: This is about what BeOS does, better POSIX conformance would be 62 // nice, though 63 64 switch (name) { 65 case _SC_ARG_MAX: 66 return ARG_MAX; 67 case _SC_CHILD_MAX: 68 return CHILD_MAX; 69 case _SC_CLK_TCK: 70 return CLK_TCK; 71 case _SC_JOB_CONTROL: 72 return 1; 73 case _SC_NGROUPS_MAX: 74 return NGROUPS_MAX; 75 case _SC_OPEN_MAX: 76 return OPEN_MAX; 77 case _SC_SAVED_IDS: 78 return 1; 79 case _SC_STREAM_MAX: 80 return STREAM_MAX; 81 case _SC_TZNAME_MAX: 82 return TZNAME_MAX; 83 case _SC_VERSION: 84 return _POSIX_VERSION; 85 case _SC_GETGR_R_SIZE_MAX: 86 return MAX_GROUP_BUFFER_SIZE; 87 case _SC_GETPW_R_SIZE_MAX: 88 return MAX_PASSWD_BUFFER_SIZE; 89 case _SC_PAGE_SIZE: 90 return B_PAGE_SIZE; 91 case _SC_SEM_NSEMS_MAX: 92 return MAX_POSIX_SEMS; 93 case _SC_SEM_VALUE_MAX: 94 return _POSIX_SEM_VALUE_MAX; 95 case _SC_SEMAPHORES: 96 return _POSIX_SEMAPHORES; 97 case _SC_THREADS: 98 return _POSIX_THREADS; 99 case _SC_IOV_MAX: 100 return IOV_MAX; 101 case _SC_NPROCESSORS_MAX: 102 return B_MAX_CPU_COUNT; 103 case _SC_NPROCESSORS_CONF: 104 { 105 system_info info; 106 err = get_system_info(&info); 107 if (err < B_OK) { 108 __set_errno(err); 109 return -1; 110 } 111 return info.cpu_count; 112 } 113 case _SC_NPROCESSORS_ONLN: 114 { 115 system_info info; 116 int i; 117 int count = 0; 118 err = get_system_info(&info); 119 if (err < B_OK) { 120 __set_errno(err); 121 return -1; 122 } 123 for (i = 0; i < info.cpu_count; i++) 124 if (_kern_cpu_enabled(i)) 125 count++; 126 return count; 127 } 128 case _SC_CPUID_MAX: 129 return B_MAX_CPU_COUNT - 1; 130 case _SC_ATEXIT_MAX: 131 return ATEXIT_MAX; 132 case _SC_PASS_MAX: 133 break; 134 //XXX:return PASS_MAX; 135 case _SC_PHYS_PAGES: 136 { 137 system_info info; 138 err = get_system_info(&info); 139 if (err < B_OK) { 140 __set_errno(err); 141 return -1; 142 } 143 return info.max_pages; 144 } 145 case _SC_AVPHYS_PAGES: 146 { 147 system_info info; 148 err = get_system_info(&info); 149 if (err < B_OK) { 150 __set_errno(err); 151 return -1; 152 } 153 return info.max_pages - info.used_pages; 154 } 155 case _SC_MAPPED_FILES: 156 return _POSIX_MAPPED_FILES; 157 case _SC_THREAD_PROCESS_SHARED: 158 return _POSIX_THREAD_PROCESS_SHARED; 159 case _SC_THREAD_STACK_MIN: 160 return MIN_USER_STACK_SIZE; 161 case _SC_THREAD_ATTR_STACKADDR: 162 return _POSIX_THREAD_ATTR_STACKADDR; 163 case _SC_THREAD_ATTR_STACKSIZE: 164 return _POSIX_THREAD_ATTR_STACKSIZE; 165 case _SC_THREAD_PRIORITY_SCHEDULING: 166 return _POSIX_THREAD_PRIORITY_SCHEDULING; 167 case _SC_REALTIME_SIGNALS: 168 return _POSIX_REALTIME_SIGNALS; 169 case _SC_MEMORY_PROTECTION: 170 return _POSIX_MEMORY_PROTECTION; 171 case _SC_SIGQUEUE_MAX: 172 return MAX_QUEUED_SIGNALS; 173 case _SC_RTSIG_MAX: 174 return SIGRTMAX - SIGRTMIN + 1; 175 case _SC_MONOTONIC_CLOCK: 176 return _POSIX_MONOTONIC_CLOCK; 177 case _SC_DELAYTIMER_MAX: 178 return MAX_USER_TIMER_OVERRUN_COUNT; 179 case _SC_TIMER_MAX: 180 return MAX_USER_TIMERS_PER_TEAM; 181 case _SC_TIMERS: 182 return _POSIX_TIMERS; 183 case _SC_CPUTIME: 184 return _POSIX_CPUTIME; 185 case _SC_THREAD_CPUTIME: 186 return _POSIX_THREAD_CPUTIME; 187 188 // not POSIX (anymore) 189 case _SC_PIPE: 190 case _SC_SELECT: 191 case _SC_POLL: 192 return 1; 193 } 194 195 __set_errno(EINVAL); 196 return -1; 197 } 198 199 200 enum { 201 FS_BFS, 202 FS_FAT, 203 FS_EXT, 204 FS_UNKNOWN 205 }; 206 207 208 static int 209 fstype(const char *fsh_name) 210 { 211 if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH)) 212 return FS_BFS; 213 if (!strncmp(fsh_name, "dos", B_OS_NAME_LENGTH)) 214 return FS_FAT; 215 if (!strncmp(fsh_name, "fat", B_OS_NAME_LENGTH)) 216 return FS_FAT; 217 if (!strncmp(fsh_name, "ext2", B_OS_NAME_LENGTH)) 218 return FS_EXT; 219 if (!strncmp(fsh_name, "ext3", B_OS_NAME_LENGTH)) 220 return FS_EXT; 221 return FS_UNKNOWN; 222 } 223 224 225 226 static long 227 __pathconf_common(struct statvfs *fs, struct stat *st, 228 int name) 229 { 230 fs_info info; 231 int ret; 232 ret = fs_stat_dev(fs->f_fsid, &info); 233 if (ret < 0) { 234 __set_errno(ret); 235 return -1; 236 } 237 238 // TODO: many cases should check for file type from st. 239 switch (name) { 240 case _PC_CHOWN_RESTRICTED: 241 return _POSIX_CHOWN_RESTRICTED; 242 243 case _PC_MAX_CANON: 244 return MAX_CANON; 245 246 case _PC_MAX_INPUT: 247 return MAX_INPUT; 248 249 case _PC_NAME_MAX: 250 return fs->f_namemax; 251 //return NAME_MAX; 252 253 case _PC_NO_TRUNC: 254 return _POSIX_NO_TRUNC; 255 256 case _PC_PATH_MAX: 257 return PATH_MAX; 258 259 case _PC_PIPE_BUF: 260 return 4096; 261 262 case _PC_LINK_MAX: 263 return LINK_MAX; 264 265 case _PC_VDISABLE: 266 return _POSIX_VDISABLE; 267 268 case _PC_FILESIZEBITS: 269 { 270 int type = fstype(info.fsh_name); 271 switch (type) { 272 case FS_BFS: 273 case FS_EXT: 274 return 64; 275 case FS_FAT: 276 return 32; 277 } 278 // XXX: add fs ? add to statvfs/fs_info ? 279 return FILESIZEBITS; 280 } 281 282 case _PC_SYMLINK_MAX: 283 return SYMLINK_MAX; 284 285 case _PC_2_SYMLINKS: 286 { 287 int type = fstype(info.fsh_name); 288 switch (type) { 289 case FS_BFS: 290 case FS_EXT: 291 return 1; 292 case FS_FAT: 293 return 0; 294 } 295 // XXX: there should be an HAS_SYMLINKS flag 296 // to fs_info... 297 return 1; 298 } 299 300 case _PC_XATTR_EXISTS: 301 case _PC_XATTR_ENABLED: 302 { 303 #if 0 304 /* those seem to be Solaris specific, 305 * else we should return 1 I suppose. 306 * we don't yet map POSIX xattrs 307 * to BFS ones anyway. 308 */ 309 if (info.flags & B_FS_HAS_ATTR) 310 return 1; 311 return -1; 312 #endif 313 __set_errno(EINVAL); 314 return -1; 315 } 316 317 case _PC_SYNC_IO: 318 case _PC_ASYNC_IO: 319 case _PC_PRIO_IO: 320 case _PC_SOCK_MAXBUF: 321 case _PC_REC_INCR_XFER_SIZE: 322 case _PC_REC_MAX_XFER_SIZE: 323 case _PC_REC_MIN_XFER_SIZE: 324 case _PC_REC_XFER_ALIGN: 325 case _PC_ALLOC_SIZE_MIN: 326 /* not yet supported */ 327 __set_errno(EINVAL); 328 return -1; 329 330 } 331 332 __set_errno(EINVAL); 333 return -1; 334 } 335 336 337 long 338 fpathconf(int fd, int name) 339 { 340 struct statvfs fs; 341 struct stat st; 342 int ret; 343 if (fd < 0) { 344 __set_errno(EBADF); 345 return -1; 346 } 347 ret = fstat(fd, &st); 348 if (ret < 0) 349 return ret; 350 ret = fstatvfs(fd, &fs); 351 if (ret < 0) 352 return ret; 353 return __pathconf_common(&fs, &st, name); 354 } 355 356 357 long 358 pathconf(const char *path, int name) 359 { 360 struct statvfs fs; 361 struct stat st; 362 int ret; 363 if (path == NULL) { 364 __set_errno(EFAULT); 365 return -1; 366 } 367 ret = lstat(path, &st); 368 if (ret < 0) 369 return ret; 370 ret = statvfs(path, &fs); 371 if (ret < 0) 372 return ret; 373 return __pathconf_common(&fs, &st, name); 374 } 375 376 377 size_t 378 confstr(int name, char *buffer, size_t length) 379 { 380 size_t stringLength = 0; 381 char *string = ""; 382 383 if (!length || !buffer) { 384 __set_errno(EINVAL); 385 return 0; 386 } 387 388 switch (name) { 389 case _CS_PATH: 390 string = kGlobalBinDirectory ":" kSystemAppsDirectory ":" 391 kCommonBinDirectory ":" kCommonDevelopToolsBinDirectory; 392 break; 393 default: 394 __set_errno(EINVAL); 395 return 0; 396 } 397 398 if (buffer != NULL) { 399 stringLength = strlen(string) + 1; 400 strlcpy(buffer, string, 401 min_c(length - 1, stringLength)); 402 } 403 404 return stringLength; 405 } 406 407 408 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf_beos", "sysconf@", "BASE"); 409 410 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__sysconf", "sysconf@@", "1_ALPHA4"); 411