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