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)
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.
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.
23 #include <l4/re/dataspace>
24 #include <l4/re/util/env_ns>
27 namespace L4Re { namespace Core {
29 Simple_store_sz<Env_dir::Size> Ns_base_dir::store;
32 Ns_base_dir::operator new(size_t s) throw()
41 Ns_base_dir::operator delete(void *b) throw()
48 Ns_dir::get_ds(const char *path, L4Re::Auto_cap<L4Re::Dataspace>::Cap *ds) throw()
50 L4Re::Auto_cap<L4Re::Dataspace>::Cap file(cap_alloc()->alloc<L4Re::Dataspace>(), cap_alloc());
55 int err = _ns->query(path, file.get());
65 Ns_dir::get_entry(const char *path, int flags, mode_t mode,
66 Ref_ptr<L4Re::Vfs::File> *f) throw()
68 (void)mode; (void)flags;
75 L4Re::Auto_cap<Dataspace>::Cap file;
76 int err = get_ds(path, &file);
81 // FIXME: should check if it is a dataspace, somehow
82 L4Re::Vfs::File *fi = 0;
84 L4::Cap<L4Re::Namespace> nsc
85 = L4::cap_dynamic_cast<L4Re::Namespace>(file.get());
88 fi = new Ro_file(file.get());
89 else // use mat protocol here!!
101 Ns_dir::faccessat(const char *path, int mode, int flags) throw()
104 L4Re::Auto_cap<void>::Cap tmpcap(cap_alloc()->alloc<void>(), cap_alloc());
106 if (!tmpcap.is_valid())
109 if (_ns->query(path, tmpcap.get()))
119 Ns_dir::fstat64(struct stat64 *b) const throw()
123 b->st_mode = S_IRWXU | S_IFDIR;
138 Ns_dir::getdents(char *buf, size_t sz) throw()
140 struct dirent64 *d = (struct dirent64 *)buf;
145 L4Re::Auto_cap<Dataspace>::Cap dirinfofile;
146 int err = get_ds(".dirinfo", &dirinfofile);
150 infosz = dirinfofile->size();
154 infoaddr = L4_PAGESIZE;
155 err = L4Re::Env::env()->rm()->attach(&infoaddr, infosz,
156 Rm::Search_addr | Rm::Read_only,
157 dirinfofile.get(), 0);
158 char *p = (char *)infoaddr + _current_dir_pos;
159 char *end = (char *)infoaddr + infosz;
163 // parse lines of dirinfofile
165 for (len = 0; p < end && *p >= '0' && *p <= '9'; ++p)
175 return 0; // error in dirinfofile
177 unsigned l = len + 1;
178 if (l > sizeof(d->d_name))
179 l = sizeof(d->d_name);
181 unsigned n = offsetof (struct dirent64, d_name) + l;
188 memcpy(d->d_name, p, len);
189 d->d_name[l - 1] = 0;
194 d = (struct dirent64 *)((unsigned long)d + n);
197 // next infodirfile line
198 while (p < end && *p && *p != '\n' && *p != '\r')
200 while (p < end && *p && (*p == '\n' || *p == '\r'))
204 _current_dir_pos += p - (char *)infoaddr;
206 if (!ret) // hack since we should only reset this at open times
207 _current_dir_pos = 0;
209 L4Re::Env::env()->rm()->detach(infoaddr, 0);
215 Env_dir::get_ds(const char *path, L4Re::Auto_cap<L4Re::Dataspace>::Cap *ds) throw()
218 Vfs::Path first = p.strip_first();
223 L4::Cap<L4Re::Namespace>
224 c = _env->get_cap<L4Re::Namespace>(first.path(), first.length());
231 *ds = L4Re::Auto_cap<L4Re::Dataspace>::Cap(L4::cap_reinterpret_cast<L4Re::Dataspace>(c));
235 L4Re::Auto_cap<L4Re::Dataspace>::Cap file(cap_alloc()->alloc<L4Re::Dataspace>(), cap_alloc());
237 if (!file.is_valid())
240 int err = c->query(p.path(), p.length(), file.get());
250 Env_dir::get_entry(const char *path, int flags, mode_t mode,
251 Ref_ptr<L4Re::Vfs::File> *f) throw()
253 (void)mode; (void)flags;
260 L4Re::Auto_cap<Dataspace>::Cap file;
261 int err = get_ds(path, &file);
266 // FIXME: should check if it is a dataspace, somehow
267 L4Re::Vfs::File *fi = 0;
269 L4::Cap<L4Re::Namespace> nsc
270 = L4::cap_dynamic_cast<L4Re::Namespace>(file.get());
273 fi = new Ro_file(file.get());
274 else // use mat protocol here!!
275 fi = new Ns_dir(nsc);
286 Env_dir::faccessat(const char *path, int mode, int flags) throw()
290 Vfs::Path first = p.strip_first();
295 L4::Cap<L4Re::Namespace>
296 c = _env->get_cap<L4Re::Namespace>(first.path(), first.length());
309 L4Re::Auto_cap<void>::Cap tmpcap(cap_alloc()->alloc<void>(), cap_alloc());
311 if (!tmpcap.is_valid())
314 if (c->query(p.path(), p.length(), tmpcap.get()))
324 Env_dir::check_type(Env::Cap_entry const *e, long protocol)
326 L4::Cap<L4::Meta> m(e->cap);
327 return m->supports(protocol).label();
331 Env_dir::fstat64(struct stat64 *b) const throw()
335 b->st_mode = S_IRWXU | S_IFDIR;
350 Env_dir::getdents(char *buf, size_t sz) throw()
352 struct dirent64 *d = (struct dirent64 *)buf;
356 && _current_cap_entry
357 && _current_cap_entry->flags != ~0UL)
359 unsigned l = strlen(_current_cap_entry->name) + 1;
360 if (l > sizeof(d->d_name))
361 l = sizeof(d->d_name);
363 unsigned n = offsetof (struct dirent64, d_name) + l;
369 memcpy(d->d_name, _current_cap_entry->name, l);
370 d->d_name[l - 1] = 0;
372 if (check_type(_current_cap_entry, L4Re::Protocol::Namespace))
374 else if (check_type(_current_cap_entry, L4Re::Protocol::Dataspace))
377 d->d_type = DT_UNKNOWN;
380 d = (struct dirent64 *)((unsigned long)d + n);
381 _current_cap_entry++;
387 // bit of a hack because we should only (re)set this when opening the dir
389 _current_cap_entry = _env->initial_caps();