L4Re – L4 Runtime Environment
vfs.h
1 /*
2  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  * Alexander Warg <warg@os.inf.tu-dresden.de>
4  * economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  *
10  * As a special exception, you may use this file as part of a free software
11  * library without restriction. Specifically, if other files instantiate
12  * templates or use macros or inline functions from this file, or you compile
13  * this file and link it with other files to produce an executable, this
14  * file does not by itself cause the resulting executable to be covered by
15  * the GNU General Public License. This exception does not however
16  * invalidate any other reasons why the executable file might be covered by
17  * the GNU General Public License.
18  */
19 #pragma once
20 
21 #include <l4/sys/compiler.h>
22 
23 #include <unistd.h>
24 #include <stdarg.h>
25 #include <fcntl.h>
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <sys/socket.h>
29 #include <utime.h>
30 #include <errno.h>
31 
32 #ifndef AT_FDCWD
33 # define AT_FDCWD -100
34 #endif
35 
36 #ifdef __cplusplus
37 
38 #include <l4/sys/capability>
39 #include <l4/re/cap_alloc>
40 #include <l4/re/dataspace>
41 #include <l4/cxx/pair>
42 #include <l4/cxx/ref_ptr>
43 
44 namespace L4Re {
48 namespace Vfs {
49 
50 class Mount_tree;
51 class File;
52 
63 {
64 public:
65  virtual ~Generic_file() throw() = 0;
77  virtual int unlock_all_locks() throw() = 0;
78 
87  virtual int fstat64(struct stat64 *buf) const throw() = 0;
88 
94  virtual int fchmod(mode_t) throw() = 0;
95 
105  virtual int get_status_flags() const throw() = 0;
106 
122  virtual int set_status_flags(long flags) throw() = 0;
123 
124  virtual int utime(const struct utimbuf *) throw() = 0;
125  virtual int utimes(const struct timeval [2]) throw() = 0;
126  virtual ssize_t readlink(char *, size_t) = 0;
127 };
128 
129 inline
130 Generic_file::~Generic_file() throw()
131 {}
132 
141 {
142 public:
143  virtual ~Directory() throw() = 0;
144 
158  virtual int faccessat(const char *path, int mode, int flags) throw() = 0;
159 
172  virtual int mkdir(const char *path, mode_t mode) throw() = 0;
173 
184  virtual int unlink(const char *path) throw() = 0;
185 
199  virtual int rename(const char *src_path, const char *dst_path) throw() = 0;
200 
214  virtual int link(const char *src_path, const char *dst_path) throw() = 0;
215 
228  virtual int symlink(const char *src_path, const char *dst_path) throw() = 0;
229 
240  virtual int rmdir(const char *path) throw() = 0;
241  virtual int openat(const char *path, int flags, mode_t mode,
242  cxx::Ref_ptr<File> *f) throw() = 0;
243 
244  virtual ssize_t getdents(char *buf, size_t sizebytes) throw() = 0;
245 
246  virtual int fchmodat(const char *pathname,
247  mode_t mode, int flags) throw() = 0;
248 
249  virtual int utimensat(const char *pathname,
250  const struct timespec times[2], int flags) throw() = 0;
251 
255  virtual int get_entry(const char *, int, mode_t, cxx::Ref_ptr<File> *) throw() = 0;
256 };
257 
258 inline
259 Directory::~Directory() throw()
260 {}
261 
268 {
269 public:
270  virtual ~Regular_file() throw() = 0;
271 
282  virtual L4::Cap<L4Re::Dataspace> data_space() const throw() = 0;
283 
293  virtual ssize_t readv(const struct iovec*, int iovcnt) throw() = 0;
294 
305  virtual ssize_t writev(const struct iovec*, int iovcnt) throw() = 0;
306 
307  virtual ssize_t preadv(const struct iovec *iov, int iovcnt, off64_t offset) throw() = 0;
308  virtual ssize_t pwritev(const struct iovec *iov, int iovcnt, off64_t offset) throw() = 0;
309 
317  virtual off64_t lseek64(off64_t, int) throw() = 0;
318 
319 
327  virtual int ftruncate64(off64_t pos) throw() = 0;
328 
334  virtual int fsync() const throw() = 0;
335 
341  virtual int fdatasync() const throw() = 0;
342 
352  virtual int get_lock(struct flock64 *lock) throw() = 0;
353 
362  virtual int set_lock(struct flock64 *lock, bool wait) throw() = 0;
363 };
364 
365 inline
366 Regular_file::~Regular_file() throw()
367 {}
368 
369 class Socket
370 {
371 public:
372  virtual ~Socket() throw() = 0;
373  virtual int bind(sockaddr const *, socklen_t) throw() = 0;
374  virtual int connect(sockaddr const *, socklen_t) throw() = 0;
375  virtual ssize_t send(void const *, size_t, int) throw() = 0;
376  virtual ssize_t recv(void *, size_t, int) throw() = 0;
377  virtual ssize_t sendto(void const *, size_t, int, sockaddr const *, socklen_t) throw() = 0;
378  virtual ssize_t recvfrom(void *, size_t, int, sockaddr *, socklen_t *) throw() = 0;
379  virtual ssize_t sendmsg(msghdr const *, int) throw() = 0;
380  virtual ssize_t recvmsg(msghdr *, int) throw() = 0;
381  virtual int getsockopt(int level, int opt, void *, socklen_t *) throw() = 0;
382  virtual int setsockopt(int level, int opt, void const *, socklen_t) throw() = 0;
383  virtual int listen(int) throw() = 0;
384  virtual int accept(sockaddr *addr, socklen_t *) throw() = 0;
385  virtual int shutdown(int) throw() = 0;
386 
387  virtual int getsockname(sockaddr *, socklen_t *) throw() = 0;
388  virtual int getpeername(sockaddr *, socklen_t *) throw() = 0;
389 };
390 
391 inline
392 Socket::~Socket() throw()
393 {}
394 
401 {
402 public:
403  virtual ~Special_file() throw() = 0;
404 
415  virtual int ioctl(unsigned long cmd, va_list args) throw() = 0;
416 };
417 
418 inline
419 Special_file::~Special_file() throw()
420 {}
421 
435 class File :
436  public Generic_file,
437  public Regular_file,
438  public Directory,
439  public Special_file,
440  public Socket
441 {
442  friend class Mount_tree;
443 
444 private:
445  void operator = (File const &);
446 
447 protected:
448  File() throw() : _ref_cnt(0) {}
449  File(File const &)
450  : Generic_file(),Regular_file(), Directory(), Special_file(), _ref_cnt(0)
451  {}
452 
453 public:
454 
455  const char *get_mount(const char *path, cxx::Ref_ptr<File> *dir,
456  cxx::Ref_ptr<Mount_tree> *mt = 0) throw();
457 
458  int openat(const char *path, int flags, mode_t mode,
459  cxx::Ref_ptr<File> *f) throw();
460 
461  void add_ref() throw() { ++_ref_cnt; }
462  int remove_ref() throw() { return --_ref_cnt; }
463 
464  virtual ~File() throw() = 0;
465 
466  cxx::Ref_ptr<Mount_tree> mount_tree() const throw()
467  { return _mount_tree; }
468 
469 private:
470  int _ref_cnt;
471  cxx::Ref_ptr<Mount_tree> _mount_tree;
472 
473 };
474 
475 inline
476 File::~File() throw()
477 {}
478 
479 class Path
480 {
481 private:
482  char const *_p;
483  unsigned _l;
484 
485 public:
486  Path() throw() : _p(0), _l(0) {}
487 
488  explicit Path(char const *p) throw() : _p(p)
489  { for (_l = 0; *p; ++p, ++_l) ; }
490 
491  Path(char const *p, unsigned l) throw() : _p(p), _l(l)
492  {}
493 
494  static bool __is_sep(char s) throw();
495 
496  Path cmp_path(char const *prefix) const throw();
497 
498  struct Invalid_ptr;
499  operator Invalid_ptr const * () const
500  { return reinterpret_cast<Invalid_ptr const *>(_p); }
501 
502  unsigned length() const { return _l; }
503  char const *path() const { return _p; }
504 
505  bool empty() const { return _l == 0; }
506 
507  bool is_sep(unsigned offset) const { return __is_sep(_p[offset]); }
508 
509  bool strip_sep()
510  {
511  bool s = false;
512  for (; __is_sep(*_p) && _l; ++_p, --_l)
513  s = true;
514  return s;
515  }
516 
517  Path first() const
518  {
519  unsigned i;
520  for (i = 0; i < _l && !is_sep(i); ++i)
521  ;
522 
523  return Path(_p, i);
524  }
525 
526  Path strip_first()
527  {
528  Path r = first();
529  _p += r.length();
530  _l -= r.length();
531  strip_sep();
532  return r;
533  }
534 
535 };
536 
537 
544 class Mount_tree
545 {
546 public:
547 
548  explicit Mount_tree(char *n) throw();
549 
550  Path lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
551  cxx::Ref_ptr<Mount_tree> *mp = 0) throw();
552 
553  Path find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw();
554 
555  cxx::Ref_ptr<File> mount() const
556  { return _mount; }
557 
558  void mount(cxx::Ref_ptr<File> const &m)
559  {
560  m->_mount_tree = cxx::ref_ptr(this);
561  _mount = m;
562  }
563 
564  static int create_tree(cxx::Ref_ptr<Mount_tree> const &root,
565  char const *path,
566  cxx::Ref_ptr<File> const &dir) throw();
567 
568  void add_child_node(cxx::Ref_ptr<Mount_tree> const &cld);
569 
570  virtual ~Mount_tree() throw() = 0;
571 
572  void add_ref() throw() { ++_ref_cnt; }
573  int remove_ref() throw() { return --_ref_cnt; }
574 
575 private:
576  friend class Real_mount_tree;
577 
578  int _ref_cnt;
579  char *_name;
582  cxx::Ref_ptr<File> _mount;
583 };
584 
585 inline
586 Mount_tree::~Mount_tree() throw()
587 {}
588 
589 inline bool
590 Path::__is_sep(char s) throw()
591 { return s == '/'; }
592 
593 inline Path
594 Path::cmp_path(char const *n) const throw()
595 {
596  char const *p = _p;
597  for (; *p && !__is_sep(*p) && *n; ++p, ++n)
598  if (*p != *n)
599  return Path();
600 
601  if (*n || (*p && !__is_sep(*p)))
602  return Path();
603 
604  return Path(p, _l - (p - _p));
605 }
606 
607 inline
608 Mount_tree::Mount_tree(char *n) throw()
609 : _ref_cnt(0), _name(n)
610 {}
611 
612 inline Path
613 Mount_tree::find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw()
614 {
615  if (!_cld)
616  return Path();
617 
618  for (cxx::Ref_ptr<Mount_tree> x = _cld; x; x = x->_sib)
619  {
620  Path const r = p.cmp_path(x->_name);
621  if (r)
622  {
623  *t = x;
624  return r;
625  }
626  }
627 
628  return Path();
629 }
630 
631 inline Path
632 Mount_tree::lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
633  cxx::Ref_ptr<Mount_tree> *mp) throw()
634 {
635  cxx::Ref_ptr<Mount_tree> x(this);
636  Path p = path;
637 
638  if (p.first().cmp_path("."))
639  p.strip_first();
640 
641  Path last_mp = p;
642 
643  if (mp)
644  *mp = x;;
645 
646  while (1)
647  {
648  Path r = x->find(p, &x);
649 
650  if (!r)
651  {
652  if (mp)
653  return last_mp;
654 
655  if (mt)
656  *mt = x;
657 
658  return p;
659  }
660 
661  r.strip_sep();
662 
663  if (mp && x->_mount)
664  {
665  last_mp = r;
666  *mp = x;
667  }
668 
669  if (r.empty())
670  {
671  if (mt)
672  *mt = x;
673 
674  if (mp)
675  return last_mp;
676  else
677  return r;
678  }
679 
680  p = r;
681  }
682 }
683 
684 inline
685 void
686 Mount_tree::add_child_node(cxx::Ref_ptr<Mount_tree> const &cld)
687 {
688  cld->_sib = _cld;
689  _cld = cld;
690 }
691 
692 
693 inline
694 const char *
695 File::get_mount(const char *path, cxx::Ref_ptr<File> *dir,
696  cxx::Ref_ptr<Mount_tree> *mt) throw()
697 {
698  if (!_mount_tree)
699  {
700  *dir = cxx::ref_ptr(this);
701  return path;
702  }
703 
705  Path p = _mount_tree->lookup(Path(path), mt, &mp);
706  if (mp->mount())
707  {
708  *dir = mp->mount();
709  return p.path();
710  }
711  else
712  {
713  *dir = cxx::ref_ptr(this);
714  return path;
715  }
716 }
717 
718 inline int
719 File::openat(const char *path, int flags, mode_t mode,
720  cxx::Ref_ptr<File> *f) throw()
721 {
722  cxx::Ref_ptr<File> dir;
724  path = get_mount(path, &dir, &mt);
725 
726  int res = dir->get_entry(path, flags, mode, f);
727 
728  if (res < 0)
729  return res;
730 
731  if (!(*f)->_mount_tree && mt)
732  (*f)->_mount_tree = mt;
733 
734  return res;
735 }
736 
745 class Mman
746 {
747 public:
749  virtual int mmap2(void *start, size_t len, int prot, int flags, int fd,
750  off_t offset, void **ptr) throw() = 0;
751 
753  virtual int munmap(void *start, size_t len) throw() = 0;
754 
756  virtual int mremap(void *old, size_t old_sz, size_t new_sz, int flags,
757  void **new_addr) throw() = 0;
758 
760  virtual int mprotect(const void *a, size_t sz, int prot) throw() = 0;
761 
763  virtual int msync(void *addr, size_t len, int flags) throw() = 0;
764 
766  virtual int madvise(void *addr, size_t len, int advice) throw() = 0;
767 
768  virtual ~Mman() throw() = 0;
769 };
770 
771 inline
772 Mman::~Mman() throw() {}
773 
774 class File_factory
775 {
776 private:
777  int _ref_cnt = 0;
778  int _proto = 0;
779  char const *_proto_name = 0;
780 
781  template<typename T> friend struct cxx::Default_ref_counter;
782  void add_ref() throw() { ++_ref_cnt; }
783  int remove_ref() throw() { return --_ref_cnt; }
784 
785 public:
786  explicit File_factory(int proto) : _proto(proto) {}
787  explicit File_factory(char const *proto_name) : _proto_name(proto_name) {}
788  File_factory(int proto, char const *proto_name)
789  : _proto(proto), _proto_name(proto_name)
790  {}
791 
792  File_factory(File_factory const &) = delete;
793  File_factory &operator = (File_factory const &) = delete;
794 
795  char const *proto_name() const { return _proto_name; }
796  int proto() const { return _proto; }
797 
798  virtual ~File_factory() throw() = 0;
799  virtual cxx::Ref_ptr<File> create(L4::Cap<void> file) = 0;
800 };
801 
802 inline File_factory::~File_factory() throw() {}
803 
804 template<typename IFACE, typename IMPL>
805 class File_factory_t : public File_factory
806 {
807 public:
808  File_factory_t()
809  : File_factory(IFACE::Protocol, L4::kobject_typeid<IFACE>()->name())
810  {}
811 
812  cxx::Ref_ptr<File> create(L4::Cap<void> file)
813  { return cxx::ref_ptr(new IMPL(L4::cap_cast<IFACE>(file))); }
814 };
815 
830 {
831 protected:
832  File_system *_next;
833 
834 public:
835  File_system() throw() : _next(0) {}
841  virtual char const *type() const throw() = 0;
842 
858  virtual int mount(char const *source, unsigned long mountflags,
859  void const *data, cxx::Ref_ptr<File> *dir) throw() = 0;
860 
861  virtual ~File_system() throw() = 0;
862 
867  File_system *next() const throw() { return _next; }
868  File_system *&next() throw() { return _next; }
869  void next(File_system *n) throw() { _next = n; }
870 };
871 
872 inline
873 File_system::~File_system() throw()
874 {}
875 
881 class Fs
882 {
883 public:
889  virtual cxx::Ref_ptr<File> get_file(int fd) throw() = 0;
890 
892  virtual cxx::Ref_ptr<File> get_root() throw() = 0;
893 
895  virtual cxx::Ref_ptr<File> get_cwd() throw() { return get_root(); }
896 
898  virtual void set_cwd(cxx::Ref_ptr<File> const &) throw() {}
899 
905  virtual int alloc_fd(cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
906 
917  virtual cxx::Pair<cxx::Ref_ptr<File>, int>
918  set_fd(int fd, cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
919 
925  virtual cxx::Ref_ptr<File> free_fd(int fd) throw() = 0;
926 
934  virtual int mount(char const *path, cxx::Ref_ptr<File> const &dir) throw() = 0;
935 
943  virtual int register_file_system(File_system *f) throw() = 0;
944 
952  virtual int unregister_file_system(File_system *f) throw() = 0;
953 
961  virtual File_system *get_file_system(char const *fstype) throw() = 0;
962 
966  int mount(char const *source, char const *target,
967  char const *fstype, unsigned long mountflags,
968  void const *data) throw();
969 
970  virtual int register_file_factory(cxx::Ref_ptr<File_factory> f) throw() = 0;
971  virtual int unregister_file_factory(cxx::Ref_ptr<File_factory> f) throw() = 0;
972  virtual cxx::Ref_ptr<File_factory> get_file_factory(int proto) throw() = 0;
973  virtual cxx::Ref_ptr<File_factory> get_file_factory(char const *proto_name) throw() = 0;
974 
975  virtual ~Fs() = 0;
976 };
977 
978 inline int
979 Fs::mount(char const *source, char const *target,
980  char const *fstype, unsigned long mountflags,
981  void const *data) throw()
982 {
983  File_system *fs = get_file_system(fstype);
984 
985  if (!fs)
986  return -ENODEV;
987 
988  cxx::Ref_ptr<File> dir;
989  int res = fs->mount(source, mountflags, data, &dir);
990 
991  if (res < 0)
992  return res;
993 
994  return mount(target, dir);
995 }
996 
997 inline
998 Fs::~Fs()
999 {}
1000 
1007 class Ops : public Mman, public Fs
1008 {
1009 public:
1010  virtual void *malloc(size_t bytes) noexcept = 0;
1011  virtual void free(void *mem) noexcept = 0;
1012  virtual ~Ops() throw() = 0;
1013 
1014  char *strndup(char const *str, unsigned l) noexcept
1015  {
1016  unsigned len;
1017  for (len = 0; str[len] && len < l; ++len)
1018  ;
1019 
1020  if (len == 0)
1021  return nullptr;
1022 
1023  ++len;
1024 
1025  char *b = (char *)this->malloc(len);
1026  if (b == nullptr)
1027  return nullptr;
1028 
1029  char *r = b;
1030  for (; len - 1 > 0 && *str; --len, ++b, ++str)
1031  *b = *str;
1032 
1033  *b = 0;
1034  return r;
1035  }
1036 
1037 };
1038 
1039 inline
1040 Ops::~Ops() throw()
1041 {}
1042 
1043 }}
1044 
1045 #endif
1046 
Abstract capability-allocator interface.
L4::Cap related definitions.
Interface for a POSIX file that is a directory.
Definition: vfs.h:141
virtual int link(const char *src_path, const char *dst_path)=0
Create a hard link (second name) for the given file.
virtual int rename(const char *src_path, const char *dst_path)=0
Rename the given file.
virtual int rmdir(const char *path)=0
Delete an empty directory.
virtual int unlink(const char *path)=0
Unlink the given file from that directory.
virtual int faccessat(const char *path, int mode, int flags)=0
Check access permissions on the given file.
virtual int symlink(const char *src_path, const char *dst_path)=0
Create a symbolic link for the given file.
virtual int mkdir(const char *path, mode_t mode)=0
Create a new subdirectory.
Basic interface for an L4Re::Vfs file system.
Definition: vfs.h:830
virtual int mount(char const *source, unsigned long mountflags, void const *data, cxx::Ref_ptr< File > *dir)=0
Create a directory object dir representing source mounted with this file system.
virtual char const * type() const =0
Returns the type of the file system, used in mount as fstype argument.
The basic interface for an open POSIX file.
Definition: vfs.h:441
POSIX File-system related functionality.
Definition: vfs.h:882
virtual void set_cwd(cxx::Ref_ptr< File > const &)
Set the current working directory for the application.
Definition: vfs.h:898
virtual int mount(char const *path, cxx::Ref_ptr< File > const &dir)=0
Mount a given file object at the given global path in the VFS.
virtual cxx::Ref_ptr< File > free_fd(int fd)=0
Free the file descriptor fd.
virtual cxx::Ref_ptr< File > get_file(int fd)=0
Get the L4Re::Vfs::File for the file descriptor fd.
virtual int alloc_fd(cxx::Ref_ptr< File > const &f=cxx::Ref_ptr<>::Nil)=0
Allocate the next free file descriptor.
virtual cxx::Ref_ptr< File > get_root()=0
Get the directory object for the applications root directory.
virtual cxx::Pair< cxx::Ref_ptr< File >, int > set_fd(int fd, cxx::Ref_ptr< File > const &f=cxx::Ref_ptr<>::Nil)=0
Set the file object referenced by the file descriptor fd.
The common interface for an open POSIX file.
Definition: vfs.h:63
virtual int set_status_flags(long flags)=0
Set file status flags (fcntl F_SETFL).
virtual int fstat64(struct stat64 *buf) const =0
Get status information for the file.
virtual int unlock_all_locks()=0
Unlock all locks on the file.
virtual int get_status_flags() const =0
Get file status flags (fcntl F_GETFL).
virtual int fchmod(mode_t)=0
Change POSIX access rights on that file.
Interface for the POSIX memory management.
Definition: vfs.h:746
virtual int mmap2(void *start, size_t len, int prot, int flags, int fd, off_t offset, void **ptr)=0
Backend for the mmap2 system call.
virtual int madvise(void *addr, size_t len, int advice)=0
Backend for the madvice system call.
virtual int msync(void *addr, size_t len, int flags)=0
Backend for the msync system call.
virtual int mprotect(const void *a, size_t sz, int prot)=0
Backend for the mprotect system call.
virtual int munmap(void *start, size_t len)=0
Backend for the munmap system call.
virtual int mremap(void *old, size_t old_sz, size_t new_sz, int flags, void **new_addr)=0
Backend for the mremap system call.
Interface for the POSIX backends for an application.
Definition: vfs.h:1008
Interface for a POSIX file that provides regular file semantics.
Definition: vfs.h:268
virtual L4::Cap< L4Re::Dataspace > data_space() const =0
Get an L4Re::Dataspace object for the file.
Interface for a POSIX file that provides special file semantics.
Definition: vfs.h:401
virtual int ioctl(unsigned long cmd, va_list args)=0
The famous IO control.
A reference-counting pointer with automatic cleanup.
Definition: ref_ptr:82
L4 compiler related defines.
Dataspace interface.
Type_info const * kobject_typeid() noexcept
Get the L4::Type_info for the L4Re interface given in T.
Definition: __typeinfo.h:692
L4Re C++ Interfaces.
Definition: cmd_control:15
L4 low-level kernel interface.
Our C++ library.
Definition: arith:22
Pair implementation.
Pair of two values.
Definition: pair:37