L4Re Operating System Framework – Interface and Usage Documentation
Loading...
Searching...
No Matches
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
44namespace L4Re {
48namespace Vfs {
49
50class Mount_tree;
51class File;
52
63{
64public:
65 virtual ~Generic_file() noexcept = 0;
77 virtual int unlock_all_locks() noexcept = 0;
78
87 virtual int fstat64(struct stat64 *buf) const noexcept = 0;
88
94 virtual int fchmod(mode_t) noexcept = 0;
95
105 virtual int get_status_flags() const noexcept = 0;
106
122 virtual int set_status_flags(long flags) noexcept = 0;
123
124 virtual int utime(const struct utimbuf *) noexcept = 0;
125 virtual int utimes(const struct timeval [2]) noexcept = 0;
126 virtual ssize_t readlink(char *, size_t) = 0;
127};
128
129inline
130Generic_file::~Generic_file() noexcept
131{}
132
141{
142public:
143 virtual ~Directory() noexcept = 0;
144
158 virtual int faccessat(const char *path, int mode, int flags) noexcept = 0;
159
172 virtual int mkdir(const char *path, mode_t mode) noexcept = 0;
173
184 virtual int unlink(const char *path) noexcept = 0;
185
199 virtual int rename(const char *src_path, const char *dst_path) noexcept = 0;
200
214 virtual int link(const char *src_path, const char *dst_path) noexcept = 0;
215
228 virtual int symlink(const char *src_path, const char *dst_path) noexcept = 0;
229
240 virtual int rmdir(const char *path) noexcept = 0;
241 virtual int openat(const char *path, int flags, mode_t mode,
242 cxx::Ref_ptr<File> *f) noexcept = 0;
243
244 virtual ssize_t getdents(char *buf, size_t sizebytes) noexcept = 0;
245
246 virtual int fchmodat(const char *pathname,
247 mode_t mode, int flags) noexcept = 0;
248
249 virtual int utimensat(const char *pathname,
250 const struct timespec times[2], int flags) noexcept = 0;
251
255 virtual int get_entry(const char *, int, mode_t, cxx::Ref_ptr<File> *) noexcept = 0;
256};
257
258inline
259Directory::~Directory() noexcept
260{}
261
268{
269public:
270 virtual ~Regular_file() noexcept = 0;
271
282 virtual L4::Cap<L4Re::Dataspace> data_space() const noexcept = 0;
283
293 virtual ssize_t readv(const struct iovec*, int iovcnt) noexcept = 0;
294
305 virtual ssize_t writev(const struct iovec*, int iovcnt) noexcept = 0;
306
307 virtual ssize_t preadv(const struct iovec *iov, int iovcnt, off64_t offset) noexcept = 0;
308 virtual ssize_t pwritev(const struct iovec *iov, int iovcnt, off64_t offset) noexcept = 0;
309
317 virtual off64_t lseek64(off64_t, int) noexcept = 0;
318
319
327 virtual int ftruncate64(off64_t pos) noexcept = 0;
328
334 virtual int fsync() const noexcept = 0;
335
341 virtual int fdatasync() const noexcept = 0;
342
352 virtual int get_lock(struct flock64 *lock) noexcept = 0;
353
362 virtual int set_lock(struct flock64 *lock, bool wait) noexcept = 0;
363};
364
365inline
366Regular_file::~Regular_file() noexcept
367{}
368
369class Socket
370{
371public:
372 virtual ~Socket() noexcept = 0;
373 virtual int bind(sockaddr const *, socklen_t) noexcept = 0;
374 virtual int connect(sockaddr const *, socklen_t) noexcept = 0;
375 virtual ssize_t send(void const *, size_t, int) noexcept = 0;
376 virtual ssize_t recv(void *, size_t, int) noexcept = 0;
377 virtual ssize_t sendto(void const *, size_t, int, sockaddr const *, socklen_t) noexcept = 0;
378 virtual ssize_t recvfrom(void *, size_t, int, sockaddr *, socklen_t *) noexcept = 0;
379 virtual ssize_t sendmsg(msghdr const *, int) noexcept = 0;
380 virtual ssize_t recvmsg(msghdr *, int) noexcept = 0;
381 virtual int getsockopt(int level, int opt, void *, socklen_t *) noexcept = 0;
382 virtual int setsockopt(int level, int opt, void const *, socklen_t) noexcept = 0;
383 virtual int listen(int) noexcept = 0;
384 virtual int accept(sockaddr *addr, socklen_t *) noexcept = 0;
385 virtual int shutdown(int) noexcept = 0;
386
387 virtual int getsockname(sockaddr *, socklen_t *) noexcept = 0;
388 virtual int getpeername(sockaddr *, socklen_t *) noexcept = 0;
389};
390
391inline
392Socket::~Socket() noexcept
393{}
394
401{
402public:
403 virtual ~Special_file() noexcept = 0;
404
415 virtual int ioctl(unsigned long cmd, va_list args) noexcept = 0;
416};
417
418inline
419Special_file::~Special_file() noexcept
420{}
421
435class 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
444private:
445 void operator = (File const &);
446
447protected:
448 File() noexcept : _ref_cnt(0) {}
449 File(File const &)
450 : Generic_file(),Regular_file(), Directory(), Special_file(), _ref_cnt(0)
451 {}
452
453public:
454
455 const char *get_mount(const char *path, cxx::Ref_ptr<File> *dir,
456 cxx::Ref_ptr<Mount_tree> *mt = 0) noexcept;
457
458 int openat(const char *path, int flags, mode_t mode,
459 cxx::Ref_ptr<File> *f) noexcept override;
460
461 void add_ref() noexcept { ++_ref_cnt; }
462 int remove_ref() noexcept { return --_ref_cnt; }
463
464 virtual ~File() noexcept = 0;
465
466 cxx::Ref_ptr<Mount_tree> mount_tree() const noexcept
467 { return _mount_tree; }
468
469private:
470 int _ref_cnt;
471 cxx::Ref_ptr<Mount_tree> _mount_tree;
472
473};
474
475inline
476File::~File() noexcept
477{}
478
479class Path
480{
481private:
482 char const *_p;
483 unsigned _l;
484
485public:
486 Path() noexcept : _p(0), _l(0) {}
487
488 explicit Path(char const *p) noexcept : _p(p)
489 { for (_l = 0; *p; ++p, ++_l) ; }
490
491 Path(char const *p, unsigned l) noexcept : _p(p), _l(l)
492 {}
493
494 static bool __is_sep(char s) noexcept;
495
496 Path cmp_path(char const *prefix) const noexcept;
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
544class Mount_tree
545{
546public:
547
548 explicit Mount_tree(char *n) noexcept;
549
550 Path lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
551 cxx::Ref_ptr<Mount_tree> *mp = 0) noexcept;
552
553 Path find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) noexcept;
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) noexcept;
567
568 void add_child_node(cxx::Ref_ptr<Mount_tree> const &cld);
569
570 virtual ~Mount_tree() noexcept = 0;
571
572 void add_ref() noexcept { ++_ref_cnt; }
573 int remove_ref() noexcept { return --_ref_cnt; }
574
575private:
576 friend class Real_mount_tree;
577
578 int _ref_cnt;
579 char *_name;
582 cxx::Ref_ptr<File> _mount;
583};
584
585inline
586Mount_tree::~Mount_tree() noexcept
587{}
588
589inline bool
590Path::__is_sep(char s) noexcept
591{ return s == '/'; }
592
593inline Path
594Path::cmp_path(char const *n) const noexcept
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
607inline
608Mount_tree::Mount_tree(char *n) noexcept
609: _ref_cnt(0), _name(n)
610{}
611
612inline Path
613Mount_tree::find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) noexcept
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
631inline Path
632Mount_tree::lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
633 cxx::Ref_ptr<Mount_tree> *mp) noexcept
634{
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
684inline
685void
686Mount_tree::add_child_node(cxx::Ref_ptr<Mount_tree> const &cld)
687{
688 cld->_sib = _cld;
689 _cld = cld;
690}
691
692inline
693const char *
694File::get_mount(const char *path, cxx::Ref_ptr<File> *dir,
695 cxx::Ref_ptr<Mount_tree> *mt) noexcept
696{
697 if (!_mount_tree)
698 {
699 *dir = cxx::ref_ptr(this);
700 return path;
701 }
702
704 Path p = _mount_tree->lookup(Path(path), mt, &mp);
705 if (mp->mount())
706 {
707 *dir = mp->mount();
708 return p.path();
709 }
710 else
711 {
712 *dir = cxx::ref_ptr(this);
713 return path;
714 }
715}
716
717inline int
718File::openat(const char *path, int flags, mode_t mode,
719 cxx::Ref_ptr<File> *f) noexcept
720{
723 path = get_mount(path, &dir, &mt);
724
725 int res = dir->get_entry(path, flags, mode, f);
726
727 if (res < 0)
728 return res;
729
730 if (!(*f)->_mount_tree && mt)
731 (*f)->_mount_tree = mt;
732
733 return res;
734}
735
744class Mman
745{
746public:
748 virtual int mmap2(void *start, size_t len, int prot, int flags, int fd,
749 off_t offset, void **ptr) noexcept = 0;
750
752 virtual int munmap(void *start, size_t len) noexcept = 0;
753
755 virtual int mremap(void *old, size_t old_sz, size_t new_sz, int flags,
756 void **new_addr) noexcept = 0;
757
759 virtual int mprotect(const void *a, size_t sz, int prot) noexcept = 0;
760
762 virtual int msync(void *addr, size_t len, int flags) noexcept = 0;
763
765 virtual int madvise(void *addr, size_t len, int advice) noexcept = 0;
766
767 virtual ~Mman() noexcept = 0;
768};
769
770inline
771Mman::~Mman() noexcept {}
772
773class File_factory
774{
775private:
776 int _ref_cnt = 0;
777 int _proto = 0;
778 char const *_proto_name = 0;
779
780 template<typename T> friend struct cxx::Default_ref_counter;
781 void add_ref() noexcept { ++_ref_cnt; }
782 int remove_ref() noexcept { return --_ref_cnt; }
783
784public:
785 explicit File_factory(int proto) : _proto(proto) {}
786 explicit File_factory(char const *proto_name) : _proto_name(proto_name) {}
787 File_factory(int proto, char const *proto_name)
788 : _proto(proto), _proto_name(proto_name)
789 {}
790
791 File_factory(File_factory const &) = delete;
792 File_factory &operator = (File_factory const &) = delete;
793
794 char const *proto_name() const { return _proto_name; }
795 int proto() const { return _proto; }
796
797 virtual ~File_factory() noexcept = 0;
798 virtual cxx::Ref_ptr<File> create(L4::Cap<void> file) = 0;
799};
800
801inline File_factory::~File_factory() noexcept {}
802
803template<typename IFACE, typename IMPL>
804class File_factory_t : public File_factory
805{
806public:
807 File_factory_t()
808 : File_factory(IFACE::Protocol, L4::kobject_typeid<IFACE>()->name())
809 {}
810
811 cxx::Ref_ptr<File> create(L4::Cap<void> file) override
812 { return cxx::ref_ptr(new IMPL(L4::cap_cast<IFACE>(file))); }
813};
814
829{
830protected:
831 File_system *_next;
832
833public:
834 File_system() noexcept : _next(0) {}
840 virtual char const *type() const noexcept = 0;
841
858 virtual int mount(char const *source, unsigned long mountflags,
859 void const *data, cxx::Ref_ptr<File> *dir) noexcept = 0;
860
861 virtual ~File_system() noexcept = 0;
862
867 File_system *next() const noexcept { return _next; }
868 File_system *&next() noexcept { return _next; }
869 void next(File_system *n) noexcept { _next = n; }
870};
871
872inline
873File_system::~File_system() noexcept
874{}
875
881class Fs
882{
883public:
889 virtual cxx::Ref_ptr<File> get_file(int fd) noexcept = 0;
890
892 virtual cxx::Ref_ptr<File> get_root() noexcept = 0;
893
895 virtual cxx::Ref_ptr<File> get_cwd() noexcept { return get_root(); }
896
898 virtual void set_cwd(cxx::Ref_ptr<File> const &) noexcept {}
899
905 virtual int alloc_fd(cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) noexcept = 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) noexcept = 0;
919
925 virtual cxx::Ref_ptr<File> free_fd(int fd) noexcept = 0;
926
934 virtual int mount(char const *path, cxx::Ref_ptr<File> const &dir) noexcept = 0;
935
943 virtual int register_file_system(File_system *f) noexcept = 0;
944
952 virtual int unregister_file_system(File_system *f) noexcept = 0;
953
961 virtual File_system *get_file_system(char const *fstype) noexcept = 0;
962
966 int mount(char const *source, char const *target,
967 char const *fstype, unsigned long mountflags,
968 void const *data) noexcept;
969
970 virtual int register_file_factory(cxx::Ref_ptr<File_factory> f) noexcept = 0;
971 virtual int unregister_file_factory(cxx::Ref_ptr<File_factory> f) noexcept = 0;
972 virtual cxx::Ref_ptr<File_factory> get_file_factory(int proto) noexcept = 0;
973 virtual cxx::Ref_ptr<File_factory> get_file_factory(char const *proto_name) noexcept = 0;
974
975 virtual ~Fs() = 0;
976};
977
978inline int
979Fs::mount(char const *source, char const *target,
980 char const *fstype, unsigned long mountflags,
981 void const *data) noexcept
982{
983 File_system *fs = get_file_system(fstype);
984
985 if (!fs)
986 return -ENODEV;
987
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
997inline
998Fs::~Fs()
999{}
1000
1007class Ops : public Mman, public Fs
1008{
1009public:
1010 virtual void *malloc(size_t bytes) noexcept = 0;
1011 virtual void free(void *mem) noexcept = 0;
1012 virtual ~Ops() noexcept = 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
1039inline
1040Ops::~Ops() noexcept
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 mkdir(const char *path, mode_t mode) noexcept=0
Create a new subdirectory.
virtual int link(const char *src_path, const char *dst_path) noexcept=0
Create a hard link (second name) for the given file.
virtual int unlink(const char *path) noexcept=0
Unlink the given file from that directory.
virtual int symlink(const char *src_path, const char *dst_path) noexcept=0
Create a symbolic link for the given file.
virtual int rmdir(const char *path) noexcept=0
Delete an empty directory.
virtual int rename(const char *src_path, const char *dst_path) noexcept=0
Rename the given file.
virtual int faccessat(const char *path, int mode, int flags) noexcept=0
Check access permissions on the given file.
Basic interface for an L4Re::Vfs file system.
Definition vfs.h:829
virtual char const * type() const noexcept=0
Returns the type of the file system used in mount as fstype argument.
virtual int mount(char const *source, unsigned long mountflags, void const *data, cxx::Ref_ptr< File > *dir) noexcept=0
Create a directory object dir representing source mounted with this file system.
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 &) noexcept
Set the current working directory for the application.
Definition vfs.h:898
virtual int mount(char const *path, cxx::Ref_ptr< File > const &dir) noexcept=0
Mount a given file object at the given global path in the VFS.
virtual cxx::Ref_ptr< File > get_file(int fd) noexcept=0
Get the L4Re::Vfs::File for the file descriptor fd.
virtual cxx::Ref_ptr< File > free_fd(int fd) noexcept=0
Free the file descriptor fd.
virtual cxx::Pair< cxx::Ref_ptr< File >, int > set_fd(int fd, cxx::Ref_ptr< File > const &f=cxx::Ref_ptr<>::Nil) noexcept=0
Set the file object referenced by the file descriptor fd.
virtual int alloc_fd(cxx::Ref_ptr< File > const &f=cxx::Ref_ptr<>::Nil) noexcept=0
Allocate the next free file descriptor.
virtual cxx::Ref_ptr< File > get_root() noexcept=0
Get the directory object for the application's root directory.
The common interface for an open POSIX file.
Definition vfs.h:63
virtual int unlock_all_locks() noexcept=0
Unlock all locks on the file.
virtual int fchmod(mode_t) noexcept=0
Change POSIX access rights on the file.
virtual int fstat64(struct stat64 *buf) const noexcept=0
Get status information for the file.
virtual int set_status_flags(long flags) noexcept=0
Set file status flags (fcntl F_SETFL).
virtual int get_status_flags() const noexcept=0
Get file status flags (fcntl F_GETFL).
Interface for POSIX memory management.
Definition vfs.h:745
virtual int mmap2(void *start, size_t len, int prot, int flags, int fd, off_t offset, void **ptr) noexcept=0
Backend for the mmap2 system call.
virtual int msync(void *addr, size_t len, int flags) noexcept=0
Backend for the msync system call.
virtual int munmap(void *start, size_t len) noexcept=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) noexcept=0
Backend for the mremap system call.
virtual int madvise(void *addr, size_t len, int advice) noexcept=0
Backend for the madvice system call.
virtual int mprotect(const void *a, size_t sz, int prot) noexcept=0
Backend for the mprotect system call.
Interface for the POSIX backends of 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 noexcept=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) noexcept=0
The famous IO control.
C++ interface for capabilities.
Definition capability.h:222
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