text: // 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);
    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);
    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_
  