3 * \brief open/read/seek/close for UX
6 * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
10 * (c) 2008-2009 Author(s)
11 * economic rights: Technische Universität Dresden (Germany)
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU Lesser General Public License 2.1.
14 * Please see the COPYING-LGPL-2.1 file for details.
17 #include <l4/lxfuxlibc/lxfuxlc.h>
18 #include <l4/l4re_vfs/backend>
19 #include <l4/util/util.h>
25 //#include <cstdio> // for debug printf
31 #include <l4/sys/thread.h>
32 #include <l4/re/env.h>
35 using namespace L4Re::Vfs;
38 class Ux_dir : public Be_file
41 explicit Ux_dir(int fd = -1) throw() : Be_file(), _fd(fd) {}
42 int get_entry(const char *, int, mode_t, Ref_ptr<File> *) throw();
43 int fstat64(struct stat64 *buf) const throw();
44 int mkdir(const char *, mode_t) throw();
45 int unlink(const char *) throw();
46 int rename(const char *, const char *) throw();
47 int faccessat(const char *path, int mode, int flags) throw();
48 ssize_t getdents(char *buf, size_t nbytes) throw();
49 ~Ux_dir() throw() { if (_fd >= 0) lx_close(_fd); }
56 class Ux_file : public Be_file
59 explicit Ux_file(int fd = -1) throw() : Be_file(), _fd(fd) {}
61 ssize_t readv(const struct iovec*, int iovcnt) throw();
62 ssize_t writev(const struct iovec*, int iovcnt) throw();
63 ssize_t preadv(const struct iovec *iov, int iovcnt, off64_t offset) throw();
64 ssize_t pwritev(const struct iovec *iov, int iovcnt, off64_t offset) throw();
66 off64_t lseek64(off64_t, int) throw();
67 int fstat64(struct stat64 *buf) const throw();
69 //int fcntl64(int cmd, unsigned long arg);
70 //int ioctl(unsigned long request, void *argp);
73 ~Ux_file() throw() { if (_fd >= 0) lx_close(_fd); }
75 //void fd(int f) { _fd = f; }
83 Ux_dir::get_entry(const char *name, int flags, mode_t mode,
84 Ref_ptr<File> *file) throw()
86 //printf("get_entry: '%s'\n", name);
89 l4_touch_ro(name, strlen(name));
90 int fd = lx_openat(_fd, name, flags, mode);
96 int res = lx_fstat64(fd, (struct lx_stat64 *)&sb);
100 if (S_ISDIR(sb.st_mode))
102 //printf("open '%s' as directory\n", name);
103 *file = new Ux_dir(fd);
107 //printf("open '%s' as file\n", name);
108 *file = new Ux_file(fd);
118 Ux_dir::fstat64(struct stat64 *buf) const throw()
120 return lx_fstat64(_fd, (struct lx_stat64*)buf);
124 Ux_dir::faccessat(const char *path, int mode, int flags) throw()
129 l4_touch_ro(path, strlen(path));
130 return lx_faccessat(_fd, path, mode);
134 Ux_dir::mkdir(const char *name, mode_t mode) throw()
136 l4_touch_ro(name, strlen(name));
137 return lx_mkdirat(_fd, name, mode);
141 Ux_dir::unlink(const char *name) throw()
143 l4_touch_ro(name, strlen(name));
144 return lx_unlinkat(_fd, name, 0);
148 Ux_dir::rename(const char *old, const char *newn) throw()
150 l4_touch_ro(old, strlen(old));
151 l4_touch_ro(newn, strlen(newn));
152 return lx_renameat(_fd, old, _fd, newn);
156 Ux_dir::getdents(char *buf, size_t nbytes) throw()
158 #define kernel_dirent64 lx_linux_dirent64
159 #define MIN(a,b) (((a)<(b))?(a):(b))
160 // taken from uclibc/ARCH-all/libc/sysdeps/linux/common/getdents64.c
162 off64_t last_offset = -1;
165 struct kernel_dirent64 *skdp, *kdp;
166 const size_t size_diff = (offsetof (struct dirent64, d_name)
167 - offsetof (struct kernel_dirent64, d_name));
169 red_nbytes = MIN (nbytes - ((nbytes /
170 (offsetof (struct dirent64, d_name) + 14)) * size_diff),
173 dp = (struct dirent64 *) buf;
174 skdp = kdp = (lx_linux_dirent64*)alloca (red_nbytes);
176 l4_touch_rw(kdp, red_nbytes);
178 retval = lx_getdents64(_fd, (char *)kdp, red_nbytes);
182 while ((char *) kdp < (char *) skdp + retval) {
183 const size_t alignment = __alignof__ (struct dirent64);
184 /* Since kdp->d_reclen is already aligned for the kernel structure
185 this may compute a value that is bigger than necessary. */
186 size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
188 if ((char *) dp + new_reclen > buf + nbytes) {
189 /* Our heuristic failed. We read too many entries. Reset
191 assert (last_offset != -1);
193 //lx_lseek64(_fd, last_offset, SEEK_SET);
194 lx_lseek(_fd, last_offset, SEEK_SET);
196 if ((char *) dp == buf) {
197 /* The buffer the user passed in is too small to hold even
199 __set_errno (EINVAL);
205 last_offset = kdp->d_off;
206 dp->d_ino = kdp->d_ino;
207 dp->d_off = kdp->d_off;
208 dp->d_reclen = new_reclen;
209 dp->d_type = kdp->d_type;
210 memcpy (dp->d_name, kdp->d_name,
211 kdp->d_reclen - offsetof (struct kernel_dirent64, d_name));
212 dp = (struct dirent64 *) ((char *) dp + new_reclen);
213 kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen);
215 return (char *) dp - buf;
217 #undef kernel_dirent64
223 Ux_file::readv(const struct iovec *iov, int cnt) throw()
225 for (int i = 0; i < cnt; ++i)
226 l4_touch_rw(iov[i].iov_base, iov[i].iov_len);
228 return lx_readv(_fd, (struct lx_iovec*)iov, cnt);
232 Ux_file::writev(const struct iovec *iov, int cnt) throw()
234 for (int i = 0; i < cnt; ++i)
235 l4_touch_ro(iov[i].iov_base, iov[i].iov_len);
237 return lx_writev(_fd, (struct lx_iovec*)iov, cnt);
241 Ux_file::preadv(const struct iovec *iov, int iovcnt, off64_t offset) throw()
243 for (int i = 0; i < iovcnt; ++i)
244 l4_touch_rw(iov[i].iov_base, iov[i].iov_len);
246 return lx_preadv(_fd, (struct lx_iovec*)iov, iovcnt, offset, offset << 32);
250 Ux_file::pwritev(const struct iovec *iov, int iovcnt, off64_t offset) throw()
252 for (int i = 0; i < iovcnt; ++i)
253 l4_touch_ro(iov[i].iov_base, iov[i].iov_len);
255 return lx_pwritev(_fd, (struct lx_iovec*)iov, iovcnt, offset, offset << 32);
259 Ux_file::lseek64(off64_t offset, int whence) L4_NOTHROW
261 //printf("lseek: fd=%d offset=%lld\n", _fd, offset);
262 return lx_lseek(_fd, offset, whence);
267 ux_file_ops::fcntl64(int cmd, unsigned long arg)
269 return lx_fcntl64(_fd, cmd, arg);
274 Ux_file::fstat64(struct stat64 *buf) const throw()
276 l4_touch_rw(buf, sizeof(*buf));
277 return lx_fstat64(_fd, (struct lx_stat64 *)buf);
282 ux_file_ops::ioctl(unsigned long cmd, void *argp)
284 return lx_ioctl(_fd, cmd, (unsigned long)argp);
288 class Ux_fs : public Be_file_system
291 Ux_fs() : Be_file_system("fuxfs")
293 l4_thread_control_start();
294 l4_thread_control_ux_host_syscall(1);
295 l4_thread_control_commit(l4re_env()->main_thread);
298 int mount(char const *source, unsigned long mountflags,
299 void const *data, cxx::Ref_ptr<File> *dir) throw()
304 l4_touch_ro(source, strlen(source));
305 int fd = lx_open(source, O_DIRECTORY, 0);
309 *dir = new Ux_dir(fd);
316 static Ux_fs _ux_fs L4RE_VFS_FILE_SYSTEM_ATTRIBUTE;