xref: /haiku/src/system/libroot/posix/unistd/conf.cpp (revision 04a0e9c7b68cbe3a43d38e2bca8e860fd80936fb)
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