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