]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re_vfs/include/impl/ro_file_impl.h
update
[l4.git] / l4 / pkg / l4re_vfs / include / impl / ro_file_impl.h
1 /*
2  * (c) 2010 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  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  *
10  * As a special exception, you may use this file as part of a free software
11  * library without restriction.  Specifically, if other files instantiate
12  * templates or use macros or inline functions from this file, or you compile
13  * this file and link it with other files to produce an executable, this
14  * file does not by itself cause the resulting executable to be covered by
15  * the GNU General Public License.  This exception does not however
16  * invalidate any other reasons why the executable file might be covered by
17  * the GNU General Public License.
18  */
19
20 #include "ds_util.h"
21 #include "ro_file.h"
22
23 #include <sys/ioctl.h>
24
25 #include <l4/re/env>
26
27 namespace L4Re { namespace Core {
28
29
30 Simple_store<Ro_file> Ro_file::store __attribute__((init_priority(1000)));
31
32
33 void *
34 Ro_file::operator new(size_t s) throw()
35 {
36   if (s != sizeof(Ro_file))
37     return 0;
38
39   return store.alloc();
40 }
41
42 void
43 Ro_file::operator delete(void *b) throw()
44 {
45   store.free(b);
46 }
47
48
49 Ro_file::~Ro_file() throw()
50 {
51   if (_addr)
52     L4Re::Env::env()->rm()->detach(l4_addr_t(_addr), 0);
53
54   release_ds(_ds);
55 }
56
57 int
58 Ro_file::fstat64(struct stat64 *buf) const throw()
59 {
60   static int fake = 0;
61
62   memset(buf, 0, sizeof(*buf));
63   buf->st_size = _size;
64   buf->st_mode = S_IFREG | 0644;
65   buf->st_dev = _ds.cap();
66   buf->st_ino = ++fake;
67   buf->st_blksize = L4_PAGESIZE;
68   buf->st_blocks = l4_round_page(_size);
69   return 0;
70 }
71
72 ssize_t
73 Ro_file::read_single(const struct iovec *vec, off64_t pos) throw()
74 {
75   off64_t l = vec->iov_len;
76   if (_size - pos < l)
77     l = _size - pos;
78
79   if (l > 0)
80     {
81       Vfs_config::memcpy(vec->iov_base, _addr + pos, l);
82       return l;
83     }
84
85   return 0;
86 }
87
88 ssize_t
89 Ro_file::preadv(const struct iovec *vec, int cnt, off64_t offset) throw()
90 {
91   if (!_addr)
92     {
93       void const *file = (void*)L4_PAGESIZE;
94       long err = L4Re::Env::env()->rm()->attach(&file, _size,
95                                                 Rm::Search_addr | Rm::Read_only,
96                                                 _ds, 0);
97
98       if (err < 0)
99         return err;
100
101       _addr = (char const *)file;
102     }
103
104   ssize_t l = 0;
105
106   while (cnt > 0)
107     {
108       ssize_t r = read_single(vec, offset);
109       offset += r;
110       l += r;
111
112       if ((size_t)r < vec->iov_len)
113         return l;
114
115       ++vec;
116       --cnt;
117     }
118   return l;
119 }
120
121 ssize_t
122 Ro_file::pwritev(const struct iovec *, int, off64_t) throw()
123 {
124   return -EROFS;
125 }
126
127 int
128 Ro_file::ioctl(unsigned long v, va_list args) throw()
129 {
130   switch (v)
131     {
132     case FIONREAD: // return amount of data still available
133       int *available = va_arg(args, int *);
134       *available = _size - pos();
135       return 0;
136     };
137   return -EINVAL;
138 }
139
140 }}