]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re_vfs/include/vfs.h
update
[l4.git] / l4 / pkg / l4re_vfs / include / 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 <utime.h>
29 #include <errno.h>
30
31 #ifndef AT_FDCWD
32 # define AT_FDCWD -100
33 #endif
34
35 #ifdef __cplusplus
36
37 #include <l4/sys/capability>
38 #include <l4/re/cap_alloc>
39 #include <l4/re/dataspace>
40 #include <l4/cxx/ref_ptr>
41 #include <cstdlib>
42 #include <cstring>
43
44 namespace L4Re {
45 /**
46  * \brief Virtual file system for interfaces POSIX libc.
47  */
48 namespace Vfs {
49
50 class Mount_tree;
51 class File;
52
53 /**
54  * \brief The common interface for an open POSIX file.
55  *
56  * This interface is common to all kinds of open files, independent of
57  * the the file type (e.g., directory, regular file etc.).  However, in
58  * the L4Re::Vfs the interface File is used for every real object.
59  *
60  * \see L4Re::Vfs::File for mor information.
61  */
62 class Generic_file
63 {
64 public:
65   virtual ~Generic_file() throw() = 0;
66   /**
67    * \brief Unlock all locks on the file.
68    * \note All locks means all locks independent by which file
69    *       the locks were taken.
70    *
71    * This method is called by the POSIX close implementation to
72    * get the POSIX semantics of releasing all locks taken by this
73    * application on a close for any fd referencing the real file.
74    *
75    * \return 0 on success, or <0 on error.
76    */
77   virtual int unlock_all_locks() throw() = 0;
78
79   /**
80    * \brief Get status information for the file.
81    *
82    * This is the backend for POSIX fstat, stat, fstat64 and friends.
83    *
84    * \retval buf This buffer is filled with the status information.
85    * \return 0 on success, or <0 on error.
86    */
87   virtual int fstat64(struct stat64 *buf) const throw() = 0;
88
89   /**
90    * \brief Change POSIX access rights on that file.
91    *
92    * Backend for POSIX chmod and fchmod.
93    */
94   virtual int fchmod(mode_t) throw() = 0;
95
96   /**
97    * \brief Get file status flags (fcntl F_GETFL).
98    *
99    * This function is used by the fcntl implementation for the F_GETFL
100    * command).
101    *
102    * \return flags such as #O_RDONLY, #O_WRONLY, #O_RDWR, #O_DIRECT, #O_ASYNC,
103    *         #O_NOATIME, #O_NONBLOCK, or <0 on error.
104    */
105   virtual int get_status_flags() const throw() = 0;
106
107   /**
108    * \brief Set file status flags (fcntl F_SETFL).
109    *
110    * This function is used by the fcntl implementation for the F_SETFL
111    * command).
112    *
113    * \param flags The file status flags to set. This must be a combination of
114    *              #O_RDONLY, #O_WRONLY, #O_RDWR, #O_APPEND, #O_ASYNC,
115    *              #O_DIRECT, #O_NOATIME, #O_NONBLOCK.
116    *
117    * \note Creation flags such as #O_CREAT, #O_EXCL, #O_NOCTTY, #O_TRUNC are
118    *       ignored.
119    *
120    * \return 0 on success, or <0 on error.
121    */
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 utimbuf [2]) throw() = 0;
126   virtual ssize_t readlink(char *, size_t) = 0;
127 };
128
129 inline
130 Generic_file::~Generic_file() throw()
131 {}
132
133 /**
134  * \brief Interface for a POSIX file that is a directory.
135  *
136  * This interface provides functionality for directory files
137  * in the L4Re::Vfs. However, real objects use always the
138  * combined L4Re::Vfs::File interface.
139  */
140 class Directory
141 {
142 public:
143   virtual ~Directory() throw() = 0;
144
145   /**
146    * \brief Check access permissions on the given file.
147    *
148    * Backend function for POSIX access and faccessat functions.
149    *
150    * \param path The path reltive to this directory.
151    *             Note: \a path is relative to this directory and
152    *             may contain subdirectories.
153    * \param mode The access mode to check.
154    * \param flags The flags as in POSIX faccessat (AT_EACCESS,
155    *              AT_SYMLINK_NOFOLLOW).
156    * \return 0 on success, or <0 on error.
157    */
158   virtual int faccessat(const char *path, int mode, int flags) throw() = 0;
159
160   /**
161    * \brief Create a new subdirectory.
162    *
163    * Backend for POSIX mkdir and mkdirat function calls.
164    *
165    * \param path The name of the subdirectory to create.
166    *             Note: \a path is relative to this directory and
167    *             may contain subdirectories.
168    * \param mode The file mode to use for the new directory.
169    * \return 0 on success, or <0 on error. -ENOTDIR if this or some component
170    *         in path is is not a directory.
171    */
172   virtual int mkdir(const char *path, mode_t mode) throw() = 0;
173
174   /**
175    * \brief Unlink the given file from that directory.
176    *
177    * Backend for the POSIX unlink and unlinkat functions.
178    *
179    * \param path The name to the file to unlink. Note: \a path
180    *             is relative to this directory and may
181    *             contain subdirectories.
182    * \return 0 on success, or <0 on error.
183    */
184   virtual int unlink(const char *path) throw() = 0;
185
186   /**
187    * \brief Rename the given file.
188    *
189    * Backend for the POSIX rename, renameat functions.
190    *
191    * \param src_path The old name to the file to rename.
192    *                 Note: \a src_path is relative to this
193    *                 directory and may contain subdirectories.
194    * \param dst_path The new name for the file.
195    *                 Note: \a dst_path is relative to this
196    *                 directory and may contain subdirectories.
197    * \return 0 on success, or <0 on error.
198    */
199   virtual int rename(const char *src_path, const char *dst_path) throw() = 0;
200
201   /**
202    * \brief Create a hard link (second name) for the given file.
203    *
204    * Backend for the POSIX link and linkat functions.
205    *
206    * \param src_path The old name to the file.
207    *                 Note: \a src_path is relative to this
208    *                 directory and may contain subdirectories.
209    * \param dst_path The new (second) name for the file.
210    *                 Note: \a dst_path is relative to this
211    *                 directory and may contain subdirectories.
212    * \return 0 on success, or <0 on error.
213    */
214   virtual int link(const char *src_path, const char *dst_path) throw() = 0;
215
216   /**
217    * \brief Create a symbolic link for the given file.
218    *
219    * Backend for the POSIX symlink and symlinkat functions.
220    *
221    * \param src_path The old name to the file.
222    *                 Note: \a src_path shall be an absolute path.
223    * \param dst_path The name for symlink.
224    *                 Note: \a dst_path is relative to this
225    *                 directory and may contain subdirectories.
226    * \return 0 on success, or <0 on error.
227    */
228   virtual int symlink(const char *src_path, const char *dst_path) throw() = 0;
229
230   /**
231    * \brief Delete an empty directory.
232    *
233    * Backend for POSIX rmdir, rmdirat functions.
234    *
235    * \param path The name of the directory to remove.
236    *             Note: \a path is relative to this
237    *             directory and may contain subdirectories.
238    * \return 0 on success, or <0 on error.
239    */
240   virtual int rmdir(const char *) 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   /**
247    * \internal
248    */
249   virtual int get_entry(const char *, int, mode_t, cxx::Ref_ptr<File> *) throw() = 0;
250 };
251
252 inline
253 Directory::~Directory() throw()
254 {}
255
256 /**
257  * \brief Interface for a POSIX file that provides regular file semantics.
258  *
259  * Real objects use always the combined L4Re::Vfs::File interface.
260  */
261 class Regular_file
262 {
263 public:
264   virtual ~Regular_file() throw() = 0;
265
266   /**
267    * \brief Get an L4Re::Dataspace object for the file.
268    *
269    * This is used as a backend for POSIX mmap and mmap2 functions.
270    * \note mmap is not possible if the functions returns an invalid
271    *       capability.
272    *
273    * \return A capability to an L4Re::Dataspace, that represents the files
274    *         contents in an L4Re way.
275    */
276   virtual L4::Cap<L4Re::Dataspace> data_space() const throw() = 0;
277
278   /**
279    * \brief Read one or more blocks of data from the file.
280    *
281    * This function acts as backend for POSIX read and readv calls and
282    * reads data starting for the f_pos pointer of that open file.
283    * The file pointer is advanced according to the number of red bytes.
284    *
285    * \return The number of bytes red from the file. or <0 on error-
286    */
287   virtual ssize_t readv(const struct iovec*, int iovcnt) throw() = 0;
288
289   /**
290    * \brief Write one or more blocks of data to the file.
291    *
292    * This function acts as backend for POSIX write and writev calls.
293    * The data is written starting at the current file pointer and the
294    * file pointer must be advanced according to the number of written
295    * bytes.
296    *
297    * \return The number of bytes written to the file, or <0 on error.
298    */
299   virtual ssize_t writev(const struct iovec*, int iovcnt) throw() = 0;
300
301   virtual ssize_t preadv(const struct iovec *iov, int iovcnt, off64_t offset) throw() = 0;
302   virtual ssize_t pwritev(const struct iovec *iov, int iovcnt, off64_t offset) throw() = 0;
303
304   /**
305    * \brief Change the file pointer.
306    *
307    * This is the backend for POSIX seek, lseek and friends.
308    *
309    * \return The new file position, or <0 on error.
310    */
311   virtual off64_t lseek64(off64_t, int) throw() = 0;
312
313
314   /**
315    * \brief Truncate the file at the given position.
316    *
317    * This function is the backend for truncate and friends.
318    * \param pos The offset at which the file shall be truncated.
319    * \return 0 on success, or <0 on error.
320    */
321   virtual int ftruncate64(off64_t pos) throw() = 0;
322
323   /**
324    * \brief Sync the data and meta data to persistent storage.
325    *
326    * This is the backend for POSIX fsync.
327    */
328   virtual int fsync() const throw() = 0;
329
330   /**
331    * \brief Sync the data to persistent storage.
332    *
333    * This is the backend for POSIX fdatasync.
334    */
335   virtual int fdatasync() const throw() = 0;
336
337   /**
338    * \brief Test if the given lock can be placed in the file.
339    *
340    * This function is used as backend for fcntl F_GETLK commands.
341    * \param lock The lock that shall be placed on the file. The
342    *             \a l_type member will contain #F_UNLCK if the lock
343    *             could be placed.
344    * \return 0 on success, <0 on error.
345    */
346   virtual int get_lock(struct flock64 *lock) throw() = 0;
347
348   /**
349    * \brief Acquire or release the given lock on the file.
350    *
351    * This function is used as backend for fcntl F_SETLK and F_SETLKW commands.
352    * \param lock The lock that shall be placed on the file.
353    * \param wait If true, then block if there is a conflicting lock on the file.
354    * \return 0 on success, <0 on error.
355    */
356   virtual int set_lock(struct flock64 *lock, bool wait) throw() = 0;
357 };
358
359 inline
360 Regular_file::~Regular_file() throw()
361 {}
362
363 /**
364  * \brief Interface for a POSIX file that provides special file semantics.
365  *
366  * Real objects use always the combined L4Re::Vfs::File interface.
367  */
368 class Special_file
369 {
370 public:
371   virtual ~Special_file() throw() = 0;
372
373   /**
374    * \brief The famous IO control.
375    *
376    * Backend for POSIX generic object invocation ioctl.
377    *
378    * \param cmd The ioctl command.
379    * \param args The arguments for the ioctl, usually some kind
380    *             of pointer.
381    * \return >=0 on success, or <0 on error.
382    */
383   virtual int ioctl(unsigned long cmd, va_list args) throw() = 0;
384 };
385
386 inline
387 Special_file::~Special_file() throw()
388 {}
389
390 /**
391  * \brief The basic interface for an open POSIX file.
392  *
393  * An open POSIX file can be anything that hides behind a
394  * POSIX file descriptor. This means that even a directories
395  * are files.  An open file can be anything from a directory to a
396  * special device file so see Generic_file, Regular_file, Directory,
397  * and Special_file for more information.
398  *
399  * \note For implementing a backend for the L4Re::Vfs you may use
400  *       L4Re::Vfs::Be_file as a base class.
401  *
402  */
403 class File :
404   public Generic_file,
405   public Regular_file,
406   public Directory,
407   public Special_file
408 {
409   friend class Mount_tree;
410
411 private:
412   void operator = (File const &);
413
414 protected:
415   File() throw() : _ref_cnt(0) {}
416   File(File const &)
417   : Generic_file(),Regular_file(), Directory(), Special_file(), _ref_cnt(0)
418   {}
419
420 public:
421
422   const char *get_mount(const char *path, cxx::Ref_ptr<File> *dir,
423                         cxx::Ref_ptr<Mount_tree> *mt = 0) throw();
424
425   int openat(const char *path, int flags, mode_t mode,
426              cxx::Ref_ptr<File> *f) throw();
427
428   void add_ref() throw() { ++_ref_cnt; }
429   int remove_ref() throw() { return --_ref_cnt; }
430
431   virtual ~File() throw() = 0;
432
433   cxx::Ref_ptr<Mount_tree> mount_tree() const throw()
434   { return _mount_tree; }
435
436 private:
437   int _ref_cnt;
438   cxx::Ref_ptr<Mount_tree> _mount_tree;
439
440 };
441
442 inline
443 File::~File() throw()
444 {}
445
446 class Path
447 {
448 private:
449   char const *_p;
450   unsigned _l;
451
452 public:
453   Path() throw() : _p(0), _l(0) {}
454
455   explicit Path(char const *p) throw() : _p(p)
456   { for (_l = 0; *p; ++p, ++_l) ; }
457
458   Path(char const *p, unsigned l) throw() : _p(p), _l(l)
459   {}
460
461   static bool __is_sep(char s) throw();
462
463   Path cmp_path(char const *prefix) const throw();
464
465   struct Invalid_ptr;
466   operator Invalid_ptr const * () const
467   { return reinterpret_cast<Invalid_ptr const *>(_p); }
468
469   unsigned length() const { return _l; }
470   char const *path() const { return _p; }
471
472   bool empty() const { return _l == 0; }
473
474   bool is_sep(unsigned offset) const { return __is_sep(_p[offset]); }
475
476   bool strip_sep()
477   {
478     bool s = false;
479     for (; __is_sep(*_p) && _l; ++_p, --_l)
480       s = true;
481     return s;
482   }
483
484   Path first() const
485   {
486     unsigned i;
487     for (i = 0; i < _l && !is_sep(i); ++i)
488       ;
489
490     return Path(_p, i);
491   }
492
493   Path strip_first()
494   {
495     Path r = first();
496     _p += r.length();
497     _l -= r.length();
498     strip_sep();
499     return r;
500   }
501
502 };
503
504
505 /**
506  * \internal
507  * \brief Internal representation for a tree of mount points.
508  * \note You should never need to deal with a Mount_tree objects
509  *       directly.
510  */
511 class Mount_tree
512 {
513 public:
514
515   explicit Mount_tree(char *n) throw();
516
517   Path lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
518               cxx::Ref_ptr<Mount_tree> *mp = 0) throw();
519
520   Path find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw();
521
522   cxx::Ref_ptr<File> mount() const
523   { return _mount; }
524
525   void mount(cxx::Ref_ptr<File> const &m)
526   {
527     m->_mount_tree = this;
528     _mount = m;
529   }
530
531   static int create_tree(cxx::Ref_ptr<Mount_tree> const &root,
532                          char const *path,
533                          cxx::Ref_ptr<File> const &dir) throw();
534
535   void add_child_node(Mount_tree *cld);
536
537   virtual ~Mount_tree() throw()  = 0;
538
539   void add_ref() throw() { ++_ref_cnt; }
540   int remove_ref() throw() { return --_ref_cnt; }
541
542 private:
543   friend class Real_mount_tree;
544
545   int _ref_cnt;
546   char *_name;
547   cxx::Ref_ptr<Mount_tree> _cld;
548   cxx::Ref_ptr<Mount_tree> _sib;
549   cxx::Ref_ptr<File> _mount;
550 };
551
552 inline
553 Mount_tree::~Mount_tree() throw()
554 {}
555
556 inline bool
557 Path::__is_sep(char s) throw()
558 { return s == '/'; }
559
560 inline Path
561 Path::cmp_path(char const *n) const throw()
562 {
563   char const *p = _p;
564   for (; *p && !__is_sep(*p) && *n; ++p, ++n)
565     if (*p != *n)
566       return Path();
567
568   if (*n || (*p && !__is_sep(*p)))
569     return Path();
570
571   return Path(p, _l - (p - _p));
572 }
573
574 inline
575 Mount_tree::Mount_tree(char *n) throw()
576 : _ref_cnt(0), _name(n)
577 {}
578
579 inline Path
580 Mount_tree::find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw()
581 {
582   if (!_cld)
583     return Path();
584
585   for (cxx::Ref_ptr<Mount_tree> x = _cld; x; x = x->_sib)
586     {
587       Path const r = p.cmp_path(x->_name);
588       if (r)
589         {
590           *t = x;
591           return r;
592         }
593     }
594
595   return Path();
596 }
597
598 inline Path
599 Mount_tree::lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
600                    cxx::Ref_ptr<Mount_tree> *mp) throw()
601 {
602   cxx::Ref_ptr<Mount_tree> x(this);
603   Path p = path;
604   Path last_mp = p;
605
606   if (mp)
607     *mp = this;
608
609   while (1)
610     {
611       Path r = x->find(p, &x);
612
613       if (!r)
614         {
615           if (mp)
616             return last_mp;
617
618           if (mt)
619             *mt = x;
620
621           return p;
622         }
623
624       r.strip_sep();
625
626       if (mp && x->_mount)
627         {
628           last_mp = r;
629           *mp = x;
630         }
631
632       if (r.empty())
633         {
634           if (mt)
635             *mt = x;
636
637           if (mp)
638             return last_mp;
639           else
640             return r;
641         }
642
643       p = r;
644     }
645 }
646
647 inline
648 void
649 Mount_tree::add_child_node(Mount_tree *cld)
650 {
651   cld->_sib = _cld;
652   _cld = cld;
653 }
654
655 /**
656  * \internal
657  * \brief This is an instantiatable mount-tree derivate.
658  */
659 class Real_mount_tree : public Mount_tree
660 {
661 public:
662   explicit Real_mount_tree(char *n) : Mount_tree(n) {}
663 };
664
665 inline int
666 Mount_tree::create_tree(cxx::Ref_ptr<Mount_tree> const &root,
667                         char const *path, cxx::Ref_ptr<File> const &dir) throw()
668 {
669   cxx::Ref_ptr<Mount_tree> base;
670   Path p = root->lookup(Path(path), &base);
671
672   while (!p.empty())
673     {
674       Path f = p.strip_first();
675
676       if (f.empty())
677         return -EEXIST;
678
679       char *name = strndup(f.path(), f.length());
680       if (!name)
681         return -ENOMEM;
682
683       cxx::Ref_ptr<Mount_tree> nt(new Real_mount_tree(name));
684       if (!nt)
685         {
686           free(name);
687           return -ENOMEM;
688         }
689
690       nt->_sib = base->_cld;
691       base->_cld = nt;
692
693       base = nt;
694
695       if (p.empty())
696         {
697           nt->_mount = dir;
698           return 0;
699         }
700     }
701
702   return -EINVAL;
703 }
704
705 inline
706 const char *
707 File::get_mount(const char *path, cxx::Ref_ptr<File> *dir,
708                 cxx::Ref_ptr<Mount_tree> *mt) throw()
709 {
710   if (!_mount_tree)
711     {
712       *dir = this;
713       return path;
714     }
715
716   cxx::Ref_ptr<Mount_tree> mp;
717   Path p = _mount_tree->lookup(Path(path), mt, &mp);
718   if (mp->mount())
719     {
720       *dir = mp->mount();
721       return p.path();
722     }
723   else
724     {
725       *dir = this;
726       return path;
727     }
728 }
729
730 inline int
731 File::openat(const char *path, int flags, mode_t mode,
732              cxx::Ref_ptr<File> *f) throw()
733 {
734   cxx::Ref_ptr<File> dir;
735   cxx::Ref_ptr<Mount_tree> mt;
736   path = get_mount(path, &dir, &mt);
737
738   int res = dir->get_entry(path, flags, mode, f);
739
740   if (res < 0)
741     return res;
742
743   if (!(*f)->_mount_tree && mt)
744     (*f)->_mount_tree = mt;
745
746   return res;
747 }
748
749 /**
750  * \brief Interface for the POSIX memory management.
751  * \note This interface exists usually as a singleton as superclass
752  *       of L4Re::Vfs::Ops.
753  *
754  * An implementation for this interface is in l4/l4re_vfs/impl/vfs_impl.h
755  * and used by the l4re_vfs library or by the VFS implementation in lsdo.
756  */
757 class Mman
758 {
759 public:
760   /// Backend for the mmap2 system call.
761   virtual int mmap2(void *start, size_t len, int prot, int flags, int fd,
762                     off_t offset, void **ptr) throw() = 0;
763
764   /// Backend for the munmap system call.
765   virtual int munmap(void *start, size_t len) throw() = 0;
766
767   /// Backend for the mremap system call.
768   virtual int mremap(void *old, size_t old_sz, size_t new_sz, int flags,
769                      void **new_adr) throw() = 0;
770
771   /// Backend for the mprotect system call.
772   virtual int mprotect(const void *a, size_t sz, int prot) throw() = 0;
773
774   /// Backend for the msync system call
775   virtual int msync(void *addr, size_t len, int flags) throw() = 0;
776
777   /// Backend for the madvice system call
778   virtual int madvise(void *addr, size_t len, int advice) throw() = 0;
779
780   virtual ~Mman() throw() = 0;
781 };
782
783 inline
784 Mman::~Mman() throw() {}
785
786 /**
787  * \brief Basic interface for an L4Re::Vfs file system.
788  * \note For implementing a special file system you may
789  *       use L4Re::Vfs::Be_file_system as a base class.
790  *
791  * The may purpose of this interface is that there is a
792  * single object for each supported file-system type (e.g., ext2, vfat)
793  * exists in your application and is registered at the L4Re::Vfs::Fs
794  * singleton available in via L4Re::Vfs::vfs_ops.
795  * At the end the POSIX mount function call the File_system::mount method
796  * for the given file-system type given in mount.
797  *
798  */
799 class File_system
800 {
801 protected:
802   File_system *_next;
803
804 public:
805   File_system() throw() : _next(0) {}
806   /**
807    * \brief Returns the type of the file system, used in mount as fstype
808    * argument.
809    * \note This method is already provided by Be_file_system.
810    */
811   virtual char const *type() const throw() = 0;
812
813   /**
814    * \brief Create a directory object \a dir representing \a source
815    *        mounted with this file system.
816    *
817    * \param source The path to the source device to mount. This may
818    *               also be some URL or anything file-system specific.
819    * \param mountflags The mount flags as specified in the POSIX
820    *                   mount call.
821    * \param data The data as specified in the POSIX mount call. The
822    *             contents are file-system specific.
823    * \retval dir A new directory object representing the file-system
824    *             root directory.
825    * \return 0 on success, and <0 on error (e.g. -EINVAL).
826    *
827    */
828   virtual int mount(char const *source, unsigned long mountflags,
829                     void const *data, cxx::Ref_ptr<File> *dir) throw() = 0;
830
831   virtual ~File_system() throw() = 0;
832
833   /**
834    * \internal
835    * \brief Get the next file system in the internal registry.
836    */
837   File_system *next() const throw() { return _next; }
838   File_system *&next() throw() { return _next; }
839   void next(File_system *n) throw() { _next = n; }
840 };
841
842 inline
843 File_system::~File_system() throw()
844 {}
845
846 /**
847  * \brief POSIX File-system related functionality.
848  * \note This class usually exists as a singleton as a superclass
849  *       of L4Re::Vfs::Ops (\see L4Re::Vfs::vfs_ops).
850  */
851 class Fs
852 {
853 public:
854   /**
855    * \brief Get the L4Re::Vfs::File for the file descriptor \a fd.
856    * \param fd The POSIX file descriptor number.
857    * \return A pointer to the File object, or 0 if \a fd is not open.
858    */
859   virtual cxx::Ref_ptr<File> get_file(int fd) throw() = 0;
860
861   /// Get the directory object for the applications root directory.
862   virtual cxx::Ref_ptr<File> get_root() throw() = 0;
863
864   /// Get the directory object for the applications current working directory.
865   virtual cxx::Ref_ptr<File> get_cwd() throw() { return get_root(); }
866
867   /// Set the current working directory for the application.
868   virtual void set_cwd(cxx::Ref_ptr<File> const &) throw() {}
869
870   /**
871    * \brief Allocate the next free file descriptor.
872    * \param f The file to assign to that file descriptor.
873    * \return the allocated file descriptor, or -EMFILE on error.
874    */
875   virtual int alloc_fd(cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
876
877   /**
878    * \brief Set the file object referenced by the file descriptor \a fd.
879    * \param fd The file descriptor to set to \a f;
880    * \param f The file object to assign.
881    * \return A pointer to the file object that was previously assigned to fd.
882    */
883   virtual cxx::Ref_ptr<File> set_fd(int fd, cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
884
885   /**
886    * \brief Free the file descriptor \a fd.
887    * \param fd The file descriptor to free.
888    * \return A pointer to the file object that was assigned to the fd.
889    */
890   virtual cxx::Ref_ptr<File> free_fd(int fd) throw() = 0;
891
892   /**
893    * \brief Mount a given file object at the given global path in the VFS.
894    * \param path The global path to mount \a dir at.
895    * \param dir A pointer to the file/directory object that shall be mountet
896    *            at \a path.
897    * \return 0 on success, or <0 on error.
898    */
899   int mount(char const *path, cxx::Ref_ptr<File> const &dir) throw();
900
901   /**
902    * \internal
903    * \brief Register a file-system type in the global registry.
904    * \note this is done automatically by Be_file_system.
905    * \param f A pointer to the file system to register.
906    * \return 0 on success, or <0 on error.
907    */
908   virtual int register_file_system(File_system *f) throw() = 0;
909
910   /**
911    * \internal
912    * \brief Removed the given file system from the global registry.
913    * \note This is done automatically by Be_file_system.
914    * \param f The file system instance to remove from the registry.
915    * \return 0 on success, <0 on error.
916    */
917   virtual int unregister_file_system(File_system *f) throw() = 0;
918
919   /**
920    * \internal
921    * \brief Find the file-system object for the given file-system type.
922    * \note This function is used by the mount.
923    * \param fstype The file-system type (e.g. ext, vfat).
924    * \return A pointer to the file-system object, or 0 on error.
925    */
926   virtual File_system *get_file_system(char const *fstype) throw() = 0;
927
928   /**
929    * \brief Backend for the POSIX mount call.
930    */
931   int mount(char const *source, char const *target,
932             char const *fstype, unsigned long mountflags,
933             void const *data) throw();
934
935   virtual ~Fs() = 0;
936 };
937
938
939 inline int
940 Fs::mount(char const *path, cxx::Ref_ptr<File> const &dir) throw()
941 {
942   if (cxx::Ref_ptr<Mount_tree> root = get_root()->mount_tree())
943     return Mount_tree::create_tree(root, path, dir);
944
945   return -EINVAL;
946 }
947
948 inline int
949 Fs::mount(char const *source, char const *target,
950           char const *fstype, unsigned long mountflags,
951           void const *data) throw()
952 {
953   File_system *fs = get_file_system(fstype);
954
955   if (!fs)
956     return -ENODEV;
957
958   cxx::Ref_ptr<File> dir;
959   int res = fs->mount(source, mountflags, data, &dir);
960
961   if (res < 0)
962     return res;
963
964   return mount(target, dir);
965 }
966
967 inline
968 Fs::~Fs()
969 {}
970
971 class App_api
972 {
973 public:
974   virtual Cap_alloc *cap_alloc() throw() = 0;
975   virtual ~App_api() = 0;
976 };
977
978 inline
979 App_api::~App_api()
980 {}
981
982 /**
983  * \brief Interface for the POSIX backends for an application.
984  * \note There usually exists a singe instance of this interface
985  *       available via L4Re::Vfs::vfs_ops that is used for all
986  *       kinds of C-Library functions.
987  */
988 class Ops : public Mman, public Fs, public App_api
989 {
990 public:
991   virtual ~Ops() throw() = 0;
992 };
993
994 inline
995 Ops::~Ops() throw()
996 {}
997
998
999
1000 }}
1001
1002 #endif
1003