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