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