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>
30 #include <l4/l4re_vfs/backend>
36 using namespace L4Re::Vfs;
39 ssize_t read(int fd, void *buf, size_t count)
44 return readv(fd, &iov, 1);
47 ssize_t write(int fd, const void *buf, size_t count)
50 iov.iov_base = const_cast<void*>(buf);
52 return writev(fd, &iov, 1);
55 static void copy_stat64_to_stat(struct stat *buf, struct stat64 *sb64)
57 memset(buf, 0, sizeof(*buf));
59 buf->st_dev = sb64->st_dev;
60 buf->st_ino = sb64->st_ino;
61 buf->st_mode = sb64->st_mode;
62 buf->st_nlink = sb64->st_nlink;
63 buf->st_uid = sb64->st_uid;
64 buf->st_gid = sb64->st_gid;
65 buf->st_rdev = sb64->st_rdev;
66 buf->st_size = sb64->st_size;
67 buf->st_blksize = sb64->st_blksize;
68 buf->st_blocks = sb64->st_blocks;
69 buf->st_atime = sb64->st_atime;
70 buf->st_mtime = sb64->st_mtime;
71 buf->st_ctime = sb64->st_ctime;
74 int fstat(int fd, struct stat *buf) L4_NOTHROW
77 int r = fstat64(fd, &sb64);
81 copy_stat64_to_stat(buf, &sb64);
85 #define ERRNO_RET(r) do { \
95 static Ref_ptr<File> __internal_get_dir(int dirfd, char const **path) L4_NOTHROW
97 Ops *vfs_ops = L4Re::Vfs::vfs_ops;
100 while (**path == '/')
103 return vfs_ops->get_root();
105 else if (dirfd == AT_FDCWD)
106 return vfs_ops->get_cwd();
108 return vfs_ops->get_file(dirfd);
112 __internal_resolvedir(int dirfd, const char *path, int flags, mode_t mode,
113 Ref_ptr<File> *f) L4_NOTHROW
117 Ref_ptr<File> dir = __internal_get_dir(dirfd, &path);
121 return dir->get_mount(path, f);
125 __internal_resolve(int dirfd, const char *path, int flags, mode_t mode,
126 Ref_ptr<File> *f) L4_NOTHROW
128 Ref_ptr<File> dir = __internal_get_dir(dirfd, &path);
132 return dir->openat(path, flags, mode, f);
136 __internal_open(const char *path, int flags, mode_t mode) L4_NOTHROW
139 int res = __internal_resolve(AT_FDCWD, path, flags, mode, &f);
143 int fd = L4Re::Vfs::vfs_ops->alloc_fd(f);
150 int open(const char *name, int flags, ...)
158 mode = va_arg(v, mode_t);
162 return __internal_open(name, flags, mode);
166 int open64(const char *name, int flags, ...)
174 mode = va_arg(v, mode_t);
178 return __internal_open(name, flags, mode);
181 extern "C" int ioctl(int fd, unsigned long request, ...) L4_NOTHROW
184 va_start(v, request);
188 int r = file->ioctl(request, v);
193 extern "C" int fcntl64(int fd, int cmd, ...)
195 Ops *o = L4Re::Vfs::vfs_ops;
196 Ref_ptr<File> f = o->get_file(fd);
200 case F_DUPFD_CLOEXEC:
201 // 'arg' has the lowest fd ... so dup isn't the correct thing
210 return f->get_status_flags();
238 extern "C" int fcntl(int fd, int cmd, ...)
244 arg = va_arg(v, unsigned long);
247 return fcntl64(fd, cmd, arg);
251 off_t lseek(int fd, off_t offset, int whence) L4_NOTHROW
253 return lseek64(fd, offset, whence);
256 int ftruncate(int fd, off_t length) L4_NOTHROW
258 return ftruncate64(fd, length);
261 int lockf(int fd, int cmd, off_t len)
272 extern "C" int dup2(int oldfd, int newfd) L4_NOTHROW
274 Ops *o = L4Re::Vfs::vfs_ops;
275 Ref_ptr<File> oldf = o->get_file(oldfd);
282 Ref_ptr<File> newf = o->set_fd(newfd, oldf);
283 if (!newf || newf == oldf)
286 // do the stuff for close;
287 newf->unlock_all_locks();
292 extern "C" int dup(int oldfd) L4_NOTHROW
294 Ops *o = L4Re::Vfs::vfs_ops;
295 Ref_ptr<File> f = o->get_file(oldfd);
302 int r = o->alloc_fd(f);
308 int stat(const char *path, struct stat *buf) L4_NOTHROW
311 int r = stat64(path, &sb64);
315 copy_stat64_to_stat(buf, &sb64);
319 int lstat(const char *path, struct stat *buf) L4_NOTHROW
322 int r = lstat64(path, &sb64);
327 copy_stat64_to_stat(buf, &sb64);
331 int close(int fd) L4_NOTHROW
333 Ops *o = L4Re::Vfs::vfs_ops;
334 Ref_ptr<File> f = o->free_fd(fd);
338 f->unlock_all_locks();
342 int access(const char *path, int mode) L4_NOTHROW
343 { return faccessat(AT_FDCWD, path, mode, 0); }
345 extern "C" ssize_t __getdents64 (int fd, char *buf, size_t nbytes)
347 Ops *o = L4Re::Vfs::vfs_ops;
348 Ref_ptr<File> fdo = o->get_file(fd);
355 ssize_t r = fdo->getdents(buf, nbytes);
366 extern "C" ssize_t __getdents(int, char *, size_t);
367 L4_STRONG_ALIAS(__getdents64,__getdents)
371 #define L4B_REDIRECT(ret, func, ptlist, plist) \
372 extern "C" ret func ptlist L4_NOTHROW \
374 cxx::Ref_ptr<L4Re::Vfs::File> file; \
375 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
377 ret r = file->L4B_REDIRECT_FUNC(func)(L4B_STRIP_FIRST(plist)); \
381 #define L4B_REDIRECT_FUNC(func) func
382 L4B_REDIRECT_3(ssize_t, readlink, const char *, char *, size_t)
383 L4B_REDIRECT_2(int, utime, const char *, const struct utimbuf *)
384 L4B_REDIRECT_2(int, utimes, const char *, const struct utimbuf *)
385 #undef L4B_REDIRECT_FUNC
387 #define L4B_REDIRECT_FUNC(func) f##func
388 L4B_REDIRECT_2(int, stat64, const char *, struct stat64 *)
389 L4B_REDIRECT_2(int, chmod, const char *, mode_t)
390 #undef L4B_REDIRECT_FUNC
392 #define L4B_REDIRECT_FUNC(func) fstat64
393 L4B_REDIRECT_2(int, lstat64, const char *, struct stat64 *)
394 #undef L4B_REDIRECT_FUNC
397 #define L4B_REDIRECT(ret, func, ptlist, plist) \
398 extern "C" ret func ptlist L4_NOTHROW \
400 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
401 _a1 = __internal_resolvedir(AT_FDCWD, _a1, 0, 0, &dir); \
402 ret r = dir->func plist; \
406 L4B_REDIRECT_1(int, unlink, const char *)
407 L4B_REDIRECT_2(int, rename, const char *, const char *)
408 L4B_REDIRECT_2(int, mkdir, const char *, mode_t)
409 L4B_REDIRECT_1(int, rmdir, const char *)
410 L4B_REDIRECT_2(int, link, const char *, const char *)
411 L4B_REDIRECT_2(int, symlink, const char *, const char *)
414 #define L4B_REDIRECT(ret, func, ptlist, plist) \
415 extern "C" ret func ptlist L4_NOTHROW \
417 cxx::Ref_ptr<L4Re::Vfs::File> file; \
418 int res = __internal_resolve(AT_FDCWD, _a1, 0, 0, &file); \
420 ret r = file->ftruncate64(L4B_STRIP_FIRST(plist)); \
424 L4B_REDIRECT_2(int, truncate, const char *, off_t)
425 L4B_REDIRECT_2(int, truncate64, const char *, off64_t)
429 #define L4B_REDIRECT(ret, func, ptlist, plist) \
430 extern "C" ret func ptlist L4_NOTHROW \
432 cxx::Ref_ptr<L4Re::Vfs::File> dir; \
433 _a2 = __internal_resolvedir(_a1, _a2, 0, 0, &dir); \
439 ret r = dir->func(L4B_STRIP_FIRST(plist)); \
443 //L4B_REDIRECT_3(int, unlinkat, int, const char *, int)
444 L4B_REDIRECT_4(int, faccessat, int, const char *, int, int)
447 // ------------------------------------------------------
450 #include <l4/util/util.h>
452 int select(int nfds, fd_set *readfds, fd_set *writefds,
453 fd_set *exceptfds, struct timeval *timeout)
455 (void)nfds; (void)readfds; (void)writefds; (void)exceptfds;
456 //printf("Call: %s(%d, %p, %p, %p, %p[%ld])\n", __func__, nfds, readfds, writefds, exceptfds, timeout, timeout->tv_usec + timeout->tv_sec * 1000000);
458 int us = timeout->tv_usec + timeout->tv_sec * 1000000;
459 l4_timeout_t to = l4_timeout(L4_IPC_TIMEOUT_NEVER,
460 l4util_micros2l4to(us));
462 // only the timeout for now
464 l4_usleep(timeout->tv_usec + timeout->tv_sec * 1000000);
473 #define L4B_REDIRECT(ret, func, ptlist, plist) \
474 ret func ptlist L4_NOTHROW \
476 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops; \
477 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(_a1); \
483 ret r = f->func(L4B_STRIP_FIRST(plist)); \
488 L4B_REDIRECT_2(int, fstat64, int, struct stat64 *)
489 L4B_REDIRECT_3(ssize_t, readv, int, const struct iovec *, int)
490 L4B_REDIRECT_3(ssize_t, writev, int, const struct iovec *, int)
491 L4B_REDIRECT_4(ssize_t, preadv, int, const struct iovec *, int, off_t)
492 L4B_REDIRECT_4(ssize_t, pwritev, int, const struct iovec *, int, off_t)
493 L4B_REDIRECT_3(__off64_t, lseek64, int, __off64_t, int)
494 L4B_REDIRECT_2(int, ftruncate64, int, off64_t)
495 L4B_REDIRECT_1(int, fsync, int)
496 L4B_REDIRECT_1(int, fdatasync, int)
497 L4B_REDIRECT_2(int, fchmod, int, mode_t)
499 static char const * const _default_current_working_dir = "/";
500 static char *_current_working_dir = const_cast<char *>(_default_current_working_dir);
502 static void free_cwd()
504 if (_current_working_dir != _default_current_working_dir)
505 free(_current_working_dir);
508 extern "C" int chdir(const char *path) L4_NOTHROW
511 int res = __internal_resolve(AT_FDCWD, path, 0, 0, &f);
517 _current_working_dir = strdup(path);
521 unsigned len_cwd = strlen(_current_working_dir);
522 unsigned len_path = strlen(path);
523 char *tmp = (char *)malloc(len_cwd + len_path + 2);
524 memcpy(tmp, _current_working_dir, len_cwd);
525 if (tmp[len_cwd - 1] != '/')
526 tmp[len_cwd++] = '/';
527 memcpy(tmp + len_cwd, path, len_path + 1);
530 _current_working_dir = tmp;
533 // would need to check whether 'f' is a directory
534 L4Re::Vfs::vfs_ops->set_cwd(f);
539 extern "C" int fchdir(int fd) L4_NOTHROW
541 L4Re::Vfs::Ops *o = L4Re::Vfs::vfs_ops;
542 cxx::Ref_ptr<L4Re::Vfs::File> f = o->get_file(fd);
549 // would need to check whether 'f' is a directory
555 ssize_t pread64(int fd, void *buf, size_t count, off64_t offset)
560 return preadv(fd, &iov, 1, offset);
564 ssize_t pwrite64(int fd, const void *buf, size_t count, off64_t offset)
567 iov.iov_base = const_cast<void*>(buf);
569 return pwritev(fd, &iov, 1, offset);
572 extern "C" char *getcwd(char *buf, size_t size) L4_NOTHROW
574 unsigned len_cwd = strlen(_current_working_dir) + 1;
576 if (buf == 0 && size == 0)
580 buf = (char *)malloc(size);
594 memcpy(buf, _current_working_dir, len_cwd);
598 extern "C" int chroot(const char *) L4_NOTHROW
604 extern "C" int mkfifo(const char *, mode_t) L4_NOTHROW
610 extern "C" int mknod(const char *, mode_t, dev_t) L4_NOTHROW
616 extern "C" int lchown(const char *, uid_t, gid_t) L4_NOTHROW