]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re_vfs/include/impl/ns_fs_impl.h
update
[l4.git] / l4 / pkg / l4re_vfs / include / impl / ns_fs_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 #include "ns_fs.h"
17 #include "vfs_api.h"
18 #include "ro_file.h"
19
20 #include <l4/re/dataspace>
21 #include <l4/re/util/env_ns>
22 #include <dirent.h>
23
24 namespace L4Re { namespace Core {
25
26 Simple_store_sz<Env_dir::Size> Ns_base_dir::store;
27
28 void *
29 Ns_base_dir::operator new(size_t s) throw()
30 {
31   if (s > Size)
32     return 0;
33
34   return store.alloc();
35 }
36
37 void
38 Ns_base_dir::operator delete(void *b) throw()
39 {
40   store.free(b);
41 }
42
43
44 int
45 Ns_dir::get_ds(const char *path, L4Re::Auto_cap<L4Re::Dataspace>::Cap *ds) throw()
46 {
47   L4Re::Auto_cap<L4Re::Dataspace>::Cap file(cap_alloc()->alloc<L4Re::Dataspace>(), cap_alloc());
48
49   if (!file.is_valid())
50     return -ENOMEM;
51
52   int err = _ns->query(path, file.get());
53
54   if (err < 0)
55     return -ENOENT;
56
57   *ds = file;
58   return err;
59 }
60
61 int
62 Ns_dir::get_entry(const char *path, int flags, mode_t mode,
63                   Ref_ptr<L4Re::Vfs::File> *f) throw()
64 {
65   (void)mode; (void)flags;
66   if (!*path)
67     {
68       *f = this;
69       return 0;
70     }
71
72   L4Re::Auto_cap<Dataspace>::Cap file;
73   int err = get_ds(path, &file);
74
75   if (err < 0)
76     return -ENOENT;
77
78   // FIXME: should check if it is a dataspace, somehow
79   L4Re::Vfs::File *fi = 0;
80
81   L4::Cap<L4Re::Namespace> nsc
82     = L4::cap_dynamic_cast<L4Re::Namespace>(file.get());
83
84   if (!nsc.is_valid())
85     fi = new Ro_file(file.get());
86   else // use mat protocol here!!
87     fi = new Ns_dir(nsc);
88
89   if (!fi)
90     return -ENOMEM;
91
92   file.release();
93   *f = fi;
94   return 0;
95 }
96
97 int
98 Ns_dir::faccessat(const char *path, int mode, int flags) throw()
99 {
100   (void)flags;
101   L4Re::Auto_cap<void>::Cap tmpcap(cap_alloc()->alloc<void>(), cap_alloc());
102
103   if (!tmpcap.is_valid())
104     return -ENOMEM;
105
106   if (_ns->query(path, tmpcap.get()))
107     return -ENOENT;
108
109   if (mode & W_OK)
110     return -EACCES;
111
112   return 0;
113 }
114
115 int Ns_dir::
116 fstat64(struct stat64 *b) const throw()
117 {
118   b->st_dev = 1;
119   b->st_ino = 1;
120   b->st_mode = S_IRWXU | S_IFDIR;
121   b->st_nlink = 0;
122   b->st_uid = 0;
123   b->st_gid = 0;
124   b->st_rdev = 0;
125   b->st_size = 0;
126   b->st_blksize = 0;
127   b->st_blocks = 0;
128   b->st_atime = 0;
129   b->st_mtime = 0;
130   b->st_ctime = 0;
131   return 0;
132 }
133
134 int
135 Env_dir::get_ds(const char *path, L4Re::Auto_cap<L4Re::Dataspace>::Cap *ds) throw()
136 {
137   Vfs::Path p(path);
138   Vfs::Path first = p.strip_first();
139
140   if (first.empty())
141     return -ENOENT;
142
143   L4::Cap<L4Re::Namespace>
144     c = _env->get_cap<L4Re::Namespace>(first.path(), first.length());
145
146   if (!c.is_valid())
147     return -ENOENT;
148
149   if (p.empty())
150     {
151       *ds = L4Re::Auto_cap<L4Re::Dataspace>::Cap(L4::cap_reinterpret_cast<L4Re::Dataspace>(c));
152       return 0;
153     }
154
155   L4Re::Auto_cap<L4Re::Dataspace>::Cap file(cap_alloc()->alloc<L4Re::Dataspace>(), cap_alloc());
156
157   if (!file.is_valid())
158     return -ENOMEM;
159
160   int err = c->query(p.path(), p.length(), file.get());
161
162   if (err < 0)
163     return -ENOENT;
164
165   *ds = file;
166   return err;
167 }
168
169 int
170 Env_dir::get_entry(const char *path, int flags, mode_t mode,
171                    Ref_ptr<L4Re::Vfs::File> *f) throw()
172 {
173   (void)mode; (void)flags;
174   if (!*path)
175     {
176       *f = this;
177       return 0;
178     }
179
180   L4Re::Auto_cap<Dataspace>::Cap file;
181   int err = get_ds(path, &file);
182
183   if (err < 0)
184     return -ENOENT;
185
186   // FIXME: should check if it is a dataspace, somehow
187   L4Re::Vfs::File *fi = 0;
188
189   L4::Cap<L4Re::Namespace> nsc
190     = L4::cap_dynamic_cast<L4Re::Namespace>(file.get());
191
192   if (!nsc.is_valid())
193     fi = new Ro_file(file.get());
194   else // use mat protocol here!!
195     fi = new Ns_dir(nsc);
196
197   if (!fi)
198     return -ENOMEM;
199
200   file.release();
201   *f = fi;
202   return 0;
203 }
204
205 int
206 Env_dir::faccessat(const char *path, int mode, int flags) throw()
207 {
208   (void)flags;
209   Vfs::Path p(path);
210   Vfs::Path first = p.strip_first();
211
212   if (first.empty())
213     return -ENOENT;
214
215   L4::Cap<L4Re::Namespace>
216     c = _env->get_cap<L4Re::Namespace>(first.path(), first.length());
217
218   if (!c.is_valid())
219     return -ENOENT;
220
221   if (p.empty())
222     {
223       if (mode & W_OK)
224         return -EACCES;
225
226       return 0;
227     }
228
229   L4Re::Auto_cap<void>::Cap tmpcap(cap_alloc()->alloc<void>(), cap_alloc());
230
231   if (!tmpcap.is_valid())
232     return -ENOMEM;
233
234   if (c->query(p.path(), p.length(), tmpcap.get()))
235     return -ENOENT;
236
237   if (mode & W_OK)
238     return -EACCES;
239
240   return 0;
241 }
242
243 int
244 Env_dir::fstat64(struct stat64 *b) const throw()
245 {
246   b->st_dev = 1;
247   b->st_ino = 1;
248   b->st_mode = S_IRWXU | S_IFDIR;
249   b->st_nlink = 0;
250   b->st_uid = 0;
251   b->st_gid = 0;
252   b->st_rdev = 0;
253   b->st_size = 0;
254   b->st_blksize = 0;
255   b->st_blocks = 0;
256   b->st_atime = 0;
257   b->st_mtime = 0;
258   b->st_ctime = 0;
259   return 0;
260 }
261
262 ssize_t
263 Env_dir::getdents(char *buf, size_t sz) throw()
264 {
265   struct dirent64 *d = (struct dirent64 *)buf;
266   ssize_t ret = 0;
267
268   while (d
269          && _current_cap_entry
270          && _current_cap_entry->flags != ~0UL)
271     {
272       unsigned l = strlen(_current_cap_entry->name) + 1;
273       if (l > sizeof(d->d_name))
274         l = sizeof(d->d_name);
275
276       unsigned n = offsetof (struct dirent64, d_name) + l;
277
278       if (n <= sz)
279         {
280           d->d_ino = 1;
281           d->d_off = 0;
282           memcpy(d->d_name, _current_cap_entry->name, l);
283           d->d_name[l - 1] = 0;
284           d->d_reclen = n;
285           ret += n;
286           sz  -= n;
287           d    = (struct dirent64 *)((unsigned long)d + n);
288           _current_cap_entry++;
289         }
290       else
291         return ret;
292     }
293
294   // bit of a hack because we should only (re)set this when opening the dir
295   if (!ret)
296     _current_cap_entry = _env->initial_caps();
297
298   return ret;
299 }
300
301 }}