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