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