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);
339 f->unlock_all_locks();
343 int access(const char *path, int mode) L4_NOTHROW
344 { return faccessat(AT_FDCWD, path, mode, 0); }
346 extern "C" ssize_t __getdents64(int fd, char *buf, size_t nbytes);
347 extern "C" ssize_t __getdents64(int fd, char *buf, size_t nbytes)
349 Ops *o = L4Re::Vfs::vfs_ops;
350 Ref_ptr<File> fdo = o->get_file(fd);
357 ssize_t r = fdo->getdents(buf, nbytes);
368 extern "C" ssize_t __getdents(int, char *, size_t);
369 L4_STRONG_ALIAS(__getdents64,__getdents)
373 #define L4B_REDIRECT(ret, func, ptlist, plist) \
374 extern "C" ret func ptlist L4_NOTHROW \
376 cxx::Ref_ptr<L4Re::Vfs::File> file; \
377 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
379 ret r = file->L4B_REDIRECT_FUNC(func)(L4B_STRIP_FIRST(plist)); \
383 #define L4B_REDIRECT_FUNC(func) func
384 L4B_REDIRECT_3(ssize_t, readlink, const char *, char *, size_t)
385 L4B_REDIRECT_2(int, utime, const char *, const struct utimbuf *)
386 L4B_REDIRECT_2(int, utimes, const char *, const struct timeval *)
387 #undef L4B_REDIRECT_FUNC
389 #define L4B_REDIRECT_FUNC(func) f##func
390 L4B_REDIRECT_2(int, stat64, const char *, struct stat64 *)
391 L4B_REDIRECT_2(int, chmod, const char *, mode_t)
392 #undef L4B_REDIRECT_FUNC
394 #define L4B_REDIRECT_FUNC(func) fstat64
395 L4B_REDIRECT_2(int, lstat64, const char *, struct stat64 *)
396 #undef L4B_REDIRECT_FUNC
399 #define L4B_REDIRECT(ret, func, ptlist, plist) \
400 extern "C" ret func ptlist L4_NOTHROW \
402 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
403 _a1 = __internal_resolvedir(AT_FDCWD, _a1, 0, 0, &dir); \
404 ret r = dir->func plist; \
408 L4B_REDIRECT_1(int, unlink, const char *)
409 L4B_REDIRECT_2(int, mkdir, const char *, mode_t)
410 L4B_REDIRECT_1(int, rmdir, const char *)
413 #define L4B_REDIRECT(ret, func, ptlist, plist) \
414 extern "C" ret func ptlist L4_NOTHROW \
416 cxx::Ref_ptr<L4Re::Vfs::File> dir1; \
417 cxx::Ref_ptr<L4Re::Vfs::File> dir2; \
418 _a1 = __internal_resolvedir(AT_FDCWD, _a1, 0, 0, &dir1); \
419 _a2 = __internal_resolvedir(AT_FDCWD, _a2, 0, 0, &dir2); \
420 ret r = dir1->func plist; \
424 L4B_REDIRECT_2(int, rename, const char *, const char *)
425 L4B_REDIRECT_2(int, link, const char *, const char *)
426 L4B_REDIRECT_2(int, symlink, const char *, const char *)
429 #define L4B_REDIRECT(ret, func, ptlist, plist) \
430 extern "C" ret func ptlist L4_NOTHROW \
432 cxx::Ref_ptr<L4Re::Vfs::File> file; \
433 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
435 ret r = file->ftruncate64(L4B_STRIP_FIRST(plist)); \
439 L4B_REDIRECT_2(int, truncate, const char *, off_t)
440 L4B_REDIRECT_2(int, truncate64, const char *, off64_t)
444 #define L4B_REDIRECT(ret, func, ptlist, plist) \
445 extern "C" ret func ptlist L4_NOTHROW \
447 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
448 _a2 = __internal_resolvedir(_a1, _a2, 0, 0, &dir); \
454 ret r = dir->func(L4B_STRIP_FIRST(plist)); \
458 //L4B_REDIRECT_3(int, unlinkat, int, const char *, int)
459 L4B_REDIRECT_4(int, faccessat, int, const char *, int, int)
462 // ------------------------------------------------------
465 #include <l4/util/util.h>
467 int select(int nfds, fd_set *readfds, fd_set *writefds,
468 fd_set *exceptfds, struct timeval *timeout)
470 (void)nfds; (void)readfds; (void)writefds; (void)exceptfds;
471 //printf("Call: %s(%d, %p, %p, %p, %p[%ld])\n", __func__, nfds, readfds, writefds, exceptfds, timeout, timeout->tv_usec + timeout->tv_sec * 1000000);
474 int us = timeout->tv_usec + timeout->tv_sec * 1000000;
475 l4_timeout_t to = l4_timeout(L4_IPC_TIMEOUT_NEVER,
476 l4util_micros2l4to(us));
479 // only the timeout for now
481 l4_usleep(timeout->tv_usec + timeout->tv_sec * 1000000);
490 #define L4B_REDIRECT(ret, func, ptlist, plist) \
491 ret func ptlist L4_NOTHROW \
493 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops; \
494 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(_a1); \
500 ret r = f->func(L4B_STRIP_FIRST(plist)); \
504 ssize_t preadv(int, const struct iovec *, int, off_t);
505 ssize_t pwritev(int, const struct iovec *, int, off_t);
507 L4B_REDIRECT_2(int, fstat64, int, struct stat64 *)
508 L4B_REDIRECT_3(ssize_t, readv, int, const struct iovec *, int)
509 L4B_REDIRECT_3(ssize_t, writev, int, const struct iovec *, int)
510 L4B_REDIRECT_4(ssize_t, preadv, int, const struct iovec *, int, off_t)
511 L4B_REDIRECT_4(ssize_t, pwritev, int, const struct iovec *, int, off_t)
512 L4B_REDIRECT_3(__off64_t, lseek64, int, __off64_t, int)
513 L4B_REDIRECT_2(int, ftruncate64, int, off64_t)
514 L4B_REDIRECT_1(int, fsync, int)
515 L4B_REDIRECT_1(int, fdatasync, int)
516 L4B_REDIRECT_2(int, fchmod, int, mode_t)
518 static char const * const _default_current_working_dir = "/";
519 static char *_current_working_dir = const_cast<char *>(_default_current_working_dir);
521 static void free_cwd()
523 if (_current_working_dir != _default_current_working_dir)
524 free(_current_working_dir);
527 extern "C" int chdir(const char *path) L4_NOTHROW
530 int res = __internal_resolve(AT_FDCWD, path, 0, 0, &f);
536 _current_working_dir = strdup(path);
540 unsigned len_cwd = strlen(_current_working_dir);
541 unsigned len_path = strlen(path);
542 char *tmp = (char *)malloc(len_cwd + len_path + 2);
543 memcpy(tmp, _current_working_dir, len_cwd);
544 if (tmp[len_cwd - 1] != '/')
545 tmp[len_cwd++] = '/';
546 memcpy(tmp + len_cwd, path, len_path + 1);
549 _current_working_dir = tmp;
552 // would need to check whether 'f' is a directory
553 L4Re::Vfs::vfs_ops->set_cwd(f);
558 extern "C" int fchdir(int fd) L4_NOTHROW
560 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops;
561 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(fd);
568 // would need to check whether 'f' is a directory
574 ssize_t pread64(int fd, void *buf, size_t count, off64_t offset)
579 return preadv(fd, &iov, 1, offset);
583 ssize_t pwrite64(int fd, const void *buf, size_t count, off64_t offset)
586 iov.iov_base = const_cast<void*>(buf);
588 return pwritev(fd, &iov, 1, offset);
591 extern "C" char *getcwd(char *buf, size_t size) L4_NOTHROW
593 unsigned len_cwd = strlen(_current_working_dir) + 1;
595 if (buf == 0 && size == 0)
599 buf = (char *)malloc(size);
613 memcpy(buf, _current_working_dir, len_cwd);
617 extern "C" int chroot(const char *) L4_NOTHROW
623 extern "C" int mkfifo(const char *, mode_t) L4_NOTHROW
629 extern "C" int mknod(const char *, mode_t, dev_t) L4_NOTHROW
635 int chown(const char *, __uid_t, __gid_t)
641 int fchown(int, __uid_t, __gid_t)
648 extern "C" int lchown(const char *, uid_t, gid_t) L4_NOTHROW