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 OPEN_MAX; 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_HOST_NAME_MAX: 75 return _POSIX_HOST_NAME_MAX; 76 case _SC_NGROUPS_MAX: 77 return NGROUPS_MAX; 78 case _SC_OPEN_MAX: 79 return getdtablesize(); 80 case _SC_REGEXP: 81 return 1; 82 case _SC_SAVED_IDS: 83 return 1; 84 case _SC_SHELL: 85 return 1; 86 case _SC_STREAM_MAX: 87 return STREAM_MAX; 88 case _SC_SYMLOOP_MAX: 89 return SYMLOOP_MAX; 90 case _SC_TTY_NAME_MAX: 91 return TTY_NAME_MAX; 92 case _SC_TZNAME_MAX: 93 return TZNAME_MAX; 94 case _SC_VERSION: 95 return _POSIX_VERSION; 96 case _SC_GETGR_R_SIZE_MAX: 97 return MAX_GROUP_BUFFER_SIZE; 98 case _SC_GETPW_R_SIZE_MAX: 99 return MAX_PASSWD_BUFFER_SIZE; 100 case _SC_PAGE_SIZE: 101 return B_PAGE_SIZE; 102 case _SC_SEM_NSEMS_MAX: 103 return _POSIX_SEM_NSEMS_MAX; 104 case _SC_SEM_VALUE_MAX: 105 return _POSIX_SEM_VALUE_MAX; 106 case _SC_SEMAPHORES: 107 return _POSIX_SEMAPHORES; 108 case _SC_THREADS: 109 return _POSIX_THREADS; 110 case _SC_IOV_MAX: 111 return IOV_MAX; 112 case _SC_NPROCESSORS_CONF: 113 { 114 system_info info; 115 err = get_system_info(&info); 116 if (err < B_OK) { 117 __set_errno(err); 118 return -1; 119 } 120 return info.cpu_count; 121 } 122 case _SC_NPROCESSORS_ONLN: 123 { 124 system_info info; 125 unsigned int i; 126 int count = 0; 127 err = get_system_info(&info); 128 if (err < B_OK) { 129 __set_errno(err); 130 return -1; 131 } 132 for (i = 0; i < info.cpu_count; i++) 133 if (_kern_cpu_enabled(i)) 134 count++; 135 return count; 136 } 137 case _SC_ATEXIT_MAX: 138 return ATEXIT_MAX; 139 case _SC_PASS_MAX: 140 break; 141 //XXX:return PASS_MAX; 142 case _SC_PHYS_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; 151 } 152 case _SC_AVPHYS_PAGES: 153 { 154 system_info info; 155 err = get_system_info(&info); 156 if (err < B_OK) { 157 __set_errno(err); 158 return -1; 159 } 160 return info.max_pages - info.used_pages; 161 } 162 case _SC_MAPPED_FILES: 163 return _POSIX_MAPPED_FILES; 164 case _SC_THREAD_PROCESS_SHARED: 165 return _POSIX_THREAD_PROCESS_SHARED; 166 case _SC_THREAD_STACK_MIN: 167 return MIN_USER_STACK_SIZE; 168 case _SC_THREAD_ATTR_STACKADDR: 169 return _POSIX_THREAD_ATTR_STACKADDR; 170 case _SC_THREAD_ATTR_STACKSIZE: 171 return _POSIX_THREAD_ATTR_STACKSIZE; 172 case _SC_THREAD_PRIORITY_SCHEDULING: 173 return _POSIX_THREAD_PRIORITY_SCHEDULING; 174 case _SC_REALTIME_SIGNALS: 175 return _POSIX_REALTIME_SIGNALS; 176 case _SC_MEMORY_PROTECTION: 177 return _POSIX_MEMORY_PROTECTION; 178 case _SC_SIGQUEUE_MAX: 179 return MAX_QUEUED_SIGNALS; 180 case _SC_RTSIG_MAX: 181 return SIGRTMAX - SIGRTMIN + 1; 182 case _SC_MONOTONIC_CLOCK: 183 return _POSIX_MONOTONIC_CLOCK; 184 case _SC_DELAYTIMER_MAX: 185 return MAX_USER_TIMER_OVERRUN_COUNT; 186 case _SC_TIMER_MAX: 187 return MAX_USER_TIMERS_PER_TEAM; 188 case _SC_TIMERS: 189 return _POSIX_TIMERS; 190 case _SC_CPUTIME: 191 return _POSIX_CPUTIME; 192 case _SC_THREAD_CPUTIME: 193 return _POSIX_THREAD_CPUTIME; 194 195 // not POSIX (anymore) 196 case _SC_PIPE: 197 case _SC_SELECT: 198 case _SC_POLL: 199 return 1; 200 } 201 202 __set_errno(EINVAL); 203 return -1; 204 } 205 206 207 enum { 208 FS_BFS, 209 FS_FAT, 210 FS_EXT, 211 FS_UNKNOWN 212 }; 213 214 215 static int 216 fstype(const char *fsh_name) 217 { 218 if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH)) 219 return FS_BFS; 220 if (!strncmp(fsh_name, "dos", B_OS_NAME_LENGTH)) 221 return FS_FAT; 222 if (!strncmp(fsh_name, "fat", B_OS_NAME_LENGTH)) 223 return FS_FAT; 224 if (!strncmp(fsh_name, "ext2", B_OS_NAME_LENGTH)) 225 return FS_EXT; 226 if (!strncmp(fsh_name, "ext3", B_OS_NAME_LENGTH)) 227 return FS_EXT; 228 return FS_UNKNOWN; 229 } 230 231 232 233 static long 234 __pathconf_common(struct statvfs *fs, struct stat *st, 235 int name) 236 { 237 fs_info info; 238 int ret; 239 ret = fs_stat_dev(fs->f_fsid, &info); 240 if (ret < 0) { 241 __set_errno(ret); 242 return -1; 243 } 244 245 // TODO: many cases should check for file type from st. 246 switch (name) { 247 case _PC_CHOWN_RESTRICTED: 248 return _POSIX_CHOWN_RESTRICTED; 249 250 case _PC_MAX_CANON: 251 return MAX_CANON; 252 253 case _PC_MAX_INPUT: 254 return MAX_INPUT; 255 256 case _PC_NAME_MAX: 257 return fs->f_namemax; 258 //return NAME_MAX; 259 260 case _PC_NO_TRUNC: 261 return _POSIX_NO_TRUNC; 262 263 case _PC_PATH_MAX: 264 return PATH_MAX; 265 266 case _PC_PIPE_BUF: 267 return VFS_FIFO_ATOMIC_WRITE_SIZE; 268 269 case _PC_LINK_MAX: 270 return LINK_MAX; 271 272 case _PC_VDISABLE: 273 return _POSIX_VDISABLE; 274 275 case _PC_FILESIZEBITS: 276 { 277 int type = fstype(info.fsh_name); 278 switch (type) { 279 case FS_BFS: 280 case FS_EXT: 281 return 64; 282 case FS_FAT: 283 return 32; 284 } 285 // XXX: add fs ? add to statvfs/fs_info ? 286 return FILESIZEBITS; 287 } 288 289 case _PC_SYMLINK_MAX: 290 return SYMLINK_MAX; 291 292 case _PC_2_SYMLINKS: 293 { 294 int type = fstype(info.fsh_name); 295 switch (type) { 296 case FS_BFS: 297 case FS_EXT: 298 return 1; 299 case FS_FAT: 300 return 0; 301 } 302 // XXX: there should be an HAS_SYMLINKS flag 303 // to fs_info... 304 return 1; 305 } 306 307 case _PC_XATTR_EXISTS: 308 case _PC_XATTR_ENABLED: 309 { 310 #if 0 311 /* those seem to be Solaris specific, 312 * else we should return 1 I suppose. 313 * we don't yet map POSIX xattrs 314 * to BFS ones anyway. 315 */ 316 if (info.flags & B_FS_HAS_ATTR) 317 return 1; 318 return -1; 319 #endif 320 __set_errno(EINVAL); 321 return -1; 322 } 323 324 case _PC_SYNC_IO: 325 case _PC_ASYNC_IO: 326 case _PC_PRIO_IO: 327 case _PC_SOCK_MAXBUF: 328 case _PC_REC_INCR_XFER_SIZE: 329 case _PC_REC_MAX_XFER_SIZE: 330 case _PC_REC_MIN_XFER_SIZE: 331 case _PC_REC_XFER_ALIGN: 332 case _PC_ALLOC_SIZE_MIN: 333 /* not yet supported */ 334 __set_errno(EINVAL); 335 return -1; 336 337 } 338 339 __set_errno(EINVAL); 340 return -1; 341 } 342 343 344 long 345 fpathconf(int fd, int name) 346 { 347 struct statvfs fs; 348 struct stat st; 349 int ret; 350 if (fd < 0) { 351 __set_errno(EBADF); 352 return -1; 353 } 354 ret = fstat(fd, &st); 355 if (ret < 0) 356 return ret; 357 ret = fstatvfs(fd, &fs); 358 if (ret < 0) 359 return ret; 360 return __pathconf_common(&fs, &st, name); 361 } 362 363 364 long 365 pathconf(const char *path, int name) 366 { 367 struct statvfs fs; 368 struct stat st; 369 int ret; 370 if (path == NULL) { 371 __set_errno(EFAULT); 372 return -1; 373 } 374 ret = lstat(path, &st); 375 if (ret < 0) 376 return ret; 377 ret = statvfs(path, &fs); 378 if (ret < 0) 379 return ret; 380 return __pathconf_common(&fs, &st, name); 381 } 382 383 384 size_t 385 confstr(int name, char *buffer, size_t length) 386 { 387 const char *string = ""; 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 strlcpy(buffer, string, length); 401 402 return strlen(string) + 1; 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