2 * (c) 2008-2009 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 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU Lesser General Public License 2.1.
7 * Please see the COPYING-LGPL-2.1 file for details.
14 # define __USE_ATFILE 1
17 #include <l4/util/atomic.h>
27 #include <sys/ioctl.h>
31 #include <l4/l4re_vfs/backend>
37 using namespace L4Re::Vfs;
40 ssize_t read(int fd, void *buf, size_t count)
45 return readv(fd, &iov, 1);
48 ssize_t write(int fd, const void *buf, size_t count)
51 iov.iov_base = const_cast<void*>(buf);
53 return writev(fd, &iov, 1);
56 static void copy_stat64_to_stat(struct stat *buf, struct stat64 *sb64)
58 memset(buf, 0, sizeof(*buf));
60 buf->st_dev = sb64->st_dev;
61 buf->st_ino = sb64->st_ino;
62 buf->st_mode = sb64->st_mode;
63 buf->st_nlink = sb64->st_nlink;
64 buf->st_uid = sb64->st_uid;
65 buf->st_gid = sb64->st_gid;
66 buf->st_rdev = sb64->st_rdev;
67 buf->st_size = sb64->st_size;
68 buf->st_blksize = sb64->st_blksize;
69 buf->st_blocks = sb64->st_blocks;
70 buf->st_atime = sb64->st_atime;
71 buf->st_mtime = sb64->st_mtime;
72 buf->st_ctime = sb64->st_ctime;
75 int fstat(int fd, struct stat *buf) L4_NOTHROW
78 int r = fstat64(fd, &sb64);
82 copy_stat64_to_stat(buf, &sb64);
86 #define ERRNO_RET(r) do { \
96 static Ref_ptr<File> __internal_get_dir(int dirfd, char const **path) L4_NOTHROW
98 Ops *vfs_ops = L4Re::Vfs::vfs_ops;
101 while (**path == '/')
104 return vfs_ops->get_root();
106 else if (dirfd == AT_FDCWD)
107 return vfs_ops->get_cwd();
109 return vfs_ops->get_file(dirfd);
113 __internal_resolvedir(int dirfd, const char *path, int flags, mode_t mode,
114 Ref_ptr<File> *f) L4_NOTHROW
118 Ref_ptr<File> dir = __internal_get_dir(dirfd, &path);
122 return dir->get_mount(path, f);
126 __internal_resolve(int dirfd, const char *path, int flags, mode_t mode,
127 Ref_ptr<File> *f) L4_NOTHROW
129 Ref_ptr<File> dir = __internal_get_dir(dirfd, &path);
133 return dir->openat(path, flags, mode, f);
137 __internal_open(const char *path, int flags, mode_t mode) L4_NOTHROW
140 int res = __internal_resolve(AT_FDCWD, path, flags, mode, &f);
144 int fd = L4Re::Vfs::vfs_ops->alloc_fd(f);
151 int open(const char *name, int flags, ...)
159 mode = va_arg(v, mode_t);
163 return __internal_open(name, flags, mode);
167 int open64(const char *name, int flags, ...)
175 mode = va_arg(v, mode_t);
179 return __internal_open(name, flags, mode);
182 extern "C" int ioctl(int fd, unsigned long request, ...) L4_NOTHROW
185 va_start(v, request);
189 int r = file->ioctl(request, v);
194 extern "C" int fcntl64(int fd, int cmd, ...)
196 Ops *o = L4Re::Vfs::vfs_ops;
197 Ref_ptr<File> f = o->get_file(fd);
201 case F_DUPFD_CLOEXEC:
202 // 'arg' has the lowest fd ... so dup isn't the correct thing
211 return f->get_status_flags();
239 extern "C" int fcntl(int fd, int cmd, ...)
245 arg = va_arg(v, unsigned long);
248 return fcntl64(fd, cmd, arg);
252 off_t lseek(int fd, off_t offset, int whence) L4_NOTHROW
254 return lseek64(fd, offset, whence);
257 int ftruncate(int fd, off_t length) L4_NOTHROW
259 return ftruncate64(fd, length);
262 int lockf(int fd, int cmd, off_t len)
273 extern "C" int dup2(int oldfd, int newfd) L4_NOTHROW
275 Ops *o = L4Re::Vfs::vfs_ops;
276 Ref_ptr<File> oldf = o->get_file(oldfd);
283 Ref_ptr<File> newf = o->set_fd(newfd, oldf);
284 if (!newf || newf == oldf)
287 // do the stuff for close;
288 newf->unlock_all_locks();
293 extern "C" int dup(int oldfd) L4_NOTHROW
295 Ops *o = L4Re::Vfs::vfs_ops;
296 Ref_ptr<File> f = o->get_file(oldfd);
303 int r = o->alloc_fd(f);
309 int stat(const char *path, struct stat *buf) L4_NOTHROW
312 int r = stat64(path, &sb64);
316 copy_stat64_to_stat(buf, &sb64);
320 int lstat(const char *path, struct stat *buf) L4_NOTHROW
323 int r = lstat64(path, &sb64);
328 copy_stat64_to_stat(buf, &sb64);
332 int close(int fd) L4_NOTHROW
334 Ops *o = L4Re::Vfs::vfs_ops;
335 Ref_ptr<File> f = o->free_fd(fd);
342 f->unlock_all_locks();
346 int access(const char *path, int mode) L4_NOTHROW
347 { return faccessat(AT_FDCWD, path, mode, 0); }
349 extern "C" ssize_t __getdents64(int fd, char *buf, size_t nbytes);
350 extern "C" ssize_t __getdents64(int fd, char *buf, size_t nbytes)
352 Ops *o = L4Re::Vfs::vfs_ops;
353 Ref_ptr<File> fdo = o->get_file(fd);
360 ssize_t r = fdo->getdents(buf, nbytes);
371 extern "C" ssize_t __getdents(int, char *, size_t);
372 L4_STRONG_ALIAS(__getdents64,__getdents)
376 #define L4B_REDIRECT(ret, func, ptlist, plist) \
377 extern "C" ret func ptlist L4_NOTHROW \
379 cxx::Ref_ptr<L4Re::Vfs::File> file; \
380 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
382 ret r = file->L4B_REDIRECT_FUNC(func)(L4B_STRIP_FIRST(plist)); \
386 #define L4B_REDIRECT_FUNC(func) func
387 L4B_REDIRECT_3(ssize_t, readlink, const char *, char *, size_t)
388 L4B_REDIRECT_2(int, utime, const char *, const struct utimbuf *)
389 L4B_REDIRECT_2(int, utimes, const char *, const struct timeval *)
390 #undef L4B_REDIRECT_FUNC
392 #define L4B_REDIRECT_FUNC(func) f##func
393 L4B_REDIRECT_2(int, stat64, const char *, struct stat64 *)
394 L4B_REDIRECT_2(int, chmod, const char *, mode_t)
395 #undef L4B_REDIRECT_FUNC
397 #define L4B_REDIRECT_FUNC(func) fstat64
398 L4B_REDIRECT_2(int, lstat64, const char *, struct stat64 *)
399 #undef L4B_REDIRECT_FUNC
402 #define L4B_REDIRECT(ret, func, ptlist, plist) \
403 extern "C" ret func ptlist L4_NOTHROW \
405 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
406 _a1 = __internal_resolvedir(AT_FDCWD, _a1, 0, 0, &dir); \
407 ret r = dir->func plist; \
411 L4B_REDIRECT_1(int, unlink, const char *)
412 L4B_REDIRECT_2(int, mkdir, const char *, mode_t)
413 L4B_REDIRECT_1(int, rmdir, const char *)
416 #define L4B_REDIRECT(ret, func, ptlist, plist) \
417 extern "C" ret func ptlist L4_NOTHROW \
419 cxx::Ref_ptr<L4Re::Vfs::File> dir1; \
420 cxx::Ref_ptr<L4Re::Vfs::File> dir2; \
421 _a1 = __internal_resolvedir(AT_FDCWD, _a1, 0, 0, &dir1); \
422 _a2 = __internal_resolvedir(AT_FDCWD, _a2, 0, 0, &dir2); \
423 ret r = dir1->func plist; \
427 L4B_REDIRECT_2(int, rename, const char *, const char *)
428 L4B_REDIRECT_2(int, link, const char *, const char *)
429 L4B_REDIRECT_2(int, symlink, const char *, const char *)
432 #define L4B_REDIRECT(ret, func, ptlist, plist) \
433 extern "C" ret func ptlist L4_NOTHROW \
435 cxx::Ref_ptr<L4Re::Vfs::File> file; \
436 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
438 ret r = file->ftruncate64(L4B_STRIP_FIRST(plist)); \
442 L4B_REDIRECT_2(int, truncate, const char *, off_t)
443 L4B_REDIRECT_2(int, truncate64, const char *, off64_t)
447 #define L4B_REDIRECT(ret, func, ptlist, plist) \
448 extern "C" ret func ptlist L4_NOTHROW \
450 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
451 _a2 = __internal_resolvedir(_a1, _a2, 0, 0, &dir); \
457 ret r = dir->func(L4B_STRIP_FIRST(plist)); \
461 //L4B_REDIRECT_3(int, unlinkat, int, const char *, int)
462 L4B_REDIRECT_4(int, faccessat, int, const char *, int, int)
465 // ------------------------------------------------------
468 #include <l4/util/util.h>
470 int select(int nfds, fd_set *readfds, fd_set *writefds,
471 fd_set *exceptfds, struct timeval *timeout)
473 (void)nfds; (void)readfds; (void)writefds; (void)exceptfds;
474 //printf("Call: %s(%d, %p, %p, %p, %p[%ld])\n", __func__, nfds, readfds, writefds, exceptfds, timeout, timeout->tv_usec + timeout->tv_sec * 1000000);
477 int us = timeout->tv_usec + timeout->tv_sec * 1000000;
478 l4_timeout_t to = l4_timeout(L4_IPC_TIMEOUT_NEVER,
479 l4util_micros2l4to(us));
482 // only the timeout for now
484 l4_usleep(timeout->tv_usec + timeout->tv_sec * 1000000);
493 #define L4B_REDIRECT(ret, func, ptlist, plist) \
494 ret func ptlist L4_NOTHROW \
496 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops; \
497 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(_a1); \
503 ret r = f->func(L4B_STRIP_FIRST(plist)); \
508 ssize_t preadv(int, const struct iovec *, int, off_t);
509 ssize_t pwritev(int, const struct iovec *, int, off_t);
512 L4B_REDIRECT_2(int, fstat64, int, struct stat64 *)
513 L4B_REDIRECT_3(ssize_t, readv, int, const struct iovec *, int)
514 L4B_REDIRECT_3(ssize_t, writev, int, const struct iovec *, int)
515 L4B_REDIRECT_4(ssize_t, preadv, int, const struct iovec *, int, off_t)
516 L4B_REDIRECT_4(ssize_t, pwritev, int, const struct iovec *, int, off_t)
517 L4B_REDIRECT_3(__off64_t, lseek64, int, __off64_t, int)
518 L4B_REDIRECT_2(int, ftruncate64, int, off64_t)
519 L4B_REDIRECT_1(int, fsync, int)
520 L4B_REDIRECT_1(int, fdatasync, int)
521 L4B_REDIRECT_2(int, fchmod, int, mode_t)
523 static char const * const _default_current_working_dir = "/";
524 static char *_current_working_dir = const_cast<char *>(_default_current_working_dir);
526 static void free_cwd()
528 if (_current_working_dir != _default_current_working_dir)
529 free(_current_working_dir);
532 extern "C" int chdir(const char *path) L4_NOTHROW
535 int res = __internal_resolve(AT_FDCWD, path, 0, 0, &f);
541 _current_working_dir = strdup(path);
545 unsigned len_cwd = strlen(_current_working_dir);
546 unsigned len_path = strlen(path);
547 char *tmp = (char *)malloc(len_cwd + len_path + 2);
548 memcpy(tmp, _current_working_dir, len_cwd);
549 if (tmp[len_cwd - 1] != '/')
550 tmp[len_cwd++] = '/';
551 memcpy(tmp + len_cwd, path, len_path + 1);
554 _current_working_dir = tmp;
557 // would need to check whether 'f' is a directory
558 L4Re::Vfs::vfs_ops->set_cwd(f);
563 extern "C" int fchdir(int fd) L4_NOTHROW
565 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops;
566 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(fd);
573 // would need to check whether 'f' is a directory
579 ssize_t pread64(int fd, void *buf, size_t count, off64_t offset)
584 return preadv(fd, &iov, 1, offset);
588 ssize_t pread(int fd, void *buf, size_t count, off_t offset)
590 return pread64(fd, buf, count, offset);
594 ssize_t pwrite64(int fd, const void *buf, size_t count, off64_t offset)
597 iov.iov_base = const_cast<void*>(buf);
599 return pwritev(fd, &iov, 1, offset);
603 ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
605 return pwrite64(fd, buf, count, offset);
608 extern "C" char *getcwd(char *buf, size_t size) L4_NOTHROW
610 unsigned len_cwd = strlen(_current_working_dir) + 1;
612 if (buf == 0 && size == 0)
616 buf = (char *)malloc(size);
630 memcpy(buf, _current_working_dir, len_cwd);
634 extern "C" int chroot(const char *) L4_NOTHROW
640 extern "C" int mkfifo(const char *, mode_t) L4_NOTHROW
646 extern "C" int mknod(const char *, mode_t, dev_t) L4_NOTHROW
652 int chown(const char *, __uid_t, __gid_t)
658 int fchown(int, __uid_t, __gid_t)
665 extern "C" int lchown(const char *, uid_t, gid_t) L4_NOTHROW