mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-10 06:52:56 +00:00
17c79a9e23
Besides adapting the components to the use of base/log.h, the patch cleans up a few base headers, i.e., it removes unused includes from root/component.h, specifically base/heap.h and ram_session/ram_session.h. Hence, components that relied on the implicit inclusion of those headers have to manually include those headers now. While adjusting the log messages, I repeatedly stumbled over the problem that printing char * arguments is ambiguous. It is unclear whether to print the argument as pointer or null-terminated string. To overcome this problem, the patch introduces a new type 'Cstring' that allows the caller to express that the argument should be handled as null-terminated string. As a nice side effect, with this type in place, the optional len argument of the 'String' class could be removed. Instead of supplying a pair of (char const *, size_t), the constructor accepts a 'Cstring'. This, in turn, clears the way let the 'String' constructor use the new output mechanism to assemble a string from multiple arguments (and thereby getting rid of snprintf within Genode in the near future). To enforce the explicit resolution of the char * ambiguity, the 'char *' overload of the 'print' function is marked as deleted. Issue #1987
258 lines
5.9 KiB
C++
258 lines
5.9 KiB
C++
/*
|
|
* \brief Sysctl facade
|
|
* \author Emery Hemingway
|
|
* \date 2016-04-27
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2016 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <util/string.h>
|
|
#include <base/env.h>
|
|
|
|
/* Genode-specific libc interfaces */
|
|
#include <libc-plugin/plugin.h>
|
|
#include <libc-plugin/fd_alloc.h>
|
|
|
|
/* Libc includes */
|
|
#include <sys/sysctl.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "libc_errno.h"
|
|
|
|
|
|
enum { PAGESIZE = 4096 };
|
|
|
|
|
|
extern "C" long sysconf(int name)
|
|
{
|
|
switch (name) {
|
|
case _SC_CHILD_MAX: return CHILD_MAX;
|
|
case _SC_OPEN_MAX: return getdtablesize();
|
|
case _SC_NPROCESSORS_CONF: return 1;
|
|
case _SC_NPROCESSORS_ONLN: return 1;
|
|
case _SC_PAGESIZE: return PAGESIZE;
|
|
|
|
case _SC_PHYS_PAGES:
|
|
return Genode::env()->ram_session()->quota() / PAGESIZE;
|
|
default:
|
|
Genode::warning(__func__, "(", name, ") not implemented");
|
|
return Libc::Errno(EINVAL);
|
|
}
|
|
}
|
|
|
|
|
|
/* non-standard FreeBSD function not supported */
|
|
extern "C" int sysctlbyname(char const *name, void *oldp, size_t *oldlenp,
|
|
void *newp, size_t newlen)
|
|
{
|
|
Genode::warning(__func__, "(", name, ",...) not implemented");
|
|
return Libc::Errno(ENOENT);
|
|
}
|
|
|
|
|
|
extern "C" int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
|
|
void *newp, size_t newlen)
|
|
{
|
|
static const ctlname ctl_names[] = CTL_NAMES;
|
|
static const ctlname ctl_kern_names[] = CTL_KERN_NAMES;
|
|
static const ctlname ctl_hw_names[] = CTL_HW_NAMES;
|
|
static const ctlname ctl_user_names[] = CTL_USER_NAMES;
|
|
static const ctlname ctl_p1003_1b_names[] = CTL_P1003_1B_NAMES;
|
|
|
|
/* read only */
|
|
if (!oldp) /* check for write attempt */
|
|
return Libc::Errno(newp ? EPERM : EINVAL);
|
|
|
|
ctlname const *ctl = nullptr;
|
|
char *buf = (char*)oldp;
|
|
int index_a = name[0];
|
|
int index_b = name[1];
|
|
|
|
if (namelen != 2) return Libc::Errno(ENOENT);
|
|
if (index_a >= CTL_MAXID) return Libc::Errno(EINVAL);
|
|
|
|
switch(index_a) {
|
|
case CTL_KERN:
|
|
if (index_b >= KERN_MAXID) return Libc::Errno(EINVAL);
|
|
ctl = &ctl_kern_names[index_b]; break;
|
|
|
|
case CTL_HW:
|
|
if (index_b >= HW_MAXID) return Libc::Errno(EINVAL);
|
|
ctl = &ctl_hw_names[index_b]; break;
|
|
|
|
case CTL_USER:
|
|
if (index_b >= USER_MAXID) return Libc::Errno(EINVAL);
|
|
ctl = &ctl_user_names[index_b]; break;
|
|
|
|
case CTL_P1003_1B:
|
|
if (index_b >= CTL_P1003_1B_MAXID) return Libc::Errno(EINVAL);
|
|
ctl = &ctl_p1003_1b_names[index_b]; break;
|
|
}
|
|
|
|
if (!ctl) return Libc::Errno(EINVAL);
|
|
|
|
if (((ctl->ctl_type == CTLTYPE_INT) && (*oldlenp < sizeof(int))) ||
|
|
((ctl->ctl_type == CTLTYPE_STRING) && (*oldlenp < 1)) ||
|
|
((ctl->ctl_type == CTLTYPE_QUAD) && (*oldlenp < sizeof(Genode::uint64_t))) ||
|
|
((ctl->ctl_type == CTLTYPE_UINT) && (*oldlenp < sizeof(unsigned int))) ||
|
|
((ctl->ctl_type == CTLTYPE_LONG) && (*oldlenp < sizeof(long))) ||
|
|
((ctl->ctl_type == CTLTYPE_ULONG) && (*oldlenp < sizeof(unsigned long))))
|
|
{
|
|
return Libc::Errno(EINVAL);
|
|
}
|
|
|
|
/* builtins */
|
|
{
|
|
switch(index_a) {
|
|
case CTL_HW: switch(index_b) {
|
|
|
|
case HW_PHYSMEM:
|
|
case HW_USERMEM:
|
|
*(unsigned long*)oldp = Genode::env()->ram_session()->quota();
|
|
*oldlenp = sizeof(unsigned long);
|
|
return 0;
|
|
|
|
case HW_PAGESIZE:
|
|
*(int*)oldp = (int)PAGESIZE;
|
|
*oldlenp = sizeof(int);
|
|
return 0;
|
|
|
|
} break;
|
|
|
|
case CTL_P1003_1B: switch(index_b) {
|
|
|
|
case CTL_P1003_1B_PAGESIZE:
|
|
*(int*)oldp = PAGESIZE;
|
|
*oldlenp = sizeof(int);
|
|
return 0;
|
|
|
|
} break;
|
|
}
|
|
}
|
|
|
|
|
|
/* runtime overrides */
|
|
{
|
|
Libc::Absolute_path sysctl_path(ctl_names[index_a].ctl_name, "/.sysctl/");
|
|
sysctl_path.append("/");
|
|
sysctl_path.append(ctl->ctl_name);
|
|
|
|
/*
|
|
* read from /.sysctl/...
|
|
*
|
|
* The abstracted libc interface is used to read files here
|
|
* rather than to explicity resolve a file system plugin.
|
|
*/
|
|
int fd = open(sysctl_path.base(), 0);
|
|
if (fd != -1) {
|
|
auto n = read(fd, buf, *oldlenp);
|
|
close(fd);
|
|
|
|
if (n > 0) switch (ctl->ctl_type) {
|
|
case CTLTYPE_INT: {
|
|
long value = 0;
|
|
Genode::ascii_to((char*)oldp, value);
|
|
*(int*)oldp = int(value);
|
|
*oldlenp = sizeof(int);
|
|
return 0;
|
|
}
|
|
|
|
case CTLTYPE_STRING:
|
|
*oldlenp = n;
|
|
return 0;
|
|
|
|
case CTLTYPE_QUAD: {
|
|
Genode::uint64_t value = 0;
|
|
Genode::ascii_to((char*)oldp, value);
|
|
*(Genode::uint64_t*)oldp = value;
|
|
*oldlenp = sizeof(Genode::uint64_t);
|
|
return 0;
|
|
}
|
|
|
|
case CTLTYPE_UINT: {
|
|
unsigned value = 0;
|
|
Genode::ascii_to((char*)oldp, value);
|
|
*(unsigned*)oldp = value;
|
|
*oldlenp = sizeof(unsigned);
|
|
return 0;
|
|
}
|
|
|
|
case CTLTYPE_LONG: {
|
|
long value = 0;
|
|
Genode::ascii_to((char*)oldp, value);
|
|
*(long*)oldp = value;
|
|
*oldlenp = sizeof(long);
|
|
return 0;
|
|
}
|
|
|
|
case CTLTYPE_ULONG: {
|
|
unsigned long value = 0;
|
|
Genode::ascii_to((char*)oldp, value);
|
|
*(unsigned long*)oldp = value;
|
|
*oldlenp = sizeof(unsigned long);
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
Genode::warning("unhandled sysctl data type for ", sysctl_path);
|
|
return Libc::Errno(EINVAL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* fallback values */
|
|
{
|
|
switch(index_a) {
|
|
|
|
case CTL_KERN:
|
|
switch(index_b) {
|
|
case KERN_OSTYPE:
|
|
Genode::strncpy(buf, "Genode", *oldlenp);
|
|
*oldlenp = Genode::strlen(buf);
|
|
return 0;
|
|
|
|
case KERN_OSRELEASE:
|
|
case KERN_OSREV:
|
|
case KERN_VERSION:
|
|
*oldlenp = 0;
|
|
return 0;
|
|
|
|
case KERN_HOSTNAME:
|
|
Genode::strncpy(buf, "localhost", *oldlenp);
|
|
*oldlenp = Genode::strlen(buf);
|
|
return 0;
|
|
|
|
} break;
|
|
|
|
case CTL_HW: switch(index_b) {
|
|
|
|
case HW_MACHINE:
|
|
*oldlenp = 0;
|
|
return 0;
|
|
|
|
case HW_NCPU:
|
|
*(int*)oldp = 1;
|
|
*oldlenp = sizeof(int);
|
|
return 0;
|
|
|
|
} break;
|
|
|
|
}
|
|
}
|
|
|
|
Genode::warning("sysctl: no builtin or override value found for ",
|
|
Genode::Cstring(ctl_names[index_a].ctl_name), ".",
|
|
Genode::Cstring(ctl->ctl_name));
|
|
return Libc::Errno(ENOENT);
|
|
}
|