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