2011-12-22 15:19:25 +00:00
|
|
|
/*
|
|
|
|
* \brief libc file operations
|
|
|
|
* \author Christian Prochaska
|
|
|
|
* \author Norman Feske
|
2017-02-01 10:28:15 +00:00
|
|
|
* \author Emery Hemingway
|
|
|
|
* \author Christian Helmuth
|
2011-12-22 15:19:25 +00:00
|
|
|
* \date 2010-01-21
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-01 10:28:15 +00:00
|
|
|
* Copyright (C) 2010-2017 Genode Labs GmbH
|
2011-12-22 15:19:25 +00:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 12:23:52 +00:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2011-12-22 15:19:25 +00:00
|
|
|
*/
|
|
|
|
|
2012-05-18 15:04:52 +00:00
|
|
|
/* Genode includes */
|
2011-12-22 15:19:25 +00:00
|
|
|
#include <base/env.h>
|
2012-10-08 12:44:31 +00:00
|
|
|
#include <os/path.h>
|
|
|
|
#include <util/token.h>
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-05-18 15:04:52 +00:00
|
|
|
/* Genode-specific libc interfaces */
|
2011-12-22 15:19:25 +00:00
|
|
|
#include <libc-plugin/plugin_registry.h>
|
|
|
|
#include <libc-plugin/plugin.h>
|
|
|
|
|
2012-05-18 15:04:52 +00:00
|
|
|
/* libc includes */
|
2011-12-22 15:19:25 +00:00
|
|
|
#include <dirent.h>
|
2012-10-08 12:44:31 +00:00
|
|
|
#include <errno.h>
|
2012-01-09 20:01:53 +00:00
|
|
|
#include <fcntl.h>
|
2011-12-22 15:19:25 +00:00
|
|
|
#include <stdlib.h>
|
2012-10-08 12:44:31 +00:00
|
|
|
#include <string.h>
|
2011-12-22 15:19:25 +00:00
|
|
|
#include <sys/types.h>
|
2012-01-09 20:01:53 +00:00
|
|
|
#include <unistd.h>
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-05-18 15:04:52 +00:00
|
|
|
/* libc-internal includes */
|
2015-06-29 15:02:08 +00:00
|
|
|
#include "libc_file.h"
|
2012-05-18 15:04:52 +00:00
|
|
|
#include "libc_mem_alloc.h"
|
2012-08-17 06:27:15 +00:00
|
|
|
#include "libc_mmap_registry.h"
|
2012-05-18 15:04:52 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
using namespace Libc;
|
|
|
|
|
|
|
|
|
2012-08-17 06:27:15 +00:00
|
|
|
Libc::Mmap_registry *Libc::mmap_registry()
|
|
|
|
{
|
|
|
|
static Libc::Mmap_registry registry;
|
|
|
|
return ®istry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
/***************
|
|
|
|
** Utilities **
|
|
|
|
***************/
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
/**
|
|
|
|
* Current working directory
|
|
|
|
*/
|
|
|
|
static Absolute_path &cwd()
|
|
|
|
{
|
|
|
|
static Absolute_path _cwd("/");
|
|
|
|
return _cwd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* path element token
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct Scanner_policy_path_element
|
|
|
|
{
|
|
|
|
static bool identifier_char(char c, unsigned /* i */)
|
|
|
|
{
|
|
|
|
return (c != '/') && (c != 0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Genode::Token<Scanner_policy_path_element> Path_element_token;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolve symbolic links in a given absolute path
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* exception */
|
|
|
|
class Symlink_resolve_error { };
|
|
|
|
|
|
|
|
static void resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|
|
|
{
|
|
|
|
char path_element[PATH_MAX];
|
|
|
|
char symlink_target[PATH_MAX];
|
|
|
|
|
|
|
|
Absolute_path current_iteration_working_path;
|
|
|
|
Absolute_path next_iteration_working_path(path, cwd().base());
|
|
|
|
|
|
|
|
enum { FOLLOW_LIMIT = 10 };
|
|
|
|
int follow_count = 0;
|
|
|
|
bool symlink_resolved_in_this_iteration;
|
|
|
|
do {
|
|
|
|
if (follow_count++ == FOLLOW_LIMIT) {
|
|
|
|
errno = ELOOP;
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
}
|
|
|
|
|
2016-05-31 10:40:35 +00:00
|
|
|
current_iteration_working_path = next_iteration_working_path;
|
2012-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
next_iteration_working_path.import("");
|
|
|
|
symlink_resolved_in_this_iteration = false;
|
|
|
|
|
|
|
|
Path_element_token t(current_iteration_working_path.base());
|
|
|
|
|
|
|
|
while (t) {
|
|
|
|
if (t.type() != Path_element_token::IDENT) {
|
|
|
|
t = t.next();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
t.string(path_element, sizeof(path_element));
|
|
|
|
|
|
|
|
try {
|
2016-05-12 10:50:16 +00:00
|
|
|
next_iteration_working_path.append_element(path_element);
|
2012-10-08 12:44:31 +00:00
|
|
|
} catch (Genode::Path_base::Path_too_long) {
|
|
|
|
errno = ENAMETOOLONG;
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If a symlink has been resolved in this iteration, the remaining
|
|
|
|
* path elements get added and a new iteration starts.
|
|
|
|
*/
|
|
|
|
if (!symlink_resolved_in_this_iteration) {
|
|
|
|
struct stat stat_buf;
|
|
|
|
int res;
|
|
|
|
FNAME_FUNC_WRAPPER_GENERIC(res = , stat, next_iteration_working_path.base(), &stat_buf);
|
|
|
|
if (res == -1) {
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
}
|
|
|
|
if (S_ISLNK(stat_buf.st_mode)) {
|
|
|
|
FNAME_FUNC_WRAPPER_GENERIC(res = , readlink,
|
|
|
|
next_iteration_working_path.base(),
|
2014-01-20 16:17:58 +00:00
|
|
|
symlink_target, sizeof(symlink_target) - 1);
|
2012-10-08 12:44:31 +00:00
|
|
|
if (res < 1)
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
|
2014-01-20 16:17:58 +00:00
|
|
|
/* zero terminate target */
|
|
|
|
symlink_target[res] = 0;
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
if (symlink_target[0] == '/')
|
|
|
|
/* absolute target */
|
|
|
|
next_iteration_working_path.import(symlink_target, cwd().base());
|
|
|
|
else {
|
|
|
|
/* relative target */
|
|
|
|
next_iteration_working_path.strip_last_element();
|
|
|
|
try {
|
2016-05-12 10:50:16 +00:00
|
|
|
next_iteration_working_path.append_element(symlink_target);
|
2012-10-08 12:44:31 +00:00
|
|
|
} catch (Genode::Path_base::Path_too_long) {
|
|
|
|
errno = ENAMETOOLONG;
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
symlink_resolved_in_this_iteration = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t = t.next();
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (symlink_resolved_in_this_iteration);
|
|
|
|
|
2016-05-31 10:40:35 +00:00
|
|
|
resolved_path = next_iteration_working_path;
|
2016-03-11 15:39:22 +00:00
|
|
|
resolved_path.remove_trailing('/');
|
2012-10-08 12:44:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void resolve_symlinks_except_last_element(char const *path, Absolute_path &resolved_path)
|
|
|
|
{
|
|
|
|
Absolute_path absolute_path_without_last_element(path, cwd().base());
|
|
|
|
absolute_path_without_last_element.strip_last_element();
|
|
|
|
|
|
|
|
resolve_symlinks(absolute_path_without_last_element.base(), resolved_path);
|
|
|
|
|
|
|
|
/* append last element to resolved path */
|
|
|
|
Absolute_path absolute_path_last_element(path, cwd().base());
|
|
|
|
absolute_path_last_element.keep_only_last_element();
|
|
|
|
try {
|
2016-05-12 10:50:16 +00:00
|
|
|
resolved_path.append_element(absolute_path_last_element.base());
|
2012-10-08 12:44:31 +00:00
|
|
|
} catch (Genode::Path_base::Path_too_long) {
|
|
|
|
errno = ENAMETOOLONG;
|
|
|
|
throw Symlink_resolve_error();
|
|
|
|
}
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
/********************
|
|
|
|
** Libc functions **
|
|
|
|
********************/
|
|
|
|
|
2015-09-18 09:10:29 +00:00
|
|
|
extern "C" int access(const char *path, int amode)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(access, resolved_path.base(), amode);
|
|
|
|
} catch (Symlink_resolve_error) {
|
|
|
|
errno = ENOENT;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
extern "C" int chdir(const char *path)
|
|
|
|
{
|
|
|
|
struct stat stat_buf;
|
|
|
|
if ((stat(path, &stat_buf) == -1) ||
|
|
|
|
(!S_ISDIR(stat_buf.st_mode))) {
|
|
|
|
errno = ENOTDIR;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
cwd().import(path, cwd().base());
|
|
|
|
return 0;
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
2017-02-01 10:28:15 +00:00
|
|
|
extern "C" int _close(int libc_fd)
|
|
|
|
{
|
|
|
|
FD_FUNC_WRAPPER(close, libc_fd);
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
extern "C" int close(int libc_fd) { return _close(libc_fd); }
|
|
|
|
|
|
|
|
|
2012-11-09 16:39:04 +00:00
|
|
|
extern "C" int _dup(int libc_fd)
|
|
|
|
{
|
2013-09-04 19:44:01 +00:00
|
|
|
File_descriptor *ret_fd;
|
|
|
|
FD_FUNC_WRAPPER_GENERIC(ret_fd =, 0, dup, libc_fd);
|
2012-11-09 16:39:04 +00:00
|
|
|
return ret_fd ? ret_fd->libc_fd : INVALID_FD;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int dup(int libc_fd)
|
|
|
|
{
|
|
|
|
return _dup(libc_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" int _dup2(int libc_fd, int new_libc_fd)
|
|
|
|
{
|
|
|
|
File_descriptor *fd = libc_fd_to_fd(libc_fd, "dup2");
|
2013-09-04 19:44:01 +00:00
|
|
|
if (!fd || !fd->plugin) {
|
|
|
|
errno = EBADF;
|
2011-12-22 15:19:25 +00:00
|
|
|
return INVALID_FD;
|
2013-09-04 19:44:01 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2013-02-21 15:39:46 +00:00
|
|
|
if (libc_fd == new_libc_fd)
|
|
|
|
return libc_fd;
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
/*
|
|
|
|
* Check if 'new_libc_fd' is already in use. If so, close it before
|
|
|
|
* allocating it again.
|
|
|
|
*/
|
|
|
|
File_descriptor *new_fd = file_descriptor_allocator()->find_by_libc_fd(new_libc_fd);
|
|
|
|
if (new_fd)
|
|
|
|
close(new_libc_fd);
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
new_fd = file_descriptor_allocator()->alloc(fd->plugin, 0, new_libc_fd);
|
|
|
|
new_fd->path(fd->fd_path);
|
2011-12-22 15:19:25 +00:00
|
|
|
/* new_fd->context must be assigned by the plugin implementing 'dup2' */
|
|
|
|
return fd->plugin->dup2(fd, new_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int dup2(int libc_fd, int new_libc_fd)
|
|
|
|
{
|
|
|
|
return _dup2(libc_fd, new_libc_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
extern "C" int _execve(char const *filename, char *const argv[],
|
|
|
|
char *const envp[])
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks(filename, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(execve, resolved_path.base(), argv, envp);
|
|
|
|
} catch (Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int execve(char const *filename, char *const argv[],
|
|
|
|
char *const envp[])
|
|
|
|
{
|
|
|
|
return _execve(filename, argv, envp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int fchdir(int libc_fd)
|
|
|
|
{
|
|
|
|
File_descriptor *fd = libc_fd_to_fd(libc_fd, "fchdir");
|
|
|
|
|
2013-09-04 19:44:01 +00:00
|
|
|
if (!fd) {
|
|
|
|
errno = EBADF;
|
2012-10-08 12:44:31 +00:00
|
|
|
return INVALID_FD;
|
2013-09-04 19:44:01 +00:00
|
|
|
}
|
2012-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
return chdir(fd->fd_path);
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
2012-01-09 20:01:53 +00:00
|
|
|
extern "C" int fcntl(int libc_fd, int cmd, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int res;
|
|
|
|
va_start(ap, cmd);
|
2013-09-04 19:44:01 +00:00
|
|
|
FD_FUNC_WRAPPER_GENERIC(res =, INVALID_FD, fcntl, libc_fd, cmd, va_arg(ap, long));
|
2012-01-09 20:01:53 +00:00
|
|
|
va_end(ap);
|
|
|
|
return res;
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
extern "C" int _fcntl(int libc_fd, int cmd, long arg) {
|
|
|
|
return fcntl(libc_fd, cmd, arg); }
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int _fstat(int libc_fd, struct stat *buf) {
|
|
|
|
FD_FUNC_WRAPPER(fstat, libc_fd, buf); }
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int fstat(int libc_fd, struct stat *buf)
|
|
|
|
{
|
|
|
|
return _fstat(libc_fd, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-28 17:44:46 +00:00
|
|
|
extern "C" int fstatat(int libc_fd, char const *path, struct stat *buf, int flags)
|
|
|
|
{
|
|
|
|
if (*path == '/') {
|
|
|
|
if (flags & AT_SYMLINK_NOFOLLOW)
|
|
|
|
return lstat(path, buf);
|
|
|
|
return stat(path, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
Libc::Absolute_path abs_path;
|
|
|
|
|
|
|
|
if (libc_fd == AT_FDCWD) {
|
2016-05-31 10:40:35 +00:00
|
|
|
abs_path = cwd();
|
2016-05-12 10:50:16 +00:00
|
|
|
abs_path.append_element(path);
|
2015-11-28 17:44:46 +00:00
|
|
|
} else {
|
|
|
|
Libc::File_descriptor *fd =
|
|
|
|
Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
|
|
|
|
if (!fd) {
|
|
|
|
errno = EBADF;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
abs_path.import(path, fd->fd_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (flags & AT_SYMLINK_NOFOLLOW)
|
|
|
|
? lstat(abs_path.base(), buf)
|
|
|
|
: stat(abs_path.base(), buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" int _fstatfs(int libc_fd, struct statfs *buf) {
|
|
|
|
FD_FUNC_WRAPPER(fstatfs, libc_fd, buf); }
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int fsync(int libc_fd) {
|
|
|
|
FD_FUNC_WRAPPER(fsync, libc_fd); }
|
|
|
|
|
|
|
|
|
2012-08-02 13:17:24 +00:00
|
|
|
extern "C" int ftruncate(int libc_fd, ::off_t length) {
|
|
|
|
FD_FUNC_WRAPPER(ftruncate, libc_fd, length); }
|
|
|
|
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" ssize_t _getdirentries(int libc_fd, char *buf, ::size_t nbytes, ::off_t *basep) {
|
|
|
|
FD_FUNC_WRAPPER(getdirentries, libc_fd, buf, nbytes, basep); }
|
|
|
|
|
|
|
|
|
2012-05-24 13:26:59 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" int ioctl(int libc_fd, int request, char *argp) {
|
|
|
|
FD_FUNC_WRAPPER(ioctl, libc_fd, request, argp); }
|
|
|
|
|
|
|
|
|
2011-12-26 19:08:58 +00:00
|
|
|
extern "C" int _ioctl(int libc_fd, int request, char *argp) {
|
|
|
|
FD_FUNC_WRAPPER(ioctl, libc_fd, request, argp); }
|
|
|
|
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" ::off_t lseek(int libc_fd, ::off_t offset, int whence) {
|
|
|
|
FD_FUNC_WRAPPER(lseek, libc_fd, offset, whence); }
|
|
|
|
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
extern "C" int lstat(const char *path, struct stat *buf)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
|
|
|
} catch (Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int mkdir(const char *path, mode_t mode)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(mkdir, resolved_path.base(), mode);
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
extern "C" void *mmap(void *addr, ::size_t length, int prot, int flags,
|
|
|
|
int libc_fd, ::off_t offset)
|
|
|
|
{
|
2012-08-20 11:52:27 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
/* handle requests for anonymous memory */
|
2012-08-17 06:27:15 +00:00
|
|
|
if (!addr && libc_fd == -1) {
|
|
|
|
void *start = Libc::mem_alloc()->alloc(length, PAGE_SHIFT);
|
|
|
|
mmap_registry()->insert(start, length, 0);
|
|
|
|
return start;
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
/* lookup plugin responsible for file descriptor */
|
|
|
|
File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap");
|
2012-08-17 06:27:15 +00:00
|
|
|
if (!fd || !fd->plugin || !fd->plugin->supports_mmap()) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::warning("mmap not supported for file descriptor ", libc_fd);
|
2013-09-04 19:44:01 +00:00
|
|
|
errno = EBADF;
|
2011-12-22 15:19:25 +00:00
|
|
|
return (void *)INVALID_FD;
|
|
|
|
}
|
|
|
|
|
2012-08-17 06:27:15 +00:00
|
|
|
void *start = fd->plugin->mmap(addr, length, prot, flags, fd, offset);
|
|
|
|
mmap_registry()->insert(start, length, fd->plugin);
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-20 11:52:27 +00:00
|
|
|
extern "C" int munmap(void *start, ::size_t length)
|
2012-08-17 06:27:15 +00:00
|
|
|
{
|
2016-05-11 16:21:47 +00:00
|
|
|
if (!mmap_registry()->registered(start)) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::warning("munmap: could not lookup plugin for address ", start);
|
2012-08-17 06:27:15 +00:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup plugin that was used for mmap
|
|
|
|
*
|
|
|
|
* If the pointer is NULL, 'start' refers to an anonymous mmap.
|
|
|
|
*/
|
|
|
|
Plugin *plugin = mmap_registry()->lookup_plugin_by_addr(start);
|
|
|
|
|
2012-08-20 11:52:27 +00:00
|
|
|
int ret = 0;
|
|
|
|
if (plugin)
|
|
|
|
ret = plugin->munmap(start, length);
|
|
|
|
else
|
2012-08-17 06:27:15 +00:00
|
|
|
Libc::mem_alloc()->free(start);
|
|
|
|
|
2012-08-20 11:52:27 +00:00
|
|
|
mmap_registry()->remove(start);
|
|
|
|
return ret;
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int _open(const char *pathname, int flags, ::mode_t mode)
|
|
|
|
{
|
2012-10-08 12:44:31 +00:00
|
|
|
Absolute_path resolved_path;
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
Plugin *plugin;
|
|
|
|
File_descriptor *new_fdo;
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
try {
|
|
|
|
resolve_symlinks_except_last_element(pathname, resolved_path);
|
|
|
|
} catch (Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & O_NOFOLLOW)) {
|
|
|
|
/* resolve last element */
|
|
|
|
try {
|
|
|
|
resolve_symlinks(resolved_path.base(), resolved_path);
|
|
|
|
} catch (Symlink_resolve_error) {
|
|
|
|
if (errno == ENOENT) {
|
|
|
|
if (!(flags & O_CREAT))
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
plugin = plugin_registry()->get_plugin_for_open(resolved_path.base(), flags);
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
if (!plugin) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::error("no plugin found for open(\"", pathname, "\", ", flags, ")");
|
2011-12-22 15:19:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
new_fdo = plugin->open(resolved_path.base(), flags);
|
2011-12-22 15:19:25 +00:00
|
|
|
if (!new_fdo) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::error("plugin()->open(\"", pathname, "\") failed");
|
2011-12-22 15:19:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-10-08 12:44:31 +00:00
|
|
|
new_fdo->path(resolved_path.base());
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
return new_fdo->libc_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-09 20:01:53 +00:00
|
|
|
extern "C" int open(const char *pathname, int flags, ...)
|
2011-12-22 15:19:25 +00:00
|
|
|
{
|
2012-01-09 20:01:53 +00:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, flags);
|
|
|
|
int res = _open(pathname, flags, va_arg(ap, unsigned));
|
|
|
|
va_end(ap);
|
|
|
|
return res;
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int pipe(int pipefd[2])
|
|
|
|
{
|
|
|
|
Plugin *plugin;
|
|
|
|
File_descriptor *pipefdo[2];
|
|
|
|
|
|
|
|
plugin = plugin_registry()->get_plugin_for_pipe();
|
|
|
|
|
|
|
|
if (!plugin) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::error("no plugin found for pipe()");
|
2011-12-22 15:19:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (plugin->pipe(pipefdo) == -1) {
|
base: avoid use of deprecated base/printf.h
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
2016-07-13 17:07:09 +00:00
|
|
|
Genode::error("plugin()->pipe() failed");
|
2011-12-22 15:19:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipefd[0] = pipefdo[0]->libc_fd;
|
|
|
|
pipefd[1] = pipefdo[1]->libc_fd;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-01 10:28:15 +00:00
|
|
|
extern "C" ssize_t _read(int libc_fd, void *buf, ::size_t count)
|
|
|
|
{
|
|
|
|
FD_FUNC_WRAPPER(read, libc_fd, buf, count);
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
extern "C" ssize_t read(int libc_fd, void *buf, ::size_t count)
|
|
|
|
{
|
|
|
|
return _read(libc_fd, buf, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 12:40:37 +00:00
|
|
|
extern "C" ssize_t readlink(const char *path, char *buf, ::size_t bufsiz)
|
2012-10-08 12:44:31 +00:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(readlink, resolved_path.base(), buf, bufsiz);
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int rename(const char *oldpath, const char *newpath)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_oldpath, resolved_newpath;
|
|
|
|
resolve_symlinks_except_last_element(oldpath, resolved_oldpath);
|
|
|
|
resolve_symlinks_except_last_element(newpath, resolved_newpath);
|
|
|
|
FNAME_FUNC_WRAPPER(rename, resolved_oldpath.base(), resolved_newpath.base());
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
2014-04-18 20:58:04 +00:00
|
|
|
extern "C" int rmdir(const char *path)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(rmdir, resolved_path.base());
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
extern "C" int stat(const char *path, struct stat *buf)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" int symlink(const char *oldpath, const char *newpath)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(newpath, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(symlink, oldpath, resolved_path.base());
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
extern "C" int unlink(const char *path)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
Absolute_path resolved_path;
|
|
|
|
resolve_symlinks_except_last_element(path, resolved_path);
|
|
|
|
FNAME_FUNC_WRAPPER(unlink, resolved_path.base());
|
|
|
|
} catch(Symlink_resolve_error) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
|
|
|
|
2012-10-08 13:38:35 +00:00
|
|
|
extern "C" ssize_t _write(int libc_fd, const void *buf, ::size_t count)
|
|
|
|
{
|
|
|
|
int flags = fcntl(libc_fd, F_GETFL);
|
|
|
|
|
|
|
|
if ((flags != -1) && (flags & O_APPEND))
|
|
|
|
lseek(libc_fd, 0, SEEK_END);
|
|
|
|
|
|
|
|
FD_FUNC_WRAPPER(write, libc_fd, buf, count);
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-10-08 12:44:31 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
extern "C" ssize_t write(int libc_fd, const void *buf, ::size_t count) {
|
|
|
|
return _write(libc_fd, buf, count); }
|
2012-10-08 12:44:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
extern "C" int __getcwd(char *dst, ::size_t dst_size)
|
|
|
|
{
|
|
|
|
Genode::strncpy(dst, cwd().base(), dst_size);
|
|
|
|
return 0;
|
|
|
|
}
|