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