blob: d5d80fea4f4ab27abab99532d428c1798eb0b63f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBRARIES_NACL_IO_KERNEL_PROXY_H_
#define LIBRARIES_NACL_IO_KERNEL_PROXY_H_
#include <map>
#include <string>
#include "nacl_io/devfs/dev_fs.h"
#include "nacl_io/event_emitter.h"
#include "nacl_io/fs_factory.h"
#include "nacl_io/host_resolver.h"
#include "nacl_io/kernel_object.h"
#include "nacl_io/nacl_io.h"
#include "nacl_io/ossignal.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/ostypes.h"
#include "nacl_io/osutime.h"
#include "nacl_io/stream/stream_fs.h"
struct fuse_operations;
struct timeval;
namespace nacl_io {
class PepperInterface;
// KernelProxy provide one-to-one mapping for libc kernel calls. Calls to the
// proxy will result in IO access to the provided Filesystem and Node objects.
//
// NOTE: The KernelProxy does not directly take any kernel locks, all locking
// is done by the parent class KernelObject. Instead, KernelProxy is
// responsible for taking the locks of the KernelHandle, and Node objects. For
// this reason, a KernelObject call should not be done while holding a handle
// or node lock. In addition, to ensure locking order, a KernelHandle lock
// must never be taken after taking the associated Node's lock.
//
// NOTE: The KernelProxy is the only class that should be setting errno. All
// other classes should return Error (as defined by nacl_io/error.h).
class KernelProxy : protected KernelObject {
public:
typedef std::map<std::string, FsFactory*> FsFactoryMap_t;
KernelProxy();
virtual ~KernelProxy();
// |ppapi| may be NULL. If so, no filesystem that uses pepper calls can be
// mounted.
virtual Error Init(PepperInterface* ppapi);
// Register/Unregister a new filesystem type. See the documentation in
// nacl_io.h for more info.
bool RegisterFsType(const char* fs_type, fuse_operations* fuse_ops);
bool UnregisterFsType(const char* fs_type);
void SetExitCallback(nacl_io_exit_callback_t exit_callback, void* user_data);
void SetMountCallback(nacl_io_mount_callback_t mount_callback,
void* user_data);
virtual int pipe(int pipefds[2]);
// NaCl-only function to read resources specified in the NMF file.
virtual int open_resource(const char* file);
// KernelHandle and FD allocation and manipulation functions.
virtual int open(const char* path, int open_flags, mode_t mode);
virtual int close(int fd);
virtual int dup(int fd);
virtual int dup2(int fd, int newfd);
virtual void exit(int status);
// Path related System calls handled by KernelProxy (not filesystem-specific)
virtual int chdir(const char* path);
virtual char* getcwd(char* buf, size_t size);
virtual char* getwd(char* buf);
virtual int mount(const char* source,
const char* target,
const char* filesystemtype,
unsigned long mountflags,
const void* data);
virtual int umount(const char* path);
// Stub system calls that don't do anything (yet), handled by KernelProxy.
virtual int chown(const char* path, uid_t owner, gid_t group);
virtual int fchown(int fd, uid_t owner, gid_t group);
virtual int lchown(const char* path, uid_t owner, gid_t group);
// System calls that take a path as an argument: The kernel proxy will look
// for the Node associated to the path. To find the node, the kernel proxy
// calls the corresponding filesystem's GetNode() method. The corresponding
// method will be called. If the node cannot be found, errno is set and -1 is
// returned.
virtual int chmod(const char* path, mode_t mode);
virtual int mkdir(const char* path, mode_t mode);
virtual int rmdir(const char* path);
virtual int stat(const char* path, struct stat* buf);
// System calls that take a file descriptor as an argument:
// The kernel proxy will determine to which filesystem the file
// descriptor's corresponding file handle belongs. The
// associated filesystem's function will be called.
virtual ssize_t read(int fd, void* buf, size_t nbyte);
virtual ssize_t write(int fd, const void* buf, size_t nbyte);
virtual int fchmod(int fd, mode_t mode);
virtual int fcntl(int fd, int request, va_list args);
virtual int fstat(int fd, struct stat* buf);
virtual int getdents(int fd, struct dirent* buf, unsigned int count);
virtual int fchdir(int fd);
virtual int ftruncate(int fd, off_t length);
virtual int fsync(int fd);
virtual int fdatasync(int fd);
virtual int isatty(int fd);
virtual int ioctl(int fd, int request, va_list args);
virtual int futimens(int fd, const struct timespec times[2]);
// lseek() relies on the filesystem's Stat() to determine whether or not the
// file handle corresponding to fd is a directory
virtual off_t lseek(int fd, off_t offset, int whence);
// remove() uses the filesystem's GetNode() and Stat() to determine whether
// or not the path corresponds to a directory or a file. The filesystem's
// Rmdir() or Unlink() is called accordingly.
virtual int remove(const char* path);
// unlink() is a simple wrapper around the filesystem's Unlink function.
virtual int unlink(const char* path);
virtual int truncate(const char* path, off_t len);
virtual int lstat(const char* path, struct stat* buf);
virtual int rename(const char* path, const char* newpath);
// access() uses the Filesystem's Stat().
virtual int access(const char* path, int amode);
virtual int readlink(const char* path, char* buf, size_t count);
virtual int utimens(const char* path, const struct timespec times[2]);
virtual int link(const char* oldpath, const char* newpath);
virtual int symlink(const char* oldpath, const char* newpath);
virtual void* mmap(void* addr,
size_t length,
int prot,
int flags,
int fd,
size_t offset);
virtual int munmap(void* addr, size_t length);
virtual int tcflush(int fd, int queue_selector);
virtual int tcgetattr(int fd, struct termios* termios_p);
virtual int tcsetattr(int fd,
int optional_actions,
const struct termios* termios_p);
virtual int kill(pid_t pid, int sig);
virtual int sigaction(int signum,
const struct sigaction* action,
struct sigaction* oaction);
virtual mode_t umask(mode_t);
#ifdef PROVIDES_SOCKET_API
virtual int select(int nfds,
fd_set* readfds,
fd_set* writefds,
fd_set* exceptfds,
struct timeval* timeout);
virtual int poll(struct pollfd* fds, nfds_t nfds, int timeout);
// Socket support functions
virtual int accept(int fd, struct sockaddr* addr, socklen_t* len);
virtual int bind(int fd, const struct sockaddr* addr, socklen_t len);
virtual int connect(int fd, const struct sockaddr* addr, socklen_t len);
virtual struct hostent* gethostbyname(const char* name);
virtual void freeaddrinfo(struct addrinfo* res);
virtual int getaddrinfo(const char* node,
const char* service,
const struct addrinfo* hints,
struct addrinfo** res);
virtual int getnameinfo(const struct sockaddr *sa,
socklen_t salen,
char *host,
size_t hostlen,
char *serv,
size_t servlen,
int flags);
virtual int getpeername(int fd, struct sockaddr* addr, socklen_t* len);
virtual int getsockname(int fd, struct sockaddr* addr, socklen_t* len);
virtual int getsockopt(int fd,
int lvl,
int optname,
void* optval,
socklen_t* len);
virtual int listen(int fd, int backlog);
virtual ssize_t recv(int fd, void* buf, size_t len, int flags);
virtual ssize_t recvfrom(int fd,
void* buf,
size_t len,
int flags,
struct sockaddr* addr,
socklen_t* addrlen);
// recvmsg ignores ancillary data.
virtual ssize_t recvmsg(int fd, struct msghdr* msg, int flags);
virtual ssize_t send(int fd, const void* buf, size_t len, int flags);
virtual ssize_t sendto(int fd,
const void* buf,
size_t len,
int flags,
const struct sockaddr* addr,
socklen_t addrlen);
// sendmsg ignores ancillary data.
virtual ssize_t sendmsg(int fd, const struct msghdr* msg, int flags);
virtual int setsockopt(int fd,
int lvl,
int optname,
const void* optval,
socklen_t len);
virtual int shutdown(int fd, int how);
virtual int socket(int domain, int type, int protocol);
virtual int socketpair(int domain, int type, int protocol, int* sv);
#endif // PROVIDES_SOCKET_API
protected:
Error MountInternal(const char* source,
const char* target,
const char* filesystemtype,
unsigned long mountflags,
const void* data,
bool create_fs_node,
ScopedFilesystem* out_filesystem);
Error FutimensInternal(const ScopedNode& node,
const struct timespec times[2]);
Error CreateFsNode(const ScopedFilesystem& fs);
protected:
FsFactoryMap_t factories_;
sdk_util::ScopedRef<StreamFs> stream_fs_;
sdk_util::ScopedRef<DevFs> dev_fs_;
int dev_;
PepperInterface* ppapi_;
static KernelProxy* s_instance_;
struct sigaction sigwinch_handler_;
nacl_io_exit_callback_t exit_callback_;
void* exit_callback_user_data_;
nacl_io_mount_callback_t mount_callback_;
void* mount_callback_user_data_;
#ifdef PROVIDES_SOCKET_API
HostResolver host_resolver_;
#endif
#ifdef PROVIDES_SOCKET_API
virtual int AcquireSocketHandle(int fd, ScopedKernelHandle* handle);
#endif
ScopedEventEmitter signal_emitter_;
DISALLOW_COPY_AND_ASSIGN(KernelProxy);
};
} // namespace nacl_io
#endif // LIBRARIES_NACL_IO_KERNEL_PROXY_H_