]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re/util/libs/name_space_svr.cc
284abf16ccce2e152a8a592f57336a6e082606c5
[l4.git] / l4 / pkg / l4re / util / libs / name_space_svr.cc
1 /*
2  * (c) 2008-2009 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 #include <l4/re/util/name_space_svr>
20 #include <l4/re/util/debug>
21
22 #include <l4/re/namespace-sys.h>
23 #include <l4/re/namespace>
24 #include <l4/re/protocols>
25 #include <l4/re/util/meta>
26
27 #include <cassert>
28 #include <cstring>
29 #include <typeinfo>
30
31
32 namespace L4Re { namespace Util { namespace Names {
33
34 bool
35 Name::operator < (Name const &r) const
36 {
37   unsigned char l = cxx::min(len(), r.len());
38   int v = strncmp(start(), r.start(), l);
39   return v < 0 || (v == 0 && len() < r.len());
40 }
41
42
43 bool
44 Entry::link(Entry *src)
45 {
46   if (src->obj()->is_replacable() || !src->obj()->is_complete())
47     {
48       src->add_link(this);
49       if (src->obj()->is_complete())
50         obj()->set(*src->obj(), obj()->flags());
51       return false;
52     }
53
54   obj()->set(*src->obj(), obj()->flags());
55   return true;
56 }
57
58 void
59 Entry::set(Obj const &o)
60 {
61   Entry *e = this;
62   while (e)
63     {
64       e->obj()->set(o, e->obj()->flags());
65       e = e->next_link();
66     }
67 }
68
69 Entry *
70 Name_space::find_iter(Name const &pname) const
71 {
72   Name name = pname;
73   _dbg.printf("resolve '%.*s': ", name.len(), name.start());
74   Name_space const *ns = this;
75   while (ns)
76     {
77       cxx::String::Index sep = name.find("/");
78       cxx::String part;
79       if (!name.eof(sep))
80         part = name.head(sep);
81       else
82         part = name;
83
84       _dbg.cprintf(" '%.*s'", part.len(), part.start());
85       Entry *o = ns->find(Name(part.start(), part.len()));
86
87       if (!o)
88         {
89           _dbg.cprintf(": resolution failed: '%.*s' remaining\n",
90                       name.len(), name.start());
91           return 0;
92         }
93
94       ns = dynamic_cast<Name_space const *>(o->obj()->obj());
95       if (ns)
96         {
97           if (!name.eof(sep))
98             {
99               name = name.substr(sep + 1);
100               continue;
101             }
102         }
103
104       _dbg.cprintf(": found object: %p (%s)\n", o->obj()->obj(), o->obj()->obj()?typeid(*(o->obj()->obj())).name():"");
105
106       return o;
107     }
108
109   return 0;
110 }
111
112
113 int
114 Name_space::query(L4::Ipc::Iostream &ios, char *buffer, size_t max_len)
115 {
116   char const *name = 0;
117   unsigned long len = max_len;
118   ios >> L4::Ipc::Buf_in<char const>(name, len);
119 #if 1
120   _dbg.printf("query: [%ld] '%.*s'\n", len, (int)len, name);
121 #endif
122
123   len = cxx::min<unsigned long>(len, max_len);
124   char const *sep = (char const*)memchr(name, '/', len);
125   unsigned long part;
126   if (sep)
127     {
128       part = sep - name;
129       memcpy(buffer, sep + 1, len - part - 1);
130     }
131   else
132     part = len;
133
134   Entry *n = find(Name(name, part));
135   if (!n)
136     return -L4_ENOENT;
137   else if (!n->obj()->is_valid())
138     return -L4_EAGAIN;
139   else
140     {
141       if (n->obj()->cap().validate(L4_BASE_TASK_CAP).label() <= 0)
142         {
143           assert (!n->obj()->is_local());
144
145           free_capability(n->obj()->cap());
146
147           if (n->is_dynamic())
148             {
149               remove(n->name());
150               free_dynamic_entry(n);
151             }
152           return -L4_ENOENT;
153         }
154
155       l4_umword_t result = 0;
156
157       if (part < len)
158         {
159           result |= L4Re::Namespace::Partly_resolved;
160           ios << (l4_umword_t)0 << L4::Ipc::Buf_cp_out<char>(buffer, len - part - 1);
161         }
162
163       unsigned flags = L4_FPAGE_RO;
164       if (n->obj()->is_rw())     flags |= L4_FPAGE_RX;
165       if (n->obj()->is_strong()) flags |= L4_FPAGE_RW;
166
167       ios << L4::Ipc::Snd_fpage(n->obj()->cap(), flags );
168       _dbg.printf(" result = %lx flgs=%x strg=%d\n",
169                   result, flags, (int)n->obj()->is_strong());
170       return result;
171     }
172 }
173
174 int
175 Name_space::insert_entry(Name const &name, unsigned flags, Entry **e)
176 {
177   Entry *n = find(name);
178   if (n && n->obj()->is_valid())
179     {
180       if (!(flags & L4Re::Namespace::Overwrite)
181           && n->obj()->cap().validate(L4_BASE_TASK_CAP).label() > 0)
182         return -L4_EEXIST;
183
184       if (!n->obj()->is_local())
185         free_capability(n->obj()->cap());
186
187       if (n->is_dynamic())
188         {
189           remove(n->name());
190           free_dynamic_entry(n);
191           n = 0;
192         }
193       else
194         {
195           n->obj()->reset(Obj::F_rw);
196           if (!n->obj()->is_replacable())
197             return -L4_EEXIST;
198         }
199     }
200
201   flags &= L4Re::Namespace::Cap_flags;
202   if (!n)
203     {
204       if (!(n = alloc_dynamic_entry(name, flags)))
205         return -L4_ENOMEM;
206       else
207         {
208           int err = insert(n);
209           if (err < 0)
210             {
211               free_dynamic_entry(n);
212               return err;
213             }
214         }
215     }
216
217   *e = n;
218   return 0;
219 }
220
221 int
222 Name_space::link_entry(L4::Ipc::Iostream &ios, char *buffer, size_t max_len)
223 {
224   char const *name = 0, *src_name = 0;
225   unsigned long len, src_len;
226   unsigned flags;
227   L4::Ipc::Snd_fpage src_cap;
228   ios >> flags >> L4::Ipc::Buf_in<char const>(name, len)
229       >> L4::Ipc::Buf_in<char const>(src_name, src_len)
230       >> src_cap;
231
232   L4::Cap<void> reg_cap(L4::Cap_base::No_init);
233   L4::Server_object *src_ns_o = 0;
234   // Did we receive something we have handed out ourselves? If yes,
235   // register the object under the given name but do not allocate
236   // anything more.
237   if (int r = get_capability(src_cap, &reg_cap, &src_ns_o))
238     return r;
239
240   Name_space *src_ns = dynamic_cast<Name_space*>(src_ns_o);
241   if (!src_ns)
242     return -L4_EINVAL;
243
244   _dbg.printf("link: '%.*s' flags=%x\n", (int)len, name, flags);
245
246   Name const src_n(src_name, src_len);
247
248   Entry *n = src_ns->find(src_n);
249   if (!n)
250     {
251       if (!(n = src_ns->alloc_dynamic_entry(src_n, 0)))
252         return -L4_ENOMEM;
253       else
254         {
255           int err = src_ns->insert(n);
256           if (err < 0)
257             {
258               src_ns->free_dynamic_entry(n);
259               return err;
260             }
261         }
262    }
263
264   // got a mapping at Rcv_cap
265   len = cxx::min(len, (unsigned long)max_len);
266   memcpy(buffer, name, len);
267   Name const dst_name(buffer, len);
268
269   Entry *dst;
270
271   if (int r = insert_entry(dst_name, flags, &dst))
272     return r;
273
274   dst->link(n);
275
276   return 0;
277 }
278
279
280 int
281 Name_space::register_entry(L4::Ipc::Iostream &ios, char *buffer, size_t max_len)
282 {
283   char const *name = 0;
284   unsigned long len;
285   unsigned flags;
286   L4::Ipc::Snd_fpage cap;
287   ios >> flags >> L4::Ipc::Buf_in<char const>(name, len);
288
289   L4::Cap<void> reg_cap(L4_INVALID_CAP);
290   l4_msgtag_t tag;
291   ios >> tag;
292   if (tag.items())
293     {
294       ios >> cap;
295
296       // Did we receive something we have handed out ourselves? If yes,
297       // register the object under the given name but do not allocate
298       // anything more.
299       if (int r = get_capability(cap, &reg_cap))
300         return r;
301     }
302
303   _dbg.printf("register: '%.*s' flags=%x\n", (int)len, name, flags);
304
305   // got a mapping at Rcv_cap
306   len = cxx::min(len, (unsigned long)max_len);
307   memcpy(buffer, name, len);
308   Name _name(buffer, len);
309
310   Entry *n;
311   if (int r = insert_entry(_name, flags, &n))
312     return r;
313
314   if (reg_cap.is_valid())
315     {
316       if (int r = save_capability(&reg_cap))
317         return r;
318
319       n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, reg_cap));
320     }
321
322   return 0;
323 }
324
325 int
326 Name_space::unlink_entry(L4::Ipc::Iostream &ios, char *buffer, size_t max_len)
327 {
328   char const *name = 0;
329   unsigned long len = max_len;
330   ios >> L4::Ipc::Buf_in<char const>(name, len);
331 #if 1
332   _dbg.printf("unlink: [%ld] '%.*s'\n", len, (int)len, name);
333 #endif
334
335   len = cxx::min<unsigned long>(len, max_len);
336   char const *sep = (char const*)memchr(name, '/', len);
337   unsigned long part;
338   if (sep)
339     {
340       part = sep - name;
341       memcpy(buffer, sep + 1, len - part - 1);
342     }
343   else
344     part = len;
345
346   Entry *n = find(Name(name, part));
347   if (!n || !n->obj()->is_valid())
348     return -L4_ENOENT;
349
350   if (!n->obj()->is_local())
351     free_capability(n->obj()->cap());
352
353   if (n->is_dynamic())
354     {
355       remove(n->name());
356       free_dynamic_entry(n);
357     }
358   else
359     return -L4_EACCESS;
360
361   return 0;
362 }
363
364
365
366 int
367 Name_space::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios, char *buffer,
368                      size_t max_len)
369 {
370   l4_msgtag_t tag;
371   ios >> tag;
372
373   switch (tag.label())
374     {
375     case L4::Meta::Protocol:
376       return L4Re::Util::handle_meta_request<L4Re::Namespace>(ios);
377
378     case L4Re::Protocol::Namespace:
379         {
380           L4::Opcode op;
381           ios >> op;
382
383
384           int err;
385           switch(op)
386             {
387             case L4Re::Namespace_::Query:
388               return query(ios, buffer, max_len);
389             case L4Re::Namespace_::Link:
390               if (!(obj & 1)) // & L4_FPAGE_X
391                 return -L4_EPERM;
392               err = link_entry(ios, buffer, max_len);
393               return err;
394             case L4Re::Namespace_::Register:
395               if (!(obj & 1)) // & L4_FPAGE_X
396                 return -L4_EPERM;
397               err = register_entry(ios, buffer, max_len);
398               return err;
399             case L4Re::Namespace_::Unlink:
400               if (!(obj & 1)) // & L4_FPAGE_X
401                 return -L4_EPERM;
402               err = unlink_entry(ios, buffer, max_len);
403               return err;
404             default:
405               return -L4_ENOSYS;
406             }
407         }
408     default:
409       return -L4_EBADPROTO;
410     }
411
412 }
413
414 }}}