L4Re - L4 Runtime Environment
backend
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  * Alexander Warg <warg@os.inf.tu-dresden.de>
5  * economic rights: Technische Universit├Ąt Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  *
11  * As a special exception, you may use this file as part of a free software
12  * library without restriction. Specifically, if other files instantiate
13  * templates or use macros or inline functions from this file, or you compile
14  * this file and link it with other files to produce an executable, this
15  * file does not by itself cause the resulting executable to be covered by
16  * the GNU General Public License. This exception does not however
17  * invalidate any other reasons why the executable file might be covered by
18  * the GNU General Public License.
19  */
20 #pragma once
21 
22 #include <l4/l4re_vfs/vfs.h>
23 #include <l4/crtn/initpriorities.h>
24 
25 namespace L4Re { namespace Vfs {
26 
27 /// Reference to the applications L4Re::Vfs::Ops singleton.
28 extern L4Re::Vfs::Ops *vfs_ops asm ("l4re_env_posix_vfs_ops");
29 
30 class Mount_tree;
31 
32 /**
33  * \brief Boiler plate class for implementing an open file for L4Re::Vfs.
34  *
35  * This class may be used as a base class for everything that a POSIX
36  * file descriptor may point to. This are things such as regular files,
37  * directories, special device files, streams, pipes, and so on.
38  */
39 class Be_file : public File
40 {
41 public:
42  void *operator new (size_t size) throw()
43  { return vfs_ops->malloc(size); }
44 
45  void *operator new (size_t, void *m) throw()
46  { return m; }
47 
48  void operator delete (void *m)
49  { vfs_ops->free(m); }
50 
51  // used in close, to unlock all locks of a file (as POSIX says)
52  int unlock_all_locks() throw()
53  { return 0; }
54 
55  // for mmap
56  L4::Cap<L4Re::Dataspace> data_space() const throw()
57  { return L4::Cap<L4Re::Dataspace>::Invalid; }
58 
59  /// Default backend for POSIX read and readv functions.
60  ssize_t readv(const struct iovec*, int) throw()
61  { return -EINVAL; }
62 
63  /// Default backend for POSIX write and writev functions.
64  ssize_t writev(const struct iovec*, int) throw()
65  { return -EINVAL; }
66 
67  /// Default backend for POSIX pwrite and pwritev functions.
68  ssize_t pwritev(const struct iovec*, int, off64_t) throw()
69  { return -EINVAL; }
70 
71  /// Default backend for POSIX pread and preadv functions.
72  ssize_t preadv(const struct iovec*, int, off64_t) throw()
73  { return -EINVAL; }
74 
75  /// Default backend for POSIX seek and lseek functions.
76  off64_t lseek64(off64_t, int) throw()
77  { return -ESPIPE; }
78 
79  /// Default backend for the POSIX truncate, ftruncate and similar functions.
80  int ftruncate64(off64_t) throw()
81  { return -EINVAL; }
82 
83  /// Default backend for POSIX fsync.
84  int fsync() const throw()
85  { return -EINVAL; }
86 
87  /// Default backend for POSIX fdatasync.
88  int fdatasync() const throw()
89  { return -EINVAL; }
90 
91  /// Default backend for POSIX ioctl.
92  int ioctl(unsigned long, va_list) throw()
93  { return -EINVAL; }
94 
95  int fstat64(struct stat64 *) const throw()
96  { return -EINVAL; }
97 
98  /// Default backend for POSIX chmod and fchmod.
99  int fchmod(mode_t) throw()
100  { return -EINVAL; }
101 
102  /// Default backend for POSIX fcntl subfunctions.
103  int get_status_flags() const throw()
104  { return 0; }
105 
106  /// Default backend for POSIX fcntl subfunctions.
107  int set_status_flags(long) throw()
108  { return 0; }
109 
110  /// Default backend for POSIX fcntl subfunctions.
111  int get_lock(struct flock64 *) throw()
112  { return -ENOLCK; }
113 
114  /// Default backend for POSIX fcntl subfunctions.
115  int set_lock(struct flock64 *, bool) throw()
116  { return -ENOLCK; }
117 
118  /// Default backend for POSIX access and faccessat functions.
119  int faccessat(const char *, int, int) throw()
120  { return -ENOTDIR; }
121 
122  /// Default backend for POSIX utime.
123  int utime(const struct utimbuf *) throw()
124  { return -EROFS; }
125 
126  /// Default backend for POSIX utimes.
127  int utimes(const struct timeval [2]) throw()
128  { return -EROFS; }
129 
130  /// Default backend for POSIX mkdir and mkdirat.
131  int mkdir(const char *, mode_t) throw()
132  { return -ENOTDIR; }
133 
134  /// Default backend for POSIX unlink, unlinkat.
135  int unlink(const char *) throw()
136  { return -ENOTDIR; }
137 
138  /// Default backend for POSIX rename, renameat.
139  int rename(const char *, const char *) throw()
140  { return -ENOTDIR; }
141 
142  /// Default backend for POSIX link, linkat.
143  int link(const char *, const char *) throw()
144  { return -ENOTDIR; }
145 
146  /// Default backend for POSIX symlink, symlinkat.
147  int symlink(const char *, const char *) throw()
148  { return -EPERM; }
149 
150  /// Default backend for POSIX rmdir, rmdirat.
151  int rmdir(const char *) throw()
152  { return -ENOTDIR; }
153 
154  /// Default backend for POSIX readlink, readlinkat.
155  ssize_t readlink(char *, size_t)
156  { return -EINVAL; }
157 
158  ssize_t getdents(char *, size_t) throw()
159  { return -ENOTDIR; }
160 
161 
162 
163  // Socket interface
164  int bind(sockaddr const *, socklen_t) throw()
165  { return -ENOTSOCK; }
166 
167  int connect(sockaddr const *, socklen_t) throw()
168  { return -ENOTSOCK; }
169 
170  ssize_t send(void const *, size_t, int) throw()
171  { return -ENOTSOCK; }
172 
173  ssize_t recv(void *, size_t, int) throw()
174  { return -ENOTSOCK; }
175 
176  ssize_t sendto(void const *, size_t, int, sockaddr const *, socklen_t) throw()
177  { return -ENOTSOCK; }
178 
179  ssize_t recvfrom(void *, size_t, int, sockaddr *, socklen_t *) throw()
180  { return -ENOTSOCK; }
181 
182  ssize_t sendmsg(msghdr const *, int) throw()
183  { return -ENOTSOCK; }
184 
185  ssize_t recvmsg(msghdr *, int) throw()
186  { return -ENOTSOCK; }
187 
188  int getsockopt(int, int, void *, socklen_t *) throw()
189  { return -ENOTSOCK; }
190 
191  int setsockopt(int, int, void const *, socklen_t) throw()
192  { return -ENOTSOCK; }
193 
194  int listen(int) throw()
195  { return -ENOTSOCK; }
196 
197  int accept(sockaddr *, socklen_t *) throw()
198  { return -ENOTSOCK; }
199 
200  int shutdown(int) throw()
201  { return -ENOTSOCK; }
202 
203  int getsockname(sockaddr *, socklen_t *) throw()
204  { return -ENOTSOCK; }
205 
206  int getpeername(sockaddr *, socklen_t *) throw()
207  { return -ENOTSOCK; }
208 
209  ~Be_file() throw() = 0;
210 
211 private:
212  /// Default backend for POSIX openat, open.
213  int get_entry(const char *, int, mode_t, cxx::Ref_ptr<File> *) throw()
214  { return -ENOTDIR; }
215 
216 protected:
217  const char *get_mount(const char *path, cxx::Ref_ptr<File> *dir) throw();
218 };
219 
220 inline
221 Be_file::~Be_file() throw() {}
222 
223 class Be_file_pos : public Be_file
224 {
225 public:
226  Be_file_pos() throw() : Be_file(), _pos(0) {}
227 
228  virtual off64_t size() const throw() = 0;
229 
230  ssize_t readv(const struct iovec *v, int iovcnt) throw()
231  {
232  ssize_t r = preadv(v, iovcnt, _pos);
233  if (r > 0)
234  _pos += r;
235  return r;
236  }
237 
238  ssize_t writev(const struct iovec *v, int iovcnt) throw()
239  {
240  ssize_t r = pwritev(v, iovcnt, _pos);
241  if (r > 0)
242  _pos += r;
243  return r;
244  }
245 
246  ssize_t preadv(const struct iovec *v, int iovcnt, off64_t offset) throw() = 0;
247  ssize_t pwritev(const struct iovec *v, int iovcnt, off64_t offset) throw() = 0;
248 
249  off64_t lseek64(off64_t offset, int whence) throw()
250  {
251  off64_t r;
252  switch (whence)
253  {
254  case SEEK_SET: r = offset; break;
255  case SEEK_CUR: r = _pos + offset; break;
256  case SEEK_END: r = size() + offset; break;
257  default: return -EINVAL;
258  };
259 
260  if (r < 0)
261  return -EINVAL;
262 
263  _pos = r;
264  return _pos;
265  }
266 
267  ~Be_file_pos() throw() = 0;
268 
269 protected:
270  off64_t pos() const throw() { return _pos; }
271 
272 private:
273  off64_t _pos;
274 };
275 
276 inline Be_file_pos::~Be_file_pos() throw() {}
277 
278 class Be_file_stream : public Be_file
279 {
280 public:
281  ssize_t preadv(const struct iovec *v, int iovcnt, off64_t) throw()
282  { return readv(v, iovcnt); }
283 
284  ssize_t pwritev(const struct iovec *v, int iovcnt, off64_t) throw()
285  { return writev(v, iovcnt); }
286 
287  ~Be_file_stream() throw () = 0;
288 
289 };
290 
291 inline Be_file_stream::~Be_file_stream() throw() {}
292 
293 /**
294  * \brief Boilerplate class for implementing a L4Re::Vfs::File_system.
295  *
296  * This class already takes care of registering and unregistering the
297  * file system in the global registry and implements the type() method.
298  */
299 class Be_file_system : public File_system
300 {
301 private:
302  char const *const _fstype;
303 
304 public:
305 
306  /**
307  * \brief Create a file-system object for the given \a fstype.
308  * \param fstype The type that type() shall return.
309  *
310  * This constructor takes care of registering the file system
311  * in the registry of L4Re::Vfs::vfs_ops.
312  */
313  explicit Be_file_system(char const *fstype) throw()
314  : File_system(), _fstype(fstype)
315  {
316  vfs_ops->register_file_system(this);
317  }
318 
319  /**
320  * \brief Destroy a file-system object.
321  *
322  * This destructor takes care of removing this file system
323  * from the registry of L4Re::Vfs::vfs_ops.
324  */
325  ~Be_file_system() throw()
326  {
327  vfs_ops->unregister_file_system(this);
328  }
329 
330  /**
331  * \brief Return the file-system type.
332  *
333  * Returns the file-system type given as \a fstype in the constructor.
334  */
335  char const *type() const throw() { return _fstype; }
336 };
337 
338 /* Make sure filesystems can register before the constructor of libmount
339  * runs */
340 #define L4RE_VFS_FILE_SYSTEM_ATTRIBUTE \
341  __attribute__((init_priority(INIT_PRIO_LATE)))
342 
343 }}