1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBRARIES_NACL_IO_KERNEL_PROXY_H_
6#define LIBRARIES_NACL_IO_KERNEL_PROXY_H_
7
8#include <map>
9#include <string>
10
11#include "nacl_io/devfs/dev_fs.h"
12#include "nacl_io/event_emitter.h"
13#include "nacl_io/fs_factory.h"
14#include "nacl_io/host_resolver.h"
15#include "nacl_io/kernel_object.h"
16#include "nacl_io/nacl_io.h"
17#include "nacl_io/ossignal.h"
18#include "nacl_io/ossocket.h"
19#include "nacl_io/ostypes.h"
20#include "nacl_io/osutime.h"
21#include "nacl_io/stream/stream_fs.h"
22
23struct fuse_operations;
24struct timeval;
25
26namespace nacl_io {
27
28class PepperInterface;
29
30
31// KernelProxy provide one-to-one mapping for libc kernel calls.  Calls to the
32// proxy will result in IO access to the provided Filesystem and Node objects.
33//
34// NOTE: The KernelProxy does not directly take any kernel locks, all locking
35// is done by the parent class KernelObject. Instead, KernelProxy is
36// responsible for taking the locks of the KernelHandle, and Node objects. For
37// this reason, a KernelObject call should not be done while holding a handle
38// or node lock. In addition, to ensure locking order, a KernelHandle lock
39// must never be taken after taking the associated Node's lock.
40//
41// NOTE: The KernelProxy is the only class that should be setting errno. All
42// other classes should return Error (as defined by nacl_io/error.h).
43class KernelProxy : protected KernelObject {
44 public:
45  typedef std::map<std::string, FsFactory*> FsFactoryMap_t;
46
47  KernelProxy();
48  virtual ~KernelProxy();
49
50  // |ppapi| may be NULL. If so, no filesystem that uses pepper calls can be
51  // mounted.
52  virtual Error Init(PepperInterface* ppapi);
53
54  // Register/Unregister a new filesystem type. See the documentation in
55  // nacl_io.h for more info.
56  bool RegisterFsType(const char* fs_type, fuse_operations* fuse_ops);
57  bool UnregisterFsType(const char* fs_type);
58
59  void SetExitCallback(nacl_io_exit_callback_t exit_callback, void* user_data);
60
61  void SetMountCallback(nacl_io_mount_callback_t mount_callback,
62                        void* user_data);
63
64  virtual int pipe(int pipefds[2]);
65
66  // NaCl-only function to read resources specified in the NMF file.
67  virtual int open_resource(const char* file);
68
69  // KernelHandle and FD allocation and manipulation functions.
70  virtual int open(const char* path, int open_flags, mode_t mode);
71  virtual int close(int fd);
72  virtual int dup(int fd);
73  virtual int dup2(int fd, int newfd);
74
75  virtual void exit(int status);
76
77  // Path related System calls handled by KernelProxy (not filesystem-specific)
78  virtual int chdir(const char* path);
79  virtual char* getcwd(char* buf, size_t size);
80  virtual char* getwd(char* buf);
81  virtual int mount(const char* source,
82                    const char* target,
83                    const char* filesystemtype,
84                    unsigned long mountflags,
85                    const void* data);
86  virtual int umount(const char* path);
87
88  // Stub system calls that don't do anything (yet), handled by KernelProxy.
89  virtual int chown(const char* path, uid_t owner, gid_t group);
90  virtual int fchown(int fd, uid_t owner, gid_t group);
91  virtual int lchown(const char* path, uid_t owner, gid_t group);
92
93  // System calls that take a path as an argument: The kernel proxy will look
94  // for the Node associated to the path. To find the node, the kernel proxy
95  // calls the corresponding filesystem's GetNode() method. The corresponding
96  // method will be called. If the node cannot be found, errno is set and -1 is
97  // returned.
98  virtual int chmod(const char* path, mode_t mode);
99  virtual int mkdir(const char* path, mode_t mode);
100  virtual int rmdir(const char* path);
101  virtual int stat(const char* path, struct stat* buf);
102
103  // System calls that take a file descriptor as an argument:
104  // The kernel proxy will determine to which filesystem the file
105  // descriptor's corresponding file handle belongs.  The
106  // associated filesystem's function will be called.
107  virtual ssize_t read(int fd, void* buf, size_t nbyte);
108  virtual ssize_t write(int fd, const void* buf, size_t nbyte);
109
110  virtual int fchmod(int fd, mode_t mode);
111  virtual int fcntl(int fd, int request, va_list args);
112  virtual int fstat(int fd, struct stat* buf);
113  virtual int getdents(int fd, void* buf, unsigned int count);
114  virtual int fchdir(int fd);
115  virtual int ftruncate(int fd, off_t length);
116  virtual int fsync(int fd);
117  virtual int fdatasync(int fd);
118  virtual int isatty(int fd);
119  virtual int ioctl(int fd, int request, va_list args);
120  virtual int futimens(int fd, const struct timespec times[2]);
121
122  // lseek() relies on the filesystem's Stat() to determine whether or not the
123  // file handle corresponding to fd is a directory
124  virtual off_t lseek(int fd, off_t offset, int whence);
125
126  // remove() uses the filesystem's GetNode() and Stat() to determine whether
127  // or not the path corresponds to a directory or a file. The filesystem's
128  // Rmdir() or Unlink() is called accordingly.
129  virtual int remove(const char* path);
130  // unlink() is a simple wrapper around the filesystem's Unlink function.
131  virtual int unlink(const char* path);
132  virtual int truncate(const char* path, off_t len);
133  virtual int lstat(const char* path, struct stat* buf);
134  virtual int rename(const char* path, const char* newpath);
135  // access() uses the Filesystem's Stat().
136  virtual int access(const char* path, int amode);
137  virtual int readlink(const char* path, char* buf, size_t count);
138  virtual int utimens(const char* path, const struct timespec times[2]);
139
140  virtual int link(const char* oldpath, const char* newpath);
141  virtual int symlink(const char* oldpath, const char* newpath);
142
143  virtual void* mmap(void* addr,
144                     size_t length,
145                     int prot,
146                     int flags,
147                     int fd,
148                     size_t offset);
149  virtual int munmap(void* addr, size_t length);
150  virtual int tcflush(int fd, int queue_selector);
151  virtual int tcgetattr(int fd, struct termios* termios_p);
152  virtual int tcsetattr(int fd,
153                        int optional_actions,
154                        const struct termios* termios_p);
155
156  virtual int kill(pid_t pid, int sig);
157  virtual int sigaction(int signum,
158                        const struct sigaction* action,
159                        struct sigaction* oaction);
160
161#ifdef PROVIDES_SOCKET_API
162  virtual int select(int nfds,
163                     fd_set* readfds,
164                     fd_set* writefds,
165                     fd_set* exceptfds,
166                     struct timeval* timeout);
167
168  virtual int poll(struct pollfd* fds, nfds_t nfds, int timeout);
169
170  // Socket support functions
171  virtual int accept(int fd, struct sockaddr* addr, socklen_t* len);
172  virtual int bind(int fd, const struct sockaddr* addr, socklen_t len);
173  virtual int connect(int fd, const struct sockaddr* addr, socklen_t len);
174  virtual struct hostent* gethostbyname(const char* name);
175  virtual void freeaddrinfo(struct addrinfo* res);
176  virtual int getaddrinfo(const char* node,
177                          const char* service,
178                          const struct addrinfo* hints,
179                          struct addrinfo** res);
180  virtual int getnameinfo(const struct sockaddr *sa,
181                          socklen_t salen,
182                          char *host,
183                          size_t hostlen,
184                          char *serv,
185                          size_t servlen,
186                          int flags);
187  virtual int getpeername(int fd, struct sockaddr* addr, socklen_t* len);
188  virtual int getsockname(int fd, struct sockaddr* addr, socklen_t* len);
189  virtual int getsockopt(int fd,
190                         int lvl,
191                         int optname,
192                         void* optval,
193                         socklen_t* len);
194  virtual int listen(int fd, int backlog);
195  virtual ssize_t recv(int fd, void* buf, size_t len, int flags);
196  virtual ssize_t recvfrom(int fd,
197                           void* buf,
198                           size_t len,
199                           int flags,
200                           struct sockaddr* addr,
201                           socklen_t* addrlen);
202  virtual ssize_t recvmsg(int fd, struct msghdr* msg, int flags);
203  virtual ssize_t send(int fd, const void* buf, size_t len, int flags);
204  virtual ssize_t sendto(int fd,
205                         const void* buf,
206                         size_t len,
207                         int flags,
208                         const struct sockaddr* addr,
209                         socklen_t addrlen);
210  virtual ssize_t sendmsg(int fd, const struct msghdr* msg, int flags);
211  virtual int setsockopt(int fd,
212                         int lvl,
213                         int optname,
214                         const void* optval,
215                         socklen_t len);
216  virtual int shutdown(int fd, int how);
217  virtual int socket(int domain, int type, int protocol);
218  virtual int socketpair(int domain, int type, int protocol, int* sv);
219#endif  // PROVIDES_SOCKET_API
220
221 protected:
222  Error MountInternal(const char* source,
223                      const char* target,
224                      const char* filesystemtype,
225                      unsigned long mountflags,
226                      const void* data,
227                      bool create_fs_node,
228                      ScopedFilesystem* out_filesystem);
229
230  Error CreateFsNode(const ScopedFilesystem& fs);
231
232 protected:
233  FsFactoryMap_t factories_;
234  sdk_util::ScopedRef<StreamFs> stream_fs_;
235  sdk_util::ScopedRef<DevFs> dev_fs_;
236  int dev_;
237  PepperInterface* ppapi_;
238  static KernelProxy* s_instance_;
239  struct sigaction sigwinch_handler_;
240  nacl_io_exit_callback_t exit_callback_;
241  void* exit_callback_user_data_;
242  nacl_io_mount_callback_t mount_callback_;
243  void* mount_callback_user_data_;
244#ifdef PROVIDES_SOCKET_API
245  HostResolver host_resolver_;
246#endif
247
248#ifdef PROVIDES_SOCKET_API
249  virtual int AcquireSocketHandle(int fd, ScopedKernelHandle* handle);
250#endif
251
252  ScopedEventEmitter signal_emitter_;
253  DISALLOW_COPY_AND_ASSIGN(KernelProxy);
254};
255
256}  // namespace nacl_io
257
258#endif  // LIBRARIES_NACL_IO_KERNEL_PROXY_H_
259