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)
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.
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.
21 #include <l4/sys/compiler.h>
32 # define AT_FDCWD -100
37 #include <l4/sys/capability>
38 #include <l4/re/cap_alloc>
39 #include <l4/re/dataspace>
40 #include <l4/cxx/ref_ptr>
46 * \brief Virtual file system for interfaces POSIX libc.
54 * \brief The common interface for an open POSIX file.
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.
60 * \see L4Re::Vfs::File for mor information.
65 virtual ~Generic_file() throw() = 0;
67 * \brief Unlock all locks on the file.
68 * \note All locks means all locks independent by which file
69 * the locks were taken.
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.
75 * \return 0 on success, or <0 on error.
77 virtual int unlock_all_locks() throw() = 0;
80 * \brief Get status information for the file.
82 * This is the backend for POSIX fstat, stat, fstat64 and friends.
84 * \retval buf This buffer is filled with the status information.
85 * \return 0 on success, or <0 on error.
87 virtual int fstat64(struct stat64 *buf) const throw() = 0;
90 * \brief Change POSIX access rights on that file.
92 * Backend for POSIX chmod and fchmod.
94 virtual int fchmod(mode_t) throw() = 0;
97 * \brief Get file status flags (fcntl F_GETFL).
99 * This function is used by the fcntl implementation for the F_GETFL
102 * \return flags such as #O_RDONLY, #O_WRONLY, #O_RDWR, #O_DIRECT, #O_ASYNC,
103 * #O_NOATIME, #O_NONBLOCK, or <0 on error.
105 virtual int get_status_flags() const throw() = 0;
108 * \brief Set file status flags (fcntl F_SETFL).
110 * This function is used by the fcntl implementation for the F_SETFL
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.
117 * \note Creation flags such as #O_CREAT, #O_EXCL, #O_NOCTTY, #O_TRUNC are
120 * \return 0 on success, or <0 on error.
122 virtual int set_status_flags(long flags) throw() = 0;
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;
130 Generic_file::~Generic_file() throw()
134 * \brief Interface for a POSIX file that is a directory.
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.
143 virtual ~Directory() throw() = 0;
146 * \brief Check access permissions on the given file.
148 * Backend function for POSIX access and faccessat functions.
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.
158 virtual int faccessat(const char *path, int mode, int flags) throw() = 0;
161 * \brief Create a new subdirectory.
163 * Backend for POSIX mkdir and mkdirat function calls.
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.
172 virtual int mkdir(const char *path, mode_t mode) throw() = 0;
175 * \brief Unlink the given file from that directory.
177 * Backend for the POSIX unlink and unlinkat functions.
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.
184 virtual int unlink(const char *path) throw() = 0;
187 * \brief Rename the given file.
189 * Backend for the POSIX rename, renameat functions.
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.
199 virtual int rename(const char *src_path, const char *dst_path) throw() = 0;
202 * \brief Create a hard link (second name) for the given file.
204 * Backend for the POSIX link and linkat functions.
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.
214 virtual int link(const char *src_path, const char *dst_path) throw() = 0;
217 * \brief Create a symbolic link for the given file.
219 * Backend for the POSIX symlink and symlinkat functions.
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.
228 virtual int symlink(const char *src_path, const char *dst_path) throw() = 0;
231 * \brief Delete an empty directory.
233 * Backend for POSIX rmdir, rmdirat functions.
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.
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;
244 virtual ssize_t getdents(char *buf, size_t sizebytes) throw() = 0;
249 virtual int get_entry(const char *, int, mode_t, cxx::Ref_ptr<File> *) throw() = 0;
253 Directory::~Directory() throw()
257 * \brief Interface for a POSIX file that provides regular file semantics.
259 * Real objects use always the combined L4Re::Vfs::File interface.
264 virtual ~Regular_file() throw() = 0;
267 * \brief Get an L4Re::Dataspace object for the file.
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
273 * \return A capability to an L4Re::Dataspace, that represents the files
274 * contents in an L4Re way.
276 virtual L4::Cap<L4Re::Dataspace> data_space() const throw() = 0;
279 * \brief Read one or more blocks of data from the file.
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.
285 * \return The number of bytes red from the file. or <0 on error-
287 virtual ssize_t readv(const struct iovec*, int iovcnt) throw() = 0;
290 * \brief Write one or more blocks of data to the file.
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
297 * \return The number of bytes written to the file, or <0 on error.
299 virtual ssize_t writev(const struct iovec*, int iovcnt) throw() = 0;
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;
305 * \brief Change the file pointer.
307 * This is the backend for POSIX seek, lseek and friends.
309 * \return The new file position, or <0 on error.
311 virtual off64_t lseek64(off64_t, int) throw() = 0;
315 * \brief Truncate the file at the given position.
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.
321 virtual int ftruncate64(off64_t pos) throw() = 0;
324 * \brief Sync the data and meta data to persistent storage.
326 * This is the backend for POSIX fsync.
328 virtual int fsync() const throw() = 0;
331 * \brief Sync the data to persistent storage.
333 * This is the backend for POSIX fdatasync.
335 virtual int fdatasync() const throw() = 0;
338 * \brief Test if the given lock can be placed in the file.
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
344 * \return 0 on success, <0 on error.
346 virtual int get_lock(struct flock64 *lock) throw() = 0;
349 * \brief Acquire or release the given lock on the file.
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.
356 virtual int set_lock(struct flock64 *lock, bool wait) throw() = 0;
360 Regular_file::~Regular_file() throw()
364 * \brief Interface for a POSIX file that provides special file semantics.
366 * Real objects use always the combined L4Re::Vfs::File interface.
371 virtual ~Special_file() throw() = 0;
374 * \brief The famous IO control.
376 * Backend for POSIX generic object invocation ioctl.
378 * \param cmd The ioctl command.
379 * \param args The arguments for the ioctl, usually some kind
381 * \return >=0 on success, or <0 on error.
383 virtual int ioctl(unsigned long cmd, va_list args) throw() = 0;
387 Special_file::~Special_file() throw()
391 * \brief The basic interface for an open POSIX file.
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.
399 * \note For implementing a backend for the L4Re::Vfs you may use
400 * L4Re::Vfs::Be_file as a base class.
409 friend class Mount_tree;
412 void operator = (File const &);
415 File() throw() : _ref_cnt(0) {}
417 : Generic_file(),Regular_file(), Directory(), Special_file(), _ref_cnt(0)
422 const char *get_mount(const char *path, cxx::Ref_ptr<File> *dir,
423 cxx::Ref_ptr<Mount_tree> *mt = 0) throw();
425 int openat(const char *path, int flags, mode_t mode,
426 cxx::Ref_ptr<File> *f) throw();
428 void add_ref() throw() { ++_ref_cnt; }
429 int remove_ref() throw() { return --_ref_cnt; }
431 virtual ~File() throw() = 0;
433 cxx::Ref_ptr<Mount_tree> mount_tree() const throw()
434 { return _mount_tree; }
438 cxx::Ref_ptr<Mount_tree> _mount_tree;
443 File::~File() throw()
453 Path() throw() : _p(0), _l(0) {}
455 explicit Path(char const *p) throw() : _p(p)
456 { for (_l = 0; *p; ++p, ++_l) ; }
458 Path(char const *p, unsigned l) throw() : _p(p), _l(l)
461 static bool __is_sep(char s) throw();
463 Path cmp_path(char const *prefix) const throw();
466 operator Invalid_ptr const * () const
467 { return reinterpret_cast<Invalid_ptr const *>(_p); }
469 unsigned length() const { return _l; }
470 char const *path() const { return _p; }
472 bool empty() const { return _l == 0; }
474 bool is_sep(unsigned offset) const { return __is_sep(_p[offset]); }
479 for (; __is_sep(*_p) && _l; ++_p, --_l)
487 for (i = 0; i < _l && !is_sep(i); ++i)
507 * \brief Internal representation for a tree of mount points.
508 * \note You should never need to deal with a Mount_tree objects
515 explicit Mount_tree(char *n) throw();
517 Path lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
518 cxx::Ref_ptr<Mount_tree> *mp = 0) throw();
520 Path find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw();
522 cxx::Ref_ptr<File> mount() const
525 void mount(cxx::Ref_ptr<File> const &m)
527 m->_mount_tree = this;
531 static int create_tree(cxx::Ref_ptr<Mount_tree> const &root,
533 cxx::Ref_ptr<File> const &dir) throw();
535 void add_child_node(Mount_tree *cld);
537 virtual ~Mount_tree() throw() = 0;
539 void add_ref() throw() { ++_ref_cnt; }
540 int remove_ref() throw() { return --_ref_cnt; }
543 friend class Real_mount_tree;
547 cxx::Ref_ptr<Mount_tree> _cld;
548 cxx::Ref_ptr<Mount_tree> _sib;
549 cxx::Ref_ptr<File> _mount;
553 Mount_tree::~Mount_tree() throw()
557 Path::__is_sep(char s) throw()
561 Path::cmp_path(char const *n) const throw()
564 for (; *p && !__is_sep(*p) && *n; ++p, ++n)
568 if (*n || (*p && !__is_sep(*p)))
571 return Path(p, _l - (p - _p));
575 Mount_tree::Mount_tree(char *n) throw()
576 : _ref_cnt(0), _name(n)
580 Mount_tree::find(Path const &p, cxx::Ref_ptr<Mount_tree> *t) throw()
585 for (cxx::Ref_ptr<Mount_tree> x = _cld; x; x = x->_sib)
587 Path const r = p.cmp_path(x->_name);
599 Mount_tree::lookup(Path const &path, cxx::Ref_ptr<Mount_tree> *mt,
600 cxx::Ref_ptr<Mount_tree> *mp) throw()
602 cxx::Ref_ptr<Mount_tree> x(this);
611 Path r = x->find(p, &x);
649 Mount_tree::add_child_node(Mount_tree *cld)
657 * \brief This is an instantiatable mount-tree derivate.
659 class Real_mount_tree : public Mount_tree
662 explicit Real_mount_tree(char *n) : Mount_tree(n) {}
666 Mount_tree::create_tree(cxx::Ref_ptr<Mount_tree> const &root,
667 char const *path, cxx::Ref_ptr<File> const &dir) throw()
669 cxx::Ref_ptr<Mount_tree> base;
670 Path p = root->lookup(Path(path), &base);
674 Path f = p.strip_first();
679 char *name = strndup(f.path(), f.length());
683 cxx::Ref_ptr<Mount_tree> nt(new Real_mount_tree(name));
690 nt->_sib = base->_cld;
707 File::get_mount(const char *path, cxx::Ref_ptr<File> *dir,
708 cxx::Ref_ptr<Mount_tree> *mt) throw()
716 cxx::Ref_ptr<Mount_tree> mp;
717 Path p = _mount_tree->lookup(Path(path), mt, &mp);
731 File::openat(const char *path, int flags, mode_t mode,
732 cxx::Ref_ptr<File> *f) throw()
734 cxx::Ref_ptr<File> dir;
735 cxx::Ref_ptr<Mount_tree> mt;
736 path = get_mount(path, &dir, &mt);
738 int res = dir->get_entry(path, flags, mode, f);
743 if (!(*f)->_mount_tree && mt)
744 (*f)->_mount_tree = mt;
750 * \brief Interface for the POSIX memory management.
751 * \note This interface exists usually as a singleton as superclass
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.
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;
764 /// Backend for the munmap system call.
765 virtual int munmap(void *start, size_t len) throw() = 0;
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;
771 /// Backend for the mprotect system call.
772 virtual int mprotect(const void *a, size_t sz, int prot) throw() = 0;
774 /// Backend for the msync system call
775 virtual int msync(void *addr, size_t len, int flags) throw() = 0;
777 /// Backend for the madvice system call
778 virtual int madvise(void *addr, size_t len, int advice) throw() = 0;
780 virtual ~Mman() throw() = 0;
784 Mman::~Mman() throw() {}
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.
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.
805 File_system() throw() : _next(0) {}
807 * \brief Returns the type of the file system, used in mount as fstype
809 * \note This method is already provided by Be_file_system.
811 virtual char const *type() const throw() = 0;
814 * \brief Create a directory object \a dir representing \a source
815 * mounted with this file system.
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
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
825 * \return 0 on success, and <0 on error (e.g. -EINVAL).
828 virtual int mount(char const *source, unsigned long mountflags,
829 void const *data, cxx::Ref_ptr<File> *dir) throw() = 0;
831 virtual ~File_system() throw() = 0;
835 * \brief Get the next file system in the internal registry.
837 File_system *next() const throw() { return _next; }
838 File_system *&next() throw() { return _next; }
839 void next(File_system *n) throw() { _next = n; }
843 File_system::~File_system() throw()
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).
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.
859 virtual cxx::Ref_ptr<File> get_file(int fd) throw() = 0;
861 /// Get the directory object for the applications root directory.
862 virtual cxx::Ref_ptr<File> get_root() throw() = 0;
864 /// Get the directory object for the applications current working directory.
865 virtual cxx::Ref_ptr<File> get_cwd() throw() { return get_root(); }
867 /// Set the current working directory for the application.
868 virtual void set_cwd(cxx::Ref_ptr<File> const &) throw() {}
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.
875 virtual int alloc_fd(cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
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.
883 virtual cxx::Ref_ptr<File> set_fd(int fd, cxx::Ref_ptr<File> const &f = cxx::Ref_ptr<>::Nil) throw() = 0;
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.
890 virtual cxx::Ref_ptr<File> free_fd(int fd) throw() = 0;
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
897 * \return 0 on success, or <0 on error.
899 int mount(char const *path, cxx::Ref_ptr<File> const &dir) throw();
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.
908 virtual int register_file_system(File_system *f) throw() = 0;
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.
917 virtual int unregister_file_system(File_system *f) throw() = 0;
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.
926 virtual File_system *get_file_system(char const *fstype) throw() = 0;
929 * \brief Backend for the POSIX mount call.
931 int mount(char const *source, char const *target,
932 char const *fstype, unsigned long mountflags,
933 void const *data) throw();
940 Fs::mount(char const *path, cxx::Ref_ptr<File> const &dir) throw()
942 if (cxx::Ref_ptr<Mount_tree> root = get_root()->mount_tree())
943 return Mount_tree::create_tree(root, path, dir);
949 Fs::mount(char const *source, char const *target,
950 char const *fstype, unsigned long mountflags,
951 void const *data) throw()
953 File_system *fs = get_file_system(fstype);
958 cxx::Ref_ptr<File> dir;
959 int res = fs->mount(source, mountflags, data, &dir);
964 return mount(target, dir);
974 virtual Cap_alloc *cap_alloc() throw() = 0;
975 virtual ~App_api() = 0;
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.
988 class Ops : public Mman, public Fs, public App_api
991 virtual ~Ops() throw() = 0;